忍者ブログ

Memeplexes

プログラミング、3DCGとその他いろいろについて

XNAで音を合成 DynamicSoundEffectInstanceクラス

突然ですが、 XNA4.0では自在に音を合成できるクラスが用意されているようです。
自在に合成とは一体何を言っているのかというと、こういうことです。

これまでXNAではたしか予め録音された音しか再生できなかったと思います。
ものが爆発した音なら爆発音を最初からファイルに保存しておいてそれを必要なときに再生するという形でした。
しかし新しいMicrosoft.Xna.Framework.Audio.DynamicSoundEffectInstanceクラスはちがいます。
波形データをリアルタイムで作って、それを再生できるのです。

もしかすると物理世界をシミュレートして、その結果として音を鳴らすというようなことが出来るかもしれませんね。
先程の例で言うと爆発時の空気の振動を計算してそれを使えるかもしれませんん。
あるいは音声の合成とかゲームとは別のベクトルで面白そうです。

ではやってみましょう。

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;

namespace XnaDynamicAudio
{
    static class Program
    {
        static void Main(string[] args)
        {
            const int samplePerSecond = 8000;
            const int secondsToPlay = 3;

            using (DynamicSoundEffectInstance dynamicSound = new DynamicSoundEffectInstance(samplePerSecond, AudioChannels.Mono))
            {
                byte[] buffer = createAWave(samplePerSecond, secondsToPlay, 440);
                dynamicSound.SubmitBuffer(buffer);
                FrameworkDispatcher.Update();
                dynamicSound.Play();
                System.Threading.Thread.Sleep(secondsToPlay * 1000);
            }
        }

        private static byte[] createAWave(int samplePerSecond, int secondsToPlay, int heltz)
        {
            byte[] buffer = new byte[samplePerSecond * secondsToPlay];

            for (int i = 0; i < buffer.Length; i++)
            {
                buffer[i] = (byte)(
                    byte.MaxValue / 4 * (1 + Math.Sin((Math.PI * heltz) * i / samplePerSecond))
                    );
            }

            return buffer;
        }
    }
}



このサンプルプログラムを実行すると、ピーという音が鳴ります。
440Hzのサイン波。
つまり、ラの音です。


クラス

このサンプルプログラムに登場した重要なクラスは2つ有ります。
DynamicSoundEffectInstanceクラスとFrameworkDispatcherクラスです。

DynamicSoundEffectInstanceはダイナミックな再生を司るクラスだからいいとして、FrameworkDispatcherとはなんでしょう?
これはXNAで使うコンポーネントを管理するらしく、普段は内部で呼ばれているようです。

が、今回のプログラムのように、「XNAは使うけれどGameは使わないよ」というような場合にはFrameworkDispatcher.Updateメソッドを自分で呼ばなければならないのです。
これは1フレームに一回の呼び出しが推奨されています

拍手[2回]

PR