SoundPlay()関数によるWAVEの再生

WAVE音声の再生にSoundPlay()関数を用いています。SoundPlay()関数はmmsystem.h 内に定義されており、そのためのライブラリ(winmm.lib)を追加して下さい。

コンパイル例:
Gami[84]% gcc -o soundplay soundplay.cpp -lwinmm

SoundPlay()関数によるWAVEの再生(soundplay.cpp)
//-----------------------------------------------------------------
// soundplay.cpp:
//      WAVE ファイルの再生
//               Last Update: <2005/06/16 19:42:37 A.Murakami>
//-----------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <mmsystem.h>
//-----------------------------------------------------------------
struct WAVE_HEADER {
    DWORD fileID,fileSize;
    DWORD fmtID,fmt_type,fmtSize;
    WAVEFORMATEX wfx;
    DWORD dataID,dataSize;
};
static char chunk_id[12][5] = { // chunk types
    "data","fact","cue ","plst","list","adtl",
    "labl","note","ltxt","smpl","inst","\0"};
//-----------------------------------------------------------------
void err_exit(char* str);
void read_waveheader(FILE** fp,WAVE_HEADER* whdr);
void play_wave(FILE** fp,WAVE_HEADER whdr);
char* swrite(char* fp,char* su,int n);
char* nwrite(char* fp,int v,int n);
void set_wavefmt(char* pfmt,WAVEFORMATEX wfx);
void set_wavelen(char* pfmt,DWORD lLength);
void disp_waveheader(char* ifile,WAVE_HEADER whdr);
//-----------------------------------------------------------------
int main(int argc,char* argv[])
{
    FILE* fp;
    char *ifile,buf[256];
    WAVE_HEADER whdr;
    // ファイル名
    if(argc >= 2) ifile = argv[1];
    else err_exit("Insufficient argument.\n");
    // 読込み開始
    fp = fopen(ifile,"rb");
    if(fp==NULL) err_exit("input file cannot open.\n");
    // ヘッダ情報の読み込み
    read_waveheader(&fp,&whdr);
    disp_waveheader(ifile,whdr);
    //
    // 再生開始
    play_wave(&fp,whdr);
    // 後片付け
    fclose(fp);
    return 0;
}

void err_exit(char* str)
{
    fprintf(stderr,str);
    exit(0);
}

void read_waveheader(FILE** fp,WAVE_HEADER* whdr)
{
    int i,find,idck=TRUE,fpos;
    DWORD drTmp; WORD cbsize;
    // file head
    fread(&whdr->fileID  ,sizeof(DWORD),1,*fp);
    fread(&whdr->fileSize,sizeof(DWORD),1,*fp);
    // fmt head
    fread(&whdr->fmtID   ,sizeof(DWORD),1,*fp);
    fread(&whdr->fmt_type,sizeof(DWORD),1,*fp);
    fread(&whdr->fmtSize ,sizeof(DWORD),1,*fp);
    fread(&whdr->wfx     ,sizeof(WAVEFORMATEX)-sizeof(WORD),1,*fp);
    // check chunk info.
    whdr->dataID   = 0;
    whdr->dataSize = 0;
    whdr->wfx.cbSize = 0;
    fseek(*fp,-2,SEEK_CUR);
    while(idck){
        if(ftell(*fp) > whdr->fileSize) break;
        fread(&drTmp,sizeof(DWORD),1,*fp);
        find = FALSE;
        for(i=0;;i++){
            if(chunk_id[i][0] == '\0') break;
            if(drTmp == mmioFOURCC('d','a','t','a')){
                whdr->dataID = drTmp;
                fread(&whdr->dataSize,sizeof(DWORD),1,*fp);
                find = TRUE;
                idck = FALSE;
                break;
            } else {
                if(drTmp == mmioFOURCC(chunk_id[i][0],chunk_id[i][1],
                                       chunk_id[i][2],chunk_id[i][3])){
                    find = TRUE;
                    fread(&drTmp,sizeof(DWORD),1,*fp);
                    fseek(*fp,ftell(*fp)+drTmp,SEEK_SET);
                    break;
                }
            }
        }
        if(!find) fseek(*fp,ftell(*fp)-(sizeof(DWORD)-1),SEEK_SET);
    }
}

