動画ファイル(AVI)中からWAVE音声(PCM)を抽出しファイル保存する例題です。AVIのコーデックに対する対応等は今回は無しということで。。
Video for Windows(VFW)を利用してAVI中の音声データにアクセスしているため、そのための準備が必要です。ヘッダファイルには(windows.h, vfw.h)を追加し、libvfw_avi32.a を追加してください。また、再生中にPlaySound()関数により音声を出力するようにしているため、mmsystem.h, libwinmm.a も追加して下さい(mmsystem.h は vfw.h 中に記載済み)。
コンパイル例:(-fvtable-thunks はgccでのコンパイル時に必要になるみたいです。。)
Gami[84]% gcc -o aviwave aviwave.cpp -lwinmm -lvfw_avi32 -fvtable-thunks |
//----------------------------------------------------------------- // aviwave.cpp: // 動画ファイル(AVI)中からWAVE音声(PCM)の抽出 // Last Update: <2005/01/27 04:12:21 A.Murakami> //----------------------------------------------------------------- #include <stdio.h> #include <stdlib.h> #include <windows.h> #include <vfw.h> //----------------------------------------------------------------- // for VC++ #pragma comment(lib,"winmm") #pragma comment(lib,"vfw32") //----------------------------------------------------------------- #define WAVBUFFER 4096 #define AVIFILE "sample.avi" //----------------------------------------------------------------- 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); //----------------------------------------------------------------- int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, LPSTR lpszCmdLine,int nCmdShow) { AVICOMPRESSOPTIONS opt; PAVISTREAM pstm,ptmp; WAVEFORMATEX wfx; FILE *fp; DWORD dwSize=0,fmtLen,dwTmp; LONG i,lStart,lEnd,lLength,lSample; LPBYTE p,pp; char *pbuf,*pfmt,*avifile; if(strlen(lpszCmdLine)) avifile = lpszCmdLine; else avifile = AVIFILE; //-------------------------------------------------- // read AVI //-------------------------------------------------- AVIFileInit(); if(AVIStreamOpenFromFile(&pstm,avifile,streamtypeAUDIO,0, OF_READ | OF_SHARE_DENY_NONE,NULL)!=0) return 0; if(AVIStreamReadFormat(pstm,lStart,NULL,&lLength)!=0) return 0; if((p=(LPBYTE)malloc(lLength))==NULL) return 0; if(AVIStreamReadFormat(pstm,lStart,p,&lLength)!=0) return 0; //-------------------------------------------------- // set wave format //-------------------------------------------------- wfx=*(LPWAVEFORMATEX)p; wfx.wFormatTag = WAVE_FORMAT_PCM; wfx.wBitsPerSample = wfx.wBitsPerSample<12?8:16; wfx.nBlockAlign = wfx.nChannels*wfx.wBitsPerSample/8; wfx.nAvgBytesPerSec = wfx.nSamplesPerSec*wfx.nBlockAlign; wfx.cbSize = 0; pbuf = (char*)malloc(sizeof(wfx)); //-------------------------------------------------- // set compression //-------------------------------------------------- memset(&opt,0,sizeof(AVICOMPRESSOPTIONS)); opt.fccType = streamtypeAUDIO; opt.lpFormat = &wfx; opt.cbFormat = sizeof(WAVEFORMATEX)-sizeof(WORD); if(AVIMakeCompressedStream(&ptmp,pstm,&opt,NULL)!=AVIERR_OK){ fprintf(stderr,"avi make compress\n"); return 0; } lStart = AVIStreamStart(ptmp); lEnd = lStart+AVIStreamLength(ptmp)-1; //-------------------------------------------------- // write wave format //-------------------------------------------------- if((fp=fopen("wavout.wav","wb"))==NULL){ fprintf(stderr,"wave open\n"); return 0; } fmtLen = sizeof(DWORD)*7+opt.cbFormat; pfmt = (char*)malloc(fmtLen); set_wavefmt(pfmt,wfx); fwrite(pfmt,fmtLen,1,fp); //-------------------------------------------------- // read wave //-------------------------------------------------- for(i=lStart;i<=lEnd;i+=lSample) { if(AVIStreamRead( ptmp,i,AVISTREAMREAD_CONVENIENT,NULL,0,&lLength,&lSample)!=0) return 0; if((lLength<=0 || lSample<=0) && AVIStreamRead(ptmp,i,WAVBUFFER,NULL,0,&lLength,&lSample)!=0) return 0; if((p=(LPBYTE)realloc(p,lLength))==NULL) return 0; if(AVIStreamRead(ptmp,i,lSample,p,lLength,&lLength,&lSample)!=0) return 0; if(fwrite(p,lLength,1,fp)!=1) return 0; // set wave sound pbuf = (char*)realloc(pbuf,fmtLen+lLength); memset(pbuf,0,fmtLen+lLength); set_wavelen(pfmt,lLength); memcpy(pbuf,pfmt,fmtLen); memcpy(pbuf+fmtLen,p,lLength); // play sound PlaySound((char*)pbuf,NULL,SND_MEMORY|SND_SYNC); dwSize+=lLength; } //-------------------------------------------------- // write wave size //-------------------------------------------------- fseek(fp,-(LONG)(dwSize+sizeof(DWORD)),SEEK_END); fwrite(&dwSize,sizeof(DWORD),1,fp); fseek(fp,sizeof(DWORD),SEEK_SET); dwSize+=sizeof(DWORD)*5+opt.cbFormat; fwrite(&dwSize,sizeof(DWORD),1,fp); fclose(fp); // clean up free(pfmt); free(p); free(pbuf); AVIStreamRelease(ptmp); AVIStreamRelease(pstm); AVIFileExit(); return 0; } //----------------------------------------------------------------- // 多バイト列の設定 //----------------------------------------------------------------- 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)); } |