Re: CheckSoundMemについて ( No.1 ) |
- 名前:管理人 日時:2023/02/11 01:30
> @CheckSoundMemは環境に関係なく音声の末尾に来た所で
> ズレなく0が返るものなのでしょうか?
音の再生には
1.DXライブラリがサウンドAPIにサウンドデータを渡す
2.サウンドAPIがサウンドデータをサウンドデバイスに渡す
3.サウンドデバイスがサウンドデータを出力( 音を出す )する
の段階を踏むのですが、CheckSoundMem は1の処理がサウンドデータを最後まで
処理した時点で 0 を返すようになりますので、厳密にはサウンドの再生終了前に
0 が返るようになります
> Aまた、CheckSoundMemはPlaySoundMem直後であっても環境にかかわらず、すき間なく1を返すものでしょうか?
> (※上記の関数ではすき間があると二回再生することになってしまうので)
PlaySoundMem 直後であっても 1 を返します
( サウンドデータが物凄く短くて PlaySoundMem 直後に CheckSoundMem を呼ぶ前に
再生が終了してしまった場合は 0 が返りますが… )
尚、@のご返答の通りサウンド処理には段階があるので、CheckSoundMem の戻り値が 0 に
なってから PlaySoundMem で次のパートを再生する処理で滑らかに再生されるかどうかは
再生する楽曲の種類やPCの環境に左右されます
なので、5秒単位でぶつ切りにして再生するサウンドデータを切り替えるという用途でしたら
ソフトウェアサウンドハンドルとソフトウェアサウンドプレイヤーを使うのが良いと思います
( リファレンスには載っていない機能です )
// ソフトウエア制御サウンド系関数
// データ用関数
int LoadSoftSound( const char *FileName ) ; // ソフトウエアで扱う波形データをファイルから作成する
int DeleteSoftSound( int SoftSoundHandle ) ; // ソフトウエアで扱う波形データを解放する
int GetSoftSoundSampleNum( int SoftSoundHandle ) ; // ソフトウエアで扱う波形データのサンプル数を取得する
// プレイヤー用関数
int MakeSoftSoundPlayer( int UseFormat_SoftSoundHandle ) ; // ソフトウエアで扱う波形データのプレイヤーを作成する( フォーマットは引数のソフトウエアサウンドハンドルと同じものにする )
int DeleteSoftSoundPlayer( int SSoundPlayerHandle ) ; // ソフトウエアで扱う波形データのプレイヤーを削除する
int AddDataSoftSoundPlayer( int SSoundPlayerHandle, int SoftSoundHandle, int AddSamplePosition, int AddSampleNum ) ; // ソフトウエアで扱う波形データのプレイヤーに波形データを追加する( フォーマットが同じではない場合はエラー )
int StartSoftSoundPlayer( int SSoundPlayerHandle ) ; // ソフトウエアで扱う波形データのプレイヤーの再生処理を開始する
int StopSoftSoundPlayer( int SSoundPlayerHandle ) ; // ソフトウエアで扱う波形データのプレイヤーの再生処理を停止する
int ResetSoftSoundPlayer( int SSoundPlayerHandle ) ; // ソフトウエアで扱う波形データのプレイヤーの状態を初期状態に戻す( 追加された波形データは削除され、再生状態だった場合は停止する )
int GetStockDataLengthSoftSoundPlayer( int SSoundPlayerHandle ) ; // ソフトウエアで扱う波形データのプレイヤーに追加した波形データでまだ再生用サウンドバッファに転送されていない波形データのサンプル数を取得する
1.再生したいサウンドファイルを LoadSoftSound で読み込む
2.再生用のサウンドプレイヤーを MakeSoftSoundPlayer で作成
3.AddDataSoftSoundPlayer で最初の5秒分のサウンドデータをサウンドプレイヤーに追加する
4.StartSoftSoundPlayer でサウンドの再生を開始
5.GetStockDataLengthSoftSoundPlayer で取得できる『未再生のサウンドサンプル数』が減ってきたら
次の5秒分のサウンドデータを AddDataSoftSoundPlayer で追加
6.以降5を繰り返し
というプログラムを組むことで、『何もサウンドが再生されていない時間』が完全に 0 の状態でご希望の処理ができます
上記にはたろうさんが希望される処理に必要な関数のみ記載しましたが、ソフトウェアサウンド関係の関数は他にもあります
その他ソフトウェアサウンドハンドルとプレイヤーの詳細な説明についてはこちらのスレッドの No.5 に
ありますので、よろしければご覧ください m(_ _)m
<サウンドの同時再生方法>
https://dxlib.xsrv.jp/cgi/patiobbs/patio.cgi?mode=past&no=1800
 |
