2008年11月14日

プログラム主体のSilverlightの勉強 その7 効果音再生

効果音も基本的にはBGMと同じで、MediaElementを使います。(Silverlight5以降はXNAのサウンド機能の方がいいかもしれません)

ただし、常に1つの曲が流れているBGMとは違い、効果音は同時にいくつ鳴るのか実行時にならないと分からないので、画面構成用のXAMLに静的に登録してしまうのではなく、動的にMediaElementオブジェクトを作成します。(使用する効果音が非常に少なかったり同じ音が同時に複数鳴らなければ静的に登録する手も有り)

まずはPage.xamlに効果音を登録するための入れ物となるCanvasを作ります。効果音は実行時に頻繁に追加/削除を繰り返すので、効果音専用にCanvasを用意すると便利です。

<UserControl x:Class="SoundTest.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Width="400" Height="300">
    <Canvas x:Name="LayoutRoot" Background="White">
        <Canvas x:Name="SpriteCanvas"/>
        <Canvas x:Name="SoundCanvas"/>
        <MediaElement x:Name="Music"/>
    </Canvas>
</UserControl>

UserControlは子要素としてコントロールを1つしか持てないので、まずは全体の入れ物となるCanvas(LayoutRoot)を作って、その中にスプライト用Canvas、サウンド用Canvas…と入れ子にします。

効果音に使うファイルは、リソースとして埋め込む方法やWebサイトにxapと一緒に置いて実行時にダウンロードさせる方法があります。ここでは実装が簡単なリソースに埋め込む方法を使います。

まず、プロジェクトに効果音として使いたいmp3(またはwma)を登録します。登録したファイルは、ソリューションエクスプローラで「ビルドアクション」を「埋め込まれたリソース」にします。(XAMLに直接MediaElementを書く場合は「埋め込まれたリソース」では駄目で「Resource」にする理由がよく分かっていません)

リソースとして埋め込んだmp3は、GetManifestResourceStreamで読み込みます。

public partial class Page : UserControl
{
    Stream Sound;
    void Page_Loaded(object sender, RoutedEventArgs e)
    {
        System.Reflection.Assembly asm = this.GetType().Assembly;
        Sound = asm.GetManifestResourceStream("SoundTest.Resources.sound.mp3");
    }

GetManifestResourceStreamに指定するリソース名は、名前空間からフルネームで指定します。大文字と小文字は区別され、フォルダの区切りは.(ピリオド)を使用します。この例ではSoundTestプロジェクトにResourcesフォルダを作って、その中にsound.mp3を入れています。

音を鳴らすときは、MediaElementオブジェクトを作成し、先ほど取得したStreamをソースに指定してPlayメソッドを呼びます。

    private void PlaySound()
    {
        MediaElement me = new MediaElement();
        me.SetSource(Sound);
        me.MediaEnded += new RoutedEventHandler(me_MediaEnded);
        SoundCanvas.Children.Add(me);
        me.Play();
    }

    void me_MediaEnded(object sender, RoutedEventArgs e)
    {
        MediaElement me = sender as MediaElement;
        SoundCanvas.Children.Remove(me);
    }

実はMediaElementはビジュアルツリーに登録しなくても、オブジェクトの参照を保持してさえいれば、音声は再生されます。しかし、ビジュアルツリーに登録しないと、再生が終わってもMediaEndedイベントが発生しないようです。

私の環境では、SoundCanvas.Children.Countが120を超えたあたりでエラーが発生しました。正確に数えた人によると、123まではOKで124個目でエラーが発生したそうです。ドキュメントにはMediaElementが100を超えるようなら制限を設けるように書いてあるだけなので、この限界値が環境依存なのかは不明です。

タグ:Silverlight
2008年11月14日 【プログラミング】 | コメント(0) |

この記事へのトラックバック

MediaElementをXAMLに記述しないでコードから呼ぼうとしてハマりました。検索しても情報が錯綜しています。 id:beta_magnus:20090625 : SilverlightのMe..
この記事へのコメント

コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。