waveOut インターフェイスに問題があります。オーディオ出力を非常に簡単にするクラス AudioStream を持つ単純なクラス構造を書きたいと思います。次の引数を取るコンストラクタがあります: AudioStream32(int sampleRate, int sampleSize, bool stereo, int bufferSize) (sampleSize はバイト単位のサンプルのサイズで、残りは自明であることを願っています)
アイデアは、AudioStream を一度初期化してから setSample(float sample) を呼び出してオーディオ ストリームを設定するというものです。このクラスは初期段階にあるため、現在はダブル バッファリングとモノラル サウンドのみが実装されています。
setSample メソッドでは、float サンプルを 0 から 2^(8*sampleSize) の範囲の unsigned int に変換し、その unsigned int を unsigned char に変換します。unsigned int を直接使用することもできますが、その方法では、他の sampleSize に使用するコードを再利用できませんでした。コード:
void AudioStream32::setSample(float sample)
{
unsigned int discreteSample = 1 + mid + ((float)mid * sample);
for (unsigned int i = 0; i < sampleSize; i++)
{
data[pointr++] = (char)(discreteSample & 255);
discreteSample = discreteSample >> 8;
// (same as dividing by 256)
}
//... Non-relevant code that makes sure the buffer is sent to the audio device
mid は、値 (1 << (sampleSize * 8 - 1)) - 1 が割り当てられた unsigned int です (これは、2^(sampleSize * 8 - 1)) を行うより高速な方法です。したがって、sampleSize が 1 の場合、これは 127 に評価され、sampleSize が 2 の場合は 32767 (または、一般に、最大値の約半分) に評価されます。
これは、sampleSize として 1 を使用する場合 (つまり、1 文字をサンプルとして使用する場合) に正常に機能します。しかし、sampleSize として 2 (またはサンプルのサイズとして 2 バイトまたは short int) を使用すると、非常に奇妙な結果が得られます。
単純な正弦波をストリーミングしようとしています。sampleSize として 1 を使用すると、実際に波形として正弦波が得られます。ただし、sampleSize として 2 を使用すると、次の奇妙な波形が得られます。
オーディオ出力とマイク入力を接続するミニジャック ケーブルを介して Audacity に波形を記録し、32 ビット フロート ストリームとして記録しました。出力は、実際には 16 ビットの int ストリームです。
これは、オーバーフローの問題、または unsigned と signed の int または char 間の変換の問題を示しているようです。さらに奇妙な動作が発生します: setSample メソッドに送信するサンプルのスケーリング (またはボリュームの変更など) は問題にならないようです。波形、0.00001 は無音になります)。
非常に奇妙なことに、256 ではなく 512 で割ろうとすると (つまり、setSample メソッドで ">> 8" を ">> 9" に変更すると)、すべてが機能するように見えます (サウンドの変更を含む)。 . ただし、sampleSize を 1 にしたときよりも音が弱くなるので、これはまだ正しい方法ではないようです。
サウンド デバイスに書き込んだサンプルと、サウンド デバイスの出力を単純な方法で比較できないのは残念です。そうすれば、少なくとも問題がバイト形式にあるのか、それとも私が行っている変換にあるのかを知ることができます。
何が起こっているのか誰にも分かりませんか?