お待たせしました
同時再生に必要な機能を追加したバージョンができましたので、
よろしければこちらをダウンロードしてください m(_ _)m
http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe // VisualC++ 用
http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe // BorlandC++ 用
(中身を既存のライブラリのファイルに上書きして、BCCをお使いの
場合は『再構築』、VCをお使いの場合は『リビルド』をして下さい)
追加した関数は以下の関数です
LoadSoundMem で取得できるサウンドハンドルとは全く別の機能となっています
// ソフトウエア制御サウンド系関数
// データ用関数
int InitSoftSound( void ) ; // ソフトウエアで扱う波形データをすべて解放する
int LoadSoftSound( const char *FileName ) ; // ソフトウエアで扱う波形データをファイルから作成する
int LoadSoftSoundFromMemImage( const void *FileImageBuffer, int FileImageSize ) ; // ソフトウエアで扱う波形データをメモリ上に展開されたファイルイメージから作成する
int MakeSoftSound( int UseFormat_SoftSoundHandle, int SampleNum ) ; // ソフトウエアで扱う空の波形データを作成する( フォーマットは引数のソフトウエアサウンドハンドルと同じものにする )
int MakeSoftSound2Ch16Bit44KHz( int SampleNum ) ; // ソフトウエアで扱う空の波形データを作成する( チャンネル数:2 量子化ビット数:16bit サンプリング周波数:44KHz )
int MakeSoftSound2Ch16Bit22KHz( int SampleNum ) ; // ソフトウエアで扱う空の波形データを作成する( チャンネル数:2 量子化ビット数:16bit サンプリング周波数:22KHz )
int MakeSoftSound2Ch8Bit44KHz( int SampleNum ) ; // ソフトウエアで扱う空の波形データを作成する( チャンネル数:2 量子化ビット数:8bit サンプリング周波数:44KHz )
int MakeSoftSound2Ch8Bit22KHz( int SampleNum ) ; // ソフトウエアで扱う空の波形データを作成する( チャンネル数:2 量子化ビット数:8bit サンプリング周波数:22KHz )
int MakeSoftSound1Ch16Bit44KHz( int SampleNum ) ; // ソフトウエアで扱う空の波形データを作成する( チャンネル数:1 量子化ビット数:16bit サンプリング周波数:44KHz )
int MakeSoftSound1Ch16Bit22KHz( int SampleNum ) ; // ソフトウエアで扱う空の波形データを作成する( チャンネル数:1 量子化ビット数:16bit サンプリング周波数:22KHz )
int MakeSoftSound1Ch8Bit44KHz( int SampleNum ) ; // ソフトウエアで扱う空の波形データを作成する( チャンネル数:1 量子化ビット数:8bit サンプリング周波数:44KHz )
int MakeSoftSound1Ch8Bit22KHz( int SampleNum ) ; // ソフトウエアで扱う空の波形データを作成する( チャンネル数:1 量子化ビット数:8bit サンプリング周波数:22KHz )
int DeleteSoftSound( int SoftSoundHandle ) ; // ソフトウエアで扱う波形データを解放する
int GetSoftSoundSampleNum( int SoftSoundHandle ) ; // ソフトウエアで扱う波形データのサンプル数を取得する
int GetSoftSoundFormat( int SoftSoundHandle, int *Channels, int *BitsPerSample, int *SamplesPerSec ) ; // ソフトウエアで扱う波形データのフォーマットを取得する
int ReadSoftSoundData( int SoftSoundHandle, int SamplePosition, int *Channel1, int *Channel2 ) ; // ソフトウエアで扱う波形データのサンプルを読み取る
int WriteSoftSoundData( int SoftSoundHandle, int SamplePosition, int Channel1, int Channel2 ) ; // ソフトウエアで扱う波形データのサンプルを書き込む
void *GetSoftSoundDataImage( int SoftSoundHandle ) ; // ソフトウエアで扱う波形データの波形イメージが格納されているメモリアドレスを取得する
int LoadSoundMemFromSoftSound( int SoftSoundHandle, int BufferNum ) ; // ソフトウエアで扱う波形データからサウンドハンドルを作成する
// プレイヤー用関数
int InitSoftSoundPlayer( void ) ; // ソフトウエアで扱う波形データのプレイヤーをすべて解放する
int MakeSoftSoundPlayer( int UseFormat_SoftSoundHandle ) ; // ソフトウエアで扱う波形データのプレイヤーを作成する( フォーマットは引数のソフトウエアサウンドハンドルと同じものにする )
int MakeSoftSoundPlayer2Ch16Bit44KHz( void ) ; // ソフトウエアで扱う波形データのプレイヤーを作成する( チャンネル数:2 量子化ビット数:16bit サンプリング周波数:44KHz )
int MakeSoftSoundPlayer2Ch16Bit22KHz( void ) ; // ソフトウエアで扱う波形データのプレイヤーを作成する( チャンネル数:2 量子化ビット数:16bit サンプリング周波数:22KHz )
int MakeSoftSoundPlayer2Ch8Bit44KHz( void ) ; // ソフトウエアで扱う波形データのプレイヤーを作成する( チャンネル数:2 量子化ビット数:8bit サンプリング周波数:44KHz )
int MakeSoftSoundPlayer2Ch8Bit22KHz( void ) ; // ソフトウエアで扱う波形データのプレイヤーを作成する( チャンネル数:2 量子化ビット数:8bit サンプリング周波数:22KHz )
int MakeSoftSoundPlayer1Ch16Bit44KHz( void ) ; // ソフトウエアで扱う波形データのプレイヤーを作成する( チャンネル数:1 量子化ビット数:16bit サンプリング周波数:44KHz )
int MakeSoftSoundPlayer1Ch16Bit22KHz( void ) ; // ソフトウエアで扱う波形データのプレイヤーを作成する( チャンネル数:1 量子化ビット数:16bit サンプリング周波数:22KHz )
int MakeSoftSoundPlayer1Ch8Bit44KHz( void ) ; // ソフトウエアで扱う波形データのプレイヤーを作成する( チャンネル数:1 量子化ビット数:8bit サンプリング周波数:44KHz )
int MakeSoftSoundPlayer1Ch8Bit22KHz( void ) ; // ソフトウエアで扱う波形データのプレイヤーを作成する( チャンネル数:1 量子化ビット数:8bit サンプリング周波数:22KHz )
int DeleteSoftSoundPlayer( int SSoundPlayerHandle ) ; // ソフトウエアで扱う波形データのプレイヤーを削除する
int AddDataSoftSoundPlayer( int SSoundPlayerHandle, int SoftSoundHandle, int AddSamplePosition, int AddSampleNum ) ; // ソフトウエアで扱う波形データのプレイヤーに波形データを追加する( フォーマットが同じではない場合はエラー )
int AddDirectDataSoftSoundPlayer( int SSoundPlayerHandle, void *SoundData, int AddSampleNum ) ; // ソフトウエアで扱う波形データのプレイヤーにプレイヤーが対応したフォーマットの生波形データを追加する
int AddOneDataSoftSoundPlayer( int SSoundPlayerHandle, int Channel1, int Channel2 ) ; // ソフトウエアで扱う波形データのプレイヤーに波形データを一つ追加する
int GetSoftSoundPlayerFormat( int SSoundPlayerHandle, int *Channels, int *BitsPerSample, int *SamplesPerSec ) ; // ソフトウエアで扱う波形データのプレイヤーが扱うデータフォーマットを取得する
int StartSoftSoundPlayer( int SSoundPlayerHandle ) ; // ソフトウエアで扱う波形データのプレイヤーの再生処理を開始する
int StopSoftSoundPlayer( int SSoundPlayerHandle ) ; // ソフトウエアで扱う波形データのプレイヤーの再生処理を停止する
int ResetSoftSoundPlayer( int SSoundPlayerHandle ) ; // ソフトウエアで扱う波形データのプレイヤーの状態を初期状態に戻す( 追加された波形データは削除され、再生状態だった場合は停止する )
int GetStockDataLengthSoftSoundPlayer( int SSoundPlayerHandle ) ; // ソフトウエアで扱う波形データのプレイヤーに追加した波形データでまだ再生用サウンドバッファに転送されていない波形データのサンプル数を取得する
int CheckSoftSoundPlayerNoneData( int SSoundPlayerHandle ) ; // ソフトウエアで扱う波形データのプレイヤーに再生用サウンドバッファに転送していない波形データが無く、再生用サウンドバッファにも無音データ以外無いかどうかを取得する( TRUE:無音データ以外無い FALSE:有効データがある )
上記の中で今回最低限使用する必要があるのは以下の関数です
// データ用関数
int LoadSoftSound( const char *FileName ) ; // ソフトウエアで扱う波形データをファイルから作成する
int DeleteSoftSound( int SoftSoundHandle ) ; // ソフトウエアで扱う波形データを解放する
int GetSoftSoundSampleNum( int SoftSoundHandle ) ; // ソフトウエアで扱う波形データのサンプル数を取得する
int ReadSoftSoundData( int SoftSoundHandle, int SamplePosition, int *Channel1, int *Channel2 ) ; // ソフトウエアで扱う波形データのサンプルを読み取る
// プレイヤー用関数
int MakeSoftSoundPlayer( int UseFormat_SoftSoundHandle ) ; // ソフトウエアで扱う波形データのプレイヤーを作成する( フォーマットは引数のソフトウエアサウンドハンドルと同じものにする )
int DeleteSoftSoundPlayer( int SSoundPlayerHandle ) ; // ソフトウエアで扱う波形データのプレイヤーを削除する
int AddOneDataSoftSoundPlayer( int SSoundPlayerHandle, int Channel1, int Channel2 ) ; // ソフトウエアで扱う波形データのプレイヤーに波形データを一つ追加する
int StartSoftSoundPlayer( int SSoundPlayerHandle ) ; // ソフトウエアで扱う波形データのプレイヤーの再生処理を開始する
int StopSoftSoundPlayer( int SSoundPlayerHandle ) ; // ソフトウエアで扱う波形データのプレイヤーの再生処理を停止する
int GetStockDataLengthSoftSoundPlayer( int SSoundPlayerHandle ) ; // ソフトウエアで扱う波形データのプレイヤーに追加した波形データでまだ再生用サウンドバッファに転送されていない波形データのサンプル数を取得する
int CheckSoftSoundPlayerNoneData( int SSoundPlayerHandle ) ; // ソフトウエアで扱う波形データのプレイヤーに再生用サウンドバッファに転送していない波形データが無く、再生用サウンドバッファにも無音データ以外無いかどうかを取得する( TRUE:無音データ以外無い FALSE:有効データがある )
今回追加した機能の簡単なご説明をします
既存の LoadSoundMem で取得できるサウンドハンドルに付随する機能は基本的に波形データ( 音の波の情報 )は
DXライブラリ内部で扱う前提になっているので、ここに複数のサウンドファイルの波形データを合成して
再生するような機能を搭載すると実装がかなり酷いことになるので今回DXライブラリ外部から波形データを
扱うことを前提とした機能を作りました
その機能に伴いソフトウエアで扱うことを前提とした波形データのハンドル( ソフトウエアサウンドハンドル )と
ソフトウエアで扱うことを前提とした波形データを再生するハンドル( ソフトウエアサウンドプレイヤーハンドル )の
2種類のハンドルが増えました
ソフトウエアサウンドプレイヤーさえあればDXライブラリ外部で用意した波形データを再生することはできるので、
上記の「データ用関数」というのはサウンドファイルの波形データを容易に取得するだけのために使用する機能です
使い方ですが、例えば BGM.wav というファイルを上記関数群を使用して再生するプログラムは以下のようになります
#include "DxLib.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
int SoftSoundHandle, SoftSoundPlayerHandle ;
int SoftSoundSampleNum, OutputSampleNum ;
int Channel1, Channel2 ;
ChangeWindowMode( TRUE ) ;
if( DxLib_Init() < 0 ) return -1 ;
// BGM.wav を読み込みソフトウエアサウンドハンドルを作成
SoftSoundHandle = LoadSoftSound( "BGM.wav" ) ;
// BGM.wav の波形サンプル数を取得
SoftSoundSampleNum = GetSoftSoundSampleNum( SoftSoundHandle ) ;
// BGM.wav のフォーマットに合ったソフトウエアサウンドプレイヤーを作成
SoftSoundPlayerHandle = MakeSoftSoundPlayer( SoftSoundHandle ) ;
// プレイヤーに出力した波形サンプルの数を初期化
OutputSampleNum = 0 ;
// 再生ループ
while( ProcessMessage() == 0 )
{
// プレイヤーに再生されずにストックされている波形サンプルの数が
// 0.1秒分以下になっていたら BGM.wav の全波形サンプルをプレイヤーに出力していない限りループの中に入る
while( GetStockDataLengthSoftSoundPlayer( SoftSoundPlayerHandle ) < 4410 && OutputSampleNum < SoftSoundSampleNum )
{
// サウンドデータハンドルを介してプレイヤーに出力していない波形サンプルを取得
ReadSoftSoundData( SoftSoundHandle, OutputSampleNum, &Channel1, &Channel2 ) ;
// 取得した波形サンプルをプレイヤーに出力
AddOneDataSoftSoundPlayer( SoftSoundPlayerHandle, Channel1, Channel2 ) ;
// プレイヤーに出力したサンプルの数をインクリメント
OutputSampleNum ++ ;
}
// まだプレイヤーの再生処理を開始していなかったら開始する
if( CheckStartSoftSoundPlayer( SoftSoundPlayerHandle ) == FALSE )
StartSoftSoundPlayer( SoftSoundPlayerHandle ) ;
// BGM.wav の全ての波形サンプルをプレイヤーに出力していて、
// 且つプレイヤーが無音データを再生し始めていたら BGM.wav の再生が終了したということなのでループを抜ける
if( OutputSampleNum == SoftSoundSampleNum && CheckSoftSoundPlayerNoneData( SoftSoundPlayerHandle ) == TRUE )
break ;
}
// プレイヤーの再生処理を停止する
StopSoftSoundPlayer( SoftSoundPlayerHandle ) ;
// ソフトウエアサウンドハンドルを削除
DeleteSoftSound( SoftSoundHandle ) ;
// ソフトウエアサウンドプレイヤーハンドルを削除
DeleteSoftSoundPlayer( SoftSoundPlayerHandle ) ;
DxLib_End() ;
return 0 ;
}
「再生ループ」のところまでは恐らく解説は必要ないと思いますので、再生ループの中について説明を
まずプレイヤーには大体0.1秒ほどの波形サンプルがストックされていないと音が途切れるなどの
現象が発生してしまいますので、GetStockDataLengthSoftSoundPlayer の戻り値が0.1秒分以下
( 上記サンプルでは 4410 にしていますが、これは BGM.wav のサンプリング周波数が 44.1KHz であると
仮定した場合の数値です( 44100 / 10 = 4410 ) )だった場合はプレイヤーに BGM.wav の波形データを出力します
出力の仕方は ReadSoftSoundData で BGM.wav から波形サンプルを一つ取得して、AddOneDataSoftSoundPlayer
でプレイヤーに取得した波形サンプルを渡すだけです、これを GetStockDataLengthSoftSoundPlayer の戻り値が
0.1秒分以上になるか、BGM.wav の全てのサンプルを出力し終わるまで繰り返します
このループの後で CheckStartSoftSoundPlayer でプレイヤーの再生処理が開始しているかを調べて、もし
開始していなかったら StartSoftSoundPlayer でプレイヤーの再生処理を開始します、再生ループに入る前に
再生処理を開始しないのは、何もプレイヤーに波形データが無い状態で再生処理を開始してしまうと無音データが
再生されてしまう為です
そして再生ループの最後では BGM.wav の全ての波形サンプルをプレイヤーに出力していて、且つプレイヤーが
無音データの再生を開始していたら( CheckSoftSoundPlayerNoneData の戻り値が TRUE だったら )再生ループから抜ける、
ということをしています
態々 CheckSoftSoundPlayerNoneData を使用して確認しているのは、プレイヤーは AddOneDataSoftSoundPlayer で
渡された波形サンプルを渡された直後に再生するわけではなく、プレイヤーにストックされている波形データの
消費と共に再生されるので、この関数で全ての有効な波形データの再生が終了して無音データの再生が開始されたか
どうかを CheckSoftSoundPlayerNoneData で確認する必要があるからです
再生ループ後は、ソフトウエアサウンドプレイヤーを停止し、ソフトウエアサウンドハンドルと
ソフトウエアサウンドプレイヤーハンドルを削除して、ソフトを終了しています
次に本題の二つのBGMを合成して再生する方法ですが、上記サンプルプログラムの中の AddOneDataSoftSoundPlayer に
渡している波形サンプルを二つのBGMファイルから抜き出したものを合成したものにすれば、二つのBGMが合成された
音を再生することができます
合成の例としてキーボードの左右キーで BGM1.wav と BGM2.wav の合成比率が変化するプログラムを書いてみました
#include "DxLib.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
int SoftSoundHandle1, SoftSoundHandle2 ;
int SoftSoundPlayerHandle ;
int SoftSoundSampleNum, OutputSampleNum ;
int Channel1_1, Channel1_2 ;
int Channel2_1, Channel2_2 ;
int BlendRatio ;
ChangeWindowMode( TRUE ) ;
if( DxLib_Init() < 0 ) return -1 ;
// BGM1.wav を読み込みソフトウエアサウンドハンドルを作成
SoftSoundHandle1 = LoadSoftSound( "BGM1.wav" ) ;
// BGM2.wav を読み込みソフトウエアサウンドハンドルを作成
SoftSoundHandle2 = LoadSoftSound( "BGM2.wav" ) ;
// BGM1.wav の波形サンプル数を取得
SoftSoundSampleNum = GetSoftSoundSampleNum( SoftSoundHandle1 ) ;
// BGM1.wav のフォーマットに合ったソフトウエアサウンドプレイヤーを作成
SoftSoundPlayerHandle = MakeSoftSoundPlayer( SoftSoundHandle1 ) ;
// プレイヤーに出力した波形サンプルの数を初期化
OutputSampleNum = 0 ;
// ブレンドの比率を中間にしておく
BlendRatio = 128 ;
// 描画先画面を裏画面にする
SetDrawScreen( DX_SCREEN_BACK ) ;
// 再生ループ
while( ProcessMessage() == 0 )
{
// 裏画面をクリア
ClearDrawScreen() ;
// キー入力の左右でブレンド率を変化
if( CheckHitKey( KEY_INPUT_LEFT ) == 1 )
{
if( BlendRatio > 0 ) BlendRatio -- ;
}
if( CheckHitKey( KEY_INPUT_RIGHT ) == 1 )
{
if( BlendRatio < 256 ) BlendRatio ++ ;
}
// プレイヤーに再生されずにストックされている波形サンプルの数が
// 0.1秒分以下になっていたら BGM1.wav の全波形サンプルをプレイヤーに出力していない限りループの中に入る
while( GetStockDataLengthSoftSoundPlayer( SoftSoundPlayerHandle ) < 4410 && OutputSampleNum < SoftSoundSampleNum )
{
// サウンドデータハンドルを介してプレイヤーに出力していない波形サンプルを取得
ReadSoftSoundData( SoftSoundHandle1, OutputSampleNum, &Channel1_1, &Channel1_2 ) ;
ReadSoftSoundData( SoftSoundHandle2, OutputSampleNum, &Channel2_1, &Channel2_2 ) ;
// 取得した波形サンプルをブレンドの比率に応じた合成をしてプレイヤーに出力
AddOneDataSoftSoundPlayer(
SoftSoundPlayerHandle,
( BlendRatio * Channel1_1 + ( 256 - BlendRatio ) * Channel2_1 ) / 256,
( BlendRatio * Channel1_2 + ( 256 - BlendRatio ) * Channel2_2 ) / 256 ) ;
// プレイヤーに出力したサンプルの数をインクリメント
OutputSampleNum ++ ;
}
// まだプレイヤーの再生処理を開始していなかったら開始する
if( CheckStartSoftSoundPlayer( SoftSoundPlayerHandle ) == FALSE )
StartSoftSoundPlayer( SoftSoundPlayerHandle ) ;
// BGM1.wav の全ての波形サンプルをプレイヤーに出力していて、
// 且つプレイヤーが無音データを再生し始めていたら BGM1.wav の再生が終了したということなのでループを抜ける
if( OutputSampleNum == SoftSoundSampleNum && CheckSoftSoundPlayerNoneData( SoftSoundPlayerHandle ) == TRUE )
break ;
// 画面にブレンド率を表示
DrawFormatString( 0, 0, GetColor( 255,255,255 ), "BGM1.wav %d BGM2.wav %d", BlendRatio, 256 - BlendRatio ) ;
// 裏面の内容を表画面に反映
ScreenFlip() ;
}
// プレイヤーの再生処理を停止する
StopSoftSoundPlayer( SoftSoundPlayerHandle ) ;
// ソフトウエアサウンドハンドルを削除
DeleteSoftSound( SoftSoundHandle1 ) ;
DeleteSoftSound( SoftSoundHandle2 ) ;
// ソフトウエアサウンドプレイヤーハンドルを削除
DeleteSoftSoundPlayer( SoftSoundPlayerHandle ) ;
DxLib_End() ;
return 0 ;
}
上記のサンプルプログラムでは一つ目のサンプルプログラムと違い、AddOneDataSoftSoundPlayer に渡す波形サンプルを
BGM1.wav と BGM2.wav から取得した波形サンプルを BlendRatio の値に応じて合成したものにしています、この例のように
vocal有りのサウンドファイルと無しのサウンドファイルを合成して再生すればパヤさんが望まれる処理を実現できると思います
と、駆け足でご説明しましたが、想定よりも複雑な機能になってしまいました
不明な点があると思いますので、どうぞご指摘下さい m(_ _;m