public static byte[] Encode(short[] pcm, short[] coefs, GcAdpcmParameters config = null) { config = config ?? new GcAdpcmParameters(); int sampleCount = config.SampleCount == -1 ? pcm.Length : config.SampleCount; var adpcm = new byte[SampleCountToByteCount(sampleCount)]; /* Execute encoding-predictor for each frame */ var pcmBuffer = new short[2 + SamplesPerFrame]; var adpcmBuffer = new byte[BytesPerFrame]; pcmBuffer[0] = config.History2; pcmBuffer[1] = config.History1; int frameCount = sampleCount.DivideByRoundUp(SamplesPerFrame); var buffers = new AdpcmEncodeBuffers(); for (int frame = 0; frame < frameCount; frame++) { int samplesToCopy = Math.Min(sampleCount - frame * SamplesPerFrame, SamplesPerFrame); Array.Copy(pcm, frame * SamplesPerFrame, pcmBuffer, 2, samplesToCopy); Array.Clear(pcmBuffer, 2 + samplesToCopy, SamplesPerFrame - samplesToCopy); DspEncodeFrame(pcmBuffer, SamplesPerFrame, adpcmBuffer, coefs, buffers); Array.Copy(adpcmBuffer, 0, adpcm, frame * BytesPerFrame, SampleCountToByteCount(samplesToCopy)); pcmBuffer[0] = pcmBuffer[14]; pcmBuffer[1] = pcmBuffer[15]; config.Progress?.ReportAdd(1); } return(adpcm); }
public static void DspEncodeFrame(short[] pcmInOut, int sampleCount, byte[] adpcmOut, short[] coefsIn, AdpcmEncodeBuffers b = null) { b = b ?? new AdpcmEncodeBuffers(); for (int i = 0; i < 8; i++) { b.Coefs[i][0] = coefsIn[i * 2]; b.Coefs[i][1] = coefsIn[i * 2 + 1]; } /* Iterate through each coef set, finding the set with the smallest error */ for (int i = 0; i < 8; i++) { DspEncodeCoef(pcmInOut, sampleCount, b.Coefs[i], b.PcmOut[i], b.AdpcmOut[i], out b.Scale[i], out b.TotalDistance[i]); } int bestCoef = 0; double min = double.MaxValue; for (int i = 0; i < 8; i++) { if (b.TotalDistance[i] < min) { min = b.TotalDistance[i]; bestCoef = i; } } /* Write converted samples */ for (int s = 0; s < sampleCount; s++) { pcmInOut[s + 2] = (short)b.PcmOut[bestCoef][s + 2]; } /* Write predictor and scale */ adpcmOut[0] = CombineNibbles(bestCoef, b.Scale[bestCoef]); /* Zero remaining samples */ for (int s = sampleCount; s < 14; s++) { b.AdpcmOut[bestCoef][s] = 0; } /* Write output samples */ for (int i = 0; i < 7; i++) { adpcmOut[i + 1] = CombineNibbles(b.AdpcmOut[bestCoef][i * 2], b.AdpcmOut[bestCoef][i * 2 + 1]); } }