ページ 11

音量変更のプログラム

Posted: 2013年3月26日(火) 22:40
by だんごさん
下記のサンプルコードについて質問があります。
音楽の音量変更をするプログラムです。

コード:

#include "DxLib.h"

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
		 LPSTR lpCmdLine, int nCmdShow )
{
	int SHandle ;

	int volume = 255 ;

	ChangeWindowMode( TRUE );

	SetAlwaysRunFlag( TRUE );

	if( DxLib_Init() == -1 )	// DXライブラリ初期化処理
	{
		 return -1;	// エラーが起きたら直ちに終了
	}

	// test.wavのメモリへの読み込みサウンドハンドルをSHandleに保存します
	SHandle = LoadSoundMem( "test.mp3" ) ;

		//音量変更
	ChangeVolumeSoundMem( volume , SHandle );

	// 読みこんだ音をバックグラウンド再生します(『PlaySoundMem』関数使用)
	PlaySoundMem( SHandle , DX_PLAYTYPE_BACK ) ;

	//裏画面
	SetDrawScreen( DX_SCREEN_BACK );


	// Aキー押されるまでループ
	while(CheckHitKey(KEY_INPUT_A)==0 && ClearDrawScreen()==0)
	{	
		// メッセージ処理
		if( ProcessMessage() == -1 )
		{
			break ;	// エラーが起きたらループを抜ける
		}

//
//リアルタイムで音量変更するときはコメントアウトしてください
//      ↓     ↓      ↓      ↓

		//if(CheckHitKey(KEY_INPUT_DOWN) == 1 ){
		//	volume--;
		//}
		//if(volume < 0)
		//	volume = 0;

		//if(CheckHitKey(KEY_INPUT_UP) == 1 ){
		//	volume++;
		//}
		//if(volume > 255)
		//	volume = 255;

		//ChangeVolumeSoundMem( volume , SHandle );


//   ↑     ↑      ↑      ↑


		DrawFormatString( 0, 0, GetColor(255,255,255) , "volume = %d    %d/10000" , volume , GetVolumeSoundMem( SHandle )); 
		
		ScreenFlip();
	}

	DxLib_End() ;		// DXライブラリ使用の終了処理

	return 0 ;		// ソフトの終了
}

えーと、まずコードは正しいでしょうか?デバッグというわけではなく、ループでChangeVolumeSoundMemを呼び出している点など中身の問題です。(デバッグはもちろんしております)

コードは正常という前提で本題です。
リアルタイムで音量を変更していると、0~255の0に近くなるほど急激に音量が下がります。このようなことが前にもおこり、ここで質問させていただきましたがその時は変数を割って求めていたことが原因でした。
しかし今回は数値を割ってもいないし、ただ数値を上下しているだけなのに音量に異常が起きています。
もしかしたらコードが問題なのかもしれませんがなぜなのかわからない状態です。

私の場合、volumeが1のときGetVolumeSoundMem(音量を取得する)は7594/10000、volumeが30で9071/10000、volumeが200のとき9895/10000となります。

VC++2008
Windows7 HP
DxLib 3.10a

Re: 音量変更のプログラム

Posted: 2013年3月27日(水) 10:46
by softya(ソフト屋)
当方では、ちゃんと音量が下がるように思います。
すごく感覚的なものなので「急激に音量が下がります。」が感覚の違いという可能性もあります。
あと考えられのは、PCの音声出力系の特性やスピーカー内蔵アンプの特性なども考えられますね。

Re: 音量変更のプログラム

Posted: 2013年3月27日(水) 18:56
by だんごさん
softya(ソフト屋) さんが書きました:すごく感覚的なものなので「急激に音量が下がります。」が感覚の違いという可能性もあります。
>>私の場合、volumeが1のときGetVolumeSoundMem(音量を取得する)は7594/10000、volumeが30で9071/10000、volumeが200のとき9895/10000となります。
初っ端から音量が7594でvolumeが上がるごとに少しずつしか音量が上がらないことが分かるので、確実だと思います。
逆に言えばvolumeが下がるごとに段々音量の変化が大きくなるということです。

