Managed DirectSoundを使ってみる

chakemiです。 先日、mciSendString()関数をPInvokeで使用しましたが、ストリームバッファを弄ろうと思ったら、 アンマネージなWindowsマルチメディアAPIをC#から使うのはしんどいと思い、 他の手を探ってました。

前回も挙げたDirectSoundですが、過去にManaged DirectXというものが開発されていて、 調べた限りではDirectX SDK (March 2008)までは含まれていましたが、現在は開発は中止され、 Microsoft XNAに置き換えられています。

Microsoft XNAはゲーム開発に重点を置いたツールのようで、いまいちなんとも言えない気がしたので、とりあえず、Managed DirectXでDirectSoundを試してみようと思いました。

幸いにも、最新?のDirectX End-User Runtimesをインストールすれば、コンポーネントが含まれているので使用できるようです。

また、DirectX SDK (March 2008)もまだ入手できます。 ドキュメントやサンプルはもっと古いものでないと入手できないようですが。。。

とりあえず、SDKと最新のRuntimeをインストールして試しにwaveファイルを再生するアプリケーションを書いてみました。

開発環境

  • WindowsXP SP3
  • VisualC#2010Express

まずは、Deviceクラスを作成します。このクラスを使用して環境設定やバッファオブジェクトの作成を行ないます。 次に、SecondaryBufferクラスを作成します。これは、サウンドデータをバッファとして格納し、再生やエフェクトなどの操作を行なうクラスです。 アプリケーションは、個々のサウンドを格納して再生するために、少なくとも 1 つのセカンダリ サウンド バッファを作成しなければならないようです。

Form1.Designer.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
using Microsoft.DirectX;
using Microsoft.DirectX.DirectSound;

namespace testDirectSound1
{
    partial class Form1
    {
        //
        //省略
        //
        private Device device = null;
        private SecondaryBuffer secBuf = null;
    }
}

Device.SetCooperativeLevelで協調レベルというものを設定するようです。他のアプリケーションとデバイスを同時に使う際の切り替えなどに影響するようです。 第一引数にメインで使用しているフォーム指定。第二引数に協調レベルを「Normal」「Priority」「WritePriority」から選択。

SecondaryBufferを生成し、第一引数にサウンドデータファイル、第二引数にデバイスを指定します。サウンドデータファイルはWAVEファイルのみ直接指定可能なようです。

SecondaryBuffer.SetCurrentPositionで再生開始位置を指定します。 SecondaryBuffer.Playの第一引数でサウンドの優先度、第二引数で再生フラグを指定します。

Form1.cs
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
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.DirectSound;

namespace testDirectSound1
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

                //デバイス作成
                device = new Device();
                //協調レベル設定
                device.SetCooperativeLevel(this, CooperativeLevel.Priority);
                //セカンダリバッファへロード
                secBuf = new SecondaryBuffer(@"C:\test.wav", device);
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            //セカンダリバッファ破棄
                secBuf.Dispose();
            //デバイス破棄
                device.Dispose();
        }

        private void button1_Click(object sender, EventArgs e)
        {
                //再生位置を頭に設定
                secBuf.SetCurrentPosition(0);
                //再生
                secBuf.Play(0, BufferPlayFlags.Default);
        }

        private void button2_Click(object sender, EventArgs e)
        {
                secBuf.Stop();
        }

    }
}

これで、WAVEファイルの再生アプリの完成ですが、Visual C#2010を使用して開発した場合、デフォルトで.NetFramework4.0環境向けにビルドされますが、そのままでは、Managed DirectX.dllを含んだアプリケーションをビルド出来ませんでした。

解決方法として、app.configファイルに以下の一行を追加してビルド出来ました。

Form1.cs
1
<startup useLegacyV2RuntimeActivationPolicy="true" />

Comments