Esempio n. 1
0
        private static int ProcessSingleBufferFillByteBuffer(
            IReadOnlyList <VstAudioBuffer> vstBufOut,
            IReadOnlyList <VstAudioPrecisionBuffer> vstBufOut2,
            bool isDoublePrecision,
            WAVParser pcmOutput,
            int vstOutputCount,
            int samplesPerBuffer
            )
        {
            for (var iSample = 0; iSample < samplesPerBuffer; iSample++)
            {
                for (int channel = 0; channel < pcmOutput.ChannelCount; channel++)
                {
                    if (channel < vstOutputCount)
                    {
                        if (!isDoublePrecision)
                        {
                            float sampleF = vstBufOut[channel][iSample];
                            pcmOutput.Samples[channel].Add(sampleF);
                        }
                        else
                        {
                            double sampleD = vstBufOut2[channel][iSample];
                            pcmOutput.Samples[channel].Add(sampleD);
                        }
                    }
                }
            }

            return(0);
        }
        public void ChangeVolumeTest(
            string input,
            double changeDb,
            string referenceFile,
            double?rmseMax
            )
        {
            WAVParser newFile;
            {
                var parser = new WAVParser(ResolveDataFile(input));
                newFile = parser.ChangeVolume(changeDb);
            }

            var parserReference = new WAVParser(ResolveDataFile(referenceFile));
            var rmseMaxValue    = rmseMax ?? 0.000_01d;

            for (int channelId = 0; channelId < newFile.Samples.Count; channelId++)
            {
                var expected = parserReference.Samples[channelId];
                var actual   = newFile.Samples[channelId];

                var sum = actual.Select((t, i) => Math.Pow(t - expected[i], 2)).Sum();

                var rmse = Math.Sqrt(sum / actual.Count);
                Assert.InRange(rmse, 0, rmseMaxValue);
            }
        }
Esempio n. 3
0
        public static void AddSilence(WAVParser input, TimeSpan duration)
        {
            var samplesCount = (int)input.GetFloorSamplesCount(duration);
            var buffer       = new double[samplesCount];

            foreach (var channel in input.Samples)
            {
                channel.AddRange(buffer);
            }
        }
Esempio n. 4
0
        public void WriteAndLoad(
            string filename,
            ushort bitsPerSample
            )
        {
            var parser        = new WAVParser(ResolveDataFile(filename));
            var temporaryFile = Path.GetTempFileName();

            parser.BitsPerSample = bitsPerSample;
            parser.Save(temporaryFile);

            //
            WAVParser reReader;

            try
            {
                reReader = new WAVParser(temporaryFile);
            }
            finally
            {
                File.Delete(temporaryFile);
            }

            Assert.Equal(parser.ChannelCount, reReader.ChannelCount);
            Assert.Equal(parser.SampleRate, reReader.SampleRate);
            Assert.Equal(parser.BitsPerSample, reReader.BitsPerSample);
            Assert.Equal(parser.SamplesCount, reReader.SamplesCount);
            Assert.Equal(parser.Duration, reReader.Duration);

            var minSampleRate  = Math.Min(bitsPerSample, parser.BitsPerSample);
            var minSampleRateC = 1 << (minSampleRate - 1);

            for (int channelId = 0; channelId < parser.ChannelCount; channelId++)
            {
                var sum = 0d;
                for (int i = 0; i < parser.SamplesCount; i++)
                {
                    var expected = parser.Samples[channelId][i];
                    var real     = reReader.Samples[channelId][i];

                    var tE = (expected > 0) ? minSampleRateC - 1 : minSampleRateC;
                    var tR = (real > 0) ? minSampleRateC - 1 : minSampleRateC;

                    var expected1 = Math.Round(expected * tE) / tE;
                    var real1     = Math.Round(real * tR) / tR;

                    var diff = real1 - expected1;
                    sum += Math.Pow(diff, 2);
                }

                var rmse = Math.Sqrt(sum / parser.SamplesCount);
                Assert.InRange(rmse, 0, 0.000_01d);
            }
        }
Esempio n. 5
0
        public void CheckWorkingPureItem()
        {
            var item = new WAVParser();

            Assert.Equal(1, item.AudioFormat);
            Assert.InRange(item.ChannelCount, 1, int.MaxValue);
            Assert.Equal(0, item.BitsPerSample % 8);
            Assert.InRange(item.BitsPerSample, 1, 96_000);
            Assert.Equal((item.BitsPerSample / 8) * item.ChannelCount, item.BlockAlign);
            Assert.Equal(0, item.SamplesCount);
            Assert.Equal(TimeSpan.Zero, item.Duration);
            Assert.NotNull(item.ToString());
        }
