録音機能の実装(2/2)
フォーマットの設定
マイクから音声を取得するとき、サンプリング周波数やサンプルあたりのビット数などを指定します。ここでは表3のように指定します。
| 項目 | 指定する内容 |
| 圧縮形式 | 無圧縮 PCM |
| サンプリング周波数(Hz) | 8,000 |
| サンプルあたりのビット数 | 8 |
| チャンネル数 | 1(モノラル) |
まずオーディオキャプチャフィルタから出力ピンのインターフェイスIPinを取得します。次に、出力ピンからIAMStreamConfigを取得します。IAMStreamConfig::SetFormatでフォーマットを指定できます。
// (DshowRec.h に追加) HRESULT SetAudioOutProp(void) { IEnumPins *pEP=NULL; IPin *pPin = NULL; HRESULT hr=NOERROR; OUT_HR(m_pAudioCap->EnumPins(&pEP)); while(pEP->Next(1,&pPin,NULL)==S_OK) { PIN_INFO pInfo; hr=pPin->QueryPinInfo(&pInfo); if(FAILED(hr)) continue; OUT_MSG(pInfo.achName); if(wcsicmp(pInfo.achName,TEXT("Capture"))!=0) { SAFE_RELEASE(pPin); continue; } IAMStreamConfig *pConfig = NULL; hr=pPin->QueryInterface(IID_IAMStreamConfig, (void**)&pConfig); OUT_HR(hr); int count, size; hr=pConfig->GetNumberOfCapabilities(&count,&size); OUT_HR(hr); if(SUCCEEDED(hr) && size==sizeof(AUDIO_STREAM_CONFIG_CAPS)) { for(int i=0;i<count;i++){ AUDIO_STREAM_CONFIG_CAPS scc; AM_MEDIA_TYPE *pmtConfig=NULL; hr = pConfig->GetStreamCaps(i, &pmtConfig, (BYTE*)&scc); if(SUCCEEDED(hr) && pmtConfig->majortype==MEDIATYPE_Audio && pmtConfig->formattype == FORMAT_WaveFormatEx) { WAVEFORMATEX *pWfx= (WAVEFORMATEX *)pmtConfig->pbFormat; // 8Khz 8bit mono if(pWfx->wFormatTag==WAVE_FORMAT_PCM && pWfx->nSamplesPerSec==8000 && pWfx->wBitsPerSample==8 && pWfx->nChannels==1) { hr=pConfig->SetFormat(pmtConfig); OUT_HR(hr); if(SUCCEEDED(hr)) break; } } if (pmtConfig->cbFormat != 0) CoTaskMemFree((PVOID)pmtConfig->pbFormat); SAFE_RELEASE(pmtConfig->pUnk); } } SAFE_RELEASE(pConfig); SAFE_RELEASE(pPin); } SAFE_RELEASE(pEP); return S_OK; }
録音の開始・停止をする
CDshowRecクラスに録音の開始・停止を行うメソッドRec,Stop、さらに録音状態を取得するためのメソッドIsNowRecordingを追加します。
// (DshowRec.h に追加) bool IsNowRecording() { OAFilterState fs; OUT_HR(m_pMC->GetState(INFINITE, &fs)); if(fs==State_Running) return true; return false; } void Stop() { OUT_MSG(_T("Stop")); OUT_HR(m_pMC->Stop()); } void Rec() { OUT_MSG(_T("Rec")); OUT_HR(m_pMC->Run()); }
解放処理
解放処理を忘れずに書きます。
// (DshowRec.h に追加) void Release() { OUT_MSG(_T("Release")); this->Stop(); SAFE_RELEASE(m_pMC); SAFE_RELEASE(m_pFG); SAFE_RELEASE(m_pGB); SAFE_RELEASE(m_pAsfWriter); SAFE_RELEASE(m_pAudioCap); }
CDshowRecクラスのメソッドを呼び出す
CDshowRecクラスの実装が終わったので、「VRecorder.cpp」に、それらのメソッドを呼び出すコードを実装します。
まずCDshowRec::InitとCDshowRec::ReleaseをWinMain関数で呼び出して、初期化と解放を行います。
次にOnPushRecButtonに録音の開始・停止のコードを実装します。
// (グローバル変数として追加しておく) CDshowRec g_MyRec; // WinMain 関数で CDShowRec::Init と CDshowRec::Release を呼び出す int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { MSG msg; CoInitializeEx(NULL, COINIT_MULTITHREADED); // アプリケーションの初期化を実行します: if (!InitInstance(hInstance, nCmdShow)) { return FALSE; } g_MyRec.Init(); // (...中略...) g_MyRec.Release(); CoUninitialize(); return (int) msg.wParam; } // (...中略...) // 録音中であれば停止、そうでなければ録音開始 void OnPushRecButton() { MessageBeep(-1); if(g_MyRec.IsNowRecording()) { g_MyRec.Stop(); } else { g_MyRec.Rec(); } }
実行結果
無事にビルドを完了し、実機へ転送したら、画面上で[Rec]ボタンをタップすると録音が始まります。
もう一度ボタンをタップすると録音が停止します。
ファイルエクスプローラで出力されたファイルをタップすると、Windows Media Playerが起動して再生できます。
おわりに
DirectShowを使って、Advanced/W-ZERO3 [es]のマイクから音声を取得し、ASF形式でファイルに出力できました。本稿では必要最低限の機能しか実装しませんでしたが、出力先ファイル名を変更するなど読者の皆さんで機能追加してみてください。
