SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Advanced/W-ZERO3 [es]で作ろう

Advanced/W-ZERO3 [es]で簡易音声レコーダを作ろう

DirectShowを使ったWindows Mobileアプリケーションの構築例

ダウンロード ソースコード (21.3 KB)

録音機能の実装(2/2)

フォーマットの設定

 マイクから音声を取得するとき、サンプリング周波数やサンプルあたりのビット数などを指定します。ここでは表3のように指定します。

表3. フォーマット
項目 指定する内容
圧縮形式 無圧縮 PCM
サンプリング周波数(Hz) 8,000
サンプルあたりのビット数 8
チャンネル数 1(モノラル)

 まずオーディオキャプチャフィルタから出力ピンのインターフェイスIPinを取得します。次に、出力ピンからIAMStreamConfigを取得します。IAMStreamConfig::SetFormatでフォーマットを指定できます。

DshowRec.h
// (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
// (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
// (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::InitCDshowRec::ReleaseWinMain関数で呼び出して、初期化と解放を行います。

 次にOnPushRecButtonに録音の開始・停止のコードを実装します。

VRecorder.cpp
// (グローバル変数として追加しておく)
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形式でファイルに出力できました。本稿では必要最低限の機能しか実装しませんでしたが、出力先ファイル名を変更するなど読者の皆さんで機能追加してみてください。

参考文献

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
Advanced/W-ZERO3 [es]で作ろう連載記事一覧

もっと読む

この記事の著者

syu5()

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/1808 2008/08/26 13:59

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー