Hey_CHさんの記述の説明のような形で回答させていただきます。
Hey_CHさんの回答は(再生していないことの判断方法や再生位置のリセット方法等若干異なりますが)最後の記述に近いものとなります。
下記のような段階を踏んだ結果最終的な形になったと考えていただければ分かりやすいでしょうか?
1.単純にNAudio
を使用してタイピング音を鳴らす場合
問題点 :reader
及びwaveOut
が1つしかない場合同時再生できるタイピング音は1つだけのため、連続して入力した場合は押しっぱなしにした場合再生が追い付かない。
c#
1 public partial class Form1 : Form
2 {
3 private AudioFileReader reader ;
4 private WaveOut waveOut ;
5
6 public Form1 ( )
7 {
8 InitializeComponent ( ) ;
9 reader = new AudioFileReader ( "keyboard1.wav" ) ;
10 waveOut = new WaveOut ( ) ;
11 waveOut . Init ( reader ) ;
12 }
13
14 private void Form1_KeyPress ( object sender , KeyPressEventArgs e )
15 {
16 // 再生位置を0秒にリセット
17 reader . Position = 0 ;
18
19 // 再生する
20 waveOut . Play ( ) ;
21 }
22
23 private void Form1_FormClosing ( object sender , FormClosingEventArgs e )
24 {
25 waveOut . Dispose ( ) ;
26 reader . Dispose ( ) ;
27 }
28 }
2.音源を複数準備してタイピング音を鳴らす場合
問題点 : (今回のコードの例だと)4つまで同時再生できるようになったが、力技(変数をたくさん定義してひたすら初期化してif文書いて。。)なのでたくさん増やすのがつらい
C#
1 public partial class Form1 : Form
2 {
3 private AudioFileReader reader ;
4 private AudioFileReader reader2 ;
5 private AudioFileReader reader3 ;
6 private AudioFileReader reader4 ;
7 private WaveOut waveOut ;
8 private WaveOut waveOut2 ;
9 private WaveOut waveOut3 ;
10 private WaveOut waveOut4 ;
11
12 public Form1 ( )
13 {
14 InitializeComponent ( ) ;
15 reader = new AudioFileReader ( "keyboard1.wav" ) ;
16 reader2 = new AudioFileReader ( "keyboard1.wav" ) ;
17 reader3 = new AudioFileReader ( "keyboard1.wav" ) ;
18 reader4 = new AudioFileReader ( "keyboard1.wav" ) ;
19 waveOut = new WaveOut ( ) ;
20 waveOut2 = new WaveOut ( ) ;
21 waveOut3 = new WaveOut ( ) ;
22 waveOut4 = new WaveOut ( ) ;
23 waveOut . Init ( reader ) ;
24 waveOut2 . Init ( reader2 ) ;
25 waveOut3 . Init ( reader3 ) ;
26 waveOut4 . Init ( reader4 ) ;
27 }
28
29 private void Form1_KeyPress ( object sender , KeyPressEventArgs e )
30 {
31 Console . WriteLine ( "called" ) ;
32
33 // 再生されてないやつを再生する
34 if ( waveOut . PlaybackState == PlaybackState . Stopped )
35 {
36 // 再生位置を0秒にリセット
37 reader . Position = 0 ;
38 waveOut . Play ( ) ;
39 Console . WriteLine ( "play1" ) ;
40 }
41 else if ( waveOut2 . PlaybackState == PlaybackState . Stopped )
42 {
43 // 再生位置を0秒にリセット
44 reader2 . Position = 0 ;
45 waveOut2 . Play ( ) ;
46 Console . WriteLine ( "play2" ) ;
47 }
48 else if ( waveOut3 . PlaybackState == PlaybackState . Stopped )
49 {
50 // 再生位置を0秒にリセット
51 reader3 . Position = 0 ;
52 waveOut3 . Play ( ) ;
53 Console . WriteLine ( "play3" ) ;
54 }
55 else if ( waveOut4 . PlaybackState == PlaybackState . Stopped )
56 {
57 // 再生位置を0秒にリセット
58 reader4 . Position = 0 ;
59 waveOut4 . Play ( ) ;
60 Console . WriteLine ( "play4" ) ;
61 }
62 }
63
64 private void Form1_FormClosing ( object sender , FormClosingEventArgs e )
65 {
66 waveOut . Dispose ( ) ;
67 waveOut2 . Dispose ( ) ;
68 waveOut3 . Dispose ( ) ;
69 waveOut4 . Dispose ( ) ;
70 reader . Dispose ( ) ;
71 reader2 . Dispose ( ) ;
72 reader3 . Dispose ( ) ;
73 reader4 . Dispose ( ) ;
74 }
75 }
3.音源を配列で管理してタイピング音を鳴らす場合
たくさん同時再生・連続再生できる。ソースもシンプルになった。
C#
1 public partial class Form1 : Form
2 {
3 private SoundPool soundPool ;
4
5 public Form1 ( )
6 {
7 InitializeComponent ( ) ;
8
9 soundPool = new SoundPool ( "keyboard1.wav" , 10 ) ;
10 }
11
12 private void Form1_KeyPress ( object sender , KeyPressEventArgs e )
13 {
14 soundPool . Play ( ) ;
15 }
16
17 private void Form1_FormClosing ( object sender , FormClosingEventArgs e )
18 {
19 soundPool . Dispose ( ) ;
20 }
21 }
22
23 /// <summary>
24 /// 同時再生のために複数の音源を管理するクラス
25 /// </summary>
26 internal class SoundPool : IDisposable
27 {
28 private AudioFileReader [ ] readers ;
29 private WaveOut [ ] waveOuts ;
30
31 public SoundPool ( string soundFilePath , int poolSize )
32 {
33 readers = new AudioFileReader [ poolSize ] ;
34 waveOuts = new WaveOut [ poolSize ] ;
35
36 for ( var i = 0 ; i < poolSize ; i ++ )
37 {
38 readers [ i ] = new AudioFileReader ( soundFilePath ) ;
39 waveOuts [ i ] = new WaveOut ( ) ;
40 waveOuts [ i ] . Init ( readers [ i ] ) ;
41 }
42 }
43
44 /// <summary>
45 /// 再生されてない音源を再生する
46 /// </summary>
47 public void Play ( )
48 {
49 for ( var i = 0 ; i < waveOuts . Length ; i ++ )
50 {
51 if ( waveOuts [ i ] . PlaybackState == PlaybackState . Stopped )
52 {
53 // 再生位置を0秒にリセット
54 readers [ i ] . Position = 0 ;
55 waveOuts [ i ] . Play ( ) ;
56 break ;
57 }
58 }
59 }
60
61 public void Dispose ( )
62 {
63 for ( var i = 0 ; i < readers . Length ; i ++ )
64 {
65 waveOuts [ i ] . Dispose ( ) ;
66 readers [ i ] . Dispose ( ) ;
67 }
68 }
69 }