Re: CheckSoundMemについて ( No.2 ) |
- 名前:たろう 日時:2023/02/11 03:42
いつもありがとうございます。
他スレを頼りに書いてみたのですが、これで使い方はあってますでしょうか?
#include "DxLib.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
ChangeWindowMode( TRUE ) ; DxLib_Init(); SetDrawScreen( DX_SCREEN_BACK ) ;
int VVH = LoadSoftSound( "stage01.wav" ) ; // ソフトウエアサウンドとしてサウンドファイルを読み込み
int 総数 = GetSoftSoundSampleNum(VVH ) ; // サウンドの総サンプル数を取得しておく
int PLAYER = MakeSoftSoundPlayer( VVH ) ; // プレイヤーの作成
StartSoftSoundPlayer( PLAYER ) ; // プレイヤーの再生開始
while( ProcessMessage() == 0 )
{
ClearDrawScreen() ;
if( GetStockDataLengthSoftSoundPlayer( PLAYER ) <=0 )// プレイヤーのストックが0以下で追加
{
AddDataSoftSoundPlayer( PLAYER, VVH, 0, 総数 ) ;
}
DrawFormatString( 0, 0, GetColor(255,255,255),"残り:%d",GetStockDataLengthSoftSoundPlayer( PLAYER ) ) ;
ScreenFlip() ;
}
DxLib_End() ;
return -1 ;
}
重ねて質問をすみません、
@特にAddDataSoftSoundPlayerのAddSamplePositionが分からず
0にしたらループがうまくいってしまったのですが…
これは演奏しきったから0という事でしょうか?
それとも0=「次の瞬間演奏される部分」という事でしょうか?
A演奏しきる前に、割り込む形で別の音(仮にVVH2)を先頭から演奏させたい場合は
どういう指定をすればよいでしょうか?
※AddDataSoftSoundPlayer( PLAYER, VVH2, 0, VVH2の総サンプル数 ) ;でしょうか?
B音量切り替えはどうしたらよいでしょうか?
CBGMは3つほどを同時に鳴らす事を予定しています(ピアノ部分、ドラム部分など)。
例えばピアノは上記の方法で鳴らし、ドラム(ピアノと同じ長さ)は通常のPlaySoundMemで同時に再生を初めて
ピアノのプレイヤーのストックが0になったところで、ピアノをAddDataSoftSoundPlayerすると同時に
ドラムをPlaySoundMemするというようにしようと考えています。
この場合環境によってピアノとドラムは大きくずれるでしょうか?(1フレ程度なら問題ないです)
(※もしそうであれば両方ともMakeSoftSoundPlayerを作って演奏する感じでしょうか)
よろしくお願いいたしますm(__)m
 |