ですが、いろんなDxLibソフトでもこのような症状がみられるので
softya(ソフト屋) さんが書きました:あと考えられのは、PCの音声出力系の特性やスピーカー内蔵アンプの特性なども考えられますね。
上記が原因かと思います。
が、手始めに何を調べていけばよいのかわかりません…。

Re: 音量変更のプログラム

Posted: 2013年3月27日(水) 19:01
by softya(ソフト屋)
数値に関しては同じです。なので内部的な数値が関係有るとは思えません。

>上記が原因かと思います。
>が、手始めに何を調べていけばよいのかわかりません…。

デバッグの基本ですが問題が何処にあるのか切り分けることです。
関連する要素をできるだけ書き出してみましょう。
勉強のため、書きだしてみてください。

Re: 音量変更のプログラム

Posted: 2013年3月27日(水) 19:31
by だんごさん
>数値に関しては同じです。なので内部的な数値が関係有るとは思えません。
というのは、
>>私の場合、volumeが1のときGetVolumeSoundMem(音量を取得する)は7594/10000、volumeが30で9071/10000、volumeが200のとき9895/10000となります。
これと同じ数値が出るということでしょうか?

softya(ソフト屋) さんが書きました:デバッグの基本ですが問題が何処にあるのか切り分けることです。関連する要素をできるだけ書き出してみましょう。勉強のため、書きだしてみてください。
・音量を変更するChangeVolumeSoundMem
・スピーカー(の設定など)
・サウンドデータをロードするかしないか
・サウンド形式

んー?こんな感じですか??

Re: 音量変更のプログラム

Posted: 2013年3月27日(水) 21:06
by softya(ソフト屋)
私も同じ数値が出ます。 この場合は、どんな意味があるかは非公開関数なので不明です。

さて問題の洗い出しですが。

a)音量を変更するChangeVolumeSoundMem
b)スピーカー(の設定など)
c)サウンドデータをロードするかしないか
d)サウンド形式

a)に関してはChangeVolumeSoundMem以外の方法を考えてみてください。
b)c)d)は試せると思うので確認をしてみてください。

比較検討なので、私の考えるデータの流れから考えてみます。
1) mp3データが原因
2) DXライブラリが原因
3) DirectSoundが原因
4) サウンドドライバが原因
5) PCのサウンド部分が原因
6) スピーカアンプが原因

で、テスト内容です。
1)は既に出てますね。
2)が原因ならDXライブラリ以外のDirectXゲームなどで確認できると思います。
3)が原因ならDirectSoundを使う他のmp3プレーヤーなどで確認できると思います。
4)が原因ならマスターボリュームでも同じ事が起こるはずです。あるいはDirectSoundを使わないmp3プレーヤーでも同じ事が起こるでしょう。
5)が原因ならこれは他のPCが必要です。
6)が原因ならヘッドフォンなどをつないでみましょう。

Re: 音量変更のプログラム

Posted: 2013年3月27日(水) 23:06
by だんごさん
すみません、まだテストは行っていないものもありますが、気づいた点だけ書かせていただきます。

・AerobeatPlusなどのソフトでは正常に音量変更が行われています。明らかに音量が違うので確実です。
・Windowsの音量ミキサーについてですが、音量は変更可能ですが音量レベル?現在の音量が緑のバーで表示されるのがありません。音量変更は正常です。
・音楽再生ソフトの音量変更は正常です。DirectSoundは使用していないと思われます。高確率で…
・ヘッドフォンに変更しても変わりません。
・モニターのオーディオ設定は特に変わりはありません。

何かと問題点が絞られた感じなので色々試してみます。

Re: 音量変更のプログラム

Posted: 2013年3月27日(水) 23:17
by softya(ソフト屋)
ChangeVolumeSoundMem()は隠し関数じゃなかったですね。失礼しました。
ところで、PlayMusic()してSetVolumeMusic()ではどうでしょうか?

