« オーディオプレイヤ開発記 その20 | メイン | オーディオプレイヤ開発記 その22 »

2006/02/26(日)

●オーディオプレイヤ開発記 その21


 それでは、bass.dll を使った音声ファイルの再生を管理する CBass クラスを作ってみます。

 とりあえず、追加の依存ファイルに bass.lib を追加します。それで、bass.dll を使うアプリケーションでは、bass.h ファイルをインクルードする必要があるんですが、Bass.h という名前を CBass クラスのヘッダファイルに使いたいので、もともとの bass.h ファイルの名前を bassinc.h などに変更しておきます。

 それでは、CBass クラスを作成します。例によって、順次、必要な機能だけを追加していきます。

//----------------------------------------------------------------------------
// Bass.h : bass.dll の管理を行う
//----------------------------------------------------------------------------
#ifndef BassH
#define BassH

#include "bassinc.h"
//----------------------------------------------------------------------------
// bass.dll の管理を行うクラス
//----------------------------------------------------------------------------
class CBass
{
public: // 関数

    CBass(): m_hStream(0) { }
    virtual ~CBass() { BASS_Free(); }

    virtual QWORD ChannelGetLength() {
        return BASS_ChannelGetLength(m_hStream);
    }
    virtual QWORD ChannelGetPosition() {
        return BASS_ChannelGetPosition(m_hStream);
    }
    virtual float ChannelGetSecondsLength() {
        return BASS_ChannelBytes2Seconds(m_hStream, ChannelGetLength());
    }
    virtual float ChannelGetSecondsPosition() {
        return BASS_ChannelBytes2Seconds(m_hStream, ChannelGetPosition());
    }
    virtual BOOL ChannelPause() {
        return BASS_ChannelPause(m_hStream);
    }
    virtual BOOL ChannelPlay() {
        return BASS_ChannelPlay(m_hStream, FALSE);
    }
    virtual BOOL Init(HWND hWnd) {
        return BASS_Init(-1, 44100, 0, hWnd, NULL);
    }
    virtual BOOL Pause() {
        return BASS_Pause();
    }
    virtual BOOL Start() {
        return BASS_Start();
    }
    virtual BOOL StreamCreateFile(LPCTSTR lpFilePath) {
        StreamFree();
        m_hStream = BASS_StreamCreateFile(FALSE, lpFilePath, 0, 0, 0);
        return m_hStream ? TRUE : FALSE;
    }
    virtual void StreamFree() {
        if(m_hStream) BASS_StreamFree(m_hStream), m_hStream = 0;
    }

protected: // メンバ変数

    HSTREAM m_hStream;
};
//----------------------------------------------------------------------------

#endif

 完全にラップを被せてるだけですね。

 CMainWnd クラスに CBass m_bass; メンバ変数を追加し、OnCreate 関数内で m_bass.Init(m_hWnd); と初期化するようにしたら、次は ファイル → 開く メニューが選択された場合に「ファイルを開く」ダイアログを表示し、指定された音声ファイルを再生するようにします。

 メニューが選ばれると CMenu_MainWnd クラスの OnCommand 関数が呼ばれるので、そこから OnOpenFileMenuSelected 関数を呼ぶようにします。

//----------------------------------------------------------------------------
// メニューが選択された
//----------------------------------------------------------------------------
void CMenu_MainWnd::OnCommand(int id, HWND/* hwndCtl*/, UINT/* codeNotify*/)
{
    switch(id)
    {
    case ID_OPENFILE:
        OnOpenFileMenuSelected();
        break;
    case ID_XXXX:
        OnXxxxMenuSelected();
        break;
    }
}
//----------------------------------------------------------------------------
// ファイル → 開くメニューが選択された
//----------------------------------------------------------------------------
void CMenu_MainWnd::OnOpenFileMenuSelected()
{
    m_rMainWnd.OpenFile();
}
//----------------------------------------------------------------------------

 CMainWnd::OpenFile 関数の方も追加しておきます。

