Wave音源で音を鳴らす

ほとんどのPCにはWavePCM)音源が搭載され、サウンド機能を利用することが出来ます。今回は、自分でサウンドの波形データを作成し、それをwaveOutWrite()などを使ってWave音源で再生してみることにしましょう。

Wave音源の処理

 Wave音源で音を鳴らす手順は、以下のようになります。

  1. バッファを確保し、波形データを作成
  2. 音声形式を指定するWAVEFORMATEX構造体を作成
  3. waveOutOpen()Waveデバイスをオープン
  4. データバッファの情報をWAVEHDR構造体で設定
  5. waveOutPrepareHeader()で再生準備
  6. waveOutWrite()でバッファの波形データを再生
  7. 再生が終了したらwaveOutClose()でデバイスを閉じる
  8. waveOutUnprepareHeader()した後バッファを解放

 波形データは、数値の配列です。データ形式には8ビットと16ビットがあり、8ビットは0−255、16ビットは符号付のー32768〜32767までの値です。いずれも中央の値(128、0)が無音状態を表し、その上下は絶対値が波形の大きさになります。データの時間方向の解像度はサンプリング周波数の逆数ですから、例えばサンプリングレートが8KHzなら最初の値が0秒、2番目の値が1/8000秒後、3番目の値が2/8000秒後における波形の状態を表しています。今回は、サンプリング周波数を8KHzとし、以下のようにしてバッファlpBufに周期10(8KHzで再生した場合は、周期1/8000×10秒、周波数800Hz)/振幅64の矩形波を作ってみました。

  lpBuf=(LPBYTE)GlobalAlloc(GPTR,8000);

  for (i=0;i<8000;i++) {

      if ((i % 10)<5)
          lpBuf[i]=192;
      else
          lpBuf[i]=64;

  }

 波形データが出来たら、8ビットモノラル、サンプリング周波数8KHz用のWAVEFORMATEX構造体wfを設定します。

  wf.wFormatTag=WAVE_FORMAT_PCM;
  wf.nChannels=1;
  wf.nSamplesPerSec=8000;
  wf.nAvgBytesPerSec=8000;
  wf.nBlockAlign=1 ;
  wf.wBitsPerSample=8 ;
  wf.cbSize=0 ;

 続いてWaveデバイスをオープンし、デバイスの操作に必要なHWAVEOUT型ハンドルhWOutを取得します。

  waveOutOpen(&hWOut,WAVE_MAPPER,&wf,(DWORD)hwnd,0,CALLBACK_WINDOW);

 次はデータバッファの情報を格納するWAVEHDR型ヘッダ、whの設定

  wh.lpData=lpBuf;
  wh.dwBufferLength=8000;
  wh.dwBytesRecorded=0;
  wh.dwUser=0;
  wh.dwFlags=0;
  wh.dwLoops=1;
  wh.lpNext=NULL ;
  wh.reserved=0 ;

 ヘッダが出来たら、そのヘッダをwaveOutPrepareHeader()に渡してデータバッファ再生の準備をします。

  waveOutPrepareHeader(hWOut,&wh,sizeof(WAVEHDR));

 これで再生の準備が出来たので、後は再生するだけ。

  waveOutWrite(hWOut,&wh,sizeof(WAVEHDR));

 再生が終わったら、デバイスをクローズしてバッファを解放します。この手順は、まず再生が終わった時点でウインドウに送られてくるMM_WOM_DONEメッセージを捉えてデバイスをクローズし、デバイスがクローズされたら送られてくるMM_WOM_CLOSEメッセージでwaveOutUnprepareHeader()の後バッファを解放、という感じです。

  case MM_WOM_DONE:

      waveOutClose(hWOut);

      return 0 ;

  case MM_WOM_CLOSE:

      waveOutUnprepareHeader(hWOut,&wh,sizeof(WAVEHDR));

      GlobalFree(lpBuf);

      return 0;

プログラム

 実行すると800Hzの矩形波を1秒間再生します。中断処理は入れていないので、途中でプログラムを終了しないでください。ビルドする時には、winmm.libをリンクに追加する必要があります。

プログラムソース表示


プログラミング資料庫 > Windowsプログラミング研究室