NAudioで信号処理 (その9)
NAudioで信号処理 (目次) - Hope is a Dream. Dream is a Hope.
NAudioで信号処理 (その9)
エフェクト処理 Part3 (Echo!!!!)
C# Audio Tutorial 9 - EffectStream Part 3 (Echo!)
やっとエフェクトの処理を実装します!
Echo.cs
先ほど作ったIEffect.csインターフェイスを実装したEcho.csを作ります。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Tutorial { public class Echo : IEffect { public int EchoLength { get; private set; } public float EchoFactor { get; set; } private Queue<float> samples; public Echo(int length = 20000, float factor = 0.5f) { this.EchoLength = length; this.EchoFactor = factor; this.samples = new Queue<float>(); for (int i = 0; i < length; i++) samples.Enqueue(0f); } float IEffect.ApplyEffect(float sample) { samples.Enqueue(sample); // add que return sample + EchoFactor * samples.Dequeue(); } } }
EffectStream.cs
using System; using System.Collections.Generic; using NAudio.Wave; namespace Tutorial { public class EffectStream : WaveStream { public WaveStream SourceStream { get; set; } public List<IEffect> Effects { get; set; } public EffectStream(WaveStream stream) { this.SourceStream = stream; this.Effects = new List<IEffect>(); } //... 省略 private int channel = 0; public override int Read(byte[] buffer, int offset, int count) { //*****************************************************************// // ここで信号処理をする //*****************************************************************// Console.WriteLine("DirectSoundOut request {0} bytes", count); int read = this.SourceStream.Read(buffer, offset, count); // 以下信号処理 for (int i = 0; i < read/4; i++) { // float = single = 32bit float sample = BitConverter.ToSingle(buffer, i * 4); // Single=4Byte // エフェクト処理 if (Effects.Count == WaveFormat.Channels) { sample = Effects[channel].ApplyEffect(sample); // ? channel = (channel + 1) % WaveFormat.Channels; // [1ch, 2ch, ...] } // float -> byte列に変換 byte[] bytes = BitConverter.GetBytes(sample); // 4Byteなので,bytes[4] // コピー //bytes.CopyTo(buffer, i * 4); // 遅い buffer[i * 4 + 0] = bytes[0]; buffer[i * 4 + 1] = bytes[1]; buffer[i * 4 + 2] = bytes[2]; buffer[i * 4 + 3] = bytes[3]; } return read; } } }
form1.cs
あとは再生系にエフェクトを指定すると使えます。
// WAV File Open OpenFileDialog open = new OpenFileDialog(); open.Filter = "WAV File (*.wav)|*.wav;"; if (open.ShowDialog() != DialogResult.OK) return; // Audio Chain WaveChannel32 wave = new WaveChannel32(new WaveFileReader(open.FileName)); EffectStream effect = new EffectStream(wave); // エフェクトをかけるためのパイプライン stream = new BlockAlignReductionStream(effect); // Effects for (int i = 0; i < wave.WaveFormat.Channels; i++) { effect.Effects.Add(new Echo(20000, 0.5f)); } // Out output = new DirectSoundOut(200); output.Init(stream); output.Play();