Re: CheckSoundMemについて ( No.3 ) |
- 名前:管理人 日時:2023/02/11 07:48
> 他スレを頼りに書いてみたのですが、これで使い方はあってますでしょうか?
if( GetStockDataLengthSoftSoundPlayer( PLAYER ) <=0 )// プレイヤーのストックが0以下で追加
↑
こちらは
if( GetStockDataLengthSoftSoundPlayer( PLAYER ) <=2205 )
↑
このように 2000 くらい以下になったら、にする必要があります
GetStockDataLengthSoftSoundPlayer の戻り値は未再生のサウンドデータの量なので、
0になってしまった時点で再生が止まってしまっているからです( 0 になる前に続きを
追加する必要がある )
AddDataSoftSoundPlayer( PLAYER, VVH, 0, 総数 ) ;
↑
こちらの『総数』は GetSoftSoundSampleNum の戻り値ですが、state01.wav が
最初にお話されていた『5秒分のサウンドデータ』でしたらこちらで大丈夫です
( この関数呼び出して 5秒分プレイヤーにサウンドデータが追加されます )
> @特にAddDataSoftSoundPlayerのAddSamplePositionが分からず
> 0にしたらループがうまくいってしまったのですが…
> これは演奏しきったから0という事でしょうか?
> それとも0=「次の瞬間演奏される部分」という事でしょうか?
AddSamplePosition は SoftSoundHandle で指定したサウンドデータの
何処からプレイヤーに渡すかを指定するための引数です( 単位はサンプル )
例えば VVH が 10秒のサウンドデータで、3秒目から7秒分プレイヤーに
サウンドデータを渡したい場合は
AddDataSoftSoundPlayer( PLAYER, VVH, 3 * 44100, 7 * 44100 ) ;
と記述します( 44100 はサウンドデータのサンプリング周波数が 44.1KHz だった場合なので、
もしサウンドデータのサンプリング周波数が 48KHz だった場合は 44100 の部分が 48000 になります )
> A演奏しきる前に、割り込む形で別の音(仮にVVH2)を先頭から演奏させたい場合は
> どういう指定をすればよいでしょうか?
> ※AddDataSoftSoundPlayer( PLAYER, VVH2, 0, VVH2の総サンプル数 ) ;でしょうか?
AddDataSoftSoundPlayer でプレイヤーに渡してしまったサウンドデータを取り消すことはできないので、
途中でサウンドデータを切り替えたい場合は AddDataSoftSoundPlayer で一気に全部
プレイヤーに渡してしまうのではなく、少しづつ渡すようにします
例えば2つのサウンドを読み込んでいおいて、スペースキーを押すたびに再生する
サウンドを切り替えるプログラムは以下のようになります( たろうさんのプログラムを元に作成しました )
#include "DxLib.h"
#define ONE_ADD_NUM 4410 // プレイヤーに一度に渡すサンプル数( 0.1秒 )
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
ChangeWindowMode( TRUE ) ; DxLib_Init(); SetDrawScreen( DX_SCREEN_BACK ) ;
int VVH[ 2 ] ;
int 総数[ 2 ] ;
int AddCount[ 2 ] = { 0, 0 } ;
VVH[ 0 ] = LoadSoftSound( "Sound1.wav" ) ; // ソフトウエアサウンドとしてサウンドファイルを読み込み
VVH[ 1 ] = LoadSoftSound( "Sound2.wav" ) ;
総数[ 0 ] = GetSoftSoundSampleNum( VVH[ 0 ] ) ; // サウンドの総サンプル数を取得しておく
総数[ 1 ] = GetSoftSoundSampleNum( VVH[ 1 ] ) ; // サウンドの総サンプル数を取得しておく
int PLAYER = MakeSoftSoundPlayer( VVH[ 0 ] ) ; // プレイヤーの作成
int UseIndex = 0 ; // どちらのサウンドを渡すか
StartSoftSoundPlayer( PLAYER ) ; // プレイヤーの再生開始
while( ProcessMessage() == 0 )
{
ClearDrawScreen() ;
// 未再生サンプル数が 2205 以下の場合は繰り返す
while( GetStockDataLengthSoftSoundPlayer( PLAYER ) <= 2205 )
{
// 一回に渡す分のサンプル数がない場合は分岐
if( AddCount[ UseIndex ] + ONE_ADD_NUM > 総数[ UseIndex ] )
{
// まだ渡していないサンプルを全てプレイヤーに渡す
AddDataSoftSoundPlayer( PLAYER, VVH[ UseIndex ], AddCount[ UseIndex ], 総数[ UseIndex ] - AddCount[ UseIndex ] ) ;
// 渡し済みサンプル数を初期化
AddCount[ UseIndex ] = 0 ;
}
else
{
// 一回に渡す分のサンプル数をプレイヤーに渡す
AddDataSoftSoundPlayer( PLAYER, VVH[ UseIndex ], AddCount[ UseIndex ], ONE_ADD_NUM ) ;
// 渡し済みサンプル数を加算
AddCount[ UseIndex ] += ONE_ADD_NUM;
}
}
// スペースキーが押されたら渡すサウンドを切り替える
if( GetInputChar( TRUE ) == ' ' )
{
UseIndex = UseIndex == 0 ? 1 : 0 ;
}
DrawFormatString( 0, 0, GetColor(255,255,255),"使用番号:%d プレイヤーの未再生サンプル数:%d", UseIndex, GetStockDataLengthSoftSoundPlayer( PLAYER ) ) ;
DrawFormatString( 0, 16, GetColor(255,255,255),"サウンド0のプレイヤーに渡し済みサンプル数:%d", AddCount[ 0 ] ) ;
DrawFormatString( 0, 32, GetColor(255,255,255),"サウンド1のプレイヤーに渡し済みサンプル数:%d", AddCount[ 1 ] ) ;
ScreenFlip() ;
}
DxLib_End() ;
return -1 ;
}
> B音量切り替えはどうしたらよいでしょうか?
音量を切り替える場合はプレイヤーに渡すサンプルの値を小さくするしかありませんので
データをそのまま渡す AddDataSoftSoundPlayer の代わりに ReadSoftSoundData と AddOneDataSoftSoundPlayer を使用します
上下キーで音量を操作できるようにしながらサウンドを再生するプログラムは以下のようになります
( たろうさんのプログラムを元に作成しました )
#include "DxLib.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
ChangeWindowMode( TRUE ) ; DxLib_Init(); SetDrawScreen( DX_SCREEN_BACK ) ;
int AddCount = 0 ;
int VVH = LoadSoftSound( "SoundData.wav" ) ; // ソフトウエアサウンドとしてサウンドファイルを読み込み
int 総数 = GetSoftSoundSampleNum( VVH ) ; // サウンドの総サンプル数を取得しておく
int PLAYER = MakeSoftSoundPlayer( VVH ) ; // プレイヤーの作成
int VOLUME = 256 ; // 音量
StartSoftSoundPlayer( PLAYER ) ; // プレイヤーの再生開始
while( ProcessMessage() == 0 )
{
ClearDrawScreen() ;
// 未再生サンプル数が 2205 以下の場合は繰り返す
while( GetStockDataLengthSoftSoundPlayer( PLAYER ) <= 2205 )
{
int CH1, CH2 ;
// 1サンプル読み込む
ReadSoftSoundData( VVH, AddCount, &CH1, &CH2 ) ;
// 音量を適用しながら1サンプルプレイヤーに追加する
AddOneDataSoftSoundPlayer( PLAYER, CH1 * VOLUME / 256, CH2 * VOLUME / 256 ) ;
// 渡したサンプル数を1足す
AddCount ++ ;
// 全てのサンプルを渡してしまったらサウンドの先頭に戻る
if( AddCount >= 総数 )
{
AddCount = 0 ;
}
}
// 上キーが押されたらボリュームを上げる
if( CheckHitKey( KEY_INPUT_UP ) == 1 && VOLUME < 256 )
{
VOLUME ++ ;
}
// 下キーが押されたらボリュームを下げる
if( CheckHitKey( KEY_INPUT_DOWN ) == 1 && VOLUME > 0 )
{
VOLUME -- ;
}
DrawFormatString( 0, 0, GetColor(255,255,255),"プレイヤーの未再生サンプル数:%d", GetStockDataLengthSoftSoundPlayer( PLAYER ) ) ;
DrawFormatString( 0, 16, GetColor(255,255,255),"ボリューム:%d", VOLUME ) ;
ScreenFlip() ;
}
DxLib_End() ;
return -1 ;
}
> CBGMは3つほどを同時に鳴らす事を予定しています(ピアノ部分、ドラム部分など)。
> 例えばピアノは上記の方法で鳴らし、ドラム(ピアノと同じ長さ)は通常のPlaySoundMemで同時に再生を初めて
> ピアノのプレイヤーのストックが0になったところで、ピアノをAddDataSoftSoundPlayerすると同時に
> ドラムをPlaySoundMemするというようにしようと考えています。
> この場合環境によってピアノとドラムは大きくずれるでしょうか?(1フレ程度なら問題ないです)
> (※もしそうであれば両方ともMakeSoftSoundPlayerを作って演奏する感じでしょうか)
前述の通りストックが 0 になってはいけない( 0 = 再生する音が尽きて再生が止まってしまっている )ので
ドラム部分も MakeSoftSoundPlayer を使って再生するのが良いです
 |
