在MAC上基于QT和ffmpeg实现最简单播放器,在完成声音播放模块后导致无法正常播放,QAudioOutput start后state仍是idel,将QAudioOutput buffer写满后就不能继续写数据了,导致播放被卡死.
QAudioOutput创建代码:
1 | QAudioFormat fmt; |
在stackoverflow Qt QAudioOutput push mode看到别人的问题和解释,发现是setSampleType引起的,代码在window上可以正常跑,只是在mac上失败.
问题
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:
1 | uint16_t *audio_outputBuffer; |
Implementation:
1 | audio_outputBuffer = (uint16_t *) malloc((96000 * 4) * 300); |
Next, I set up my audio device with some basic parameters:
1 | // Set up the format |
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:
1 | if(audio_outputDevice->isOpen() && audio_outputStream->state() != QAudio::StoppedState) { |
Once I start the audio output process, I get the following output on the console:
1 | Current audio state: 3 Error: 0 |
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.
解释
Upfront just wanna point out: This is not a Qt bug. Why? The answer is that in the WAV spec’, 8-bit samples are always unsigned, whereas 16-bit samples are always signed. Any other combination does not work. This is device related, the framework can not do anything about it.
So this will not work because you have set 16 bit sample size and unsigned integer format. And yes, the solution is: you have to set the sample type to signed for 16-bit resolution:
1 | format.setSampleType(QAudioFormat::SignedInt); |
Inversely for 8-bit samples you would have to put:
1 | format.setSampleType(QAudioFormat:UnsignedInt); |
Also this very similar question (same problem but with 8-bit) shows you that it is not a particular problem of using signed or unsigned samples in Qt, but that it is the combination of samples size and type that matters (for the audio device, not for Qt ;) QAudioOutput in Qt5 is not producing any sound
IMHO the fact that Qt does not take care of handling these cases by forcing the correct format is a flaw but not a lack in functionnality.
You can learn more about this in the notes section of this page: https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
I’ve figured this out — apparently Qt has issues with UNSIGNED samples. If you set the sample type to signed, everything works fine, regardless of platform.