トップページ > 記事閲覧
音楽ファイルの波形
名前:うずら 日時: 2014/09/23 17:59

質問1 現在制作しているソフトで、音楽ファイルの波形を表示する必要があるのですが、 プログラム全体がDXライブラリを使用していているので DXライブラリのサウンドハンドルから波形データを取り出したいです。 イメージとしてはフリーソフトのAudacityのようなものです。 自分で組もうとも思ったのですが、ライブラリでそういうことができると WaveやMP3,Oggなど複数フォーマットの対応が簡単なのでできれば自作は避けたいです。 現在ライブラリにはそのような機能が存在しますか? 無い場合機能の追加をお願いできますか?(特に急ぎの案件ではないです) 質問2 GetCurrentPositionSoundMem関数を使用して サウンドハンドルの現在再生位置を取得したいのですが、 この関数はメモリに読み込んであるサウンドハンドルなら 必ず正常な結果が帰ってきますか? (類似の関数で正しくない結果が返ってくる場合があると書いてあるものがあったので)
メンテ

Page: 1 |

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 を使用することをお勧めします
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存