Re: CheckSoundMemについて ( No.4 ) |
- 名前:たろう 日時:2023/02/11 15:24
いつもありがとうございます。
サンプルを確認させていただき、勉強させていただいておりますm(__)m
5分まるごとではなく、こまめに再生する分を送って使うようにしようと思います
また何度も質問すみません、
@パンを使いたい場合の適用される音量についてお聞きしたいのですが、サンプルの場合、例えば
AddOneDataSoftSoundPlayer( PLAYER, CH1 * VOLUME / 256, CH2 * 200 / 256 ) ;とすると、
数値の意味としては、通常再生の場合のCHChangePanSoundMem(hd,-55);と同じでしょうか?
Aこの方式だと3Dサウンドは使えない事になるでしょうか?
リバーブをかけたりしたいのですが、もしやり方があれば教えていただければと思います。
※なくても音声編集ソフトで対応するので、大丈夫です
よろしくお願いいたします。
|
Re: CheckSoundMemについて ( No.5 ) |
- 名前:管理人 日時:2023/02/11 17:30
> @パンを使いたい場合の適用される音量についてお聞きしたいのですが、サンプルの場合、例えば
> AddOneDataSoftSoundPlayer( PLAYER, CH1 * VOLUME / 256, CH2 * 200 / 256 ) ;とすると、
> 数値の意味としては、通常再生の場合のCHChangePanSoundMem(hd,-55);と同じでしょうか?
はい、その通りです
> Aこの方式だと3Dサウンドは使えない事になるでしょうか?
はい、3Dサウンドではこの方式は使用できません
> リバーブをかけたりしたいのですが、もしやり方があれば教えていただければと思います。
> ※なくても音声編集ソフトで対応するので、大丈夫です
サンプルを直接プレイヤーに流すので、自前でリバーブ処理したサンプルをプレイヤーに渡せば
リバーブが掛けられますが、すみません、ちょっとその処理の書き方は私は分からないです
こちらにリバーブのプログラミングについて解説されていましたが、参考にして実装するには
そこそこの勉強と規模の大きめの『リバーブシステム』のプログラムを組む必要がありそうです
<畳み込み演算を用いた残響効果の理論と実装>
https://qiita.com/stringamp/items/078e4f962e2073119b01
|
Re: CheckSoundMemについて ( No.6 ) |
- 名前:たろう 日時:2023/02/11 23:38
いつも回答いただきありがとうございます。
すみません、リバーブはやはり編集ソフトで付けます。
まだ勉強中ですが、また質問をすみません。
No.3で頂いたサンプル(プログラム)についてですが…
ゲームに音量設定がある都合上、Bのようにして
1づつサンプル数を足す方式が必須と考えましたが、
それでAのほうを見て疑問に思ったのですが、
ONE_ADD_NUMを使い0.1秒づつ読む仕組みを取られているのは
何か理由があるのでしょうか?
1づつであれば分岐もいらない?と思うのですが、あえてそうするのは
1づつサンプル数を足す仕組みに何かデメリットがあるということでしょうか?
音量設定のないゲームはほぼ無いと思うので、もしデメリットがあるとすれば
ONE_ADD_NUMを使うような形で音量変更をする方法もあるのでしょうか?
たびたびすみません、よろしくお願いいたしますm(__)m
|
Re: CheckSoundMemについて ( No.7 ) |
- 名前:管理人 日時:2023/02/12 01:28
> それでAのほうを見て疑問に思ったのですが、
> ONE_ADD_NUMを使い0.1秒づつ読む仕組みを取られているのは
> 何か理由があるのでしょうか?
一度に沢山のサンプルをプレイヤーに送った方が処理が軽くて済むからです
1サンプルづつ関数を呼び出して送るのはやはり処理が重くなります
( 最近のCPUでしたら問題ないと思いますが… )
> ONE_ADD_NUMを使うような形で音量変更をする方法もあるのでしょうか?
すみません、ありません
|
Re: CheckSoundMemについて ( No.8 ) |
- 名前:たろう 日時:2023/02/12 02:52
何度もすみません、ありがとうございます。
早速、1サンプルずつ送るケースとまとめて送るケースとで
タスクマネージャーで比較してみましたが、
当初の予定通り複数StartSoftSoundPlayerを同時に使う場合は
CPU使用率で1〜2%の差が出るようです。
そんなに大きくはないですが、なるべく軽くしたいので、
私の用途の場合、すき間が開いて困るのは主旋律(仮にピアノ)だけというのもあって
No2のC番で述べた仕組みがいいような気がしています。
それでその場合、ピアノをNo3のBの方式で再生しつつ、
if( AddCount >= 総数 ){ AddCount = 0 ;}のタイミングで
通常のPlaySoundMemでドラム部分を開始する仕組みにする事になるのですが
このやり方だとある程度、環境依存になるにしても、
(毎回のスタートのタイミングだけある程度そろえば満足なのですが)、
1,2フレーム(fps:60で)のズレが出るだけだと想像するのですが…
すみません、知識が足りず見当はずれの質問かもしれませんが
環境によってはもっとズレるものなのでしょうか?
よろしくお願いいたします
|
Re: CheckSoundMemについて ( No.9 ) |
- 名前:管理人 日時:2023/02/12 07:41
> それでその場合、ピアノをNo3のBの方式で再生しつつ、
> if( AddCount >= 総数 ){ AddCount = 0 ;}のタイミングで
> 通常のPlaySoundMemでドラム部分を開始する仕組みにする事になるのですが
if( AddCount >= 総数 ){ AddCount = 0 ;}のタイミングは、サウンドデータの再生が
終わったタイミングではなく、プレイヤーにサウンドデータを全て渡したタイミングとなりますので
プレイヤーに渡したサウンドデータが実際に再生されるのは
GetStockDataLengthSoftSoundPlayer( PLAYER ) / 44100.0f + プレイヤー側が持つバッファ(0.03333) 秒後となります
( サンプリング周波数が 48KHz の場合は 44100 ではなく 48000 となります )
具体的には
while( GetStockDataLengthSoftSoundPlayer( PLAYER ) <= 2205 )
↑
この条件で AddOneDataSoftSoundPlayer をしている場合は 0.05秒後となり
これにプレイヤー側の持つ 0.033333秒分のバッファを足すと合計 0.08333333秒
60fps の場合の 1フレームは 1.0f / 60.0f = 0.016666...秒 なので
0.08333333 / 0.01666666.. = 4.9999999....
となり、if( AddCount >= 総数 ){ AddCount = 0 ;}のタイミングで PlaySoundMem を
実行すると約5フレームずれることになります
なので、PlaySoundMem は if( AddCount >= 総数 ){ AddCount = 0 ;}のタイミングの
約5フレーム後に実行する必要があります
> すみません、知識が足りず見当はずれの質問かもしれませんが
> 環境によってはもっとズレるものなのでしょうか?
60fpsが保てない場合は PlaySoundMem のタイミングがよりずれてしまうことになるので、
性能の低い環境ほどよりズレが大きくなると思います
また、サウンドAPIがサウンドデータを一度に処理するサンプル数はサウンドAPI毎に異なるので
( 例えばデフォルトで使用するサウンドAPI である WASAPI は 0.01秒 )
使用するサウンドAPIによってその分の誤差が発生します
 |
