Hope is a Dream. Dream is a Hope.

非公開ブログは再開しました。

NAudioで信号処理 (その3)

チュートリアル その3

hope-is-dream.hatenablog.com

NAudioをつかってMP3からWAVへ変換

C# Audio Tutorial 3 - Convert MP3 File to Wave File

f:id:hope_is_dream:20170505232831p:plain

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

hope-is-dream.hatenablog.com

NAudioを使ってMP3/Waveファイルの再生

C# Audio Tutorial 2 - MP3/WAV File with NAudio

f:id:hope_is_dream:20170505221730p:plain

肝は、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();
        }
    }
}

NAudioで信号処理 (目次)

NAudioで信号処理

www.giawa.comさんが公開している動画を参考にさせていただきます。

f:id:hope_is_dream:20170505222531p:plain

GitHub - peace098beat/NAudioDemos: Demo NAudio.

1. WAVファイルの再生

f:id:hope_is_dream:20170505192539p:plain

NAudioで信号処理 (その1) - Hope is a Dream. Dream is a Hope.

2. MP3/WAVファイルの再生

f:id:hope_is_dream:20170505221730p:plain

NAudioで信号処理 (その2) - Hope is a Dream. Dream is a Hope.

private NAudio.Wave.BlockAlignReductionStream stream = null; 
private NAudio.Wave.DirectSoundOut output = 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);
}

output = new NAudio.Wave.DirectSoundOut();
output.Init(new NAudio.Wave.WaveChannel32(stream));
output.Play();

3. MP3からWAVへコンバート

f:id:hope_is_dream:20170505232831p:plain

NAudioで信号処理 (その3) - Hope is a Dream. Dream is a Hope.

 // 3. Convert mp3 -> wav
using (Mp3FileReader mp3 = new Mp3FileReader(open.FileName))
{
    using(WaveStream pcm = WaveFormatConversionStream.CreatePcmStream(mp3))
    {
        WaveFileWriter.CreateWaveFile(save.FileName, pcm);
    }
}

4. SinWaveの生成と再生

f:id:hope_is_dream:20170506085248p:plain

NAudioで信号処理 (その4) - Hope is a Dream. Dream is a Hope.

// 再生デバイス
private BlockAlignReductionStream stream = null;
private DirectSoundOut output = null;

// オーディオチェイン
WaveTone tone = new WaveTone(1000, 0.1);
stream = new BlockAlignReductionStream(tone);

output = new DirectSoundOut();
output.Init(stream);
output.Play();

以下 WaveTone:WaveStream
// 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
}

5. エフェクト処理の準備

f:id:hope_is_dream:20170506124450p:plain

hope-is-dream.hatenablog.com

 // Audio Chain
WaveChannel32 wave = new WaveChannel32(new WaveFileReader(open.FileName));
EffectStream effect = new EffectStream(wave); // エフェクトをかけるためのパイプライン
stream = new BlockAlignReductionStream(effect);

output = new DirectSoundOut(200);
output.Init(stream);
output.Play();

6. オーディオの録音と再生

C# Audio Tutorial 6 - Audio Loopback using NAudio

hope-is-dream.hatenablog.com

f:id:hope_is_dream:20170506124002p:plain

#region Member
private NAudio.Wave.WaveIn sourceStream = null; // 録音なのでWaveInを使用
private NAudio.Wave.DirectSoundOut waveOut = null;
#endregion


// waveIn Select Recording Device
sourceStream = new NAudio.Wave.WaveIn();
sourceStream.DeviceNumber = deviceNumber; // 使用するデバイスを選択
sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(44100, WaveIn.GetCapabilities(deviceNumber).Channels); 

// WaveInProviderで包み込む
WaveInProvider waveIn = new NAudio.Wave.WaveInProvider(sourceStream); // ?

// waveOut
waveOut = new DirectSoundOut();
waveOut.Init(waveIn);

sourceStream.StartRecording();
waveOut.Play();

f:id:hope_is_dream:20170507174215p:plain

7. Wavファイルへの録音

hope-is-dream.hatenablog.com

f:id:hope_is_dream:20170506131304p:plain

#region Member
private NAudio.Wave.WaveIn sourceStream = null;
private NAudio.Wave.DirectSoundOut waveOut = null;
private NAudio.Wave.WaveFileWriter waveWriter = null;
#endregion
// waveIn Select Recording Device
sourceStream = new NAudio.Wave.WaveIn();
sourceStream.DeviceNumber = deviceNumber;
sourceStream.WaveFormat = new NAudio.Wave.WaveFormat(44100, WaveIn.GetCapabilities(deviceNumber).Channels);

WaveInProvider waveIn = new NAudio.Wave.WaveInProvider(sourceStream); // ?

// waveOut
waveOut = new DirectSoundOut();
waveOut.Init(waveIn);

sourceStream.StartRecording();
waveOut.Play();

8. エフェクトの準備 Part2

f:id:hope_is_dream:20170506133840p:plain

hope-is-dream.hatenablog.com

// 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);

// Out
output = new DirectSoundOut(200);
output.Init(stream);
output.Play();

namespace Tutorial
{
    public interface IEffect
    {
        float ApplyEffect(float sample);
    }
}

EffectStream:WaveStream


9. エフェクトの実装(Echo!!)

f:id:hope_is_dream:20170506140459p:plain

hope-is-dream.hatenablog.com

10. グラフ描画

f:id:hope_is_dream:20170506144102p:plain

hope-is-dream.hatenablog.com

11. グラフ描画 2

f:id:hope_is_dream:20170506170929p:plain

hope-is-dream.hatenablog.com

12.

[NAudio ライブラリでオーディオを再生する(1)](http://blog.ume108.mobi/?p=925

https://i1.wp.com/blog.ume108.mobi/wp-content/uploads/2012/12/naudiodemo3.png?w=393

13.

NAudio ライブラリでオーディオを再生する(2)

https://i1.wp.com/blog.ume108.mobi/wp-content/uploads/2012/12/NAudio-Stream.png?resize=1024%2C258

14.

NAudio ライブラリでオーディオを再生する(3)

https://i1.wp.com/blog.ume108.mobi/wp-content/uploads/2012/12/NAudio-3png.png?w=400

15.

NAudio ライブラリでオーディオを再生する(4)

https://i1.wp.com/blog.ume108.mobi/wp-content/uploads/2013/01/c396df18792a8635a9e693bb0cce5dee.png?w=601

16.

NAudio ライブラリでオーディオを再生する(5)

https://i2.wp.com/blog.ume108.mobi/wp-content/uploads/2013/01/endpoint-image.png?w=600


Practical C# Charts and Graphics: Advanced Chart and Graphics Programming for Real-world .net Applications

Practical C# Charts and Graphics: Advanced Chart and Graphics Programming for Real-world .net Applications

Practical .Net Chart Development and Applications

Practical .Net Chart Development and Applications

Practical WPF Charts and Graphics

Practical WPF Charts and Graphics