public void AlignedAdpcmIsCorrect(int multiple, int loopStart, int sineCycles, int tolerance) { int loopEnd = sineCycles * 4 * SamplesPerFrame + loopStart; short[] pcm = GenerateSineWave(GetNextMultiple(loopEnd, SamplesPerFrame), 1, SamplesPerFrame * 4); short[] coefs = GcAdpcmCoefficients.CalculateCoefficients(pcm); byte[] adpcm = GcAdpcmEncoder.Encode(pcm, coefs); var alignment = new GcAdpcmAlignment(multiple, loopStart, loopEnd, adpcm, coefs); short[] pcmAligned = GcAdpcmDecoder.Decode(alignment.AdpcmAligned, coefs, new GcAdpcmParameters { SampleCount = alignment.SampleCountAligned }); short[] pcmExpected = GenerateSineWave(alignment.SampleCountAligned, 1, SamplesPerFrame * 4); var diff = new double[alignment.SampleCountAligned]; //Skip the first sine cycle and last ADPCM frame due to history samples int end = GetNextMultiple(alignment.SampleCountAligned, SamplesPerFrame) - SamplesPerFrame; for (int i = SamplesPerFrame * 4; i < end; i++) { double dist = Math.Abs(pcmExpected[i] - pcmAligned[i]); diff[i] = dist; } Assert.All(diff, x => Assert.InRange(x, 0, tolerance)); }
public GcAdpcmChannel EncodeChannel(short[] pcm) { int sampleCount = pcm.Length; short[] coefs = GcAdpcmCoefficients.CalculateCoefficients(pcm); byte[] adpcm = GcAdpcmEncoder.Encode(pcm, coefs); return(new GcAdpcmChannel(adpcm, coefs, sampleCount)); }
public GcAdpcmAlignment(int multiple, int loopStart, int loopEnd, byte[] adpcm, short[] coefs) { AlignmentMultiple = multiple; LoopStart = loopStart; LoopEnd = loopEnd; AlignmentNeeded = !Helpers.LoopPointsAreAligned(loopStart, multiple); if (!AlignmentNeeded) { return; } int loopLength = loopEnd - loopStart; LoopStartAligned = Helpers.GetNextMultiple(loopStart, multiple); SampleCountAligned = loopEnd + (LoopStartAligned - loopStart); AdpcmAligned = new byte[SampleCountToByteCount(SampleCountAligned)]; PcmAligned = new short[SampleCountAligned]; int framesToKeep = loopEnd / SamplesPerFrame; int bytesToKeep = framesToKeep * BytesPerFrame; int samplesToKeep = framesToKeep * SamplesPerFrame; int samplesToEncode = SampleCountAligned - samplesToKeep; var param = new GcAdpcmParameters { SampleCount = loopEnd }; short[] oldPcm = GcAdpcmDecoder.Decode(adpcm, coefs, param); Array.Copy(oldPcm, 0, PcmAligned, 0, loopEnd); var newPcm = new short[samplesToEncode]; Array.Copy(oldPcm, samplesToKeep, newPcm, 0, loopEnd - samplesToKeep); for (int currentSample = loopEnd - samplesToKeep; currentSample < samplesToEncode; currentSample += loopLength) { Array.Copy(PcmAligned, loopStart, newPcm, currentSample, Math.Min(loopLength, samplesToEncode - currentSample)); } param.SampleCount = samplesToEncode; param.History1 = samplesToKeep < 1 ? (short)0 : oldPcm[samplesToKeep - 1]; param.History2 = samplesToKeep < 2 ? (short)0 : oldPcm[samplesToKeep - 2]; byte[] newAdpcm = GcAdpcmEncoder.Encode(newPcm, coefs, param); Array.Copy(adpcm, 0, AdpcmAligned, 0, bytesToKeep); Array.Copy(newAdpcm, 0, AdpcmAligned, bytesToKeep, newAdpcm.Length); short[] decodedPcm = GcAdpcmDecoder.Decode(newAdpcm, coefs, param); Array.Copy(decodedPcm, 0, PcmAligned, samplesToKeep, samplesToEncode); }
public void AlignedPcmIsCorrect(int multiple, int loopStart, int sineCycles) { int loopEnd = sineCycles * 4 * SamplesPerFrame + loopStart; var pcm = GenerateSineWave(GetNextMultiple(loopEnd, SamplesPerFrame), 1, SamplesPerFrame * 4); var coefs = GcAdpcmCoefficients.CalculateCoefficients(pcm); var adpcm = GcAdpcmEncoder.Encode(pcm, coefs); var alignment = new GcAdpcmAlignment(multiple, loopStart, loopEnd, adpcm, coefs); var pcmAligned = alignment.PcmAligned; var pcmExpected = GcAdpcmDecoder.Decode(alignment.AdpcmAligned, coefs, new GcAdpcmParameters { SampleCount = alignment.SampleCountAligned }); Assert.Equal(pcmExpected, pcmAligned); }
/// <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> /// Encodes the samples. /// </summary> /// <returns>The samples.</returns> /// <param name="samples">Samples.</param> public static byte[] EncodeSamples(short[] samples, DspAdpcmContext info, int loopStart) { //Encode data. byte[] dspAdpcm = GcAdpcmEncoder.Encode(samples, info.GetCoeffs(), new GcAdpcmParameters() { History1 = info.yn1, History2 = info.yn2, SampleCount = samples.Length }); //Loop stuff. if (loopStart > 0) { info.loop_yn1 = samples[loopStart - 1]; } if (loopStart > 1) { info.loop_yn2 = samples[loopStart - 2]; } //Return data. return(dspAdpcm); }
/*public void ToHPS() * { * * }*/ #endregion #region WAVE private void FromWAVE(byte[] wavFile) { if (wavFile.Length < 0x2C) { throw new NotSupportedException("File is not a valid WAVE file"); } Channels.Clear(); using (BinaryReader r = new BinaryReader(new MemoryStream(wavFile))) { if (new string(r.ReadChars(4)) != "RIFF") { throw new NotSupportedException("File is not a valid WAVE file"); } r.BaseStream.Position = 0x14; var comp = r.ReadInt16(); var channelCount = r.ReadInt16(); Frequency = r.ReadInt32(); r.ReadInt32(); // block rate r.ReadInt16(); // block align var bpp = r.ReadInt16(); if (comp != 1) { throw new NotSupportedException("Compressed WAVE files not supported"); } if (bpp != 16) { throw new NotSupportedException("Only 16 bit WAVE formats accepted"); } while (new string(r.ReadChars(4)) != "data") { var skip = r.ReadInt32(); r.BaseStream.Position += skip; } var channelSizes = r.ReadInt32() / channelCount / 2; List <List <short> > channels = new List <List <short> >(); for (int i = 0; i < channelCount; i++) { channels.Add(new List <short>()); } for (int i = 0; i < channelSizes; i++) { foreach (var v in channels) { v.Add(r.ReadInt16()); } } Channels.Clear(); foreach (var data in channels) { var c = new DSPChannel(); var ss = data.ToArray(); c.COEF = GcAdpcmCoefficients.CalculateCoefficients(ss); c.Data = GcAdpcmEncoder.Encode(ss, c.COEF); c.NibbleCount = c.Data.Length * 2; c.InitialPredictorScale = c.Data[0]; Channels.Add(c); } } }
[Benchmark] public byte[] GenerateCoefsAndEncodeAdpcm() => GcAdpcmEncoder.Encode(_pcm, GcAdpcmCoefficients.CalculateCoefficients(_pcm));
[Benchmark] public byte[] EncodeAdpcm() => GcAdpcmEncoder.Encode(_pcm, _coefs);
public void DspEncodeFrame(short[] pcmInOut, int sampleCount, byte[] adpcmOut, short[] coefsIn) { GcAdpcmEncoder.DspEncodeFrame(pcmInOut, sampleCount, adpcmOut, coefsIn); }