/*------------------------------------------------------------
DirectMusic サンプルプログラム
2007 Copyright(C) Toru
ToruのDirectXプログラミング講座
URL : http://toruweb.web.fc2.com/
Mail : toru_website@hotmail.com
--------------------------------------------------------------*/
#define STRICT
// インクルード
//#include
#include "OggVorbis.h"
#include
#include
// インターフェイス解放
#define RELEASE(p) { if(p){(p)->Release();p=NULL;} }
// アプリケーション情報
HINSTANCE g_hInst; // インスタンスハンドル
HWND g_hWnd; // ウインドウハンドル
CHAR g_szAppName[] = "DirectMusic Sample"; // アプリケーション名
// DirectMusicの変数
IDirectMusicPerformance8* g_lpPerformance = NULL; // パフォーマンス
IDirectMusicLoader8* g_lpLoader = NULL; // ローダー
IDirectMusicSegment8* g_lpSegment = NULL; // セグメント
CHAR* g_lpWaveData = NULL; // メモリ領域
/* 注意:OggVorbisファイルを各自で用意してください */
/* サイズが大きくなるので用意していません */
CHAR g_szFileName[] = "bgm.ogg"; // 再生するファイル
// メッセージ関数の定義
LRESULT CALLBACK MainWndProc( HWND hWnd, UINT msg, UINT wParam, LONG lParam );
// アプリケーションの初期化
BOOL InitApp( HINSTANCE hInst, INT nCmdShow )
{
// インスタンスハンドル保存
g_hInst = hInst;
// COMの初期化
HRESULT hr = CoInitialize( NULL );
if( FAILED(hr) )
{
DXTRACE_ERR( "COMの初期化に失敗", hr );
return FALSE;
}
// ウインドウクラスの登録
WNDCLASS wc;
ZeroMemory( &wc, sizeof(wc) );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.lpszClassName = "Main Window";
wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
wc.hInstance = hInst;
wc.style = CS_BYTEALIGNCLIENT | CS_VREDRAW|CS_HREDRAW;
wc.lpfnWndProc = (WNDPROC)MainWndProc;
if( ! RegisterClass(&wc) )
{
DXTRACE_MSG( "ウインドウクラスの登録に失敗" );
return FALSE;
}
// メインウインドウの作成
g_hWnd = CreateWindowEx( 0, "Main Window", g_szAppName,
WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION,
CW_USEDEFAULT, CW_USEDEFAULT, 320, 240,
(HWND)NULL, (HMENU)NULL, hInst, (LPSTR)NULL);
if( g_hWnd == NULL )
{
DXTRACE_MSG( "メインウインドウ作成に失敗" );
return FALSE;
}
// メインウインドウの表示
ShowWindow( g_hWnd, nCmdShow );
UpdateWindow( g_hWnd );
return TRUE;
}
// DirectMusicの初期化
BOOL InitDMusic()
{
HRESULT hr;
// パフォーマンスの作成
hr = CoCreateInstance( CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC,
IID_IDirectMusicPerformance8, (LPVOID*)&g_lpPerformance );
if( FAILED(hr) )
{
DXTRACE_ERR( "DirectMusicPerformance8オブジェクトの作成に失敗", hr );
return FALSE;
}
// パフォーマンスの初期化
hr = g_lpPerformance->InitAudio(
NULL, // IDirectMusicインターフェイスは不要
NULL, // IDirectSoundインターフェイスは不要
g_hWnd, // ウィンドウハンドル
DMUS_APATH_SHARED_STEREOPLUSREVERB, // デフォルトのオーディオパスタイプ
64, // パフォーマンスチャンネルの数
DMUS_AUDIOF_ALL, // シンセサイザの機能
NULL ); // オーディオパラメータにはデフォルトを使用
if( FAILED(hr) )
{
DXTRACE_ERR( "DirectMusicPerformance8の初期化に失敗", hr );
return FALSE;
}
// ローダーの作成
hr = CoCreateInstance( CLSID_DirectMusicLoader, NULL, CLSCTX_INPROC,
IID_IDirectMusicLoader8, (LPVOID*)&g_lpLoader );
if( FAILED(hr) )
{
DXTRACE_ERR( "DirectMusicLoader8オブジェクトの作成に失敗", hr );
return FALSE;
}
// ローダーの初期化(検索パスをカレントディレクトリに設定)
CHAR strPath[ MAX_PATH ];
DWORD i = GetCurrentDirectory( MAX_PATH, strPath );
if( i==0 || MAX_PATHSetSearchDirectory( GUID_DirectMusicAllTypes, wstrSearchPath, FALSE );
if( FAILED(hr) )
{
DXTRACE_ERR( "検索パスの設定に失敗", hr );
return FALSE;
}
// OggVorbisをWaveへデコード
LONG lWaveSize;
if( ! LoadOggVorbis( g_szFileName, 2, &g_lpWaveData, &lWaveSize ) )
{
DXTRACE_MSG( "OggVorbisをWaveへのデコードに失敗" );
return FALSE;
}
// セグメント作成
DMUS_OBJECTDESC desc;
ZeroMemory( &desc, sizeof(DMUS_OBJECTDESC) );
desc.dwSize = sizeof(DMUS_OBJECTDESC);
desc.dwValidData = DMUS_OBJ_CLASS | DMUS_OBJ_MEMORY;
desc.guidClass = CLSID_DirectMusicSegment;
desc.pbMemData = (LPBYTE)g_lpWaveData;
desc.llMemLength = lWaveSize;
hr = g_lpLoader->GetObject( &desc, IID_IDirectMusicSegment8, (LPVOID*)&g_lpSegment );
if( FAILED(hr) )
{
DXTRACE_ERR( "セグメント作成に失敗", hr );
return FALSE;
}
// バンドのロード
hr = g_lpSegment->Download( g_lpPerformance );
if( FAILED(hr) )
{
DXTRACE_ERR( "バンドのロードに失敗", hr );
return FALSE;
}
// セグメントの再生
g_lpPerformance->PlaySegmentEx(
g_lpSegment, // 演奏するセグメント
NULL, // 使用しない
NULL, // トランザクション用
0, // フラグ
0, // 開始タイム、0 は即時
NULL, // セグメント状態を受け取るポインタ
NULL, // 停止するオブジェクト
NULL // オーディオパス、デフォルトでない場合
);
return TRUE;
}
// DirectMusicの終了処理
BOOL ReleaseDMusic()
{
HRESULT hr;
// 演奏停止
if( g_lpPerformance )
{
hr = g_lpPerformance->Stop( NULL, NULL, 0, 0 );
if( FAILED(hr) )
DXTRACE_ERR( "全セグメントの演奏停止に失敗", hr );
}
// セグメントのアンロード
if( g_lpSegment )
{
hr = g_lpSegment->Unload( g_lpPerformance );
if( FAILED(hr) )
DXTRACE_ERR( "セグメントのアンロードに失敗", hr );
}
// セグメントを開放
RELEASE( g_lpSegment );
// ローダを開放
RELEASE( g_lpLoader );
// パフォーマンスを解放
if( g_lpPerformance )
{
hr = g_lpPerformance->CloseDown();
if( FAILED(hr) )
DXTRACE_ERR( "IDirectMusicPerformance8::CloseDownに失敗", hr );
}
RELEASE( g_lpPerformance );
// 確保したメモリを解放
SAFE_DELETE( g_lpWaveData );
return TRUE;
}
// アプリケーションの終了処理
BOOL EndApp()
{
// COMを解放
CoUninitialize();
return TRUE;
}
// ウインドウ処理
LRESULT CALLBACK MainWndProc( HWND hWnd, UINT msg, UINT wParam, LONG lParam )
{
switch( msg )
{
// ウインドウが破棄される
case WM_DESTROY:
PostQuitMessage( 0 );
break;
// その他のメッセージ
default:
return DefWindowProc( hWnd, msg, wParam, lParam );
}
return 0L;
}
// メイン
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, INT nCmdShow)
{
MSG msg;
// アプリケーションの初期化
if( InitApp( hInst, nCmdShow ) )
{
// DirectMusicの初期化
if( InitDMusic() )
{
// メッセージループ
while( GetMessage( &msg, 0, 0, 0 ) )
{
if( msg.message == WM_QUIT ) break;
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
}
// DirectMusicの終了処理
ReleaseDMusic();
// アプリケーションの終了処理
EndApp();
return msg.wParam;
}
#include "OggVorbis.h"
//-----------------------------------------------------------------------------
// Name: LoadOggVorbis()
// Desc: OggVorbisをWaveへ変換
// Argu: szName ファイル名
// iWord 量子化バイト数。1(8bit)か2(16bit)を指定。
// lplpWaveData Waveを保存するメモリ領域のポインタのポインタ
// lplWaveDataSize Waveのサイズを保存する変数のポインタ
// Rtn : TRUE 成功
// FALSE 失敗
//-----------------------------------------------------------------------------
BOOL LoadOggVorbis( LPCSTR szName, INT iWord, CHAR **lplpWaveData, LPLONG lplWaveDataSize )
{
// 量子化バイト数が正しい値か
if( ! ( iWord == 1 || iWord == 2 ) ) return FALSE;
// ファイルを開く
FILE *lpFile = fopen( szName, "rb" );
if( lpFile == NULL ) return FALSE;
// OggVorbisのファイル情報を取得
OggVorbis_File vf;
if( ov_open( lpFile, &vf, NULL, 0 ) < 0 )
{
fclose( lpFile );
return FALSE;
}
// OggVorbisの情報を取得
vorbis_info *vi = ov_info( &vf, -1 );
if( vi == NULL )
{
ov_clear( &vf );
return FALSE;
}
// ヘッダサイズの取得。sizeof(wh) だと正確なサイズが出ない
WAVEFILEHEADER wh;
LONG lWHSize = sizeof(wh.cRIFF) + sizeof(wh.iSizeRIFF) + sizeof(wh.cType) +
sizeof(wh.cFmt) + sizeof(wh.iSizeFmt) + sizeof(wh.WaveFmt) +
sizeof(wh.cData) + sizeof(wh.iSizeData);
// デコード後のデータサイズを求め、メモリ確保
LONG lDataSize = (LONG)ceil( vi->channels * vi->rate * ov_time_total( &vf,-1 ) * iWord );
*lplpWaveData = new CHAR[ lDataSize + lWHSize ];
if( lplpWaveData == NULL )
{
ov_clear( &vf );
return FALSE;
}
// OggVorbisをWaveへデコード
INT iCurrentSection;
LONG lWriteSize;
LONG lReadSize = 0;
while( 1 )
{
// デコード
lWriteSize = ov_read( &vf, *lplpWaveData + lReadSize + lWHSize, lDataSize - lReadSize, 0, iWord, 1, &iCurrentSection );
// 終了
if( ! lWriteSize )
{
break;
}
// エラー
else if ( lWriteSize < 0 )
{
SAFE_DELETE( *lplpWaveData );
ov_clear( &vf );
return FALSE;
}
// 全てデコードできなかった
lReadSize += lWriteSize;
}
// ヘッダの初期化
memcpy( wh.cRIFF, "RIFF", 4 );
wh.iSizeRIFF = lWHSize + lReadSize - 8;
memcpy( wh.cType, "WAVE", 4 );
memcpy( wh.cFmt, "fmt ", 4 );
wh.iSizeFmt = sizeof(WAVEFORMATEX);
wh.WaveFmt.cbSize = sizeof(WAVEFORMATEX);
wh.WaveFmt.wFormatTag = WAVE_FORMAT_PCM;
wh.WaveFmt.nChannels = vi->channels;
wh.WaveFmt.nSamplesPerSec = vi->rate;
wh.WaveFmt.nAvgBytesPerSec = vi->rate * vi->channels * iWord;
wh.WaveFmt.nBlockAlign = vi->channels * iWord;
wh.WaveFmt.wBitsPerSample = iWord * 8;
memcpy( wh.cData, "data", 4 );
wh.iSizeData = lReadSize;
// メモリ内のヘッダへ書き込み
INT iSize = 0;
memcpy(*lplpWaveData, &wh.cRIFF, sizeof(wh.cRIFF)); iSize += sizeof(wh.cRIFF);
memcpy(*lplpWaveData + iSize, &wh.iSizeRIFF, sizeof(wh.iSizeRIFF)); iSize += sizeof(wh.iSizeRIFF);
memcpy(*lplpWaveData + iSize, &wh.cType, sizeof(wh.cType)); iSize += sizeof(wh.cType);
memcpy(*lplpWaveData + iSize, &wh.cFmt, sizeof(wh.cFmt)); iSize += sizeof(wh.cFmt);
memcpy(*lplpWaveData + iSize, &wh.iSizeFmt, sizeof(wh.iSizeFmt)); iSize += sizeof(wh.iSizeFmt);
memcpy(*lplpWaveData + iSize, &wh.WaveFmt, sizeof(wh.WaveFmt)); iSize += sizeof(wh.WaveFmt);
memcpy(*lplpWaveData + iSize, &wh.cData, sizeof(wh.cData)); iSize += sizeof(wh.cData);
memcpy(*lplpWaveData + iSize, &wh.iSizeData, sizeof(wh.iSizeData));
// 終了処理
ov_clear( &vf );
// デコードしたWave形式のサイズ
*lplWaveDataSize = lReadSize + lWHSize;
return TRUE;
}
#pragma once
// インクルード
#include
#include
#include
#include
// Waveファイルのヘッダ
typedef struct{
char cRIFF[4];
int iSizeRIFF;
char cType[4];
char cFmt[4];
int iSizeFmt;
WAVEFORMATEX WaveFmt;
char cData[4];
int iSizeData;
} WAVEFILEHEADER;
// メモリ解放
#define SAFE_DELETE(p) if(p){delete []p;p=NULL;}
// OggVorbisをWaveへ変換
BOOL LoadOggVorbis( LPCSTR szName, INT iWord, CHAR **lplpWaveData, LPLONG lplWaveDataSize );
- Last Update 2007/1/21
- Copyright © 2002-2007 Toru. All Rights Reserved.
- toru_website@hotmail.com