Пример #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
        /// <summary>
        /// Wraps the decoded DSP data into a WAVE file stored as a byte array
        /// </summary>
        /// <returns></returns>
        public byte[] ToWAVE()
        {
            using (var stream = new MemoryStream())
            {
                using (BinaryWriter w = new BinaryWriter(stream))
                {
                    w.Write("RIFF".ToCharArray());
                    w.Write(0); // wave size

                    w.Write("WAVE".ToCharArray());

                    short BitsPerSample = 16;
                    var   byteRate      = Frequency * Channels.Count * BitsPerSample / 8;
                    short blockAlign    = (short)(Channels.Count * BitsPerSample / 8);

                    w.Write("fmt ".ToCharArray());
                    w.Write(16);       // chunk size
                    w.Write((short)1); // compression
                    w.Write((short)Channels.Count);
                    w.Write(Frequency);
                    w.Write(byteRate);
                    w.Write(blockAlign);
                    w.Write(BitsPerSample);

                    w.Write("data".ToCharArray());
                    var subchunkOffset = w.BaseStream.Position;
                    w.Write(0);

                    int subChunkSize = 0;
                    if (Channels.Count == 1)
                    {
                        short[] sound_data = GcAdpcmDecoder.Decode(Channels[0].Data, Channels[0].COEF);
                        subChunkSize += sound_data.Length * 2;
                        foreach (var s in sound_data)
                        {
                            w.Write(s);
                        }
                    }
                    if (Channels.Count == 2)
                    {
                        short[] sound_data1 = GcAdpcmDecoder.Decode(Channels[0].Data, Channels[0].COEF);
                        short[] sound_data2 = GcAdpcmDecoder.Decode(Channels[1].Data, Channels[1].COEF);
                        subChunkSize += (sound_data1.Length + sound_data2.Length) * 2;
                        for (int i = 0; i < sound_data1.Length; i++)
                        {
                            w.Write(sound_data1[i]);
                            w.Write(sound_data2[i]);
                        }
                    }

                    w.BaseStream.Position = subchunkOffset;
                    w.Write(subChunkSize);

                    w.BaseStream.Position = 4;
                    w.Write((int)(w.BaseStream.Length - 8));
                }
                return(stream.ToArray());
            }
        }
Пример #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
 public static byte GetPredScale(byte[] adpcm, int sampleNum) => GcAdpcmDecoder.GetPredictorScale(adpcm, sampleNum);
Пример #6
0
 private void EnsurePcmDecoded() => AlignedPcm = AlignedPcm ?? GcAdpcmDecoder.Decode(AlignedAdpcm, Coefs, new GcAdpcmParameters {
     SampleCount = AlignedSampleCount
 });
Пример #7
0
 public short[] GetPcmAudio() => AlignmentNeeded
     ? Alignment.PcmAligned
     : Pcm ?? GcAdpcmDecoder.Decode(GetAdpcmAudio(), Coefs,
                                    new GcAdpcmParameters {
     SampleCount = SampleCount, History1 = StartContext.Hist1, History2 = StartContext.Hist2
 });
Пример #8
0
 public short[] DecodeAdpcm(byte[] adpcm, short[] coefs, int sampleCount)
 {
     return(GcAdpcmDecoder.Decode(adpcm, coefs, new GcAdpcmParameters {
         SampleCount = sampleCount
     }));
 }