ストリーミング且つループ再生そのものは問題なく出来たのですが、プツッ、っといったノイズが混じります。
多分ハードウェア的な問題だろうかと思い調べてみたのですが、どうやらループ箇所の波形データの不規則な変化によるノイズじゃないかと思いました。
終端ループ位置→ノイズ→開始ループ→終端ループ位置→ノイズ→・・・・・
となっているので終端のループ位置の波形データと開始位置の波形データの大きな相違が原因ではと思うのですが、いかんせん音を鳴らす仕組みがハードウェアレベルで理解出来て居ないので良く分かりません。
どこかのスレッドにあったシーク前に
source_voice->SetVolume(0.0f);
をやってみたのですがやはりノイズがありました。
これを解消するためにはどうしたら良いでしょうか。
ちなみに、ストリーミングとループ処理はCallBackでイベントを引っ掛けてメンバ関数をスレッド関数にして待機させています。
XAudioでのループ再生時のノイズについて
Re: XAudioでのループ再生時のノイズについて
コードを乗せた方が分かりやすいと思うので
Seek()はwaveファイルの読み取り位置をループ初期位置に設定する関数です。
また、CSourceVoiceStreamはCWaveFileを継承しています。
また、AddBuffer()はバッファを追加する関数です
整理しきれていないので、ごちゃごちゃしてますが其処はお許し下さい。
エラーチェックが凄く甘いですが、ノイズの原因を取ってからにしようと思ったので後回しになってます。
void WaitEvent(){
//イベントハンドルの取得 call_backを包含し、ファンクタでイベントハンドルを取得出来るようにしてます。
HANDLE handle[2]={call_back(STREAM_END_EV),call_back(BUFFER_END_EV)};
//イベント用フラグ
DWORD flag;
while(loop==TRUE){
flag=WaitForMultipleObjects(2,handle,FALSE,loop_end_pos);
if(flag==WAIT_OBJECT_0){
//ループ処理
LoopSeek();
ResetEvent(handle[0]);
write_end=FALSE;
//二つのバッファを交互に使用しているので、二つ入れておく
AddBuffer();
AddBuffer();
}
if(flag==WAIT_OBJECT_0+1){
//ストリーミング処理
if(!write_end) AddBuffer();
ResetEvent(handle[1]);
}
}
}
また、CSourceVoiceStreamはCWaveFileを継承しています。
void CSourceVoiceStream::Seek(){
CWaveFile::Seek(loop_primary_pos,SEEK_SET);
CurrentPos=loop_primary_pos;
}
HRESULT CWaveFile::Seek(DWORD offset,int iOrigin){
if(hmmio==NULL){
DXTRACE_MSG(_T("Seek関数 hmmioが初期化されていません"));
return S_FALSE;
}
if(WSize<offset+SeekPos){
DXTRACE_MSG(_T("Seek関数 オフセット位置が大きすぎます"));
return S_FALSE;
}
SeekPos=mmioSeek(hmmio,offset,iOrigin);
if(-1==SeekPos){
DXTRACE_MSG( "Seek関数 シークエラー", E_FAIL );
return S_FALSE;
}
return S_OK;
}
整理しきれていないので、ごちゃごちゃしてますが其処はお許し下さい。
void CSourceVoiceStream::AddBuffer(){
DWORD Read_=pwfx->nAvgBytesPerSec*PlaySec/1000;
if(write_end) return;
//サイズが大きければ切り詰め
if(WSize<CurrentPos+Read_){
Read_=WSize-CurrentPos;
write_end=TRUE;
}
//ループ処理がある場合の切り詰め
if(loop){
if(loop_end_pos<=CurrentPos+Read_){
Read_=loop_end_pos-CurrentPos;
write_end=TRUE;
}
}
Read(Read_,Data[flip]); //秒数分読み込む
CurrentPos+=Data[flip].size();
XAUDIO2_BUFFER buffer = { 0 };
if(write_end){
buffer.Flags = XAUDIO2_END_OF_STREAM;
}
buffer.AudioBytes = Data[flip].size();
buffer.pAudioData = &Data[flip][0];
source_voice->SubmitSourceBuffer( &buffer );
if(flip==0)
flip=1;
else
flip=0;
}
Re: XAudioでのループ再生時のノイズについて
Data は std::vector ですか?
もしそうだとすると、
buffer.AudioBytes = Data[flip].size();
の部分が怪しいです。
ちゃんと読み取ったサイズに合わせて resize していますか?
もしくは、buffer.AudioBytes には Read() で読み取ることのできたバイト数を直接設定するべきかと思います。
もしそうだとすると、
buffer.AudioBytes = Data[flip].size();
の部分が怪しいです。
ちゃんと読み取ったサイズに合わせて resize していますか?
もしくは、buffer.AudioBytes には Read() で読み取ることのできたバイト数を直接設定するべきかと思います。
Re: XAudioでのループ再生時のノイズについて
はい、std::vectorです。梨樹 さんが書きました:Data は std::vector ですか?
もしそうだとすると、
buffer.AudioBytes = Data[flip].size();
の部分が怪しいです。
ちゃんと読み取ったサイズに合わせて resize していますか?
もしくは、buffer.AudioBytes には Read() で読み取ることのできたバイト数を直接設定するべきかと思います。
//CWaveFile::Read関数
HRESULT CWaveFile::Read(DWORD size,std::vector<BYTE> &Data){
if(hmmio==NULL){
DXTRACE_MSG(_T("Read関数 hmmioが初期化されていません"));
return S_FALSE;
}
if(WSize<SeekPos+size){ //超えていたら
size=WSize-SeekPos; //サイズの調整
}
if(size<=0){
return S_FALSE;
}
std::vector<BYTE> t_data(size);
ReadSize = mmioRead(hmmio,(HPSTR)&t_data[0],size);
if(ReadSize!=t_data.size()){
DXTRACE_MSG(_T("Read関数 サイズが違います"));
return S_FALSE;
}
Data=t_data;
return S_OK;
}
これで切り詰めもばっちりかとおもいますし、ずれていたら失敗するようになってます。
(ブレークポイント今は入れてるだけですが、後々、HRESULTのチェックします)
Re: XAudioでのループ再生時のノイズについて
追加なのですが、いきなり停止してもプツっと言うノイズが出ます。
一時停止なら問題ないのですが、いきなり無音状態に移行すると同じようなノイズが出ました。
そこで暫く自分で探してみて、同じような症状が。
//2ch DirectX初心者スレ30より
停止→再構築→再生でノイズが入るわけじゃなくて
再生中のを停止する時点でノイズ入ってるな
これは多分何やっても駄目だと思う
停止ではなく段階的にボリューム落として無音にしていきつつ
別バッファで新しく再生とやれば大丈夫だと思うが、多分これでは求めてる物にはならないだろう
良く考えるとこの状態でした。
音が鳴ってる状態
↓
直後、無音になるとプツっという音が鳴る。
先ほど確認した所、XAudio2のループを使っても出ましたので。
うーん、上記にある通り段階的にボリュームを落とすって結構難しそうなんですが(自分がぱっと思いついたのはループ最初とループ最期のバッファを別に用意して、10msec位で段階的にボリュームを落とし、ループ始めにボリュームを上げる方法)。
もう気にしない方向で行きますかね・・・・。
追記
XAudioで無理に大きなファイル(BGM用)を再生するより、directshowを使った方が良いですかね。(ただ流すだけならさして難しくありませんし)
前にISleさんが仰ったように再生グラフ辺りで戻せそうですので。
一時停止なら問題ないのですが、いきなり無音状態に移行すると同じようなノイズが出ました。
そこで暫く自分で探してみて、同じような症状が。
//2ch DirectX初心者スレ30より
停止→再構築→再生でノイズが入るわけじゃなくて
再生中のを停止する時点でノイズ入ってるな
これは多分何やっても駄目だと思う
停止ではなく段階的にボリューム落として無音にしていきつつ
別バッファで新しく再生とやれば大丈夫だと思うが、多分これでは求めてる物にはならないだろう
良く考えるとこの状態でした。
音が鳴ってる状態
↓
直後、無音になるとプツっという音が鳴る。
先ほど確認した所、XAudio2のループを使っても出ましたので。
うーん、上記にある通り段階的にボリュームを落とすって結構難しそうなんですが(自分がぱっと思いついたのはループ最初とループ最期のバッファを別に用意して、10msec位で段階的にボリュームを落とし、ループ始めにボリュームを上げる方法)。
もう気にしない方向で行きますかね・・・・。
追記
XAudioで無理に大きなファイル(BGM用)を再生するより、directshowを使った方が良いですかね。(ただ流すだけならさして難しくありませんし)
前にISleさんが仰ったように再生グラフ辺りで戻せそうですので。