Re: CheckSoundMemについて ( No.10 ) |
- 名前:たろう 日時:2023/02/12 17:41
いつもありがとうございます、頂いた情報をもとに
下のようなプログラムを書きましたm(__)m
>60fpsが保てない場合は〜
フレームではなく時間で見る様にして、50+33-10(WASAPIの最も速いケース?)ミリ秒後に「副音」を鳴らす仕組みにしました
※私の環境ではこれでピッタリになっています
>また、サウンドAPIがサウンドデータを一度に処理するサンプル数はサウンドAPI毎に異なる〜
これがよくわからなかったのですが、つまりWASAPIが0.01秒単位で発音タイミングが来るという意味でしょうか?
そう解釈して前のめりにして、その分-10にしました。
古いPCでの動作は気にしないつもりなのですが、
これで最悪で2フレ程度の誤差に収まると思うのですが、どうでしょうか?
現在のPCで、WASAPIの0.01秒よりも、よほど遅い環境というのは、
どの程度遅いのかまったく知識がたりず…よろしければ感想など頂けると助かります。
よろしくお願いいたしますm(__)m
/////////////////////////////////////////////////////////////////
#include "DxLib.h"
float FPSave(){ static float rt=0; static int t=GetNowCount(),m=t,i=0; i++;if(i>120){i=0;m=t;t=GetNowCount();rt=1000.0f/((t-m)/120.0f);} return rt;}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
ChangeWindowMode( TRUE ) ; DxLib_Init(); SetDrawScreen( DX_SCREEN_BACK ) ;
int AddCount= 0;
int H0 = LoadSoftSound( "test.wav" ) ; // 「主音」
int 総数 = GetSoftSoundSampleNum( H0 ) ; // サウンドの総サンプル数を取得しておく
int PLAYER = MakeSoftSoundPlayer( H0 ) ; // プレイヤーの作成
int VOLUME = 256;
int H1 = LoadSoundMem( "test.wav",1); // 「副音」
int T=-1,m=0;
int N=5;
StartSoftSoundPlayer( PLAYER ) ;
while( ProcessMessage() == 0 )
{
ClearDrawScreen() ;
while( GetStockDataLengthSoftSoundPlayer( PLAYER ) <= 2205 )// 未再生サンプル数が 2205(44100/20※0.05秒)以下の場合は繰り返す
{
int CH1, CH2 ;
ReadSoftSoundData( H0, AddCount, &CH1, &CH2 ) ;
AddOneDataSoftSoundPlayer( PLAYER, CH1 * VOLUME / 256, CH2 * VOLUME / 256 ) ;
AddCount ++ ;
if( AddCount >= 総数 ){ AddCount = 0 ;T=GetNowCount(); }
}
if( T>=0&& GetNowCount()>=T+86-10){T=-1;PlaySoundMem(H1,DX_PLAYTYPE_BACK);}// (0.05秒+0.0333秒)/0.0166 = 5
if( CheckHitKey( KEY_INPUT_UP )==1 && VOLUME < 256){ VOLUME ++ ; }// 上キー
if( CheckHitKey( KEY_INPUT_DOWN )==1 && VOLUME > 0 ){ VOLUME -- ; }// 下キー
if( CheckHitKey( KEY_INPUT_LEFT )==1 && m==0){ N ++ ;m=10; } // 左キー遅らせる
if( CheckHitKey( KEY_INPUT_RIGHT)==1 && m==0){ N -- ;m=10; } // 右キー早める
DrawFormatString( 0, 32, GetColor(255,255,255),"ずらすタイミング(%d) FPS(%.1f)", N,FPSave() ) ;
ScreenFlip() ;if(m>0)m--;
}
DxLib_End() ;
return -1 ;
}
 |
