Solved Can't get QAudioInput from qtaudio_windows to work
-
I'm using the qtaudio_windows plugin because I'm running on Win7, and the standard multimedia stuff assumes Win8 or higher.
I create a QAudioInput, successfully set its format to 48KHz 16-bit stereo, give it a 4K buffer, and set its notify interval to 6ms (a little over 1/4 of the buffer). Out of curiosity, I read back the buffer size and interval to make sure the driver didn't change them, and it didn't.
In my notify handler, I use readAll() on the QIODevice, and I always get a QByteArray whose size is 0, 1638, 2457, or occasionally 3276, all multiples of 819 (0x333) bytes. Out of curiosity, I called bytesAvailable() on the device before the readAll(), and I always get zero!
The data I'm getting looks like valid audio samples (I know what kind of waveforms I'm listening to), but of course the data should be a multiple of four bytes, so there are partial samples at the beginning and/or end. When I add up the number of bytes I get over time, it comes out to about a 47.1KHz sample rate, so it is dropping data, or the 6ms notify interval is averaging out to something less than 6ms.
What could be wrong? You'd think that readAll() would "read all", not almost all. Or does anyone know where the source is for this plugin?
-
Hi,
I might be wrong but I think the notify interval is too small. You are asking to get data at about 167 Herz.
-
@sgaist 6ms isn't unusual for low latency audio, and it's a fast machine. But I changed the buffer size from 4K to 64K, and computed the interval using QAudioFormat::durationForBytes, which came out to 86, and now it's giving me either 13107 or 26214 bytes on every notification. (Note that those are powers of two divided by 10.)
This suggests that the sound card driver is returning blocks of data every 68.266ms, and so the notification interval sometimes finds one block in the buffer, sometimes two. I don't know what the significance of that number is--it's not related to some other standard rate like 44100Hz, or 60Hz, or 59.94Hz NTSC.
But it shouldn't matter, except that my program is getting non-integral numbers of samples. I've never heard of an audio device delivering or accepting numbers of bytes that weren't integral multiples of the frame size.
So I don't know if this is a Qt issue or if my sound card has a buggy driver. I'd really like to find the source code for this version of QAudioInput, but the Qt source library looks like a huge jungle to me.
-
Hi
- I'd really like to find the source code for this version of QAudioInput
You can browse around at
https://code.woboq.org/qt5/qtmultimedia/src/multimedia/audio/qaudioinput.cpp.html
its hot linked and makes the code easier to navigate (IMHO)
- I'd really like to find the source code for this version of QAudioInput
-
@mrjj That's all the abstract stuff. I need to find the source for the Windows plugin that's pulled in by
QTPLUGIN.audio = qtaudio_windows
in my project file. I searched for files with "qtaudio_windows" in the name and came up empty. -
It's in the plugins sub folder under windowsaudio.
-
@sgaist The problem is in qtmultimedia/src/plugins/windowsaudio/qwindowsaudioinput.cpp, in the open() function. It supplies a default buffer size of 200ms, and assigns a period size (the size of the individual blocks to be returned to the application) to be 1/5 of the buffer size, so you only get complete samples if you explicitly set a buffer size that is a multiple of five frames, whatever that turns out to be (20 bytes for 16-bit stereo). I've filed this bug report. In the meantime, you just have to set an explicit buffer size, instead of letting it choose a default.