スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

睡眠導入剤NISHIを服用の際は十分ご注意ください

そろそろ地元の人たちが「就職」という言葉を発するようになってきて不安な毎日です。
いろいろやってるそうで、こっちはといえばだんだんと暇になってきました。
ただ不安に感じるだけでどうこうしようという気は一切起きないからもうどうとでもなーれ。
やることがねぇよ、っと。だからこそこのような文章を書いている次第でございます。
このブログの更新頻度は私の感じる暇さ加減を表すバロメータのようなものなのだよ。


そんなどうでもいい話は置いといてだね、結局別のどうでもいい話をするのだけれど。

とりあえず魅惑の西ボイス「こんなものかっ(笑」をボリュームおよびピッチ変更して、
まるまるそのまま読み込んで再生することには成功した。つまるところ、あとはMSの用意した
コールバッククラスを継承して、別スレッドでストリーミングな読み込みをするだけ。
だけとはいってもそこがわからなかったから今まで放置していたのだけれどね。

XAudio2を使う上で最低限やることの流れをまとめると

1.XAudio2の本体を作る。
2.最終的な出力先であるマスターボイス、たぶんスピーカー的な位置づけの人を作る。
3.音声データそのものを読み込む。
4.個別の出力であるソースボイス、たぶん音声データから実際に音を作ってくれる人を作る。
5.ならす。

割と簡単。DirectSoundもだいたいこんな感じだったと思うが。

暇だし、いっこずつ見ていきましょうか。そういえば塾の子らはどっかしらには受かったのかしら。
フォローのしがたいお子さんがたくさんで、塾講師始めてからすこし今後の日本を心配しましたけど。

1.XAudio2の本体を作る。
   IXAudio2* pXAudio2 = NULL;
   XAudio2Create(&pXAudio2, 0);
   エラーチェックしなければ以上。

2.最終的な出力先であるマスターボイス、たぶんスピーカー的な位置づけの人を作る。
   IXAudio2MasteringVoice* pMasteringVoice = NULL;
   pXAudio2->CreateMasteringVoice(&pMasteringVoice)
   エラーチェックしなければ以上。

3.音声データそのものを読み込む。
    //mmioによるファイルハンドルみたいなものだと思う
    HMMIO hMmio = NULL;

    //RIFFファイル読み取りの際に必要な諸情報を格納する構造体
    MMIOINFO mmioInfo ={0};
    MMCKINFO riffChunk ={0};
    MMCKINFO formatChunk ={0};
    MMCKINFO dataChunk ={0};

    //読んで字のごとくWAVEファイルのフォーマット情報を格納する構造体
    WAVEFORMATEX wfx ={0};

    //データを格納するバッファ
    BYTE* pData;

    try{
        //ファイルオープン
        hMmio =mmioOpen(L"test.wav", &mmioInfo, MMIO_READ);
        if(!hMmio)
            throw "Waveファイルのオープンに失敗しました";

        //RIFFチャンク検索
        riffChunk.fccType =mmioFOURCC('W', 'A', 'V', 'E');
        if(mmioDescend(hMmio, &riffChunk, NULL, MMIO_FINDRIFF) != MMSYSERR_NOERROR)
            throw "RIFFチャンクの検索に失敗しました";

        //RIFFチャンクからfmtチャンクへ降りる
        formatChunk.ckid =mmioFOURCC('f', 'm', 't', ' ');
        if(mmioDescend(hMmio, &formatChunk, &riffChunk, MMIO_FINDCHUNK) != MMSYSERR_NOERROR)
            throw "fmtチャンクの検索に失敗しました";

        //fmtチャンクからWAVEフォーマットを読み取る
        if(mmioRead(hMmio, (HPSTR)&wfx, formatChunk.cksize) != formatChunk.cksize)
            throw "フォーマット読み取りに失敗しました";

        //RIFFチャンクへ上る
        mmioAscend(hMmio, &formatChunk, 0);

        //RIFFチャンクからデータチャンクへ降りる
        dataChunk.ckid =mmioFOURCC('d', 'a', 't', 'a');
        if(mmioDescend(hMmio, &dataChunk, &riffChunk, MMIO_FINDCHUNK) != MMSYSERR_NOERROR)
            throw "dataチャンクの検索に失敗しました";

        //波形データそのものを読み取り
        //Waveデータのサイズからまるまる全部入るだけのバッファを作成

        pData =new BYTE[dataChunk.cksize];
        if(mmioRead(hMmio, (HPSTR)pData, dataChunk.cksize) != dataChunk.cksize)
            throw "データの読み取りに失敗しました";

    }
    catch(char* error_str)
    {
        //ファイルを閉じる
        mmioClose(hMmio, 0);

        cout<< error_str <    }

    ああ長い。よくわからないけどWAVEの読み取り方はこうやるのがセオリーなんだろう、ググった結果。
    ここらへんに関してはWvaeAnalizerみたいなクラスにまとめちゃうのがいいのかもしれんから、
    そっち先に作るか。ぶっちゃけDirectXのサンプルについてるそんな感じのクラスを使ったほうが
    早いのかもしれないけど、なんだか何やってんだかよくわからないから性能悪くても自分で作る。
    だって、ひまだもの。


4.個別の出力であるソースボイス、たぶん音声データから実際に音を作ってくれる人を作る。
   IXAudio2SourceVoice* pSourceVoice = NULL;
   pXAudio2->CreateSourceVoice(&pSourceVoice, &wfx)
   エラーチェックしなければ以上。

5.ならす。
   pSourceVoice->Start();
   やったね!

DirectSoundと違ってWaveファイルの読み込みさえできれば、XAudio2に関する部分においては
10行程度で記述できると思われるし、使い勝手はそれなりに簡単になっている模様。
一応ループフラグを立てておくと延々と「こんなものか(笑」って言ってくれた。マジうざい。
再生したい生データをそのまんまキューに送ってやれば勝手に再生してくれるうえ、
コールバックを設定できるのでストリーミングの実装方法の理屈自体は理解しやすい。
よってこれから学ぶべきはマルチスレッド。別スレッドを作ることはそこまで難しくないしのんびりやるか。




スポンサーサイト
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。