I've got a question about using QAudioOutput to directly write samples at a specific sample rate to the sound output device. I'm writing an emulator that emualates sound chips on a per-frame basis, and then gets a buffer containing a frame's worth of audio samples, which I would like to write to the audio output. Currently, to test my audio output routine, I allocate a huge (5 minute) buffer to put random numbers into, like so:
Header:
uint16_t *audio_outputBuffer;
uint32_t audio_bytesRemainingToRead;
QAudioOutput *audio_outputStream;
QIODevice *audio_outputDevice;
Implementation:
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;
Next, I set up my audio device with some basic parameters:
// 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();
Then, in my timer tick routine, which is called by a QTimer at 60 FPS, I do the following code to write a 'chunk' of audio data to the QAudioOutput's buffer:
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();
}
Once I start the audio output process, I get the following output on the console:
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)
To me, it looks like QAudioOutput isn't flushing it's internal buffer to the sound card, which goes along with the entire "no sound coming out of my computer" thing.
What would cause this issue, and how could I fix it?
(By the way, I'm compiling my code against Qt 4.8.1, on Mac OS X 10.7.4.)
Thanks for any answers.