//----------------------------------------------------------------------------
// ファイルを開く
//----------------------------------------------------------------------------
void CMainWnd::OpenFile()
{
    TCHAR filePath[MAX_PATH] = "";
    OPENFILENAME ofn;
    ZeroMemory(&ofn, sizeof(OPENFILENAME));
    ofn.lStructSize = sizeof(OPENFILENAME);
    ofn.hInstance = GetModuleHandle(NULL);
    ofn.hwndOwner = m_hWnd;
    ofn.lpstrFilter = TEXT("再生可能な音声ファイル(*.wav;*.mp3;*.ogg)\0*.wav;*.mp3;*.ogg\0すべてのファイル (*.*)\0*.*\0\0");
    ofn.lpstrFile = filePath;
    ofn.nMaxFile = MAX_PATH;
    ofn.Flags = OFN_FILEMUSTEXIST;

    if(GetOpenFileName(&ofn))
    {
        m_bass.StreamCreateFile(filePath);
        m_bass.ChannelPlay();
        m_timeLabel.SetTime((int)m_bass.ChannelGetSecondsPosition(), (int)m_bass.ChannelGetSecondsLength());
        m_timeSlider.SetTime((LONG)m_bass.ChannelGetPosition(), (LONG)m_bass.ChannelGetLength());
    }
}
//----------------------------------------------------------------------------

 これで、指定された音声ファイルが再生されるようになりました。ここまでのソースコードはこちら ( Hayaemon20060226_src.lzh ) 。

 次は、ファイルの再生位置にあわせて、再生位置表示用ラベルやスライダを変更するようにします。これは、0.5 秒間隔のタイマーでやることにします。まず、CWnd クラスに SetTimer, KillTimer, OnTimer 関数を追加し、WndProc から OnTimer に分岐するようにします。

virtual void KillTimer(UINT_PTR nIDEvent) {
    ::KillTimer(m_hWnd, nIDEvent);
}
virtual void SetTimer(UINT_PTR nIDEvent, UINT nElapse) {
    ::SetTimer(m_hWnd, nIDEvent, nElapse, NULL);
}
virtual void OnTimer(UINT id) {
    WindowProc(WM_TIMER, (WPARAM)id, 0);
}
// CWnd::WndProc 関数内
case WM_TIMER:
    pWnd->OnTimer((UINT)wParam);
    return 0;

 それで、CWnd::OnTimer 関数をオーバーライドした CMainWnd::OnTimer 関数を追加し、ファイルが開かれた時点で、SetTimer(1, 500); とするようにしておきます。

virtual void OnTimer(UINT id) {
    m_timeLabel.SetTime(m_bass.ChannelGetSecondsPosition(), m_bass.ChannelGetSecondsLength());
    m_timeSlider.SetThumbPos(m_bass.ChannelGetPosition());
    CFrameWnd::OnTimer(id);
}

 これで、ファイルの再生位置にあわせて、再生位置表示用ラベルやスライダが変更されるようになりました。ここまでのソースコードはこちら ( Hayaemon20060226_2_src.lzh ) 。

 続いて、ツールバーの「ファイルを開く」ボタンが押された場合にも、「ファイルを開く」ダイアログを出すようにします。まず、CMainWnd::OnCommand 関数からメニューやツールバーの OnCommand 関数を呼び出すようにします。

virtual void OnCommand(int id, HWND hwndCtl, UINT codeNotify) {
    if(!hwndCtl)
        m_menu.OnCommand(id, hwndCtl, codeNotify);
    else if(hwndCtl == (HWND)m_toolBar)
        m_toolBar.OnCommand(id, hwndCtl, codeNotify);
    CFrameWnd::OnCommand(id, hwndCtl, codeNotify);
}

 CToolBar_MainWnd クラスに OnCommand, OnOpenFileButtonSelected 関数を追加しておきます。

//----------------------------------------------------------------------------
// ファイルを開くボタンが選択された
//----------------------------------------------------------------------------
void CToolBar_MainWnd::OnOpenFileButtonSelected()
{
    m_rMainWnd.OpenFile();
}
//----------------------------------------------------------------------------
// ボタンが選択された
//----------------------------------------------------------------------------
void CToolBar_MainWnd::OnCommand(int id, HWND/* hwndCtl*/, UINT/* codeNotify*/)
{
    switch(id)
    {
    case ID_OPENFILE:
        OnOpenFileButtonSelected();
        break;
    }
}
//----------------------------------------------------------------------------

 これで、ツールバーの「ファイルを開く」ボタンが押された場合にも、「ファイルを開く」ダイアログが出るようになりました。ここまでのソースコードはこちら ( Hayaemon20060226_3_src.lzh ) 。

トラックバックURL

このエントリーのトラックバックURL:
http://www.edolfzoku.com/diary/mt-tb.cgi/147

コメントする