WAVEファイルの読込み/再生

WAVEファイルの読込み/再生に関するページです。

WAVEファイルのフォーマット例の紹介とC言語の例題を以下のように準備しました。

  • WAVEファイルのフォーマット例
  • WAVEフォーマットの読取
  • MCI(Media Control Interface)を利用したWAVEの再生
  • SoundPlay()関数によるWAVEの再生
  • WAVEの編集(ノイズの付加)・保存
  • 動画ファイル(AVI)中からWAVE音声(PCM)の抽出
  •  WAVEファイルのフォーマット例

    以下に示すフォーマットは簡易的なWAVEファイルのフォーマットですので、詳細は他のサイトを参考にして下さい(ex. The Programmer's File Format Collection, WAVE PCM soundfile format)。

    バイト数説明
    ヘッダ 
    4Bytes (DWORD)文字列"RIFF"(AVIと共通)
    4Bytes (DWORD)ファイルサイズ-8
     音声データ情報   WAVEFORMATEX (in mmsystem.h)
    4Bytes (DWORD)文字列"WAVE"(AVIの場合は"AVI ")
    4Bytes (DWORD)文字列"fmt "(最後は半角スペース)
    4Bytes (DWORD)音声データ情報のバイト数(PCM:16)
    2Bytes (WORD)フォーマットID(PCM:1) WORD wFormatTag
    2Bytes (WORD)チャンネル数(モノラル:1 ステレオ:2) WORD nChannels
    4Bytes (DWORD)サンプリング周波数(11025、22050、44100..) DWORD nSamplesPerSec
    4Bytes (DWORD)1秒あたりの音声データのバイト数(Byte/sec) DWORD nAvgBytesPerSec
    2Bytes (WORD)1サンプルあたりのバイト数(Byte/sample×チャンネル数) WORD nBlockAlign
    2Bytes (WORD)サンプルあたりのビット数(Bit/sample) WORD wBitsPerSample
    拡張部分 
    2Bytes (WORD)拡張部分のバイト数 = nWORD cbSize
    nBytes (DWORD)拡張データバイト
    音声データ 
    4Bytes (DWORD)文字列"data"
    4Bytes (DWORD)音声データのバイト数(mとします)
    mBytes音声データ(波形の変位のデータが順番に並びます。
    ステレオの場合はLRLRの順に並びます。8bitデータは
    0〜255, 16bitのデータは-32768〜+32767の範囲で値を
    とります。
    コメント 
    残りの部分コメント文字列

    WAVEファイルのダンプ例
    Gami[84]% dump ding.wav
    ding.wav:
    
      Addr     0 1  2 3  4 5  6 7  8 9  A B  C D  E F 0 2 4 6 8 A C E 
    --------  ---- ---- ---- ---- ---- ---- ---- ---- ----------------
    00000000  5249 4646 d03b 0100 5741 5645 666d 7420 RIFFP;..WAVEfmt 
    00000010  1000 0000 0100 0200 2256 0000 8858 0100 ........"V...X..
    00000020  0400 1000 6461 7461 7c3b 0100 f8ff 0100 ....data|;..x...
    00000030  ffff feff 0500 0200 0500 0300 0300 fdff ..~...........}.
    00000040  0100 0000 0200 faff ffff fdff fcff fbff ......z...}.|.{.
    00000050  fbff faff f9ff f9ff f9ff f9ff f4ff f9ff {.z.y.y.y.y.t.y.
    00000060  f8ff f7ff f5ff fbff f8ff fcff f7ff fdff x.w.u.{.x.|.w.}.
    00000070  fbff 0300 0000 0500 fdff 0100 0300 0b00 {.......}.......
    00000080  0500 0800 0700 0e00 0600 0a00 0900 0f00 ................
    00000090  0900 1000 0f00 1200 0700 0f00 0d00 1000 ................
    000000a0  0b00 1200 0a00 0e00 0a00 0c00 0900 0e00 ................
    000000b0  0700 0900 0500 0800 0600 0700 fcff 0000 ............|...
    000000c0  0400 0400 fbff fcff faff fdff fbff fcff ....{.|.z.}.{.|.
    000000d0  faff fcff faff fbff f9ff faff f5ff f6ff z.|.z.{.y.z.u.v.
    000000e0  f6ff f7ff f6ff f8ff f4ff f7ff fbff f9ff v.w.v.x.t.w.{.y.
    000000f0  f8ff fbff 0000 ffff f9ff faff 0800 0600 x.{.....y.z.....
    

     ヘッダ情報表示例

    Windows XPに標準で付属の(ding.wav)というファイルを読み込んで表示した様子です。

    Gami[948]% ./wave_info.exe ding.wav
    FILE: ding.wav
    **FILE HEAD
        FILE ID: RIFF
      FILE SIZE: 80[kByte]
    **WAVE FORMAT
      FORMAT ID: WAVE
    FORMAT TYPE: fmt
    FORMAT SIZE: 16
    **WAVE INFO.
       WAVE TAG: 1
        CHANNEL: 2
     SAMPLE/SEC: 22050
    BYTE/SAMPLE*CHANNEL: 4
     BIT/SAMPLE: 16
    **WAVE DATA INFO.
        DATA ID: data
      DATA SIZE: 80[kByte]
    Gami[949]%
    

     MCIを利用したWAVEの再生

    MCI(Media Control Interface)はWindows APIに付属のライブラリの中でマルチメディア関連の入出力を扱うものです。MCIを利用すると比較的簡単に音声・画像等を扱うことができます。

    下記のソースは、MCIを利用したWAVE再生の例です。 cygwin/gcc でのコンパイル時にはMCIを利用可能にするよう、"windows.h"と"mmsystem.h"のインクルードと、libwinmm.aへのリンクが必要になります。

    Gami[84]% gcc -o wav_p wav_p.c -lwinmm 
    

    MCIを利用したWAVE再生の例(wav_p.c)
    //-----------------------------------------------------------------
    // wav_p.cpp:
    //     MCIデバイスのWAVE再生の例
    //                  Last Update: <2005/01/27 04:07:20 A.Murakami>
    //-----------------------------------------------------------------
    #include <stdio.h>
    #include <windows.h>
    #include <mmsystem.h>
    //-----------------------------------------------------------------
    int InitMciDev(char* wav_file);
    void TermMciDev();
    int PlayMciDev();
    int MCILength();
    //-----------------------------------------------------------------
    int main()
    {
        int mLen;
        char wav_file[] = "samp.wav";
        // WAVの指定
        if(InitMciDev(wav_file)){
            fprintf(stderr,"MCIデバイスオープン失敗\n");
            return -1;
        }
        // 演奏時間の取得
        mLen = MCILength();
        if(mLen <= 0){
            fprintf(stderr,"演奏時間取得失敗\n");
        }
        // 演奏開始
        if(PlayMciDev()){
            fprintf(stderr,"再生にエラーが発生しました\n");
            return -1;
        }
        // 演奏時間の間停止。
        printf("**%s:\n",wav_file);
        printf("  演奏時間[%d]秒\n",mLen);
        if(!mLen) mLen+=5;
        sleep(mLen);
        printf("**演奏終了\n");
        // 終了
        TermMciDev();
        return 0;
    }
    //-----------------------------------------------------------------
    // MCIデバイスのオープン
    //-----------------------------------------------------------------
    int InitMciDev(char* wav_file)
    {
        char cmd[256];
        memset(cmd,0,sizeof(char)*256);
        sprintf(cmd,"open %s type waveaudio alias wav1",wav_file);
        return mciSendString(cmd,NULL,0,0);
    }
    //-----------------------------------------------------------------
    // MCIデバイスを閉じる
    //-----------------------------------------------------------------*/
    void TermMciDev()
    {
        mciSendString("stop wav1",NULL,0,0);
    }
    //-----------------------------------------------------------------
    // MCIデバイスを再生する
    //-----------------------------------------------------------------
    int PlayMciDev()
    {
        return mciSendString("play wav1",NULL,0,0);
    }
    //-----------------------------------------------------------------
    // 演奏時間の取得
    //-----------------------------------------------------------------
    int MCILength()
    {
        int ret;
        char status[30];
        mciSendString("set wav1 time format milliseconds",NULL,0,0);
        ret = mciSendString("status wav1 length",status,30,0);
        if(ret) return 0;
        return atoi(status)/1000;
    }
    
    inserted by FC2 system