SHOEISHA iD

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

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

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

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

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

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

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

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

 DirectShowを使う準備ができたら、いよいよ肝となる録音機能を実装していきます。

DirectShowの概要

 DirectShowでは「フィルタ」と呼ばれるコンポーネットを繋ぐことにより映像や音声を処理します。フィルタには1つ以上の「ピン」と呼ばれるフィルタ同士の接続ポイントがあります。ピンには「入力ピン」と「出力ピン」があり、データは出力ピンから入力ピンに向かって流れます。

 フィルタを繋いでいくと、いわゆる有向グラフとなります。これを「フィルタグラフ」と呼びます。

フィルタとフィルタグラフ
フィルタとフィルタグラフ

 DirectShowにはさまざまな機能を持ったフィルタが用意されています(もちろん自分で作ることもできます)。開発者は目的に合わせてフィルタを選択し、フィルタグラフを構築します。本稿で構築するフィルタグラフのイメージを下図に示します。

構築するフィルタグラフのイメージ
構築するフィルタグラフのイメージ

フィルタグラフを構築する準備をする

 フィルタグラフを構築するために、表1に示すインターフェイスを取得します。これらはCOMのAPIである、CoCreateInstanceを使って作成します。

表1. 作成するCOMクラス
名称 フィルタグラフ キャプチャグラフビルダ
クラス ID CLSID_FilterGraph CLSID_CaptureGraphBuilder
インターフェイス ID IID_IGraphBuilder IID_ICaptureGraphBuilder2
IGraphBuilder ICaptureGraphBuilder2
役割 フィルタグラフを構築する。
フィルタ同士を接続する。
フィルタ同士の接続を容易にする。

 さらに、フィルタグラフ制御用にIGraphBuilderからIMediaControlインターフェイスをIUnknown::QueryInterfaceを使って取得します。

 まずはここまで実装してみます。フィルタグラフを制御するクラスをCDshowRecクラスとして「DshowRec.h」に実装します。「stdafx.h」に#include "DshowRec.h"を追加します。

DshowRec.h
#pragma once

#define SAFE_RELEASE(p) { if((p)!=NULL) { (p)->Release(); (p)=NULL; }}

// DirectShow による WMA の音声レコーダクラス
class CDshowRec {
    ICaptureGraphBuilder2 *m_pGB;
    IGraphBuilder *m_pFG;
    IMediaControl *m_pMC;
    IBaseFilter *m_pAudioCap;
    IBaseFilter *m_pAsfWriter;
public:
    CDshowRec() :
        m_pGB(NULL), m_pFG(NULL), m_pMC(NULL),
        m_pAudioCap(NULL), m_pAsfWriter(NULL)
    {
    }
    void Init() {
        OUT_MSG(_T("Init"));
        OUT_HR(CoCreateInstance(CLSID_CaptureGraphBuilder,
            NULL, CLSCTX_INPROC, IID_ICaptureGraphBuilder2,
            (void **)&m_pGB));
        OUT_HR(CoCreateInstance(CLSID_FilterGraph, NULL,
            CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pFG));
        OUT_HR(m_pGB->SetFiltergraph(m_pFG));
        OUT_HR(m_pFG->QueryInterface(IID_IMediaControl, (void**)&m_pMC));
// ( ... 続く)

フィルタを作成し、フィルタグラフへ追加する

 CoCreateInstanceを使ってフィルタを作成し、フィルタグラフへ追加します。作成するフィルタを表2に挙げます。

表2. 作成するフィルタ
名称 オーディオキャプチャフィルタ WM ASF ライタ
クラス ID CLSID_AudioCapture CLSID_ASFWriter
インターフェイス ID IID_IBaseFilter IID_IBaseFilter
IBaseFilter IBaseFilter
役割 音声をキャプチャする。 ASF 形式でファイルに出力。

 オーディオキャプチャフィルタは、マイクから音声を取得するフィルタです。オーディオキャプチャフィルタを追加する前にIPersistPropertyBagインターフェイスを取得し、IPersistPropertyBag::Loadを呼び出しておきます。

 WM ASFライタフィルタは、ASF形式でファイルに出力するフィルタです。IFileSinkFilterインターフェイスを取得し、IFileSinkFilter::SetFileNameでファイル名を指定します。指定されたファイル名でASF形式のファイルが出力されます。

 オーディオキャプチャフィルタとWM ASFライタをICaptureGraphBuilder2::RenderStreamを使って接続します。

DshowRec.h
// (CDshowRec::Init の続き)
    // AudioCapture フィルタの初期化
    OUT_HR(CoCreateInstance(CLSID_AudioCapture, NULL,
        CLSCTX_INPROC, IID_IBaseFilter, (void **)&m_pAudioCap));
    IPersistPropertyBag *pPSBag=NULL;
    OUT_HR(m_pAudioCap->QueryInterface(IID_IPersistPropertyBag,
        (void**)&pPSBag));
    OUT_HR(pPSBag->Load(NULL, NULL));
    SAFE_RELEASE(pPSBag);
    // ASF ライタ フィルタの追加と出力ファイル名の設定
    OUT_HR(CoCreateInstance(CLSID_ASFWriter, NULL, CLSCTX_INPROC,
        IID_IBaseFilter, (void **)&m_pAsfWriter));
    IFileSinkFilter *pSink=NULL;
    OUT_HR(m_pAsfWriter->QueryInterface(IID_IFileSinkFilter,
        (void**)&pSink));
    OUT_HR(pSink->SetFileName(
        L"\\My Documents\\my_voice_memo.asf", NULL));
    SAFE_RELEASE(pSink);
    // フィルタをフィルタグラフへ追加し、接続する
    OUT_HR(m_pFG->AddFilter(m_pAudioCap,_T("")));
    OUT_HR(m_pFG->AddFilter(m_pAsfWriter,_T("")));
    SetAudioOutProp(); // あとで実装する
    OUT_HR(m_pGB->RenderStream(&PIN_CATEGORY_CAPTURE,
        &MEDIATYPE_Audio, m_pAudioCap, NULL, m_pAsfWriter));
}

次のページ
録音機能の実装(2/2)

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

Advanced/W-ZERO3 [es]で作ろう連載記事一覧

もっと読む

この記事の著者

syu5()

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

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

この記事をシェア

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

イベント

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

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

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

メールバックナンバー