Esempio n. 6
0
        public static WAVParser ChangeVolume(WAVParser wavParser, double changeDb)
        {
            var newSamples = wavParser
                             .Samples
                             .Select(channel => ChangeVolume(channel, changeDb))
                             .ToList();

            var outputFile = wavParser.Clone();

            outputFile.Samples = newSamples;

            return(outputFile);
        }
Esempio n. 7
0
        public void WriteTest()
        {
            var rnd = new Random();
            // ReSharper disable once UseObjectOrCollectionInitializer
            var parser = new WAVParser();

            parser.ChannelCount = 1;
            parser.Samples      = new List <List <double> >()
            {
                new List <double>()
            };
            parser.BlockAlign = (ushort)(parser.ChannelCount * parser.BitsPerSample / 8);

            for (int i = 0; i < 1000; i++)
            {
                parser.Samples[0].Add(rnd.NextDouble() * 2 - 1);
            }

            // Re read
            var newRiff  = parser.GetDataAsRiff();
            var reReader = new WAVParser(newRiff);

            Assert.Equal(parser.ChannelCount, reReader.ChannelCount);
            Assert.Equal(parser.AudioFormat, reReader.AudioFormat);
            Assert.Equal(parser.BlockAlign, reReader.BlockAlign);
            Assert.Equal(parser.SampleRate, reReader.SampleRate);
            Assert.Equal(parser.BitsPerSample, reReader.BitsPerSample);
            Assert.Equal(parser.SamplesCount, reReader.SamplesCount);
            Assert.Equal(parser.Duration, reReader.Duration);

            for (int channelId = 0; channelId < parser.ChannelCount; channelId++)
            {
                for (int i = 0; i < parser.SamplesCount; i++)
                {
                    var diff = reReader.Samples[channelId][i] - parser.Samples[channelId][i];
                    Assert.InRange(diff, -0.000_1d, 0.000_1d);
                }
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Read 2-bytes octets from byteBuffer and put them to VstAudioBuffer
        /// </summary>
        /// <param name="samplesOffset"></param>
        /// <param name="vstBufIn"></param>
        /// <param name="vstBufIn2"></param>
        /// <param name="isDoublePrecision"></param>
        /// <param name="pcmInput"></param>
        /// <param name="pcmOutput"></param>
        /// <param name="vstOutputCount"></param>
        /// <returns></returns>
        private static int ProcessSingleBufferFillBufferInput(
            int samplesOffset,
            IReadOnlyList <VstAudioBuffer> vstBufIn,
            IReadOnlyList <VstAudioPrecisionBuffer> vstBufIn2,
            bool isDoublePrecision,
            WAVParser pcmInput,
            WAVParser pcmOutput,
            int vstOutputCount
            )
        {
            for (int i = samplesOffset;
                 i < Math.Min(pcmInput.SamplesCount, samplesOffset + pcmInput.SampleRate);
                 i++)
            {
                var iSample = i - samplesOffset;
                for (int channel = 0; channel < pcmOutput.ChannelCount; channel++)
                {
                    if (channel >= vstOutputCount)
                    {
                        continue;
                    }

                    double sample = pcmInput.Samples[channel][i];

                    if (!isDoublePrecision)
                    {
                        vstBufIn[channel][iSample] = (float)sample;
                    }
                    else
                    {
                        vstBufIn2[channel][iSample] = sample;
                    }
                }
            } // int i = 0; i < bytesReadFromAudioStream

            return(0);
        }
Esempio n. 9
0
        public void ParseFiles(
            string filename,
            int channelCount,
            int sampleRate,
            int bitsPerSample,
            int sampleCount,
            string templateFilename,
            Tuple <int, double, bool> toneTest
            )
        {
            WAVParser parser;

            using (var stream = File.Open(ResolveDataFile(filename), FileMode.Open))
            {
                parser = new WAVParser(stream);
                Assert.Equal(channelCount, parser.ChannelCount);
                Assert.Equal((uint)sampleRate, parser.SampleRate);
                Assert.Equal(bitsPerSample, parser.BitsPerSample);

                Assert.NotNull(parser.ToString());
                Assert.InRange(parser.StartDataSeek, 42, 1024);

                Assert.Equal(sampleCount, parser.SamplesCount);
                foreach (var list in parser.Samples)
                {
                    Assert.Equal(sampleCount, list.Count);
                    foreach (var sample in list)
                    {
                        Assert.InRange(sample, -1, 1);
                    }
                }

                var durationDiff      = parser.Duration - TimeSpan.FromSeconds(sampleCount * 1d / sampleRate);
                var durationDiffTicks = Math.Abs(durationDiff.Ticks);
                Assert.InRange(durationDiffTicks, 0, TimeSpan.TicksPerMillisecond - 1);

                Assert.Equal(TimeSpan.TicksPerSecond, parser.GetSpanForSamples(sampleRate).Ticks);
                Assert.Equal(sampleRate, parser.GetFloorSamplesCount(1));
            }

            if (templateFilename != null)
            {
                Assert.NotEqual(filename, templateFilename);
                WAVParser parserTemplate;
                using (var stream = File.Open(ResolveDataFile(templateFilename), FileMode.Open))
                {
                    parserTemplate = new WAVParser(stream);
                }

                Assert.Equal(sampleCount, parserTemplate.SamplesCount);
                var minSampleRate  = Math.Min(parserTemplate.BitsPerSample, parser.BitsPerSample);
                var minSampleRateC = 1 << (minSampleRate - 1);

                for (int channelId = 0; channelId < parser.Samples.Count; channelId++)
                {
                    var sum = 0d;
                    for (int i = 0; i < sampleCount; i++)
                    {
                        var expected = parserTemplate.Samples[channelId][i];
                        var real     = parser.Samples[channelId][i];

                        var tE = (expected > 0) ? minSampleRateC - 1 : minSampleRateC;
                        var tR = (real > 0) ? minSampleRateC - 1 : minSampleRateC;

                        var expected1 = Math.Round(expected * tE) / tE;
                        var real1     = Math.Round(real * tR) / tR;

                        sum += Math.Pow(real1 - expected1, 2);
                    }

                    var rmse = Math.Sqrt(sum / sampleCount);
                    Assert.InRange(rmse, 0, 0.006d);
                }
            }

            if (toneTest != null)
            {
                var(sinusoidHz, sinusoidValue, isSquare) = toneTest;
                var sinusoidHzR = Math.PI * 2 * sinusoidHz / parser.SampleRate;

                double minValue = double.NaN, maxValue = double.NaN;

                foreach (var channelSamples in parser.Samples)
                {
                    var sum            = 0d;
                    var sumRMSE_Square = 0d;
                    var sumRMSE_Sin    = 0d;

                    for (var i = 0; i < channelSamples.Count; i++)
                    {
                        var sample = channelSamples[i];

                        minValue = !double.IsNaN(minValue) ? Math.Min(sample, minValue) : sample;
                        maxValue = !double.IsNaN(maxValue) ? Math.Max(sample, maxValue) : sample;
                        sum     += sample;
                        if (isSquare)
                        {
                            sumRMSE_Square += Math.Pow(Math.Abs(sample) - sinusoidValue, 2);
                        }
                        else
                        {
                            var angleRad      = i * sinusoidHzR;
                            var expectedValue = Math.Sin(angleRad) * sinusoidValue;
                            sumRMSE_Sin += Math.Pow(sample - expectedValue, 2);
                        }
                    }

                    var averageValue = sum / channelSamples.Count;
                    Assert.InRange(averageValue, 0, 0.000_02d);
                    if (isSquare)
                    {
                        var rmse = Math.Sqrt(sumRMSE_Square / channelSamples.Count);
                        Assert.InRange(rmse, 0, 0.000_1d);
                    }
                    else
                    {
                        var rmse = Math.Sqrt(sumRMSE_Sin / channelSamples.Count);
                        Assert.InRange(rmse, 0, 0.000_1d);
                    }
                }

                {
                    var sinusoidValue_Min = Math.Min(sinusoidValue / 1.00037d, sinusoidValue);
                    var sinusoidValue_Max = Math.Min(sinusoidValue * 1.00037d, 1);

                    Assert.InRange(-minValue, sinusoidValue_Min, sinusoidValue_Max);
                    Assert.InRange(maxValue, sinusoidValue_Min, sinusoidValue_Max);
                }
            }
        }
Esempio n. 10
0
        public static WAVParser ChangeSampleRate(WAVParser parser, int newSampleRate)
        {
            var newFile = parser.Clone(true);

            if (newFile.SampleRate == newSampleRate)
            {
                return(newFile);
            }

            int hz1, hz2;

            {
                var nok = NOK((int)parser.SampleRate, newSampleRate);

                hz1 = (int)(nok / newSampleRate);
                hz2 = (int)(nok / parser.SampleRate);
            }

            int[]    indexes;
            double[] rCoefs;
            {
                var indexesA = new List <int>(hz2);
                var rCoefsA  = new List <double>(hz2);
                for (int j = 0; j < hz2; j++)
                {
                    var coef   = j * 1d * hz1 / hz2;
                    var index1 = (int)Math.Floor(coef);
                    var r1     = coef - index1;

                    indexesA.Add(index1);
                    rCoefsA.Add(r1);
                }

                indexes = indexesA.ToArray();
                rCoefs  = rCoefsA.ToArray();
            }

            var channelFull = new List <List <double> >();

            foreach (var channelA in parser.Samples.Select(t => t.ToList()))
            {
                int      maxSampleCount = (int)Math.Ceiling(channelA.Count * 1d * hz2 / hz1);
                double[] channel;
                {
                    var fillValue = channelA.Last();
                    while (channelA.Count % hz1 != 0)
                    {
                        channelA.Add(fillValue);
                    }

                    channelA.Add(fillValue);
                    channel = channelA.ToArray();
                }

                var samplesNew = new List <double>();
                channelFull.Add(samplesNew);
                for (int i = 0; i < channel.Length - 1; i += hz1)
                {
                    samplesNew.Add(channel[i]);
                    for (int j = 1; j < hz2; j++)
                    {
                        var index1 = indexes[j];
                        var r1     = rCoefs[j];

                        var v1 = channel[index1 + i];
                        var v2 = channel[index1 + 1 + i];
                        if (v1 == v2)
                        {
                            samplesNew.Add(v1);
                            continue;
                        }

                        var value = (1 - r1) * v1 + r1 * v2;
                        samplesNew.Add(value);
                    }
                }

                while (samplesNew.Count > maxSampleCount)
                {
                    samplesNew.RemoveAt(samplesNew.Count - 1);
                }
            }

            newFile.Samples    = channelFull;
            newFile.SampleRate = (ushort)newSampleRate;

            return(newFile);
        }
Esempio n. 11
0
 public static WAVParser ChangeSampleRate(WAVParser parser, uint newSampleRate)
 {
     return(ChangeSampleRate(parser, (int)newSampleRate));
 }
Esempio n. 12
0
        public static WAVParser MergeFiles(
            WAVParser file1,
            WAVParser file2,
            MergeFileAlgorithm algorithm = MergeFileAlgorithm.AverageX2
            )
        {
            var realFile1 = file1.Clone();
            var realFile2 = file2.Clone();

            if (realFile1.SampleRate > realFile2.SampleRate)
            {
                realFile2 = ChangeSampleRate(realFile2, realFile1.SampleRate);
            }
            else if (realFile1.SampleRate < realFile2.SampleRate)
            {
                realFile1 = ChangeSampleRate(realFile1, realFile2.SampleRate);
            }

            var mergeMap = new List <List <int> >();

            if (realFile1.ChannelCount == realFile2.ChannelCount)
            {
                for (int i = 0; i < realFile1.ChannelCount; i++)
                {
                    mergeMap.Add(new List <int>()
                    {
                        i, i
                    });
                }
            }
            else
            {
                if (realFile1.ChannelCount == 1)
                {
                    for (int i = 0; i < realFile2.ChannelCount; i++)
                    {
                        mergeMap.Add(new List <int>()
                        {
                            0, i
                        });
                    }
                }
                else if (realFile2.ChannelCount == 1)
                {
                    for (int i = 0; i < realFile1.ChannelCount; i++)
                    {
                        mergeMap.Add(new List <int>()
                        {
                            i, 0
                        });
                    }
                }
                else
                {
                    throw new Exception(string.Format("File 1 has {0} channels. File 2 has {1} channels. Can't merge",
                                                      realFile1.ChannelCount, realFile2.ChannelCount));
                }
            }

            var samples = new List <List <double> >();

            foreach (var map in mergeMap)
            {
                var channel1 = realFile1.Samples[map[0]];
                var channel2 = realFile2.Samples[map[1]];

                samples.Add(MergeSamples(channel1, channel2, algorithm));
            }

            var newFile = realFile1.Clone();

            newFile.Samples = samples;

            return(newFile);
        }
Esempio n. 13
0
        private static int ProcessSingleBuffer(
            IVstPluginContext pluginContext,
            int samplesOffset,
            VstAudioBuffer[] vstBufIn,
            VstAudioBuffer[] vstBufOut,
            VstAudioPrecisionBuffer[] vstBufIn2,
            VstAudioPrecisionBuffer[] vstBufOut2,
            bool isDoublePrecision,
            WAVParser pcmInput,
            WAVParser pcmOutput,
            int vstInputCount,
            int vstOutputCount,
            int samplesPerBuffer
            )
        {
            var result = ProcessSingleBufferClearBuffers(
                vstBufIn,
                vstBufOut,
                vstBufIn2,
                vstBufOut2,
                isDoublePrecision,
                vstInputCount,
                vstOutputCount,
                samplesPerBuffer
                );

            if (result != 0)
            {
                return(result);
            }

            result = ProcessSingleBufferFillBufferInput(
                samplesOffset,
                vstBufIn,
                vstBufIn2,
                isDoublePrecision,
                pcmInput,
                pcmOutput,
                vstOutputCount
                );
            if (result != 0)
            {
                return(result);
            }

            if (isDoublePrecision)
            {
                pluginContext.PluginCommandStub.ProcessReplacing(vstBufIn2, vstBufOut2);
            }
            else
            {
                pluginContext.PluginCommandStub.ProcessReplacing(vstBufIn, vstBufOut);
            }

            result = ProcessSingleBufferFillByteBuffer(
                vstBufOut,
                vstBufOut2,
                isDoublePrecision,
                pcmOutput,
                vstOutputCount,
                samplesPerBuffer
                );

            return(result);
        }
Esempio n. 14
0
        public static int ProcessFile(
            string inputFile,
            string outputFile,
            VstPluginContext pluginContext,
            System.Threading.CancellationToken cancellationToken
            )
        {
            var isDoublePrecision = pluginContext.PluginInfo.Flags.HasFlag(VstPluginFlags.CanDoubleReplacing);

            var pcmInput  = new WAVParser(inputFile);
            var pcmOutput = new WAVParser
            {
                ChannelCount = pcmInput.ChannelCount,
                Samples      = new List <List <double> >(),
                SampleRate   = pcmInput.SampleRate,
            };

            for (int i = 0; i < pcmOutput.ChannelCount; i++)
            {
                pcmOutput.Samples.Add(new List <double>());
            }

            pluginContext.PluginCommandStub.SetSampleRate(pcmInput.SampleRate);
            pluginContext.PluginCommandStub.SetProcessPrecision(VstProcessPrecision.Process32);

            // hint: samples per buffer should be equal to pcmInput.SampleRate
            int samplesPerBuffer = (int)pcmInput.SampleRate;

            pluginContext.PluginCommandStub.SetBlockSize(samplesPerBuffer);

            int inputCount  = pluginContext.PluginInfo.AudioInputCount;
            int outputCount = pluginContext.PluginInfo.AudioOutputCount;

            VstAudioBuffer[]          vstBufIn  = null, vstBufOut = null;
            VstAudioPrecisionBuffer[] vstBufIn2 = null, vstBufOut2 = null;

            if (isDoublePrecision)
            {
                var vstBufManIn  = new VstAudioPrecisionBufferManager(inputCount, samplesPerBuffer);
                var vstBufManOut = new VstAudioPrecisionBufferManager(outputCount, samplesPerBuffer);

                vstBufIn2  = NumeratorToArray(vstBufManIn.GetEnumerator());
                vstBufOut2 = NumeratorToArray(vstBufManOut.GetEnumerator());
            }
            else
            {
                var vstBufManIn  = new VstAudioBufferManager(inputCount, samplesPerBuffer);
                var vstBufManOut = new VstAudioBufferManager(outputCount, samplesPerBuffer);

                vstBufIn  = NumeratorToArray(vstBufManIn.GetEnumerator());
                vstBufOut = NumeratorToArray(vstBufManOut.GetEnumerator());
            }

            pluginContext.PluginCommandStub.MainsChanged(true);
            pluginContext.PluginCommandStub.StartProcess();

            for (int samplesOffset = 0;
                 samplesOffset < pcmInput.SamplesCount;
                 samplesOffset += (int)pcmInput.SampleRate)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return(ReturnCodeOffset + 20);
                }

                var result = ProcessSingleBuffer(
                    pluginContext,
                    samplesOffset,
                    vstBufIn,
                    vstBufOut,
                    vstBufIn2,
                    vstBufOut2,
                    isDoublePrecision,
                    pcmInput,
                    pcmOutput,
                    inputCount,
                    outputCount,
                    samplesPerBuffer
                    );

                if (result != 0)
                {
                    return(result);
                }
            }

            // Close VST Context
            pluginContext.PluginCommandStub.StopProcess();
            pluginContext.PluginCommandStub.MainsChanged(false);

            // Save
            pcmOutput.Save(outputFile);

            return(0);
        }