Example #1
0
        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);
        }
Example #2
0
        public static short[] Decode(byte[] adpcm, short[] coefficients, GcAdpcmParameters config = null)
        {
            config = config ?? new GcAdpcmParameters {
                SampleCount = ByteCountToSampleCount(adpcm.Length)
            };
            var pcm = new short[config.SampleCount];

            if (config.SampleCount == 0)
            {
                return(pcm);
            }

            int   frameCount    = config.SampleCount.DivideByRoundUp(SamplesPerFrame);
            int   currentSample = 0;
            int   outIndex      = 0;
            int   inIndex       = 0;
            short hist1         = config.History1;
            short hist2         = config.History2;

            for (int i = 0; i < frameCount; i++)
            {
                byte  predictorScale = adpcm[inIndex++];
                int   scale          = (1 << GetLowNibble(predictorScale)) * 2048;
                int   predictor      = GetHighNibble(predictorScale);
                short coef1          = coefficients[predictor * 2];
                short coef2          = coefficients[predictor * 2 + 1];

                int samplesToRead = Math.Min(SamplesPerFrame, config.SampleCount - currentSample);

                for (int s = 0; s < samplesToRead; s++)
                {
                    int   adpcmSample     = s % 2 == 0 ? GetHighNibbleSigned(adpcm[inIndex]) : GetLowNibbleSigned(adpcm[inIndex++]);
                    int   distance        = scale * adpcmSample;
                    int   predictedSample = coef1 * hist1 + coef2 * hist2;
                    int   correctedSample = predictedSample + distance;
                    int   scaledSample    = (correctedSample + 1024) >> 11;
                    short clampedSample   = Clamp16(scaledSample);

                    hist2 = hist1;
                    hist1 = clampedSample;

                    pcm[outIndex++] = clampedSample;
                    currentSample++;
                }
            }
            return(pcm);
        }