Пример #1
0
        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));
        }
Пример #2
0
        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));
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }
Пример #5
0
        /// <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);
        }
Пример #6
0
        /// <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);
        }
Пример #7
0
        /*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);
                }
            }
        }
Пример #8
0
 [Benchmark] public byte[] GenerateCoefsAndEncodeAdpcm() => GcAdpcmEncoder.Encode(_pcm, GcAdpcmCoefficients.CalculateCoefficients(_pcm));
Пример #9
0
 [Benchmark] public byte[] EncodeAdpcm() => GcAdpcmEncoder.Encode(_pcm, _coefs);
Пример #10
0
 public void DspEncodeFrame(short[] pcmInOut, int sampleCount, byte[] adpcmOut, short[] coefsIn)
 {
     GcAdpcmEncoder.DspEncodeFrame(pcmInOut, sampleCount, adpcmOut, coefsIn);
 }