1st step to understand DirectShow (DirectShow入門 その1)

playing a wave file that was recorded using coded DirectShow and watching it on Jyaiko1.1 


    0.表題の 「DirectShow入門 その1」の 機械翻訳が、まずい

        これの機械翻訳は

            Introduction to DirectShow  No.1

         耐え難い....私は、そんな風に、奢った人間じゃ、ありません。

         せめて、表題くらい、正しく伝えて欲しいのです.......機械さん、お願い。

                   思い出したのですが、

         交信した YLさんに、おっさんが、'88'と、返すのは、変な気がします。

         '88' と返すのは、YL局だけです。 優しいお父さんは、つい、'88'と、応えてしまいますが、'73'で正しいと、思いますよ。

         もう、10数年前、アフリカの局と、cwで交信したとき、 '88'と、返ってきて、目の前が急に、パッと、明るく輝いたのを、思い出しました (^_^;;


    1.先ずは、見よう見まねで

     Japan MSDN のオーディオキャプチャグラフの作成のコードを、そのまま試す。
   
       最初に、骨格を作っておかねば、なりません。
i       
       int _tmain(int argc, _TCHAR* argv[])
        {

            CoInitialize(NULL);

            CoUninitialize();

        } 

        CoInitialze(NULL) と CoUninitialze()の間に、コードを埋めていくのです。

      int _tmain(int argc, _TCHAR* argv[])
        {

            CoInitialize(NULL);
 IBaseFilter *pSrc = NULL, *pWaveDest = NULL, *pWriter = NULL;
IFileSinkFilter *pSink= NULL;
IGraphBuilder *pGraph;
// フィルタ グラフ マネージャを作成する。
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
    IID_IGraphBuilder, (void**)&pGraph);

// 省略 : システム デバイス列挙子を使ってオーディオ キャプチャ
// フィルタを作成する。

// フィルタ グラフにオーディオ キャプチャ フィルタを追加する。
pGraph->AddFilter(pSrc, L"Capture");

// WavDest とファイル ライタを追加する。
AddFilterByCLSID(pGraph, CLSID_WavDest, L"WavDest", &pWavDest);
AddFilterByCLSID(pGraph, CLSID_FileWriter, L"File Writer", &pWriter);

// ファイル名を設定する。
pWriter->QueryInterface(IID_IFileSinkFilter, (void**)&pSink);
pSink->SetFileName(L"C:\\MyWavFile.wav", NULL);

// フィルタを接続する。
ConnectFilters(pGraph, pSrc, pWavDest);
ConnectFilters(pGraph, pWavDest, pWriter);

          CoUninitialize();

        } 

     AddFilterByCLSIDと、ConnectFilters は、このぺージを辿って、拾ってきます。

// 省略 : システム デバイス列挙子を使ってオーディオ キャプチャ
// フィルタを作成する。
     
     ここは、省略されているので、同ページのリンクから、列挙の例を拾ってきて、この部位に挿入します。

ICreateDevEnum *pSysDevEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
    IID_ICreateDevEnum, (void **)&pSysDevEnum);
if (FAILED(hr))
{
    return hr;
}


IEnumMoniker *pEnumCat = NULL;
hr = pSysDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEnumCat, 0);

if (hr == S_OK)
{
    // モニカを列挙する。
    IMoniker *pMoniker = NULL;
    ULONG cFetched;
   // while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
    if(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)//最初のデバイスを入力とする
    {
        IPropertyBag *pPropBag;
        hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
            (void **)&pPropBag);
        if (SUCCEEDED(hr))
        {
            // フィルタのフレンドリ名を取得するには、次の処理を行う。
            VARIANT varName;
            VariantInit(&varName);
            hr = pPropBag->Read(L"FriendlyName", &varName, 0);
            if (SUCCEEDED(hr))
            {
                // なんらかの方法で UI に名前を表示する。
    printf("%S\n",varName.pcVal);
            }
            VariantClear(&varName);

            // フィルタのインスタンスを作成するには、次の処理を行う。
          //  IBaseFilter *pFilter;
            hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,
                (void**)&pSrc);
            // ここでグラフにフィルタを追加する。
            // 後で忘れずに pFilter を解放すること。
            pPropBag->Release();
        }
        pMoniker->Release();
    }
    pEnumCat->Release();
}
pSysDevEnum->Release();

     build しても エラーがでます。

     エラー 5 error C2065: 'CLSID_WavDest' : 定義されていない識別子です。 

     この WavDestなんですが、これは、Samplesの中にありますから、

          buildして、レジストリーに登録しなければなりません。

     Windows SDK (以前のPlatform SDK から、こちらに移っています。)なら、

          solutionファイルがありますから、これをクリックして

     VisualStudioを立ち上げれば、buildできます。


     ここで、buildして出来た WavDest.dllを regSvr32で、レジストリーに登録しなければならなかったのか、

     buildだけで、レジストリーに登録されたのか、ちょっと忘れました。

     この登録されたWavDestを、oleview.exeで確かめて、appIDを控えておきましょう。

     これが、GUIDになります。



     んで、GUIDの定義を参考に、以下のコードを追加します。

/*typedef struct _GUID {  //guiddef.h
    unsigned long  Data1;
    unsigned short Data2;
    unsigned short Data3;
    unsigned char  Data4[ 8 ];
} GUID;
*/
//3C78B8E2-6C4D-11D1-ADE2-0000F8754B99

 GUID CLSID_WavDest={
  0x3C78B8E2, 0x6C4D, 0x11D1, 0xAD, 0xE2, 0x00, 0x00, 0xF8, 0x75, 0x4B, 0x99};

     これで、無事buildでき、起動します。

     あれっ? wavファイルが、出来ていません.....

     調べて見ました所、これは、設定ができただけの話で、何も作動していない事が原因でした。

     そんで、作動させる役割を持つのが、IMediaControlだ、そうですねん、抜かったわ (^_^;;

          で、以下のコードを追加しました。

    // MediaControlインターフェース取得
    IMediaControl *pMediaControl = NULL;
    pGraph->QueryInterface(IID_IMediaControl,(LPVOID *)&pMediaControl);
 
    // 録音開始
    pMediaControl->Run();

 ::getchar();
 

    // 録音終了
    pMediaControl->Stop();

    // 終了処理
    pMediaControl->Release();

    これで、出来ました! wavファイルが生成されました、うれぴー。

    最初の図は、出来上がったwavファイルを再生して、これを、Jyaiko1.1で聞いている所です。

    しかし、これは、44.1KHzsamplingですね....

    そんな訳で、defaultのsettingを、modifyして、48KHz,96KHz samplingに、しなければなりませんね。

    これを、今、調べています。


 2. 機械翻訳に怒る
  
     前々節 「Jyaiko1.1を3つのサウンドカードで試す」を、機械翻訳で見てみたら、

     意味が逆になってる.... 海外からも見てくれてはるのに....

     Edirol FA-66の所で、私は

         実に安定して、聞こえる。
         再起動しても、音声が割れる事はなかった。

     と、書いた。
     
     これが機械翻訳だと

        Very stable and sound. 
        Restart your voice is breaking things.

    再起動したら、'breaking things'  じゃ、ないでしょっ!反対に、stable なんですって。

    私の、broken English のほうが、ましやわ....

    
    H.20.2.21