トップページ > 過去ログ > 記事閲覧
メモリ内音楽操作について。
名前:ヒキニート072 日時: 2009/05/03 21:15

現在Dxライブラリでゲーム開発させていただいています。 僕のような知識の乏しい者でもゲーム開発が出来、大変助かっています。 今回プログラムで、僕の手に終えなさそうな挙動が出ましたので質問させていただきます。 挙動は以下です。 特定の条件で、 LoadSoundMem ↓ SetLoopPosSoundMem ↓ ChangeVolumeSoundMem ↓ PlaySoundMem という操作をおこなった場合、 ChangeVolumeSoundMem以下がエラーを返し、 (SetLoopPosSoundMemまでは、エラーでない。確認済) 音楽が再生されないという状況が発生しました。 (僕の環境のみかもしれませんが) 確認用に、この「特定状況」を再現したプログラムを組んできましたので、 以下に公開いたします。 //****************************************************************** /* 参考サイト、C言語ゲームプログラミングの館さん。 */ #include "DxLib.h" //システムデータ********************************************************************************************* char Key[256];//キーボードの入力状態を入れる配列。 int fdmu=0,btmu=0;//音楽のハンドル。 int fdmu_loop=0,btmu_loop=0;//ループ指定の戻り値格納変数。 int fdmu_blm=0,btmu_blm=0;//音量変更関数戻り値用変数。 int bgm_vol=5;//音量、十段階。 int no=1;//出力状態に振る番号。 //入力キーを押しっぱなしにしても、大丈夫にする関数。 //入力キー状態とフラグを渡す。フラグを返す。(フラグがそのままキーの入力状態になる) //flag=0入力可能押されていない、flag=1入力された、flag=2キー押しっぱなし、入力されていない。 int botan(int key,int flag){ if(key==1&&flag==0){//キーが押されていて、キーが押し続けられていないなら。 flag=1;//入力されている。 } else if(key==1)//キーが押され続けていたら。 flag=2;//フラグをあさってに折る。 else if(key==0)//キーが離されたら flag=0;//入力可能。 return flag; } //音楽をメモリに格納する関数。 void refd_mu(){ //音を止める。 StopSoundMem( fdmu ) ; StopSoundMem( btmu ) ; DeleteSoundMem( fdmu ) ;//二重に読み込んでしまわないように消しておく。 DeleteSoundMem( btmu ) ; switch(no){ case 1: fdmu = LoadSoundMem( "mad\\fdmu01.ogg" ) ;//音楽を読み込む。 fdmu_loop=SetLoopPosSoundMem( 73916, fdmu );//音楽ループ位置指定。 btmu = LoadSoundMem( "mad\\btmu01.ogg" ) ;//音楽を読み込む。 btmu_loop=SetLoopPosSoundMem( 1637 , btmu );//音楽ループ位置指定。 break; case 2: fdmu = LoadSoundMem( "mad\\mtmu01.ogg" ) ;//フィールド音楽を読み込む。fdmuをハンドルとする。 fdmu_loop=SetLoopPosSoundMem( 9704 , fdmu ) ;//音楽ループ位置指定。 break; } fdmu_blm=ChangeVolumeSoundMem( 255*bgm_vol/10 , fdmu ) ;//音量設定。 btmu_blm=ChangeVolumeSoundMem( 255*bgm_vol/10 , btmu ) ;//音量設定。 return; } //フィールド用ループ関数。 void field(int *bt_flag){ int B1_Flag=0,B2_Flag=0,B3_Flag=0;//ボタン変数。 int fdmu_play=0,btmu_play=0;//再生関数戻り値用変数。 int White = GetColor( 255 , 255 , 255 );//色宣言。 int stepon=0;//使わない音だが、バグの発生条件で必要。 stepon = LoadSoundMem( "mad\\step01.ogg" ) ;//バグの発生条件、音を読み込む。 if(*bt_flag==0){//初回のみ。 refd_mu();//音楽読み込み。 ChangeVolumeSoundMem( 255*bgm_vol/10 , fdmu ) ;//音量変更。 fdmu_play=PlaySoundMem( fdmu , DX_PLAYTYPE_LOOP ) ;//フィールド音ループ再生。 } *bt_flag=0;//0にしておく。 while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){ //↑メッセージ処理 ↑画面をクリア ↑キーボード入力状態取得 ↑ESCが押されると終了 //ボタン入力判別。 B1_Flag=botan(Key[ KEY_INPUT_A ],B1_Flag);//1番ボタン連続入力防止。 B2_Flag=botan(Key[ KEY_INPUT_S ],B2_Flag);//2番ボタン連続入力防止。 B3_Flag=botan(Key[ KEY_INPUT_D ],B3_Flag);//3番ボタン連続入力防止。 if(B1_Flag==1){//Aが押されたら、メモリに読み込んでいる音楽を書き換える。 if(no==1){//no1の場合、2に書き換えて出力。 no=2; refd_mu(); fdmu_play=PlaySoundMem( fdmu , DX_PLAYTYPE_LOOP ) ;//音ループ再生開始。 } else if(no==2){//no2の場合、1に書き換えて出力。 no=1; refd_mu(); fdmu_play=PlaySoundMem( fdmu , DX_PLAYTYPE_LOOP ) ;//音ループ再生開始。 } } else if(B2_Flag==1){//S入力で音楽切り替え。 if(CheckSoundMem( fdmu ) ==1){//fdmu音楽流れているなら StopSoundMem( fdmu ) ;//音楽を止め btmu_play=PlaySoundMem( btmu , DX_PLAYTYPE_LOOP ) ;//別の音楽再生。 } else if(CheckSoundMem( btmu ) ==1){//btmu音楽流れているなら StopSoundMem( btmu ) ;//音楽を止め fdmu_play=PlaySoundMem( fdmu , DX_PLAYTYPE_LOOP ) ;//別の音楽再生。 } else{//それ以外なら、 StopSoundMem( fdmu ) ;//とりあえず、両方止めて StopSoundMem( btmu ) ;// fdmu_play=PlaySoundMem( fdmu , DX_PLAYTYPE_LOOP ) ;//両方再生。 btmu_play=PlaySoundMem( btmu , DX_PLAYTYPE_LOOP ) ;// } } else if(B3_Flag==1){//D入力で DeleteSoundMem( stepon ) ;//読んだ音を削除。 *bt_flag=1; break;//ループを抜ける。 } DrawFormatString( 0 , 0 , White , "fdmu音楽ハンドル        %d" , fdmu) ; DrawFormatString( 0 , 20 , White , "fdmuループ箇所指定関数戻り値  %d" , fdmu_loop) ; DrawFormatString( 0 , 40 , White , "fdmuボリューム変更関数戻り値  %d" , fdmu_blm) ; DrawFormatString( 0 , 60 , White , "fdmu再生関数戻り値       %d" , fdmu_play) ; DrawFormatString( 0 , 80 , White , "fdmu再生状態          %d" , CheckSoundMem( fdmu )) ; DrawFormatString( 0 ,120 , White , "btmu音楽ハンドル        %d" , btmu) ; DrawFormatString( 0 ,140 , White , "btmuループ箇所指定関数戻り値  %d" , btmu_loop) ; DrawFormatString( 0 ,160 , White , "btmuボリューム変更関数戻り値  %d" , btmu_blm) ; DrawFormatString( 0 ,180 , White , "btmu再生関数戻り値       %d" , btmu_play) ; DrawFormatString( 0 ,200 , White , "btmu再生状態          %d" , CheckSoundMem( btmu )) ; DrawFormatString( 0 ,240 , White , "no(メモリ内音楽番号)     %d" , no) ; DrawString( 0 , 280 , "Aキーでメモリ内音楽変更" , White ); DrawString( 0 , 300 , "Sキーで再生音楽変更" , White ); DrawString( 0 , 320 , "Dキーでブレーク(バグ発生)" , White ); DrawString( 0 , 360 , "音楽提供 煉獄庭園" , White ); ScreenFlip();//裏画面の画像を表に出力。 } return; } //メイン関数 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){ SetOutApplicationLogValidFlag(FALSE) ;//ログ出力を行うか否か(TRUE:行う FALSE:行わない) int bt_flag=0; if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //ウィンドウ化と初期化処理 SetDrawScreen( DX_SCREEN_BACK ) ; //描画先を裏画面に設定 while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){ //↑メッセージ処理 ↑画面をクリア ↑キーボード入力状態取得 ↑ESCが押されると終了 field(&bt_flag);//フィールド用ループ関数。戦闘フラグのポインタを渡す。フィールド処理関数。 } DxLib_End();//ゲーム終了。 return 0; } //****************************************************************** 以上です。 一応実行ファイルも、製作してきましたのでアップロードさせていただきます。 http://www1.axfc.net/uploader/Ne/so/51391 上記のプログラムは、各々の変数の状態を出力しつつ Aキーでメモリ内の音楽を書き換え(no=1,no=2の2パターン) Sキーで再生する音楽を変更する(ハンドルfdmu,btmuの二種類)プログラムです。 AキーとSキーのみで操作する場合は、正常に動作します。 (出力している変数、noが2の時btmuにエラーが出ますが これはこの変数に音楽を読み込んでいないからなので無視してください) ですが、Dキーを入力し(長押ししてください)『ループをブレーク』すると 最初に説明しました挙動が発生します。 具体的には、no=2の状態でAキーを押し、fdmuとbtmuを再読み込みすると、 正常に機能していたはずのno=1状態でのfdmuが再生されなくなります。 (btmuは、正常に機能します) この挙動は、 field関数の stepon = LoadSoundMem( "mad\\step01.ogg" ) ; または、refd_mu関数の fdmu_loop=SetLoopPosSoundMem( 73916, fdmu ); btmu_loop=SetLoopPosSoundMem( 1637 , btmu ); または、refd_mu関数の btmu = LoadSoundMem( "mad\\btmu01.ogg" ) ; btmu_loop=SetLoopPosSoundMem( 1637 , btmu ); のいずれかをコメント文にし、外すことで発生しなくなります。 (逆に言えば上記が、この挙動の発生条件) ですが、僕の目指すプログラムではこれらは外すことが出来ません。 なんとかこの挙動の発生条件までは、突き止めたのですが これ以上どうすることも出来ず、質問に上がったしだいです。 お手数ですが、なにとぞご教授ください。

