public void WavReaderMakeMultiChannelWav() { const double Tau = 2 * Math.PI; var a = new double[22050].Select((v, i) => Math.Sin(Tau * i * 500 / 22050)).ToArray(); var b = new double[22050].Select((v, i) => Math.Sin(Tau * i * 1500 / 22050)).ToArray(); var c = new double[22050].Select((v, i) => Math.Sin(Tau * i * 2500 / 22050)).ToArray(); var d = new double[22050].Select((v, i) => Math.Sin(Tau * i * 3500 / 22050)).ToArray(); var multiplexed = new double[22050 * 4].Select( (v, i) => { switch (i % 4) { case 0: return(a[i / 4]); case 1: return(b[i / 4]); case 2: return(c[i / 4]); case 3: return(d[i / 4]); } return(double.NaN); }); var reader = new WavReader(multiplexed.ToArray(), 4, 16, 22050); CollectionAssert.AreEqual(a, reader.GetChannel(0)); CollectionAssert.AreEqual(b, reader.GetChannel(1)); CollectionAssert.AreEqual(c, reader.GetChannel(2)); CollectionAssert.AreEqual(d, reader.GetChannel(3)); }
public void WavReaderChannelOutOfBoundsFails() { var source = PathHelper.GetTestAudioFile("different_channels_tone.wav"); var reader = new WavReader(source); Assert.ThrowsException <IndexOutOfRangeException>(() => { reader.GetChannel(-1); }); Assert.ThrowsException <IndexOutOfRangeException>(() => { reader.GetChannel(5); }); Assert.ThrowsException <IndexOutOfRangeException>(() => { reader[0, -1].ToString(); }); Assert.ThrowsException <IndexOutOfRangeException>(() => { reader[0, 5].ToString(); }); }
public void WavReaderReadsSamplesAccurately24bit() { // 11025Hz fake array var a = new double[44100 * 5].Select((v, i) => i % 4 == 3 ? -1 : i % 2).ToArray(); var source = PathHelper.GetTestAudioFile("11025Hz-24bit.wav"); var info = this.audioUtility.Info(source); var reader = new WavReader(source); TestHelper.WavReaderAssertions(reader, info); Assert.AreEqual(5.0M, reader.ExactDurationSeconds); var mono = reader.GetChannel(0); Assert.AreEqual(a.Length, reader.Samples.Length); Assert.AreEqual(a.Length, mono.Length); for (int i = 0; i < a.Length; i++) { Assert.AreEqual(a[i], reader.Samples[i], double.Epsilon); Assert.AreEqual(a[i], mono[i], double.Epsilon); } }
private static void DoFrequencyAnalysis( AudioUtilityInfo expected, int[][] expectedFrequencies) { var reader = new WavReader(expected.SourceFile); TestHelper.WavReaderAssertions(reader, expected); for (var channel = 0; channel < expectedFrequencies.Length; channel++) { var samples = reader.GetChannel(channel); TestHelper.AssertFrequencyInSignal(reader, samples, expectedFrequencies[channel]); } }
public void WavReaderGetChannel() { var source = PathHelper.GetTestAudioFile("4channelsPureTones.wav"); var info = this.audioUtility.Info(source); var reader = new WavReader(source); TestHelper.WavReaderAssertions(reader, info); var channels = new double[4][]; var expectedFrequencies = new int[] { 4000, 3000, 2000, 1000 }; for (int c = 0; c < channels.Length; c++) { channels[c] = reader.GetChannel(c); TestHelper.AssertFrequencyInSignal(reader, channels[c], new[] { expectedFrequencies[c] }); } }
public void WavReaderReadsSamplesAccuratelytMultiChannelRandom(int bitDepth, int sampleRate, int channels) { const int testSampleCount = 500; // generate some fake data // generates a repeating saw wave of 0, 1, 0 -1 var a = new double[testSampleCount].Select((v, i) => i % 4 == 3 ? -1.0 : i % 2).ToArray(); // random data var random = TestHelpers.Random.GetRandom(); double Clamp(double value) { return(Math.Max(Math.Min(value, 1.0), -1.0)); } var b = new double[testSampleCount].Select(v => Clamp(random.NextDouble() * 2.0 - 1.0)).ToArray(); // now write the file var temp = PathHelper.GetTempFile("wav"); var signals = new double[channels][]; switch (channels) { case 4: signals[0] = a; signals[1] = b; signals[2] = b; signals[3] = a; break; case 2: signals[0] = a; signals[1] = b; break; case 1: var c = new double[a.Length + b.Length]; a.CopyTo(c, 0); b.CopyTo(c, a.Length); signals[0] = c; break; default: throw new InvalidOperationException(); } WavWriter.WriteWavFileViaFfmpeg(temp, signals, bitDepth, sampleRate); // verify file written correctly var info = this.audioUtility.Info(temp); var reader = new WavReader(temp); // verify the writer wrote (the header) correctly TestHelper.WavReaderAssertions(reader, new AudioUtilityInfo() { BitsPerSample = bitDepth, BitsPerSecond = channels * bitDepth * sampleRate, ChannelCount = channels, Duration = TimeSpan.FromSeconds(testSampleCount * (channels == 1 ? 2 : 1) / (double)sampleRate), MediaType = MediaTypes.MediaTypeWav1, SampleRate = sampleRate, }); // verify the wav reader read correctly TestHelper.WavReaderAssertions(reader, info); // our ability to faithfully convert numbers depends on the bit depth of the signal double epilson = reader.Epsilon; for (int c = 0; c < channels; c++) { double[] expected; double e; switch (c) { case 0 when channels == 1: var ex = new double[a.Length + b.Length]; a.CopyTo(ex, 0); b.CopyTo(ex, a.Length); expected = ex; e = epilson; break; case 0: expected = a; e = 0.0; break; case 1: expected = b; e = epilson; break; case 2: expected = b; e = epilson; break; case 3: expected = a; e = 0.0; break; default: throw new InvalidOperationException(); } var mono = reader.GetChannel(c); Assert.AreEqual(expected.Length, mono.Length); for (int i = 0; i < a.Length; i++) { Assert.AreEqual(expected[i], mono[i], epilson, $"failed at index {i} channel {c}"); } } }