我有一个关于使用QAudioOutput将特定采样率的样本直接写入声音输出设备的问题。我正在编写一个仿真器,该仿真器以每帧为基础对声音芯片进行仿真,然后获得一个包含一帧音频样本的缓冲区,我想将其写入音频输出。当前,为了测试我的音频输出例程,我分配了一个巨大的缓冲区(5分钟)以将随机数放入其中,如下所示:
header :
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();
然后,在我的计时器滴答例程(由QTimer以60 FPS调用)中,我执行以下代码将音频数据的“块”写入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 X 10.7.4上针对Qt 4.8.1编译我的代码。)
感谢您的任何答案。
最佳答案
前期只想指出:这不是Qt错误。为什么?答案是在“WAV规范”中,8位采样始终是无符号的,而16位采样始终是有符号的。任何其他组合均无效。这与设备有关,框架对此无能为力。
因此这将不起作用,因为您已设置了16位样本大小和无符号整数格式。
是的,解决方案是:您必须将样本类型设置为带符号才能获得16位分辨率:
format.setSampleType(QAudioFormat::SignedInt);
相反,对于8位样本,您必须输入:
format.setSampleType(QAudioFormat:UnsignedInt);
同样,这个非常相似的问题(相同的问题,但是是8位的)也向您表明,在Qt中使用带符号或无符号样本并不是一个特殊的问题,但重要的是样本大小和类型的组合(对于音频设备) ,而不是Qt;)QAudioOutput in Qt5 is not producing any sound
恕我直言,Qt不会通过强制采用正确的格式来处理这些情况,这是一个缺陷,但并非缺乏功能。
您可以在此页面的注释部分中了解更多有关此的信息:https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
关于Qt QAudioOutput推送模式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15651407/