Page: 1 |

Re: メモリ内音楽操作について。 ( No.1 )
名前:管理人 日時:2009/05/04 01:05

ご報告有難うございます ご指摘の通り SetLoopPosSoundMem にバグがありました 修正版をアップしましたので、宜しければお使い下さい m(_ _)m http://homepage2.nifty.com/natupaji/DxLib/DxLibVCTest.exe //VC用 http://homepage2.nifty.com/natupaji/DxLib/DxLibBCCTest.exe //BCC用 (中身を既存のライブラリのファイルに上書きして、BCCをお使いの 場合は『再構築』、VCをお使いの場合は『リビルド』をして下さい) あと、BGMの様な長いサウンドファイルを扱う場合は SetCreateSoundDataType 関数を使用してストリーミング再生をするようにすると 読込時間を大幅に短縮できますので、宜しければお使いになってみてください ( DX_SOUNDDATATYPE_MEMPRESS がお勧めです ) SetCreateSoundDataType関数の説明 http://homepage2.nifty.com/natupaji/DxLib/function/dxfunc_other.html#R15N25
改善されません。 ( No.2 )
名前:ヒキニート072 日時:2009/05/05 01:12

素早い対応ありがとうございます。 ですが、症状が改善されません。 そちらの環境では改善されましたでしょうか? (Dキーを長押しした後、no=2の状態でAキーを押し音楽が鳴るか?) それとも、僕が修正版の扱い方を間違えているのでしょうか? 僕は、VCを使用しているのですが DxLibVCTest.exeを解凍して、出てきたフォルダの中身を 「プロジェクトに追加すべきファイル_VC用」のフォルダの中に上書き。 リビルドに関しては、 今回お見せしたプログラムを選択した状態で 「ソリューションのリビルド」と「DxLib_VC2005用のリビルド」と ソリューションエクスプローラ内の「DxLib_VC2005用」「ソリューション'DxLib_VC2008_and_2005用'」 を各々右クリックしてリビルドしてみましたが いずれも効果なしです。(二週してみました) 知識薄のためまったく関係ないところにファイルを移したり、 まったく関係ないところをリビルドしてしまったりしているかもしれません。 何度もお手間を取らせてしまって、申し訳ありませんが なにとぞよろしくお願いいたします。
Re: メモリ内音楽操作について。 ( No.3 )
名前:管理人 日時:2009/05/06 17:14

