5

QAudioOutputを使用して、特定のサンプルレートでサンプルをサウンド出力デバイスに直接書き込むことについて質問があります。フレームごとにサウンドチップをエミュレートし、オーディオ出力に書き込みたいフレーム相当のオーディオサンプルを含むバッファーを取得するエミュレーターを作成しています。現在、オーディオ出力ルーチンをテストするために、次のように、ランダムな数値を入れるための巨大な(5分)バッファーを割り当てています。

ヘッダ:

uint16_t *audio_outputBuffer;
uint32_t audio_bytesRemainingToRead;
QAudioOutput *audio_outputStream;
QIODevice *audio_outputDevice;

実装:

audio_outputBuffer = (uint16_t *) malloc((96000 * 4) * 300);
int i = 0;

uint16_t *tempAudioBuffer = audio_outputBuffer;
for(i = 0; i < ((96000 * 4) * 150); i++) {
    *tempAudioBuffer = (uint16_t) rand() & 0xFFFF;
    tempAudioBuffer++;
}

audio_bytesRemainingToRead = (96000 * 4) * 300;

次に、いくつかの基本的なパラメータを使用してオーディオデバイスを設定します。

// Set up the format
QAudioFormat format;
format.setFrequency(96000); // Usually this is specified through an UI option
format.setChannels(2);
format.setSampleSize(16);
format.setCodec("audio/pcm");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::UnSignedInt);

// There's code here to notify the user of inability to match the format and choose an action, which is omitted for clarity

// Create audio output stream, set up signals
audio_outputStream = new QAudioOutput(format, this);

connect(audio_outputStream, SIGNAL(stateChanged(QAudio::State)), this, SLOT(audio_stateChanged(QAudio::State)));

audio_outputDevice = audio_outputStream->start();

次に、60 FPSでQTimerによって呼び出されるタイマーティックルーチンで、次のコードを実行して、オーディオデータの「チャンク」をQAudioOutputのバッファーに書き込みます。

if(audio_outputDevice->isOpen() && audio_outputStream->state() != QAudio::StoppedState) {
    qint64 bytesOfAudioWrittenToDevice = audio_outputDevice->write((char *) audio_outputBuffer, audio_outputStream->periodSize());
    audio_bytesRemainingToRead -= bytesOfAudioWrittenToDevice;
    qDebug() << "Wrote" << bytesOfAudioWrittenToDevice << "bytes of audio to output device. Remaining bytes to read:" << audio_bytesRemainingToRead;
    qDebug() << "Free bytes in audio output:" << audio_outputStream->bytesFree();
}

オーディオ出力プロセスを開始すると、コンソールに次の出力が表示されます。

Current audio state: 3 Error: 0 
Wrote 2048 bytes of audio to output device. Remaining bytes to read: 115197952 
Free bytes in audio output: 6144 
Current audio state: 0 Error: 0 
Wrote 2048 bytes of audio to output device. Remaining bytes to read: 115195904 
Free bytes in audio output: 4096 
Wrote 2048 bytes of audio to output device. Remaining bytes to read: 115193856 
Free bytes in audio output: 2048
Wrote 2048 bytes of audio to output device. Remaining bytes to read: 115191808 
Free bytes in audio output: 0 (This and the above line is repeated forever)

私には、QAudioOutputが内部バッファをサウンドカードにフラッシュしていないように見えます。これは、「コンピュータから音が出ない」こと全体に伴います。

この問題の原因は何ですか?また、どうすれば修正できますか?

(ちなみに、私はMac OS X10.7.4のQt4.8.1に対してコードをコンパイルしています。)

答えてくれてありがとう。

4

2 に答える 2

8

前もって指摘したいのですが、これはQtのバグではありません。なんで?答えは、WAV仕様では、8ビットサンプルは常に署名されていないのに対し、16ビットサンプルは常に署名されているということです。他の組み合わせは機能しません。これはデバイスに関連しており、フレームワークはそれについて何もできません。

したがって、16ビットのサンプルサイズと符号なし整数形式を設定しているため、これは機能しません。はい、解決策は次のとおりです。サンプルタイプを16ビット解像度の署名付きに設定する必要があります。

format.setSampleType(QAudioFormat::SignedInt);

逆に、8ビットサンプルの場合は、次のように入力する必要があります。

format.setSampleType(QAudioFormat:UnsignedInt);

また、この非常によく似た質問(同じ問題ですが8ビット)は、Qtで符号付きまたは符号なしのサンプルを使用することの特定の問題ではなく、サンプルのサイズとタイプの組み合わせが重要であることを示しています(オーディオデバイスの場合) 、Qt用ではありません;)Qt5のQAudioOutputは音を出していません

私見では、Qtが正しい形式を強制することによってこれらのケースを処理しないという事実は欠陥ですが、機能性の欠如ではありません。

これについて詳しくは、このページのメモセクションをご覧ください:https ://ccrma.stanford.edu/courses/422/projects/WaveFormat/

于 2014-01-04T06:37:33.523 に答える
1

私はこれを理解しました—どうやらQtはUNSIGNEDサンプルに問題があります。サンプルタイプをsignedに設定すると、プラットフォームに関係なく、すべてが正常に機能します。

于 2013-03-31T14:52:42.197 に答える