void play_wave(FILE** fp,WAVE_HEADER whdr)
{
    WAVEFORMATEX* f = &whdr.wfx;
    int rc,fmtLen,i_flame,n_flame;
    int block_size = (f->nChannels*f->nSamplesPerSec*f->wBitsPerSample/8/
                      f->nBlockAlign) * f->nBlockAlign;
    char *pfmt,*pbuf,*wav;
    // 再生用WAVEフォーマットの設定
    f->wFormatTag = WAVE_FORMAT_PCM;
    fmtLen = sizeof(DWORD)*7+sizeof(WAVEFORMATEX)-sizeof(WORD);
    pfmt = (char*)malloc(fmtLen);
    wav  = (char*)malloc(block_size);
    pbuf = (char*)malloc(fmtLen+block_size);
    set_wavefmt(pfmt,*f);
    set_wavelen(pfmt,block_size);
    memcpy(pbuf,pfmt,fmtLen);
    // 読込み/再生
    i_flame = 0;
    n_flame = whdr.dataSize/block_size;
    fprintf(stdout,"\nFrame: %4d/%4d",i_flame,n_flame);
    fflush(stdout);
    while(1){
        rc = fread(wav,1,block_size,*fp);
        set_wavelen(pfmt,rc);
        memcpy(pbuf,pfmt,fmtLen);
        memcpy(pbuf+fmtLen,wav,rc);
        // play sound
        PlaySound((char*)pbuf,NULL,SND_MEMORY|SND_SYNC);
        fprintf(stdout,"\rFrame: %4d/%4d",++i_flame,n_flame);
        fflush(stdout);
        if(rc != block_size) break;
    }
    fputs("\n",stdout); fflush(stdout);
    free(pfmt);
    free(wav);
    free(pbuf);
}

//-----------------------------------------------------------------
// 多バイト列の設定
//-----------------------------------------------------------------
char* swrite(char* fp,char* su,int n)
{
    for(int i=0;i<n;i++,su++,fp++) *fp = *su;
    return fp;
}
char* nwrite(char* fp,int v,int n)
{
    for(int i=0;i<n;i++,fp++) *fp = (v>>8*i) & 0xff;
    return fp;
}
//-----------------------------------------------------------------
// WAVE format の設定
//-----------------------------------------------------------------
void set_wavefmt(char* pfmt,WAVEFORMATEX wfx)
{
    DWORD dwTmp,fmtlen=sizeof(WAVEFORMATEX)-sizeof(WORD);
    char* p= pfmt;
    dwTmp = mmioFOURCC('R','I','F','F');
    p = nwrite(p,dwTmp,sizeof(DWORD));
    p = nwrite(p,0,sizeof(DWORD));
    dwTmp = mmioFOURCC('W','A','V','E');
    p = nwrite(p,dwTmp,sizeof(DWORD));
    dwTmp = mmioFOURCC('f','m','t',' ');
    p = nwrite(p,dwTmp,sizeof(DWORD));
    p = nwrite(p,fmtlen,sizeof(DWORD));
    p = swrite(p,(char*)&wfx,fmtlen);
    dwTmp = mmioFOURCC('d','a','t','a');
    p = nwrite(p,dwTmp,sizeof(DWORD));
    p = nwrite(p,0,sizeof(DWORD));
}
void set_wavelen(char* pfmt,DWORD lLength)
{
    DWORD dwlen;
    char* p=pfmt+sizeof(DWORD);
    dwlen = sizeof(DWORD)*5+sizeof(WAVEFORMATEX)-sizeof(WORD)+lLength;
    p = nwrite(p,dwlen,sizeof(DWORD));
    p = pfmt+sizeof(DWORD)*6+sizeof(WAVEFORMATEX)-sizeof(WORD);
    p = nwrite(p,lLength,sizeof(DWORD));
}

//-----------------------------------------------------------------
// WAVE format の表示
//-----------------------------------------------------------------
void disp_waveheader(char* ifile,WAVE_HEADER whdr)
{
    char tag[5]; tag[4] = 0;
    printf("FILE: %s\n",ifile);
    printf("**FILE HEAD\n");
    memcpy(tag,&whdr.fileID,sizeof(DWORD));
    printf("    FILE ID: %s\n",tag);
    printf("  FILE SIZE: %ld[Byte]\n",whdr.fileSize);
    printf("**WAVE FORMAT\n");
    memcpy(tag,&whdr.fmtID,sizeof(DWORD));
    printf("  FORMAT ID: %s\n",tag);
    memcpy(tag,&whdr.fmt_type,sizeof(DWORD));
    printf("FORMAT TYPE: %s\n",tag);
    printf("FORMAT SIZE: %ld\n",whdr.fmtSize);
    printf("**WAVE INFO.\n");
    printf("   WAVE TAG: %d\n",whdr.wfx.wFormatTag);
    printf("    CHANNEL: %d\n",whdr.wfx.nChannels);
    printf(" SAMPLE/SEC: %ld\n",whdr.wfx.nSamplesPerSec);
    printf("BYTE/SAMPLE*CHANNEL: %d\n",whdr.wfx.nBlockAlign);
    printf(" BIT/SAMPLE: %d\n",whdr.wfx.wBitsPerSample);
    if(whdr.wfx.cbSize){
        printf("EXTRA FORMAT SIZE: %d\n",whdr.wfx.cbSize);
    }
    printf("**WAVE DATA INFO.\n");
    if(whdr.dataID){
        memcpy(tag,&whdr.dataID,sizeof(DWORD));
        printf("    DATA ID: %s\n",tag);
    } else {
        printf("    DATA ID: null\n");
    }
    printf("  DATA SIZE: %ld[Byte]\n",whdr.dataSize);
}
inserted by FC2 system