class AudioGenerator : public QIODevice { Q_OBJECT public: qint64 readData(char *data, qint64 maxLen) override { // This is called by the audio engine when it needs more data. // You have ~10-50ms to fill this buffer. generateSamples(data, maxLen); return maxLen; } void start() { QAudioFormat format; format.setSampleRate(48000); format.setChannelCount(2); format.setSampleFormat(QAudioFormat::Int16); m_audio = new QAudioSink(format, this); m_audio->start(this); // Qt pulls data automatically } private: QAudioSink *m_audio; };
For a sequencer or drum machine, do not rely on QTimer . Timers are not accurate enough. Instead, use a QAudioSink with a small buffer size and use the number of bytes processed to calculate the exact playback position in samples. Qt makes network audio surprisingly easy. You can pipe a QNetworkAccessManager reply directly into a buffer. qt audio engine
// Simplified streaming concept void NetworkStreamer::onReadyRead() { QByteArray chunk = m_reply->readAll(); m_ringBuffer->write(chunk); if (!m_isPlaying && m_ringBuffer->size() > MIN_BUFFER_SIZE) { m_audioSink->start(m_ringBuffer); // Start only when safe } } 1. The "No Sound" on Linux Qt often defaults to PulseAudio, but if it isn't running, it fails silently. Always check QAudioDevice::availableDevices() and provide a fallback to "default" or "hw:0". 2. Format Mismatches Your QAudioFormat must match the exact format your hardware expects. Query QAudioDevice::preferredFormat() and resample if necessary. Trying to force 96kHz on a soundcard that only supports 48kHz will crash. 3. The Missing Codec QMediaPlayer relies on platform codecs (DirectShow on Windows, GStreamer on Linux, AVFoundation on macOS). MP3 might work on one machine but fail on another. For critical deployments, bundle a decoder (like FFmpeg) and feed raw PCM into QAudioSink . The Future: Qt 6 Multimedia With Qt 6, the multimedia module was largely rewritten. The good news: QAudioSink and QAudioSource are now more stable and cross-platform. The bad news: The QML SoundEffect and MediaPlayer types changed significantly. class AudioGenerator : public QIODevice { Q_OBJECT public:
Have you built an audio tool with Qt? Let me know about your experience with latency and GStreamer backends in the comments. Timers are not accurate enough
However, beware of (not enough data) and overruns (too much data). A professional engine implements a dynamic jitter buffer—essentially a QBuffer that delays playback by 200-500ms to absorb network fluctuations.
If you are starting a new project today, stick to the QAudioSink / QAudioSource C++ classes for engine logic, and expose only control properties (volume, play/pause) to the GUI layer via signals. Is Qt a "professional" audio engine framework like JUCE or PortAudio? No. But is it a highly capable, cross-platform solution that integrates seamlessly with a GUI? Absolutely.