Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use QtMultimedia to play a wav file?

Tags:

c++

qt

audio

My current code is:

void Sound::run() {
    QFile audio_file(mResourcePath);
    if(audio_file.open(QIODevice::ReadOnly)) {
        audio_file.seek(44); // skip wav header
        QByteArray audio_data = audio_file.readAll();
        audio_file.close();

        QBuffer* audio_buffer = new QBuffer(&audio_data);
        qDebug() << audio_buffer->size();

        QAudioFormat format;

        format.setSampleSize(16);
        format.setSampleRate(44100);
        format.setChannelCount(2);
        format.setCodec("audio/pcm");
        format.setByteOrder(QAudioFormat::LittleEndian);
        format.setSampleType(QAudioFormat::UnSignedInt);

        QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
        if (!info.isFormatSupported(format)) {
            qWarning()<<"raw audio format not supported by backend, cannot play audio.";
            return;
        }
        qDebug() << info.deviceName();

        QAudioOutput* output = new QAudioOutput(info, format);
        output->start(audio_buffer);
    }
}

This whole thing is started as a QRunnable in a QThreadPool and that part works fine. Problem is I never get any audio. My sound device is operational, the buffer is filled. I don't know what's wrong. I use app.exec(). Help appreciated.

like image 917
svenstaro Avatar asked Apr 06 '12 13:04

svenstaro


1 Answers

  1. The device (QBuffer) has to be open:

    QBuffer audio_buffer(&audio_data);        
    audio_buffer.open(QIODevice::ReadOnly);
    
  2. QAudioOutput needs an event loop to play anything, and that loop has to be running in the thread it belongs to. Which is the thread it was created in when you don't explicitly move it to another thread:

    // Create the device and start playing...
    QAudioOutput output(info, format);
    output.start(&audio_buffer);     
    
    // ...then wait for the sound to finish 
    QEventLoop loop;
    QObject::connect(&output, SIGNAL(stateChanged(QAudio::State)), &loop, SLOT(quit()));
    do {
        loop.exec();            
    } while(output.state() == QAudio::ActiveState);        
    
  3. Everything you allocate should be deallocated when the sound has finished playing, or you would have a memory leak, and the event loop will now run inside the function, so you can allocate everything locally.

like image 171
alexisdm Avatar answered Nov 16 '22 03:11

alexisdm