Date

Scope サンプルは、オーディオを入力し、波形をウィンドウに表示するレンダラーフィルタである。Platform SDKにサンプルプログラムとして付属している。正式なフィルタ名は Oscilloscope である。フィルタのインスタンスを作成すると以下のようなウィンドウが表示される。

ところで、このフィルタは8bit/16bitのmono/stereoの無圧縮PCM形式に対応しているが、それより高解像度のデータには対応していない。ここでは 24bit PCMを受け付けるように改造する方法を紹介しする。オーディオフォーマットを表す構造体はWAVEFORMATEXではなくWAVEFORMATEXTENSIBLEとする。

CheckMediaType

scope.cppのCScopeInputPin::CheckMediaTypeで、入力メディアタイプを検査している。WAVEFORMATEXTENSIBLE構造体の場合は、無圧縮PCMであってもWAVEFORMATEX::wFormatTagWAVE_FORMAT_PCM(==0x1)ではなくWAVE_FORMAT_EXTENSIBLE(==0xFFFE)となる。そこでwFormatTagの検査コードを以下のように変更する。

1
2
3
4
5
//変更
    pwfx->Format.wFormatTag != WAVE_FORMAT_PCM)
{
    return E_INVALIDARG;
}

SetMediaType

CScopeInputPin::SetMediaTypeWAVEFORMATEXTENSIBLEにあうように書き換える。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class
HRESULT hr = CBaseInputPin::SetMediaType(pmt);
if(SUCCEEDED(hr))
{
    //以下、変更
    WAVEFORMATEXTENSIBLE *pwfx=
        (WAVEFORMATEXTENSIBLE *)pmt->Format();
    m_pFilter->m_Window.m_nChannels = pwfx->Format.nChannels;
    m_pFilter->m_Window.m_nSamplesPerSec = pwfx->Format.nSamplesPerSec;
    m_pFilter->m_Window.m_nBitsPerSample = pwfx->Format.wBitsPerSample;
    m_pFilter->m_Window.m_nBlockAlign = pwfx->Format.nBlockAlign;
    m_pFilter->m_Window.m_MaxValue = 128;
    m_pFilter->m_Window.m_nIndex = 0;

SetHorizScrollRange

CScopeWindow::SetHorizScrollRangeは、フィルタ独自のメソッドである。switch文がありますが、ここに34(※)のcaseを追加する。ここで設定した文字列がウィンドウにフォーマット情報として表示される。24bit PCMの場合、nBitPerSampleは32となるので、あえて「S-32」としている。

1
2
3
4
5
6
7
8
18:
            16-bit
            (0"));
            break;
        34:
            32-bit
            (0"));
            break;

※ ここのswitch文はチャンネル数とサンプルあたりのビット数を加算した値で分岐している。フォーマットが 32bit 2ch の場合、 32 + 2 = 34 となる。

CopyWaveform

サンプルあたりのビット数によって値の範囲が違うわけですが、それを0-255に正規化しているのがCScopeWindow::CopyWaveformメソッドである。正規化することにより、ウィンドウ内に波形がきっちりおさまって表示される。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
switch(m_nBitsPerSample + m_nChannels)
    {
        BYTE * pb;
        WORD * pw;
        DWORD *pdw;
// (中略)
        // 追加
        34:
        { 32-bit
            pdw = (DWORD *)pWave;
            while(nSamplesPerChan--)
            {
                m_pPoints1[m_nIndex].y = (24);
                m_pPoints2[m_nIndex].y = (24);
                if(++m_nIndex == m_nSamplesPerSec)
                    m_nIndex = 0;
            }
            break;
        }

高解像度なWAVファイルを組み合わせて遊んでみる。

ここではWAVEFORMATEXTENSIBLEでサポートしているマルチチャンネルには対応していない。それには、さらに追加のコーディングが必要となる。

24bit なのに 32bit?

24bitでもWAVEFORMATEXTENSIBLE::Format::wBitsPerSampleは32になることがある。つまりL/Rチャンネルを持つ場合、1つのオーディオフレームは8バイトになる。

では、24bitなのか32bitなのか判定するにはどうしたらいいのかというと、WAVEFORMATEXTENSIBLE::Samples::wValidBitsPerSampleで確認できる。

詳細はこちらを参照のこと


Comments

comments powered by Disqus