ちょっと変なタイトルですけど、XAudio2で連続音が出ました。
いきなりソースです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
using System; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; using SharpDX; using SharpDX.Multimedia; using SharpDX.XAudio2; using SharpDX.XAudio2.Fx; namespace XAudio_Test { public partial class Form1 : Form { public Form1() { InitializeComponent(); } XAudio2 xaudio2; MasteringVoice masteringVoice; SourceVoice sourceVoice; WaveFormat waveFormat; AutoResetEvent bufferEndEvent; AudioBuffer[] audioBuffersRing; DataStream dataStream; Task playTask; double phase; int bufferSize, numberOfSamples; private void button1_Click(object sender, EventArgs e) { sourceVoice.Start(); playTask = Task.Factory.StartNew(Play, TaskCreationOptions.LongRunning); bufferEndEvent.Set(); } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { masteringVoice.Dispose(); sourceVoice.Dispose(); xaudio2.Dispose(); } private void Form1_Load(object sender, EventArgs e) { xaudio2 = new XAudio2(); masteringVoice = new MasteringVoice(xaudio2); waveFormat = new WaveFormat(44100, 32, 2); sourceVoice = new SourceVoice(xaudio2, waveFormat); sourceVoice.BufferEnd += sourceVoice_BufferEnd; bufferEndEvent = new AutoResetEvent(false); audioBuffersRing = new AudioBuffer[3]; for(int i = 0; i < audioBuffersRing.Length; i++) { audioBuffersRing[i] = new AudioBuffer(); } bufferSize = waveFormat.ConvertLatencyToByteSize(1000); dataStream = new DataStream(bufferSize, true, true); numberOfSamples = bufferSize / waveFormat.BlockAlign; phase = 0; } void Play() { int nextBuffer = 0; while (true) { getSndData(); dataStream.Position = 0; audioBuffersRing[nextBuffer].AudioDataPointer = dataStream.DataPointer; audioBuffersRing[nextBuffer].AudioBytes = (int)dataStream.Length; bufferEndEvent.WaitOne(); sourceVoice.SubmitSourceBuffer(audioBuffersRing[nextBuffer], null); nextBuffer = ++nextBuffer % audioBuffersRing.Length; } } void getSndData() { for (int i = 0; i < numberOfSamples; i++) { float value = (float)(0.5 * Math.Sin(phase)); dataStream.Write(value); dataStream.Write(value); phase += 2.0 * Math.PI * 800.0 / waveFormat.SampleRate; if (phase > 2.0 * Math.PI) phase -= 2 * Math.PI; } } void sourceVoice_BufferEnd(IntPtr ogj) { bufferEndEvent.Set(); } } } |
AudioBufferの配列を作って、そこにsin波のデータを順番に書き込んで連続音を出すようにしました。
play()というスレッドを走らせて、Audiobufferにデータを格納する前で、waitoneで止めておきます。
一方、SourceVoiseのイベントハンドラに、sourceVoice_BufferEndを設定してbufferの再生が終わった時にset()が呼び出されるようにします。
set()が呼び出されると、2つ前のAudiobufferにデータが格納されます。
これを永遠と繰り返します。
ただ、bufferSizeが1秒以下になると、Formを閉じた時に例外が発生します。 今のところ原因不明です。
とりあえず、想定していた機能は実現できたので、次のステップに進みたいと思います。
結構、長かったなぁ..。