Re: CheckSoundMemについて ( No.11 ) |
- 名前:管理人 日時:2023/02/13 00:02
> >また、サウンドAPIがサウンドデータを一度に処理するサンプル数はサウンドAPI毎に異なる〜
> これがよくわからなかったのですが、つまりWASAPIが0.01秒単位で発音タイミングが来るという意味でしょうか?
> そう解釈して前のめりにして、その分-10にしました。
AddDataSoftSoundPlayer を使用する例では一度に 4410サンプル処理するように、
サウンドAPIがサウンドデータを処理する際も1サンプルづつではなく一度に複数のサンプルを処理します
WASAPI の場合は一度に処理するサンプル数が 0.01秒分( 441サンプルや 480サンプル )というわけです
( 尚、WASAPI 初期化時の設定によってこのサンプル数は変化します )
> 古いPCでの動作は気にしないつもりなのですが、
> これで最悪で2フレ程度の誤差に収まると思うのですが、どうでしょうか?
確かにフレーム数でタイミングを図るのではなく GetNowCount() の戻り値を使用して
再生タイミングを図るのでしたら2フレ程度の誤差に収まると思います
|
Re: CheckSoundMemについて ( No.12 ) |
- 名前:たろう(解決) 日時:2023/02/13 00:21
ありがとうございます、大変勉強になりました。
複数個プレイヤーを使うのをやめて一つにするほうがもしかすると
自由度が上がる気もしていて、決めかねているのですが
どちらにしても希望通りの動作を得る方法が分かり
大変助かりました。
今回もまた、長々と失礼いたしました。
ありがとうございましたm(__)m
|
Re: CheckSoundMemについて ( No.13 ) |
- 名前:たろう 日時:2023/02/25 19:08
また蒸し返してすみません、たろうです。
下の様に二つの方法で「test.wav」を読み込みんで
それぞれ音量を変えてMakeSoftSoundPlayerの音とPlaySoundMemの音を
聞き比べるプログラムを組んだのですが、
音量を80くらいにすると明らかにMakeSoftSoundPlayerの音のほうが大きくなってしまいます。
PlaySoundMemの音量と揃えたいのですが、
どのように指定したらよいでしょうか?
教えていただけると助かります
よろしくお願いいたしますm(__)m
#include "DxLib.h"
float FPSave(){ static float rt=0; static int t=GetNowCount(),m=t,i=0; i++;if(i>120){i=0;m=t;t=GetNowCount();rt=1000.0f/((t-m)/120.0f);} return rt;}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
ChangeWindowMode( TRUE ) ; DxLib_Init(); SetDrawScreen( DX_SCREEN_BACK ) ;
int AddCount= 0;
int H0 = LoadSoftSound( "test.wav" ) ; // 「主音」
int 総数 = GetSoftSoundSampleNum( H0 ) ; // サウンドの総サンプル数を取得しておく
int PLAYER = MakeSoftSoundPlayer( H0 ) ; // プレイヤーの作成
int VOLUME = 256;
int H1 = LoadSoundMem( "test.wav",1); // 「副音」
int T=-1,m=0;
StartSoftSoundPlayer( PLAYER ) ;
while( ProcessMessage() == 0 )
{
ClearDrawScreen() ;
while( GetStockDataLengthSoftSoundPlayer( PLAYER ) <= 2205 )// 未再生サンプル数が 2205(44100/20※0.05秒)以下の場合は繰り返す
{
int CH1, CH2 ;
ReadSoftSoundData( H0, AddCount, &CH1, &CH2 ) ;
AddOneDataSoftSoundPlayer( PLAYER, CH1 * VOLUME / 256, CH2 * VOLUME / 256 ) ;
AddCount ++ ;
if( AddCount >= 総数 ){ AddCount = 0 ;T=GetNowCount(); }
}
if( T>=0&& GetNowCount()>=T+500){T=-1;ChangeVolumeSoundMem(VOLUME,H1) ;PlaySoundMem(H1,DX_PLAYTYPE_BACK);}// (0.05秒+0.0333秒)/0.0166 = 5
if( CheckHitKey( KEY_INPUT_UP )==1 && VOLUME < 256){ VOLUME ++ ; }// 上キー
if( CheckHitKey( KEY_INPUT_DOWN )==1 && VOLUME > 0 ){ VOLUME -- ; }// 下キー
DrawFormatString( 0, 32, GetColor(255,255,255),"音量(%d) FPS(%.1f)", VOLUME,FPSave() ) ;
ScreenFlip() ;if(m>0)m--;
}
DxLib_End() ;
return -1 ;
}
 |
