Xamarin.Mac/効果音を再生する

提供: MonoBook
< Xamarin.Mac
2015年9月30日 (水) 14:30時点における126.213.4.201 (トーク)による版
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)
ナビゲーションに移動 検索に移動

Xamarin.Macで効果音を再生したい。

NSSoundを使う[編集 | ソースを編集]

NSSoundを使うと簡単に効果音を再生できる。

            var path = Path.Combine(NSBundle.MainBundle.BundlePath, "Contents", "Resources");
            var file = Path.Combine(path,"se001.mp3");

            var sound = new NSSound(file, byRef:false);

            sound.Play();

利点[編集 | ソースを編集]

MonoMacからXamarin.MacXamarin.iOSまでアップル系プラットフォームであれば新旧を問わず幅広く利用できる。

欠点[編集 | ソースを編集]

NSSoundはメインスレッドでしか使用できないという欠点を抱えている。 しかも画像系APIと異なり、メインスレッド以外で実行しても効果音の再生がされないだけでエラーにはならない。

これに気がつかずバグったときのデバッグで苦しむことになるかもしれない。

AVFoundationのAVAudioPlayerを使う[編集 | ソースを編集]

AVAudioPlayerを使用しても簡単に効果音を再生できる。 現状ではベストな方法ではないかと思われる。

            var path = Path.Combine(NSBundle.MainBundle.BundlePath, "Contents", "Resources");
            var file = Path.Combine(path,"se001.mp3");
            var url = new NSUrl(file, isDir: false);

            var player = AVAudioPlayer.FromUrl(url);

            player.PrepareToPlay();

            player.Play();

利点[編集 | ソースを編集]

AVAudioPlayerはアプリ外部の音声関連サービスに再生を依頼する方式であるため、メインスレッドでなくても問題なく使用できるという利点がある。 このため再生処理を以下のようにスレッドプールに逃がすことでメインスレッドが占有されることもなくなる。

            Task.Run( () => player.Play() );

また、PrepareToPlayメソッドで即時再生用にメモリに先読みしておくこともできるため初回再生が若干遅いということもない。

欠点[編集 | ソースを編集]

AVFoundationということで同APIのサポートが(実用レベルで)追加されたXamarin.Macの2015年中頃のバージョン以降に限定される。古いXamarin.Macを購入しバージョンアップしていない人やMonoMacの人は残念賞なようだ。なお、Xamarin.iOSもこの方法を利用できる。

共通[編集 | ソースを編集]

再生開始までのタイムラグを無くすため、音声再生に関するクラスインスタンスの生成はウインドウ初期化時(AwakeFromNibメソッド)などで行い、フィールド変数として保持しておくことが望ましい。

        AVAudioPlayer _player;

        public override void AwakeFromNib()
        {
            base.AwakeFromNib();

            var path = Path.Combine(NSBundle.MainBundle.BundlePath, "Contents", "Resources");
            var file = Path.Combine(path,"se-033a.mp3");
            var url = new NSUrl(file, isDir: false);

            _player = AVAudioPlayer.FromUrl(url);
            _player.PrepareToPlay();
        }


        public override void MouseDown(NSEvent theEvent)
        {
            Task.Run(() => _player.Play());
        }

連射音[編集 | ソースを編集]

AVAudioPlayerでは1インスタンス1音の再生となる。 複数のスレッドから一斉にPlayメソッドを叩いた場合は最初の再生が終わるまで全部無効となる。

そのような場合は高速化など糞食らえで複数のインスタンスを生成する。

        public override void MouseDown(NSEvent theEvent)
        {
            Task.Run(() => { 
                var path = Path.Combine(NSBundle.MainBundle.BundlePath, "Contents", "Resources");
                var file = Path.Combine(path,"se001.caf");
                var url = new NSUrl(file, isDir: false);

                var player = AVAudioPlayer.FromUrl(url);
                player.Play();
            });
            Console.WriteLine("click");
        }

注意点としては複数インスタンスでの同時再生はcafファイル(Apple CoreAudio フォーマット)に限られ、mp3ファイルなどは使用できない。 mp3ファイルなどからcafファイルへの変換はMac上のターミナルからafconvertコマンドでできる。

関連項目[編集 | ソースを編集]

参考文献[編集 | ソースを編集]