/// <summary> /// Decode DSP-ADPCM data. /// </summary> /// <param name="src">DSP-ADPCM source.</param> /// <param name="dst">Destination array of samples.</param> /// <param name="cxt">DSP-APCM context.</param> /// <param name="samples">Number of samples.</param> public static void Decode(byte[] src, ref Int16[] dst, ref DspAdpcmInfo cxt, UInt32 samples) { //Each DSP-APCM frame is 8 bytes long. It contains 1 header byte, and 7 sample bytes. //Set initial values. short hist1 = cxt.yn1; short hist2 = cxt.yn2; int dstIndex = 0; int srcIndex = 0; //Until all samples decoded. while (dstIndex < samples) { //Get the header. byte header = src[srcIndex++]; //Get scale and co-efficient index. UInt16 scale = (UInt16)(1 << (header & 0xF)); byte coef_index = (byte)(header >> 4); short coef1 = cxt.coefs[coef_index][0]; short coef2 = cxt.coefs[coef_index][1]; //7 sample bytes per frame. for (UInt32 b = 0; b < 7; b++) { //Get byte. byte byt = src[srcIndex++]; //2 samples per byte. for (UInt32 s = 0; s < 2; s++) { sbyte adpcm_nibble = ((s == 0) ? GetHighNibble(byt) : GetLowNibble(byt)); short sample = Clamp16(((adpcm_nibble * scale) << 11) + 1024 + ((coef1 * hist1) + (coef2 * hist2)) >> 11); hist2 = hist1; hist1 = sample; dst[dstIndex++] = sample; if (dstIndex >= samples) { break; } } if (dstIndex >= samples) { break; } } } }
/// <summary> /// Encodes the samples. /// </summary> /// <returns>The samples.</returns> /// <param name="samples">Samples.</param> public static byte[] EncodeSamples(short[] samples, out DspAdpcmInfo info, uint loopStart) { //Encod data. short[] coeffs = GcAdpcmCoefficients.CalculateCoefficients(samples); byte[] dspAdpcm = GcAdpcmEncoder.Encode(samples, coeffs); info = new DspAdpcmInfo(); info.coefs = new short[8][]; info.coefs[0] = new short[2]; info.coefs[1] = new short[2]; info.coefs[2] = new short[2]; info.coefs[3] = new short[2]; info.coefs[4] = new short[2]; info.coefs[5] = new short[2]; info.coefs[6] = new short[2]; info.coefs[7] = new short[2]; info.coefs[0][0] = coeffs[0]; info.coefs[0][1] = coeffs[1]; info.coefs[1][0] = coeffs[2]; info.coefs[1][1] = coeffs[3]; info.coefs[2][0] = coeffs[4]; info.coefs[2][1] = coeffs[5]; info.coefs[3][0] = coeffs[6]; info.coefs[3][1] = coeffs[7]; info.coefs[4][0] = coeffs[8]; info.coefs[4][1] = coeffs[9]; info.coefs[5][0] = coeffs[10]; info.coefs[5][1] = coeffs[11]; info.coefs[6][0] = coeffs[12]; info.coefs[6][1] = coeffs[13]; info.coefs[7][0] = coeffs[14]; info.coefs[7][1] = coeffs[15]; //Loop stuff. if (loopStart > 0) { info.loop_yn1 = samples[loopStart - 1]; } if (loopStart > 1) { info.loop_yn2 = samples[loopStart - 2]; } return(dspAdpcm); }
/// <summary> /// Read data. /// </summary> /// <param name="br">The reader.</param> public override void ReadData(BinaryDataReader br) { //Read data. WaveFormat = (WaveFormatType)br.ReadUInt16(); NumChannels = br.ReadUInt16(); SampleRate = br.ReadUInt32(); br.ReadUInt32(); //Byte rate. br.ReadUInt16(); //Block align. BitsPerSample = br.ReadUInt16(); //Extra parameters. if (WaveFormat == WaveFormatType.DSPADPCM) { //Read extra data. br.ReadUInt16(); //Extra data. br.ReadUInt16(); //Padding. br.ReadUInt16(); //Unknown. br.ReadUInt16(); //Padding. DspAdpcmNumSamples = br.ReadUInt32(); //Foreach channel. ChannelInfo = new List <DspAdpcmInfo>(); for (int i = 0; i < NumChannels; i++) { DspAdpcmInfo d = new DspAdpcmInfo(); d.coefs = new short[8][]; for (int j = 0; j < 8; j++) { d.coefs[j] = br.ReadInt16s(2); } br.ReadUInt16(); //Padding. d.pred_scale = br.ReadUInt16(); d.yn1 = br.ReadInt16(); d.yn2 = br.ReadInt16(); d.loop_pred_scale = br.ReadUInt16(); d.loop_yn1 = br.ReadInt16(); d.loop_yn2 = br.ReadInt16(); ChannelInfo.Add(d); } //Read the last part. br.ReadUInt16(); //Unknown. } }