Re: CheckSoundMemについて ( No.14 ) |
- 名前:管理人 日時:2023/02/26 14:51
ChangeVolumeSoundMem による音量指定は、DirectSound などがデシベル( dB )での指定となっている
関係で計算式が少し複雑になっています
ChangeVolumeSoundMem に渡す音量値と同じボリューム計算をされたい場合は
CH1 と CH2 に乗算する値を以下の式で算出するようにしてください m(_ _)m
( CalcVolume の計算に処理負荷の高い pow や log10 を使用しているので、whileループの外で1回だけ計算しています )
int CalcVolume = ( int )( pow( 10.0f, log10( VOLUME / 256.0 ) * 2.5 ) * 256 );
while( GetStockDataLengthSoftSoundPlayer( PLAYER ) <= 2205 )// 未再生サンプル数が 2205(44100/20※0.05秒)以下の場合は繰り返す
{
int CH1, CH2 ;
ReadSoftSoundData( H0, AddCount, &CH1, &CH2 ) ;
AddOneDataSoftSoundPlayer( PLAYER, CH1 * CalcVolume / 256, CH2 * CalcVolume / 256 ) ;
AddCount ++ ;
if( AddCount >= 総数 ){ AddCount = 0 ;T=GetNowCount(); }
}
|
Re: CheckSoundMemについて ( No.15 ) |
- 名前:たろう(解決) 日時:2023/02/26 19:16
いつもありがとうございます。
早速確認させていただきました。
望み通りの結果が得られたようです。
お忙しいところご対応いただき、
ありがとうございましたm(__)m
|
|