はい、私の環境では修正版を使用した場合は Dキーを長押しした後、no=2の状態でAキーを押しても、音楽は鳴ります うーん、DXライブラリのファイルを「プロジェクトに追加すべきファイル_VC用」フォルダから 参照しているのだとしますとヒキニート072さんが採られた手順で問題ないはずです 私の環境で正常に動作したときの実行ファイルと Visual C++ のプロジェクトをアップしましたので 宜しければヒキニート072さんの環境でも正常に動作するかどうかお試しになってみてください http://homepage2.nifty.com/natupaji/temp/PlaySoundTest.zip ちなみに no=2 の時に A を押したときは2曲分圧縮音声ファイルを展開するので再生までに時間がかかります
改善されました。 ( No.4 )
名前:ヒキニート072 日時:2009/05/08 10:56

アップロードしていただいたファイル、正常に動作いたしました。 また、新しくプロジェクトを製作しましたところ こちらでコンパイルしたファイルも正常に動作いたしました。 DXライブラリーをダウンロードした際に出来ているプロジェクトファイル DxLib_VC2008_and_2005用.slnを使い続けたことが原因だったようです。 (このプロジェクトでコンパイルするといまだに妙な動作をします) 特に、5月1日で更新されたDXライブラリーを導入する際に 以前のDXライブラリーを丸ごと削除し、プロジェクトの設定を 何も弄らず新しいVerを使用したのも問題だったかも知れません。 後、ストリーミング再生ですが これはあえて使っていません。 プログラミング技術に自信が無いため、CPUに負荷が掛かるような行動を避けたいのです。 メモリを節約できるという利点もありますが 700kb程度の作業域を取られるとのことですので、あまりメモリを節約できるわけでもなさそうですし。 また、該当する音声読み込み箇所は一度読んでしまえば暫く使うことの出来る箇所です。 読み込みの速さよりも、CPUへの負荷軽減を選択した結果です。 賢くない選択をしてしまっているかもしれませんが。 コレでゲーム製作が続けられます、ありがとうございました。 また、こちらのミスで振り回してしまい申し訳ありませんでした。

Page: 1 |