NAudioで信号処理 (その4)
NAudioで信号処理 (目次) - Hope is a Dream. Dream is a Hope.
チュートリアル その4
NAudioをつかってSin音を生成
C# Audio Tutorial 2 - MP3/WAV File with NAudio
// 再生デバイス private DirectSoundOut output = null; private BlockAlignReductionStream stream = null; // オーディオチェイン WaveTone tone = new WaveTone(1000, 0.1); stream = new BlockAlignReductionStream(tone); output = new DirectSoundOut(); output.Init(stream); output.Play(); // SinWaveを生成 for (int i = 0; i < samples; i++) { double sine = amplitude * Math.Sin(Math.PI * 2 * frequency * time); time += 1.0 / 44100; short truncated = (short)Math.Round(sine * (Math.Pow(2, 15) - 1)); //16bit buffer[i * 2] = (byte)(truncated & 0x00ff); // 下半分を取り出し 8bit buffer[i * 2 + 1] = (byte)((truncated & 0xff00) >> 8); // 上半分を取り出してシフト 8bit }
using System; using System.Windows.Forms; using NAudio.Wave; namespace Tutorial { public partial class Form1 : Form { public Form1() { InitializeComponent(); } /// <summary> /// フォームの初期設定。 /// </summary> private void Form1_Load(object sender, EventArgs e) { // ボタンの初期状態 this.Text = @"Tutorial 4"; linkLabel1.Text = "https://www.youtube.com/watch?v=Tumpkl-xJuA"; } #region Member private DirectSoundOut output = null; private BlockAlignReductionStream stream = null; #endregion /// <summary> /// フォームのクロージング処理 /// Wave関連オブジェクトのDispose処理を担当 /// </summary> private void Form1_FormClosing(object sender, FormClosingEventArgs e) { output?.Dispose(); output = null; stream?.Dispose(); stream = null; } private void button_StartTone_Click(object sender, EventArgs e) { WaveTone tone = new WaveTone(1000, 0.1); stream = new BlockAlignReductionStream(tone); output = new DirectSoundOut(); output.Init(stream); output.Play(); } private void button_StopTone_Click(object sender, EventArgs e) { output?.Stop(); } } /// <summary> /// /// WaveStreamは抽象クラス /// </summary> public class WaveTone : WaveStream { private double frequency; private double amplitude; private double time; public WaveTone(double f, double a) { this.time = 0; this.frequency = f; this.amplitude = a; } public override long Position { get; set; } public override long Length { get { return long.MaxValue; } } public override WaveFormat WaveFormat { get { return new WaveFormat(44100, 32, 1); } } /// <summary> /// </summary> public override int Read(byte[] buffer, int offset, int count) { // byte(8bit) // short(16bit) int samples = count / 2; // ? for (int i = 0; i < samples; i++) { double sine = amplitude * Math.Sin(Math.PI * 2 * frequency * time); time += 1.0 / 44100; short truncated = (short)Math.Round(sine * (Math.Pow(2, 15) - 1)); //16bit buffer[i * 2] = (byte)(truncated & 0x00ff); // 下半分を取り出し 8bit buffer[i * 2 + 1] = (byte)((truncated & 0xff00) >> 8); // 上半分を取り出してシフト 8bit } return count; } } }
NAudioで信号処理 (その3)
チュートリアル その3
NAudioをつかってMP3からWAVへ変換
C# Audio Tutorial 3 - Convert MP3 File to Wave File
MP3FileReaderでmp3ファイルをロード. WaveStreamに変換してあと、WaveFileWriterへ渡す。だけ。おまじない。
// 3. Convert mp3 -> wav using (Mp3FileReader mp3 = new Mp3FileReader(open.FileName)) { using(WaveStream pcm = WaveFormatConversionStream.CreatePcmStream(mp3)) { WaveFileWriter.CreateWaveFile(save.FileName, pcm); } }
using System; using System.Windows.Forms; using NAudio.Wave; namespace Tutorial2 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } /// <summary> /// フォームの初期設定。 /// </summary> private void Form1_Load(object sender, EventArgs e) { // ボタンの初期状態 this.Text = @"Tutorial 3"; linkLabel1.Text = "https://www.youtuabe.com/watch?v=l9sT26LEiD4"; } #region Member #endregion /// <summary> /// フォームのクロージング処理 /// Wave関連オブジェクトのDispose処理を担当 /// </summary> private void Form1_FormClosing(object sender, FormClosingEventArgs e) { } /// <summary> /// MP3ファイルをWAVファイルへコンバート /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button_Convert_Click(object sender, EventArgs e) { // 1. Open MP3 File OpenFileDialog open = new OpenFileDialog(); open.Filter = "Mp3 File (*.mp3)|*.mp3;"; if (open.ShowDialog() != DialogResult.OK) return; // 2. Select Save WAV File SaveFileDialog save = new SaveFileDialog(); save.Filter = "WAV File (*.wav)|*.wav;"; if (save.ShowDialog() != DialogResult.OK) return; // 3. Convert mp3 -> wav using (Mp3FileReader mp3 = new Mp3FileReader(open.FileName)) { using(WaveStream pcm = WaveFormatConversionStream.CreatePcmStream(mp3)) { WaveFileWriter.CreateWaveFile(save.FileName, pcm); } } } } }
NAudioで信号処理 (その2)
チュートリアル その2
NAudioを使ってMP3/Waveファイルの再生
C# Audio Tutorial 2 - MP3/WAV File with NAudio
肝は、MP3/WAVファイルをどちらもWaveStreamとしてロードして、DirectSoundで再生する。
private NAudio.Wave.BlockAlignReductionStream stream = null; ...省略 if (open.FileName.EndsWith(".mp3")) { NAudio.Wave.WaveStream pcm = NAudio.Wave.WaveFormatConversionStream.CreatePcmStream(new NAudio.Wave.Mp3FileReader(open.FileName)); stream = new NAudio.Wave.BlockAlignReductionStream(pcm); } else if (open.FileName.EndsWith(".wav")) { NAudio.Wave.WaveStream pcm = new NAudio.Wave.WaveChannel32(new NAudio.Wave.WaveFileReader(open.FileName)); stream = new NAudio.Wave.BlockAlignReductionStream(pcm); }
メインのソースコードは以下のようになる。WAVの再生には、WAVファイルの選択->WAVのReaderの設定->出力先を指定->再生開始。のほかにも再生中断/再開や、再生が停止されたときのDispose処理が関わってくる。このチュートリアル(その1)では基本的なWAVファイル再生をベースとして、周辺のプレ処理、クロージング処理を実装しているので注目して欲しい。
using System; using System.Windows.Forms; namespace Tutorial2 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } /// <summary> /// フォームの初期設定。 /// </summary> private void Form1_Load(object sender, EventArgs e) { // ボタンの初期状態 // TODO: 初期化関数は別に準備 button_PauseWav.Enabled = false; this.Text = @"Tutorial 2"; linkLabel1.Text = "https://www.youtube.com/watch?v=2ij2vqgprU0"; } #region Member private NAudio.Wave.BlockAlignReductionStream stream = null; private NAudio.Wave.DirectSoundOut output = null; #endregion /// <summary> /// WAVオープンボタン /// </summary> private void button_OpenWav_Click(object sender, EventArgs e) { OpenFileDialog open = new OpenFileDialog(); open.Filter = "Audio File (*.wav, *.mp3) |*.wav;*.mp3;|All files (*.*)|*.*"; if (open.ShowDialog() != DialogResult.OK) return; DisposeWave(); if (open.FileName.EndsWith(".mp3")) { NAudio.Wave.WaveStream pcm = NAudio.Wave.WaveFormatConversionStream.CreatePcmStream(new NAudio.Wave.Mp3FileReader(open.FileName)); stream = new NAudio.Wave.BlockAlignReductionStream(pcm); } else if (open.FileName.EndsWith(".wav")) { NAudio.Wave.WaveStream pcm = new NAudio.Wave.WaveChannel32(new NAudio.Wave.WaveFileReader(open.FileName)); stream = new NAudio.Wave.BlockAlignReductionStream(pcm); } else { MessageBox.Show("Not a correct audio file type."); return; //throw new InvalidOperationException("Not a correct audio file type."); } output = new NAudio.Wave.DirectSoundOut(); output.Init(new NAudio.Wave.WaveChannel32(stream)); output.Play(); button_PauseWav.Enabled = true; } /// <summary> /// 再生/一時停止ボタン /// </summary> private void button_PauseWav_Click(object sender, EventArgs e) { if (output != null) { if (output.PlaybackState == NAudio.Wave.PlaybackState.Playing) output.Pause(); else if (output.PlaybackState == NAudio.Wave.PlaybackState.Paused) output.Play(); } } /// <summary> /// Wave関連オブジェクトのDispose処理。 /// </summary> private void DisposeWave() { if (output != null) { if (output.PlaybackState == NAudio.Wave.PlaybackState.Playing) output.Stop(); output.Dispose(); output = null; } if (stream != null) { stream.Dispose(); stream = null; } } /// <summary> /// フォームのクロージング処理 /// Wave関連オブジェクトのDispose処理を担当 /// </summary> private void Form1_FormClosing(object sender, FormClosingEventArgs e) { this.DisposeWave(); } } }