/// <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); }
/// <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); }