Re: 音楽ファイルの波形 ( No.1 ) |
- 名前:管理人 日時:2014/09/24 00:26
> 質問1
波形データそのものでしたら LoadSoftSound という関数でサウンドファイルを読み込んで得られる
ソフトサウンドハンドルを ReadSoftSoundData という関数に渡して読み取ることができます
// ソフトウエアで扱う波形データハンドルをサウンドファイルから作成する
// ( 戻り値 -1:エラー -1以外:ソフトサウンドハンドル )
int LoadSoftSound( const TCHAR *FileName ) ;
// ソフトウエアで扱う波形データハンドルのサンプルを読み取る
int ReadSoftSoundData( int SoftSoundHandle, int SamplePosition, int *Channel1, int *Channel2 ) ;
対応しているフォーマットは LoadSoundMem と同じです
ReadSoftSoundData は8bit量子化のサウンドの場合は -128〜127 の値が、
16bit量子化のサウンドの場合が -32768〜32767 の値が Channel1, Channel2 に代入されます
他に読み込んだサウンドのサンプル数を取得する関数やフォーマットを取得する関数などがあります
// ソフトウエアで扱う波形データハンドルのサンプル数を取得する
int GetSoftSoundSampleNum( int SoftSoundHandle ) ;
// ソフトウエアで扱う波形データハンドルのフォーマットを取得する
int GetSoftSoundFormat( int SoftSoundHandle, int *Channels, int *BitsPerSample, int *SamplesPerSec ) ;
あと1サンプル毎に ReadSoftSoundData で読み取ると遅いので、GetSoftSoundDataImage で
サウンドデータが格納されているメモリアドレスを取得して、ポインタでゴリゴリアクセスする方法もあります
// ソフトウエアで扱う波形データハンドルの波形イメージが格納されているメモリアドレスを取得する
void *GetSoftSoundDataImage( int SoftSoundHandle ) ;
使用し終わったソフトサウンドハンドルは DeleteSoftSound で削除してください
// ソフトウエアで扱う波形データハンドルを削除する
int DeleteSoftSound( int SoftSoundHandle ) ;
> 質問2
正確な再生位置を確実に取得したい場合でしたら、GetCurrentPositionSoundMem の使用も含めて
以下の3点を抑えてください
1.DxLib_Init の前に SetEnableXAudioFlag( FALSE ) ; を実行して、
XAudio ではなく DirectSound を使用するようにする
XAudio は取得できる再生位置は実際に再生されている位置より数ミリ秒遅い値が返ってくるので
DirectSound を使用する方が精度が高いです
2.サウンドファイルはPCMデータのwavファイルか、oggファイルを使用する( MP3は× )
MP3→PCM変換に外部コーデックを使用するので環境によって読み込みが失敗するなど安定しません
加えてMP3の仕様として、MP3変換後と元のPCMでは再生時間が数ミリ秒変化するというものがあり、
正確さが求められる場面では使わないほうが良いです
3.サウンドの再生位置取得には GetCurrentPositionSoundMem を使用する
GetCurrentPositionSoundMem 以外の GetSoundCurrentTime などはサンプル単位ではなく
時間で位置を取得できるのですが、フォーマットの判別が失敗した場合や圧縮フォーマットでは
正しい「サンプル/秒」が取得できていない場合があったりして、変な値が返ってくることがあります
( PCM形式の Wav や Ogg を使用すれば大丈夫だと思いますが・・・ )
|
Re: 音楽ファイルの波形 ( No.2 ) |
- 名前:うずら 日時:2014/09/24 01:10
回答ありがとうございます。何とかできそうです。
LoadSoftSound で生成したサウンドハンドルを再生するには普通のサウンドハンドルと同じく
PlaySoundMemなどで再生することができますか?
ヘッダのソフトサウンドハンドル周りに出てくる
ソフトウエアで扱う波形データのプレイヤーハンドル
というのがよくわかりません(-_-;)
GetSoftSoundDataImage関数についてですが、void型のポインタが返ってきているんですが、
Waveファイルの先頭位置が返ってきてるようなものですか?
|
Re: 音楽ファイルの波形 ( No.3 ) |
- 名前:管理人 日時:2014/09/25 00:11
> LoadSoftSound で生成したサウンドハンドルを再生するには普通のサウンドハンドルと同じく
> PlaySoundMemなどで再生することができますか?
そのまま再生するにはソフトウエアサウンドのプレイヤーを使う方法がありますが、処理負荷が高く、
普通の再生には使わない特殊用途用なので、普通に再生する場合は LoadSoundMemFromSoftSound という関数で
ソフトサウンドハンドルからサウンドハンドルを作成して、PlaySoundMem で再生します
// ソフトウエアサウンドハンドルが持つサウンドデータからサウンドハンドルを作成する
int LoadSoundMemFromSoftSound( int SoftSoundHandle ) ;
この関数で作成したサウンドハンドルはソフトハンドルとは関係がありませんので、
必要が無くなったら DeleteSoundMem で削除してください
> ヘッダのソフトサウンドハンドル周りに出てくる
> ソフトウエアで扱う波形データのプレイヤーハンドル
> というのがよくわかりません(-_-;)
ソフトサウンドのプレイヤーは動的に作成した波形を再生するための機能で、
前述の通り処理負荷が高く、仕組み上どうしても遅延が発生するので、通常の再生の用途では使用しません
こちらのスレッドで「二つのBGMファイルを全く同じタイミングで再生したい」という
ご要望に応える形で実装しました、No.6に二つのwavファイルを合成して再生するプログラムがありますので、よろしければご覧ください
http://hpcgi2.nifty.com/natupaji/bbs/patio.cgi?mode=past&no=1800
> GetSoftSoundDataImage関数についてですが、void型のポインタが返ってきているんですが、
> Waveファイルの先頭位置が返ってきてるようなものですか?
Waveファイルの先頭アドレスではなく、波形データの先頭アドレスが返ってきます、
( char * ) や ( short * ) にキャストして使用します
例えば量子化 16bit 2チャンネルのサウンドデータの1234サンプル目を ReadSoftSoundData で読み取ると以下のようになりますが
int Channel1, Channel2 ;
ReadSoftSoundData( SoftSoundHandle, 1234, &Channel1, &Channel2 ) ;
GetSoftSoundDataImage を使用すると以下のようになります
short *PcmData ;
int Channel1, Channel2 ;
PcmData = ( short * )GetSoftSoundDataImage( SoftSoundHandle ) ;
Channel1 = ( int )PcmData[ 1234 * 2 ] ;
Channel2 = ( int )PcmData[ 1234 * 2 + 1 ] ;
1サンプルや数サンプルだけアクセスする場合は ReadSoftSoundData を使用しても GetSoftSoundDataImage を使用しても
処理負荷に殆ど違いはありませんが、例えば全てのサンプルにアクセスするような場合は1サンプルごとに
ReadSoftSoundData を呼ぶ場合と、GetSoftSoundDataImage を最初の1回だけ呼んであとのサンプルはポインタを使うだけでは
処理負荷が全然違ってきます
ReadSoftSoundData を使用して全てのサンプルを読み取った場合
int SampleNum, Channel1, Channel2, i ;
SampleNum = GetSoftSoundSampleNum( SoftSoundHandle ) ;
for( i = 0 ; i < SampleNum ; i ++ )
{
// 毎回関数を呼ぶと遅い
ReadSoftSoundData( SoftSoundHandle, i, &Channel1, &Channel2 ) ;
}
GetSoftSoundDataImage を使用して全てのサンプルを読み取った場合
int SampleNum, Channel1, Channel2, i ;
short *PcmData ;
SampleNum = GetSoftSoundSampleNum( SoftSoundHandle ) ;
PcmData = ( short * )GetSoftSoundDataImage( SoftSoundHandle ) ;
for( i = 0 ; i < SampleNum ; i ++ )
{
// 関数を呼ばないので速い
Channel1 = ( int )PcmData[ 0 ] ;
Channel2 = ( int )PcmData[ 1 ] ;
PcmData += 2 ;
}
ただ、ポインタは扱いを少し間違うと直ぐエラーが発生するので、ReadSoftSoundData で速度的に問題ない場合は
ReadSoftSoundData を使用することをお勧めします
|
|