XAudioでのループ再生時のノイズについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
赤鬼
記事: 58
登録日時: 8年前

XAudioでのループ再生時のノイズについて

#1

投稿記事 by 赤鬼 » 7年前

ストリーミング且つループ再生そのものは問題なく出来たのですが、プツッ、っといったノイズが混じります。
多分ハードウェア的な問題だろうかと思い調べてみたのですが、どうやらループ箇所の波形データの不規則な変化によるノイズじゃないかと思いました。
終端ループ位置→ノイズ→開始ループ→終端ループ位置→ノイズ→・・・・・
となっているので終端のループ位置の波形データと開始位置の波形データの大きな相違が原因ではと思うのですが、いかんせん音を鳴らす仕組みがハードウェアレベルで理解出来て居ないので良く分かりません。
どこかのスレッドにあったシーク前に
source_voice->SetVolume(0.0f);
をやってみたのですがやはりノイズがありました。
これを解消するためにはどうしたら良いでしょうか。

ちなみに、ストリーミングとループ処理はCallBackでイベントを引っ掛けてメンバ関数をスレッド関数にして待機させています。

赤鬼
記事: 58
登録日時: 8年前

Re: XAudioでのループ再生時のノイズについて

#2

投稿記事 by 赤鬼 » 7年前

コードを乗せた方が分かりやすいと思うので

コード:

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]);
		}
	}
}
Seek()はwaveファイルの読み取り位置をループ初期位置に設定する関数です。
また、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;
}
また、AddBuffer()はバッファを追加する関数です
整理しきれていないので、ごちゃごちゃしてますが其処はお許し下さい。

コード:

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;
}
エラーチェックが凄く甘いですが、ノイズの原因を取ってからにしようと思ったので後回しになってます。

アバター
lriki
記事: 88
登録日時: 9年前

Re: XAudioでのループ再生時のノイズについて

#3

投稿記事 by lriki » 7年前

Data は std::vector ですか?

もしそうだとすると、
buffer.AudioBytes = Data[flip].size();
の部分が怪しいです。
ちゃんと読み取ったサイズに合わせて resize していますか?

もしくは、buffer.AudioBytes には Read() で読み取ることのできたバイト数を直接設定するべきかと思います。

赤鬼
記事: 58
登録日時: 8年前

Re: XAudioでのループ再生時のノイズについて

#4

投稿記事 by 赤鬼 » 7年前

梨樹 さんが書きました:Data は std::vector ですか?

もしそうだとすると、
buffer.AudioBytes = Data[flip].size();
の部分が怪しいです。
ちゃんと読み取ったサイズに合わせて resize していますか?

もしくは、buffer.AudioBytes には Read() で読み取ることのできたバイト数を直接設定するべきかと思います。
はい、std::vectorです。

コード:

//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のチェックします)

赤鬼
記事: 58
登録日時: 8年前

Re: XAudioでのループ再生時のノイズについて

#5

投稿記事 by 赤鬼 » 7年前

追加なのですが、いきなり停止してもプツっと言うノイズが出ます。
一時停止なら問題ないのですが、いきなり無音状態に移行すると同じようなノイズが出ました。
そこで暫く自分で探してみて、同じような症状が。

//2ch DirectX初心者スレ30より
停止→再構築→再生でノイズが入るわけじゃなくて
再生中のを停止する時点でノイズ入ってるな
これは多分何やっても駄目だと思う
停止ではなく段階的にボリューム落として無音にしていきつつ
別バッファで新しく再生とやれば大丈夫だと思うが、多分これでは求めてる物にはならないだろう

良く考えるとこの状態でした。
音が鳴ってる状態

直後、無音になるとプツっという音が鳴る。
先ほど確認した所、XAudio2のループを使っても出ましたので。

うーん、上記にある通り段階的にボリュームを落とすって結構難しそうなんですが(自分がぱっと思いついたのはループ最初とループ最期のバッファを別に用意して、10msec位で段階的にボリュームを落とし、ループ始めにボリュームを上げる方法)。

もう気にしない方向で行きますかね・・・・。

追記
XAudioで無理に大きなファイル(BGM用)を再生するより、directshowを使った方が良いですかね。(ただ流すだけならさして難しくありませんし)
前にISleさんが仰ったように再生グラフ辺りで戻せそうですので。

閉鎖

“C言語何でも質問掲示板” へ戻る