Re: 音量変更のプログラム

Posted: 2013年3月27日(水) 23:24
by qwea
横槍で失礼なのですが、この記事が参考になりませんかね?

http://hpcgi2.nifty.com/natupaji/bbs/pa ... st&no=1486

以前自分も詰まったところなので…

Re: 音量変更のプログラム

Posted: 2013年3月27日(水) 23:30
by だんごさん
softya(ソフト屋) さんが書きました:ところで、PlayMusic()してSetVolumeMusic()ではどうでしょうか?
ロードした時と同様の結果です。症状は治っていません。

qweaさん、ご返答ありがとうございます。参考にして今からやってみます。

Re: 音量変更のプログラム

Posted: 2013年3月28日(木) 00:10
by だんごさん
色々実証してみようと試みたのですが、URL先を読んでもチンプンカンプンで…。申し訳ないです。
dbに変換する関数も一体何があってそういう計算になるのかわからない状態です。
言い訳にしかなりませんがまだ高校入ってやっと1年くらいなもので…。logとかはまだ習っていません。

とりあえずURL先の質問と症状が全く同じような感じですので原因は大体分かりました。
あとはどういうプログラムを書けばよいかですね。

Re: 音量変更のプログラム

Posted: 2013年3月28日(木) 00:47
by softya(ソフト屋)
こっちの関数を使って
extern int SetVolumeSoundMem( int VolumePal, int SoundHandle ) ; // サウンドハンドルのボリュームを設定する( 100分の1デシベル単位 )

この関数はdb単位なので、Dixq さんの質問に出てきた関数
// % 単位の値を渡し、 dB 単位に変換する
static inline long Calc_dB( int par ){
return (par == 0) ? -10000 : ((int)(log10f((float)par) * 5000.0f) - 10000);
}
この値を更に100で割るだけでしょう。
SetVolumeSoundMem( Calc_dB(par)/100,
こんな感じ?

Re: 音量変更のプログラム

Posted: 2013年3月28日(木) 01:27
by だんごさん
softya(ソフト屋)さん、ありがとうございます!

>>上記の式は私が DirectSound を直接扱っていたときに使用していた計算関数です。
>>しかし、範囲が違う(0 ~ -10000 を返す)し、%より細かい単位を指定できないのでそのままでは使えませんが。
範囲が違うというのは大丈夫ですよね…?

それから、計算式にあるlog10fというのはなんでしょうか?実行したら綺麗にエラーが出てきました。おそらくfloat型10のlogということで合っていますか?…というのを前提としてmath.h追加してlogを計算しましたが予想通り意味不明な値が返りました・・・

Re: 音量変更のプログラム

Posted: 2013年3月28日(木) 05:25
by FUNK
私も昔同じ様な問題を抱えまして、
上記で上がったURL先の内容を元に、関数を作成して問題を解決しました。
今も現役で使用できているのでよろしかったら参考にしてください。

コード:

// 一次関数的デシベル変換
// 引数の範囲は0~255
long CalcDB( int sound_val )
{
	int par;

	par = 100 * sound_val / 255;

    return ( par == 0 ) ? 0 : ( (int)( log10f( (float)par ) * 5000.0f ) );
}

SetVolumeSoundMem( CalcDB( 255 ), sound_handle );

Re: 音量変更のプログラム

Posted: 2013年3月28日(木) 10:37
by softya(ソフト屋)
昨日は寝ぼけていたようです。SetVolumeSoundMem( Calc_dB(par)/100,だと単位が有ってない!
FUNKさんの関数を使ってみてください。

Re: 音量変更のプログラム

Posted: 2013年3月28日(木) 18:51
by だんごさん
私も寝ぼけていたようです。log10fっていう関数があったのに変な解釈をしてしまいました。

問題はFUNKさんの関数で無事解決しました。関数の計算は未だ理解できないですが綺麗に音量変更ができています。
ありがとうございました。