Example #1
0
        /// <summary>
        /// Decode gain parameters for the coded bands
        /// </summary>
        /// <param name="block">     the gainblock for the current band </param>
        /// <param name="numBands">  amount of coded bands </param>
        private int decodeGainControl(GainBlock block, int numBands)
        {
            int b;

            for (b = 0; b <= numBands; b++)
            {
                block.gBlock[b].numPoints = br.read(3);
                int[] level = block.gBlock[b].levCode;
                int[] loc   = block.gBlock[b].locCode;

                for (int j = 0; j < block.gBlock[b].numPoints; j++)
                {
                    level[j] = br.read(4);
                    loc[j]   = br.read(5);
                    if (j > 0 && loc[j] <= loc[j - 1])
                    {
                        return(AT3_ERROR);
                    }
                }
            }

            // Clear the unused blocks
            for (; b < 4; b++)
            {
                block.gBlock[b].numPoints = 0;
            }

            return(0);
        }
Example #2
0
        /// <summary>
        /// Decode a Sound Unit
        /// </summary>
        /// <param name="snd">           the channel unit to be used </param>
        /// <param name="output">        the decoded samples before IQMF in float representation </param>
        /// <param name="channelNum">    channel number </param>
        /// <param name="codingMode">    the coding mode (JOINT_STEREO or regular stereo/mono) </param>
        private int decodeChannelSoundUnit(ChannelUnit snd, float[] output, int channelNum, int codingMode)
        {
            int       ret;
            GainBlock gain1 = snd.gainBlock[snd.gcBlkSwitch];
            GainBlock gain2 = snd.gainBlock[1 - snd.gcBlkSwitch];

            if (codingMode == JOINT_STEREO && channelNum == 1)
            {
                if (br.read(2) != 3)
                {
                    Console.WriteLine(string.Format("JS mono Sound Unit id != 3"));
                    return(AT3_ERROR);
                }
            }
            else
            {
                if (br.read(6) != 0x28)
                {
                    Console.WriteLine(string.Format("Sound Unit id != 0x28"));
                    return(AT3_ERROR);
                }
            }

            // number of coded QMF bands
            snd.bandsCoded = br.read(2);

            ret = decodeGainControl(gain2, snd.bandsCoded);
            if (ret != 0)
            {
                return(ret);
            }

            snd.numComponents = decodeTonalComponents(snd.components, snd.bandsCoded);

            if (snd.numComponents < 0)
            {
                return(snd.numComponents);
            }

            int numSubbands = decodeSpectrum(snd.spectrum);

            // Merge the decoded spectrum and tonal components
            int lastTonal = addTonalComponents(snd.spectrum, snd.numComponents, snd.components);

            // calculate number of used MLT/QMF bands according to the amount of coded
            // spectral lines
            int numBands = (subband_tab[numSubbands] - 1) >> 8;

            if (lastTonal >= 0)
            {
                numBands = max((lastTonal + 256) >> 8, numBands);
            }

            // Reconstruct time domain samples
            for (int band = 0; band < 4; band++)
            {
                // Perform the IMDCT step without overlapping
                if (band <= numBands)
                {
                    imlt(snd.spectrum, band * 256, snd.imdctBuf, 0, (band & 1) != 0);
                }
                else
                {
                    Arrays.Fill(snd.imdctBuf, 0, 512, 0f);
                }

                // gain compensation and overlapping
                ctx.gaincCtx.gainCompensation(snd.imdctBuf, 0, snd.prevFrame, band * 256, gain1.gBlock[band], gain2.gBlock[band], 256, output, band * 256);
            }

            // Swap the gain control buffers for the next frame
            snd.gcBlkSwitch ^= 1;

            return(0);
        }