C#でサウンドを鳴らす

前回の記事([XAML+C#でWPF NotifyIconを使ってオリジナル通知アイコンを表示する](http://qiita.com/Oichan/items/68a5fd339e12193b3ca4))では、
指定時間が経過すると、通知ウィンドウが表示されるところまで作成しました。

今回は通知ウィンドウに合わせてサウンドが鳴るようにしてみます。
調べてみると色々な方法があるようなので、各種ライブラリを試してみました。

## System.Media.SoundPlayer
Waveファイルを再生するだけであれば、デフォルトで組み込まれている`System.Media.SoundPlayer`を使用するのが一番簡単です。

```csharp:StopWatch.xaml.cs
// showBalloon() の前に追加
StopSound();
PlaySound();
```

```csharp
private System.Media.SoundPlayer player = null;
string SoundFile = "HogeHoge.wav";

private void StopSound()
{
    if (player != null)
    {
        player.Stop();
        player.Dispose();
        player = null;
    }
}

private void PlaySound()
{
    player = new System.Media.SoundPlayer(SoundFile);
    player.Play();
}        
```

waveファイルを用意すれば、上記のコードで再生・停止ができます。
しかし、mp3は再生できません。


## Microsoft Small Basic 1.1
>[C#で音楽を再生する一番簡単な方法(Null and void)](http://d.hatena.ne.jp/chi-bd/20140216/1392534158)

上記で紹介されている[Small Basic](http://smallbasic.com/doc.aspx?o=Sound&l=ja)のdllを参照する方法です。
Small BasicのSoundクラスではmp3を再生することができる事に加えて、プリセットのサウンドを再生するメソッドを持っています。

開発するPCにSmall Basicをインストールして、プロジェクトにDLL参照を追加します。
(画像は64bit版OSの場合のインストール先フォルダ)
![image](https://qiita-image-store.s3.amazonaws.com/0/90051/0806b35d-364d-ca75-38b1-dba3583d4680.png)

展開するPCでもDLLが必要ですが、ローカルコピーをTrueにしておくとインストール(ダウンロード)は不要です。

![002.png](https://qiita-image-store.s3.amazonaws.com/0/90051/7a2326cc-4d7e-0cbe-8be6-0e6cf63ba38d.png)

```csharp:StopWatch.xaml.cs
// showBalloon() の前に追加
Microsoft.SmallBasic.Library.Sound.PlayChimes(); 
```

指定の音声ファイルを再生する場合は以下のようにします。

```csharp:StopWatch.xaml.cs
// TimerStart()のメソッド内に追加
StopSound();

// showBalloon() の前に追加
PlaySound();
  
```

```csharp
     
private void PlaySound()
{
    Microsoft.SmallBasic.Library.Sound.Play("HogeHoge.mp3");
}  

private void StopSound()
{
    Microsoft.SmallBasic.Library.Sound.Stop("HogeHoge.mp3");
}
  
```
>MP3、WAV、またはWMAファイルを再生できます。それ以外のファイル形式は、コンピューターにインストールされているオーディオ コーデックによって、再生できない場合があります。
>(Small Basic リファレンスページより引用)



## [naudio](http://naudio.codeplex.com/)
>[C# で音楽再生(アカベコマイリ)](http://akabeko.me/blog/2009/12/c-%E3%81%A7%E9%9F%B3%E6%A5%BD%E5%86%8D%E7%94%9F-1/)

上記で紹介されている[naudio](http://naudio.codeplex.com/)のdllを参照する方法です。
非常に高機能なので、使いこなせれば本格的なオーディオ再生アプリケーションが作れそうです。

DLLをダウンロードしてプロジェクトから参照するまでの手順はSmall Basicと同様です。
色々な機能があるので試してみたくなりますが、ここでは最低限の機能のみ実装してみます。

WaveStreamを生成する処理では、サンプルプログラムのMeteringStreamクラスをそのまま利用していますのでご注意下さい。

```csharp:StopWatch.xaml.cs
// TimerStart()のメソッド内に追加
StopSound();
 
```
```csharp   
// showBalloon() の前に追加
PlaySound();
 
```
```csharp

//コンストラクタに追加
var reader = new NAudio.Wave.Mp3FileReader(soundfile);
var pcmStream = NAudio.Wave.WaveFormatConversionStream.CreatePcmStream(reader);
var blockAlignedStream = new NAudio.Wave.BlockAlignReductionStream(pcmStream);

NAudio.Wave.WaveChannel32 stream = new NAudio.Wave.WaveChannel32(blockAlignedStream);
audioStream = new MeteringStream(stream, stream.WaveFormat.SampleRate / 10);
this.player = new NAudio.Wave.WaveOut() { DesiredLatency = 200 };
this.player.Init(audioStream);
  
```
```csharp

private NAudio.Wave.WaveOut player;
private NAudio.Wave.WaveStream audioStream;
string SoundFile = "HogeHoge.mp3";

private void StopSound()
{
    if (this.player.PlaybackState == NAudio.Wave.PlaybackState.Playing)
    {
        this.player.Stop();
        this.audioStream.Position = 0;
    }
}

private void PlaySound()
{
    player.Play();
}
  
```

NAudio.Wave名前空間の配下にあるクラスでMP3を読み込んで、オーディオストリームとして扱います。
一度再生したサウンドを再度再生するには、`audioStream.Position = 0;`で頭出しをする必要があります。


# まとめ
簡易タイマーへの機能追加はこれで一旦完了です。

業務アプリでは標準のライブラリしか使ったことがなかったため、色々な方法がある事に驚きました。
これ以外にもWMPコントロールを使ったり、COMコンポーネントを使う方法があるようです。
要件に合わせて、ライブラリを選択して頂ければと思います。
簡易タイマーには最もコードが短くて済む、Small Basicを選択しました。 
プリセットのチャイムを鳴らすようにしています。

ソースコードはこちら→[GitHub](https://github.com/MakotoUwaya/SimpleTimer)

***
naudioを使った自作オーディオプレイヤー開発も試してみたいです。
作ってみたいものがいっぱいで困ります。
それではまた。