RIFF構造データの表示(AVI/WAVE+MP3)

RIFF構造を有するデータの表示/再生を行う例題です。Video for Windows(VFW)による読込み等を行っているため、他のOSの移植等は全く考慮していません(一から読込みのは大変だったので..)。例題では、AVI画像(映像:divx,xvid 等にも対応, 音声:ACM,PCM)の再生/表示、WAVE音声(PCM)の再生/波形(+FFT)表示、MP3音声の再生/波形(+FFT)表示、音声入力(WAVE:PCM)の波形(+FFT)表示を行っています。

動画ファイル(AVI)中の音声がPCM以外のWAVE音声の場合、AVIMakeCompressedStream()関数によりPCMに変換していますが、上手く変換できない場合があります。ここら辺の対処が上手くいくようになれば、再度掲載します。MP3の音声はWin32のAPI(msacm.h, msacm32.lib)によりPCMへ変換しています(acmStreamOpen(),AcmConveart()等の関数を参照)。

AVIの画像はdivx,xvid 等にも対応するようになっていますが、専用のコーデックを他のサイトからダウンロードする必要があります。コーデックがインストールされているかどうかを確認したい場合は、[コントロールパネル]-[管理ツール]-[コンピュータの管理]-[デバイスマネージャ]-[サウンド、ビデオ、およびゲームコントローラ]-[オーディオ(ビデオ)CODEC](XPの場合)において目的のコーデックがあるか確認してください。


実行形式(dgwriff.exe)

 ダウンロード

RIFF構造データの表示(AVI/WAVE+MP3)(dgwriff.cpp)
//-----------------------------------------------------------------
// dgwriff.cpp:
//      RIFF構造のデータ表示(AVI/WAVE)
//               Last Update: <2005/06/04 11:06:26 A.Murakami>
//-----------------------------------------------------------------
#include <windows.h>
#include <vfw.h>
#include "resource.h"
#include "driff.h"
//-----------------------------------------------------------------
// for VC++
#pragma comment(linker,"/subsystem:windows")
//-----------------------------------------------------------------
// グローバル変数:
//-----------------------------------------------------------------
HINSTANCE hAppInst;                       // 現在のインスタンス
TCHAR szTitle[256];                       // タイトルバーテキスト
TCHAR szWindowClass[256];                 // タイトルバーテキスト
//-----------------------------------------------------------------
// 関数宣言:
//-----------------------------------------------------------------
ATOM MyRegisterClass(HINSTANCE hInst);
BOOL InitInstance(HINSTANCE hInst,int nCmdSw);
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
void GetWinRect(HWND hWnd,int* x,int* y);
//-----------------------------------------------------------------
int APIENTRY WinMain(HINSTANCE hInst,HINSTANCE hpInst,LPSTR lpArgv,int nCmdSw)
{
    MSG msg; HACCEL hAccelTable;
    // グローバルストリングを読込み
    LoadString(hInst,IDS_APP_TITLE,szTitle,256);
    LoadString(hInst,IDC_DG,szWindowClass,256);
    MyRegisterClass(hInst);
    // アプリケーションの初期化
    if(!InitInstance(hInst,nCmdSw)) {
        return FALSE;
    }
    hAccelTable = LoadAccelerators(hInst,(LPCTSTR)IDC_DG);
    // メインメッセージループ:
    while(GetMessage(&msg,NULL,0,0)) {
        if(!TranslateAccelerator (msg.hwnd,hAccelTable,&msg)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return msg.wParam;
}
//-----------------------------------------------------------------
// MyRegisterClass()
//-----------------------------------------------------------------
ATOM MyRegisterClass(HINSTANCE hInst)
{
    WNDCLASSEX wcex;
    wcex.cbSize         = sizeof(WNDCLASSEX); 
    wcex.style            = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = (WNDPROC)WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInst;
    wcex.hIcon            = NULL;
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName    = (LPCSTR)IDC_DG;
    wcex.lpszClassName    = szWindowClass;
    wcex.hIconSm        = NULL;
    return RegisterClassEx(&wcex);
}
//-----------------------------------------------------------------
// InitInstance(HANDLE, int)
//-----------------------------------------------------------------
BOOL InitInstance(HINSTANCE hInst,int nCmdSw)
{
   HWND hWnd;
   hAppInst = hInst;
   hWnd = CreateWindow(szWindowClass,szTitle,
                       WS_OVERLAPPEDWINDOW,
                       CW_USEDEFAULT,0,
                       CW_USEDEFAULT,0,
                       NULL,NULL,hInst,NULL);
   if(!hWnd) return FALSE;
   ShowWindow(hWnd,nCmdSw);
   UpdateWindow(hWnd);
   return TRUE;
}
//-----------------------------------------------------------------
// WndProc(HWND, unsigned, WORD, LONG)
//-----------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
    static HWND hEdit; // 情報表示窓
    static int wx,wy,wex,wey;
    switch(msg) {
    case WM_CREATE:
        GetWinRect(hWnd,&wx,&wy);
        hEdit = CreateWindow("EDIT",
                             NULL,
                             WS_CHILD | WS_THICKFRAME | WS_VISIBLE |
                             ES_MULTILINE | ES_WANTRETURN |
                             ES_AUTOHSCROLL | ES_AUTOVSCROLL | WS_HSCROLL,
                             wx-200,-3,
                             200+5,wy+5,
                             hWnd,
                             (HMENU)ID_EDIT,
                             hAppInst,
                             NULL);
        SendMessage(hEdit,EM_SETLIMITTEXT,(WPARAM)1024*64,0);
        set_win(hWnd,hEdit);
        // DIB 初期化
        dg_DDib = DrawDibOpen();
        break;
    case WM_COMMAND:
        switch(LOWORD(wParam)) { // メニュー選択
        case IDM_EXIT:  DestroyWindow(hWnd);      break;
        case IDM_OPEN:  dg_fileopen(hWnd);        break;
        case IDM_CLOSE: dg_close();               break;
        case IDM_ISAVE: dg_isave(hWnd);           break;
        case IDM_DWG1:  set_wavedraw(DGW_NORMAL); break;
        case IDM_DWG2:  set_wavedraw(DGW_FFT);    break;
        case IDM_DWG3:  dg_wavein(hWnd);          break;
        }
        InvalidateRect(hWnd,NULL,TRUE);
        break;
    case MM_WOM_DONE: break; // 音声再生完了
    case MM_WIM_DATA: // 音声入力完了
        dg_windraw(hWnd);
        break;
    case WM_PAINT:
        break;
    case WM_SIZE:
        GetWinRect(hWnd,&wx,&wy);
        GetWinRect(hEdit,&wex,&wey);
        if(wex>wx) wex=wx;
        if(wex<5)  wex=5;
        MoveWindow(hEdit,wx-wex,-3,wex+5,wy+5,TRUE);
        InvalidateRect(hWnd,NULL,TRUE);
        SendMessage(hWnd,WM_PAINT,0,0);
        break;
    case WM_DESTROY:
        dg_close();
        DrawDibClose(dg_DDib);
        PostQuitMessage(0);
        break;
    }
    return DefWindowProc(hWnd,msg,wParam,lParam);
}

void GetWinRect(HWND hWnd,int* x,int* y)
{
    RECT rc;
    GetClientRect(hWnd,&rc);
    *x = rc.right - rc.left;
    *y = rc.bottom - rc.top;
    return;
}