int DecodeTable2(MaiBitReader mbr0, MaiAt3PlusCoreDecoderChnInfo[] chnInfos, uint chns)
        {
            int rs = 0;

            if (chnInfos[0].JointChnInfo.NumBandSplitedUsed != 0)                //
            {
                chnInfos[0].JointChnInfo.Var90 = (uint)mbr0.GetWithI32Buffer(1); //[90] tmp4 [arg1]

                for (uint a0 = 0; a0 < chns; a0++)
                {
                    for (uint a1 = 0; a1 < 0x20; a1++)
                    {
                        chnInfos[a0].Table2[a1] = 0;
                    }

                    chnInfos[a0].Var1034 = (uint)mbr0.GetWithI32Buffer(1);                //[1034] tmp5

                    MAPCDSF_makeTable0CheckTable(chnInfos[a0], chnInfos[a0].CheckTable0); //check

                    if (0 != (rs = MAPCDSF_decodeTable2_func_list0[
                                  chnInfos[a0].ChnFlag * 4 + mbr0.GetWithI32Buffer(2)]
                                       (mbr0, chnInfos[a0])
                              ))
                    {
                        return(rs);
                    }
                }

                //comp
            }

            return(rs);
        }
        int DecodeTable0(MaiBitReader mbr0, MaiAt3PlusCoreDecoderChnInfo[] chnInfos, uint chns)
        {
            int rs = 0;

            for (uint a0 = 0; a0 < chns; a0++)
            {
                for (uint a1 = 0; a1 < 0x20; a1++)
                {
                    chnInfos[a0].Table0[a1] = 0;
                }

                if ((rs = MAPCDSF_decodeTable0_func_list0[chnInfos[a0].ChnFlag * 4 + mbr0.GetWithI32Buffer(2)]
                              (mbr0, chnInfos[a0])
                     ) != 0)
                {
                    return(rs);
                }
            }

            chnInfos[0].JointChnInfo.NumBandSplitedUsed =
                chnInfos[0].JointChnInfo.NumBandSplitedDeclared; //[B0]

            if (chns == 2)
            {
                while (0 != chnInfos[0].JointChnInfo.NumBandSplitedUsed &&
                       0 == chnInfos[0].Table0[chnInfos[0].JointChnInfo.NumBandSplitedUsed - 1] &&
                       0 == chnInfos[1].Table0[chnInfos[0].JointChnInfo.NumBandSplitedUsed - 1])
                {
                    chnInfos[0].JointChnInfo.NumBandSplitedUsed--;
                }
            }
            else
            {
                while (0 != chnInfos[0].JointChnInfo.NumBandSplitedUsed &&
                       0 == chnInfos[0].Table0[chnInfos[0].JointChnInfo.NumBandSplitedUsed - 1])
                {
                    chnInfos[0].JointChnInfo.NumBandSplitedUsed--;
                }
            }

            chnInfos[0].JointChnInfo.NumBandUsed =
                (uint)MaiAT3PlusCoreDecoder_StaticData.MAPCDSD_band_num_table0[
                    chnInfos[0].JointChnInfo.NumBandSplitedUsed] + 1;

            //check
            for (uint a0 = 0; a0 < chns; a0++)
            {
                for (uint a1 = 0; a1 < 0x20; a1++)
                {
                    if (chnInfos[a0].Table0[a1] < 0 || chnInfos[a0].Table0[a1] >= 8)
                    {
                        return(-0x10B);
                    }
                }
            }

            return(rs);
        }
        int DecodeAcc2Pre(MaiBitReader mbr0, MaiAt3PlusCoreDecoderChnInfo[] chnInfos, uint chns)
        {
            int rs = 0;

            for (uint a0 = 0; a0 < chns; a0++)
            {
                MAPCDSF_readPackTable0(mbr0, chnInfos[a0].AccDataNow.Acc,
                                       chnInfos[0].JointChnInfo.NumBandDeclared);
            }

            return(rs);
        }
        public int ParseStream(MaiBitReader mbr0, uint chns, uint jointFlag)
        {
            int rs = 0;

            _chnInfo[0].JointChnInfo.JointFlag = jointFlag;
            _chnInfo[0].JointChnInfo.Chns      = chns;

            while (true)
            {
                if (0 != (rs = DecodeBandNum(mbr0, _chnInfo)))
                {
                    break;
                }
                if (0 != (rs = DecodeTable0(mbr0, _chnInfo, _chnInfo[0].JointChnInfo.Chns)))
                {
                    break;
                }
                if (0 != (rs = DecodeTable1(mbr0, _chnInfo, _chnInfo[0].JointChnInfo.Chns)))
                {
                    break;
                }
                if (0 != (rs = DecodeTable2(mbr0, _chnInfo, _chnInfo[0].JointChnInfo.Chns)))
                {
                    break;
                }
                if (0 != (rs = DecodeTable3(mbr0, _chnInfo, _chnInfo[0].JointChnInfo.Chns)))
                {
                    break;
                }
                if (0 != (rs = DecodeAcc2Pre(mbr0, _chnInfo, _chnInfo[0].JointChnInfo.Chns)))
                {
                    break;
                }
                if (0 != (rs = DecodeAcc2Main(mbr0, _chnInfo, _chnInfo[0].JointChnInfo.Chns)))
                {
                    break;
                }
                if (0 != (rs = DecodeAcc6Inner(mbr0, _chnInfo, _chnInfo[0].JointChnInfo.Chns)))
                {
                    break;
                }
                if (0 != (rs = DecodeTailInfo(mbr0, _chnInfo, _chnInfo[0].JointChnInfo.Chns)))
                {
                    break;
                }

                break;
            }

            return(rs);
        }
        int DecodeTailInfo(MaiBitReader mbr0, MaiAt3PlusCoreDecoderChnInfo[] chnInfos, uint chns)
        {
            int rs = 0;

            chnInfos[0].JointChnInfo.Var94 = mbr0.GetWithI32Buffer(1);

            if (chnInfos[0].JointChnInfo.Var94 != 0)
            {
                chnInfos[0].JointChnInfo.Var98 = mbr0.GetWithI32Buffer(4);
                chnInfos[0].JointChnInfo.Var9C = mbr0.GetWithI32Buffer(4);
            }

            return(rs);
        }
        int DecodeBandNum(MaiBitReader mbr0, MaiAt3PlusCoreDecoderChnInfo[] chnInfos)
        {
            chnInfos[0].JointChnInfo.NumBandSplitedDeclared =
                (uint)mbr0.GetWithI32Buffer(5) + 1;


            chnInfos[0].JointChnInfo.NumBandDeclared =
                (uint)MaiAT3PlusCoreDecoder_StaticData.MAPCDSD_band_num_table0[
                    chnInfos[0].JointChnInfo.NumBandSplitedDeclared] + 1;

            chnInfos[0].JointChnInfo.Var118 =
                mbr0.GetWithI32Buffer(1);

            return(0);
        }
        int DecodeTable1(MaiBitReader mbr0, MaiAt3PlusCoreDecoderChnInfo[] chnInfos, uint chns)
        {
            int rs = 0;

            if (chnInfos[0].JointChnInfo.NumBandSplitedUsed != 0) //
            {
                for (uint a0 = 0; a0 < chns; a0++)
                {
                    for (uint a1 = 0; a1 < 0x20; a1++)
                    {
                        chnInfos[a0].Table1[a1] = 0;
                    }

                    if (0 != (rs = MAPCDSF_decodeTable1_func_list0[
                                  chnInfos[a0].ChnFlag * 4 + mbr0.GetWithI32Buffer(2)]
                                       (mbr0, chnInfos[a0])
                              ))
                    {
                        return(rs);
                    }
                }
            }

            //check
            for (uint a0 = 0; a0 < chns; a0++)
            {
                for (uint a1 = 0; a1 < 0x20; a1++)
                {
                    if (chnInfos[a0].Table1[a1] < 0 ||
                        chnInfos[a0].Table1[a1] >= 0x40
                        )
                    {
                        return(-0x110);
                    }
                }
            }

            return(rs);
        }
        public int DecodeFrame(byte *pFrameData, int dataLen, out int pChns, out short[] ppSampleBuf)
        {
            int rs = 0;

            var mbr0 = new MaiBitReader(dataLen + 0x10);

            mbr0.AddData(pFrameData, dataLen);
            var pad = stackalloc byte[0x10];

            mbr0.AddData(pad, 0x10);

            if (mbr0.GetWithI32Buffer(1) != 0)
            {
                rs = -1;
            }


            int counterSubstream = 0;
            int counterChn       = 0;

            while (rs == 0)
            {
                int  substreamType = mbr0.GetWithI32Buffer(2);
                uint jointFlag     = 0;
                uint chns          = 0;

                if (substreamType == 0)
                {
                    jointFlag = 0;
                    chns      = 1;
                }
                else if (substreamType == 1)
                {
                    jointFlag = 1;
                    chns      = 2;
                }
                else if (substreamType == 3)
                {
                    break;
                }
                else
                {
                    rs = -1;
                }

                if (_cores[counterSubstream] == null)
                {
                    _cores[counterSubstream] = new MaiAt3PlusCoreDecoder();
                }

                if (0 != (rs = _cores[counterSubstream].ParseStream(mbr0, chns, jointFlag)))
                {
                    break;
                }

                if (0 != (rs = _cores[counterSubstream].decodeStream(chns)))
                {
                    break;
                }

                for (int a0 = 0; a0 < chns; a0++)
                {
                    _cores[counterSubstream].getAudioSamplesI16((uint)a0,
                                                                new ManagedPointer <short>(_sampleBufTmp, 0x800 * (counterChn++)));
                }

                counterSubstream++;
            }

            for (int a0 = 0; a0 < 0x800; a0++)
            {
                for (int a1 = 0; a1 < counterChn; a1++)
                {
                    _sampleBuf[a0 * counterChn + a1] = _sampleBufTmp[a1 * 0x800 + a0];
                }
            }
            mbr0.Dispose();

            pChns       = counterChn;
            ppSampleBuf = _sampleBuf;

            return(rs);
        }
        static int DecodeAcc6Inner(MaiBitReader mbr0, MaiAt3PlusCoreDecoderChnInfo[] chnInfos, uint chns)
        {
            int rs = 0;

            if (chns == 2)
            {
                chnInfos[0].AccTableNow.Inner.TableUnk0 = new MaiAt3PlusCoreDecoderPackTable0();
                chnInfos[0].AccTableNow.Inner.TableUnk1 = new MaiAt3PlusCoreDecoderPackTable0();
                chnInfos[0].AccTableNow.Inner.TableUnk2 = new MaiAt3PlusCoreDecoderPackTable0();
            }

            for (uint a0 = 0; a0 < chns; a0++)
            {
                chnInfos[a0].AccTableNow.TableReset();
                for (uint a1 = 0; a1 < 0x10; a1++)
                {
                    chnInfos[a0].AccTableNow.Table[a1].Unk[7] = 0x20;
                    chnInfos[a0].AccTableNow.Table[a1].Unk[6] = 0;
                }
            }

            chnInfos[0].AccTableNow.Inner.PtrToUseNow =
                chnInfos[0].AccTableNow.Inner.Data;

            chnInfos[0].AccTableNow.Inner.Unk0 =
                mbr0.GetWithI32Buffer(1);

            if (chnInfos[0].AccTableNow.Inner.Unk0 != 0)
            {
                chnInfos[0].AccTableNow.Inner.Unk1 =
                    mbr0.GetWithI32Buffer(1);

                chnInfos[0].AccTableNow.Inner.Unk2 = (int)(
                    MAPCDSF_getHuffValue(MaiAT3PlusCoreDecoder_StaticData.MAPCDSD_huff_table_global_11[0], mbr0)
                    + 1
                    );


                if (chns == 2)
                {
                    MAPCDSF_readPackTable0(mbr0, chnInfos[0].AccTableNow.Inner.TableUnk0,
                                           (uint)chnInfos[0].AccTableNow.Inner.Unk2);
                    MAPCDSF_readPackTable0(mbr0, chnInfos[0].AccTableNow.Inner.TableUnk2,
                                           (uint)chnInfos[0].AccTableNow.Inner.Unk2);
                    MAPCDSF_readPackTable0(mbr0, chnInfos[0].AccTableNow.Inner.TableUnk1,
                                           (uint)chnInfos[0].AccTableNow.Inner.Unk2);
                }

                for (uint a0 = 0; a0 < chns; a0++)
                {
                    //call 477e60
                    if ((rs = MAPCDSF_decodeACC6InnerSub0(mbr0, chnInfos[a0])) != 0)
                    {
                        break;
                    }
                }

                if (chns == 2)
                {
                    for (int a0 = 0; a0 < chnInfos[0].AccTableNow.Inner.Unk2; a0++)
                    {
                        if (chnInfos[0].AccTableNow.Inner.TableUnk0.Data[a0] != 0)
                        {
                            /*for (int a1 = 0; a1 < 0xA; a1++)
                             * {
                             *  chn_infos[1].acc_table_now.table[a0].unk[a1] =
                             *      chn_infos[0].acc_table_now.table[a0].unk[a1];
                             *  //memcpy?
                             * }*/
                            Mai_memcpy(
                                out chnInfos[1].AccTableNow.Table[a0],
                                ref chnInfos[0].AccTableNow.Table[a0]
                                );

                            //left to right acc5 copy 0x10 + 0x28 * a0 0x4 add zumi
                            //left to right acc5 copy 0x14 + 0x28 * a0 0x4 add zumi
                            //left to right acc5 copy 0x18 + 0x28 * a0 0x4 add zumi
                            //left to right acc5 copy 0x1C + 0x28 * a0 0x4 add zumi
                        }

                        if (chnInfos[0].AccTableNow.Inner.TableUnk2.Data[a0] != 0)
                        {
                            //swap?
                            MaiAt3PlusCoreDecoderChnAccTableTable tmpbuf0;

                            Mai_memcpy(
                                out tmpbuf0,
                                ref chnInfos[1].AccTableNow.Table[a0]
                                );

                            Mai_memcpy(
                                out chnInfos[1].AccTableNow.Table[a0],
                                ref chnInfos[0].AccTableNow.Table[a0]
                                );

                            Mai_memcpy(
                                out chnInfos[0].AccTableNow.Table[a0],
                                ref tmpbuf0
                                );

                            /*
                             * int tmpbuf0[0xA];
                             * for (int a1 = 0; a1 < 0xA; a1++)
                             * {
                             *  tmpbuf0[a1] = *(int*)&infos.acc_struct_6_1.table0[a0 * 0x28 + a1 * 0x4];
                             * }
                             * for (int a1 = 0; a1 < 0xA; a1++)
                             * {
                             *(int*)&infos.acc_struct_6_1.table0[a0 * 0x28 + a1 * 0x4] =
                             *(int*)&infos.acc_struct_6_0.table0[a0 * 0x28 + a1 * 0x4];
                             * }
                             * for (int a1 = 0; a1 < 0xA; a1++)
                             * {
                             *(int*)&infos.acc_struct_6_0.table0[a0 * 0x28 + a1 * 0x4] =
                             *      tmpbuf0[a1];
                             * }*/
                        }
                    }
                }
            }

            return(rs);
        }
        int DecodeAcc2Main(MaiBitReader mbr0, MaiAt3PlusCoreDecoderChnInfo[] chnInfos, uint chns)
        {
            int rs = 0;

            for (uint a0 = 0; a0 < chns; a0++)
            {
                chnInfos[a0].AccDataNow.TableMemset();

                uint uk1B444 = (uint)mbr0.GetWithI32Buffer(1);

                if (uk1B444 != 0)
                {
                    chnInfos[a0].Uk1B450 = (uint)mbr0.GetWithI32Buffer(4) + 1;
                    uint uk1B448 = (uint)mbr0.GetWithI32Buffer(1);

                    uint uk1B44C = chnInfos[a0].Uk1B450;
                    if (uk1B448 != 0)
                    {
                        uk1B44C = (uint)mbr0.GetWithI32Buffer(4) + 1;
                    }

                    //call 478200
                    if ((rs = MAPCDSF_decodeACC2MainSub0(mbr0, chnInfos[a0])) != 0)
                    {
                        break;
                    }

                    //call 478270
                    if ((rs = MAPCDSF_decodeACC2MainSub1(mbr0, chnInfos[a0])) != 0)
                    {
                        break;
                    }

                    //call 478330
                    if ((rs = MAPCDSF_decodeACC2MainSub2(mbr0, chnInfos[a0])) != 0)
                    {
                        break;
                    }

                    if (uk1B448 != 0)
                    {
                        for (uint b0 = chnInfos[a0].Uk1B450; b0 < uk1B44C; b0++)
                        {
                            chnInfos[a0].AccDataNow.Table[b0].NumAcc =
                                chnInfos[a0].AccDataNow.Table[b0 - 1].NumAcc;
                            for (uint b1 = 0; b1 < (uint)chnInfos[a0].AccDataNow.Table[b0].NumAcc; b1++)
                            {
                                chnInfos[a0].AccDataNow.Table[b0].Data1[b1] =
                                    chnInfos[a0].AccDataNow.Table[b0 - 1].Data1[b1];
                                chnInfos[a0].AccDataNow.Table[b0].Data0[b1] =
                                    chnInfos[a0].AccDataNow.Table[b0 - 1].Data0[b1];
                            }
                        }
                    }
                }
                else
                {
                    uint uk1B44C = 0;
                }
            }

            return(rs);
        }
        int DecodeTable3(MaiBitReader mbr0, MaiAt3PlusCoreDecoderChnInfo[] chnInfos, uint chns)
        {
            int rs = 0;

            for (uint a0 = 0; a0 < chns; a0++)
            {
                for (uint a1 = 0; a1 < 0x800; a1++)
                {
                    chnInfos[a0].Table3[a1] = 0;
                }
                for (uint a1 = 0; a1 < 0x5; a1++)
                {
                    chnInfos[a0].Table4[a1] = 0x0F;
                }

                for (uint a1 = 0; a1 < chnInfos[0].JointChnInfo.NumBandSplitedUsed; a1++)
                {
                    if (chnInfos[a0].Table0[a1] == 0)
                    {
                        for (uint a2 = 0; a2 < MaiAT3PlusCoreDecoder_StaticData.MAPCDSD_bind_table1[a1]; a2++)
                        {
                            chnInfos[a0].Table3[MaiAT3PlusCoreDecoder_StaticData.MAPCDSD_bind_table0[a1] + a2] = 0;
                        }
                    }
                    else
                    {
                        uint atmp0 = 0;

                        if (0 == chnInfos[a0].JointChnInfo.Var90)
                        {
                            atmp0 = MaiAT3PlusCoreDecoder_StaticData.MAPCDSD_bind_table2[
                                (chnInfos[a0].Var1034 * 7 + chnInfos[a0].Table0[a1]) * 4 +
                                chnInfos[a0].Table2[a1]]; //tmp4 5 6
                        }
                        else
                        {
                            atmp0 = chnInfos[a0].Table2[a1];
                        }

                        MaiAT3PlusCoreDecoderSearchTableDes huffTableNow =
                            MaiAT3PlusCoreDecoder_StaticData.MAPCDSD_huff_table3[
                                (chnInfos[a0].Var1034 * 8 + atmp0) * 7 + chnInfos[a0].Table0[a1]]; //tmp5 6

                        MAPCDSF_decodeTable3Sub0(mbr0,
                                                 chnInfos[a0].Table3
                                                 .GetPointer((int)MaiAT3PlusCoreDecoder_StaticData.MAPCDSD_bind_table0[a1]),
                                                 MaiAT3PlusCoreDecoder_StaticData.MAPCDSD_bind_table1[a1], huffTableNow);
                    }
                }

                if (chnInfos[0].JointChnInfo.NumBandSplitedUsed > 2)
                {
                    for (uint a1 = 0;
                         a1 < (uint)(MaiAT3PlusCoreDecoder_StaticData.MAPCDSD_band_num_table1[
                                         MaiAT3PlusCoreDecoder_StaticData.MAPCDSD_band_num_table0[
                                             chnInfos[0].JointChnInfo.NumBandSplitedUsed] + 1] + 1);
                         a1++)
                    {
                        chnInfos[a0].Table4[a1] = (uint)mbr0.GetWithI32Buffer(4);
                    }
                }
            }

            if (chns == 2)
            {
                MAPCDSF_readPackTable0(mbr0, chnInfos[0].JointChnInfo.Table48,
                                       chnInfos[0].JointChnInfo.NumBandUsed);
                MAPCDSF_readPackTable0(mbr0, chnInfos[0].JointChnInfo.Table00,
                                       chnInfos[0].JointChnInfo.NumBandUsed);
            }


            return(rs);
        }