Search code examples
c++qt5.5qtmultimedia

QT5.5 QSound isFinshed


I am busy making a reverb algorithm. While working with QSound I found a few problems.

First, the sound doesn't play while trying the QSound::play() like this:

/// Play output .wav file.
QSound sound("C:/Users/mvdelft/Documents/Reverb_configurator/output.wav", this);
sound.play();

It only plays the sound if I give the path againt with the QSound::play (QString file) like this:

/// Play output .wav file.
QSound sound("C:/Users/mvdelft/Documents/Reverb_configurator/output.wav", this);
sound.play("C:/Users/mvdelft/Documents/Reverb_configurator/output.wav");

A related problem I have has to do with the function bool QSound::isFinshed() which doesn't work for me. Code:

 /// Play output .wav file.
QSound sound("C:/Users/mvdelft/Documents/Reverb_configurator/output.wav", this);
sound.play("C:/Users/mvdelft/Documents/Reverb_configurator/output.wav");
sound.setLoops(10);

/// Check is sound is finished
while (!sound.isFinished()){}

ui->listWidget->addItem("Finished playing sound");
}/// End of scope

Solution

  • In the first version, you create a QSound object on stack with a file, start playing it, and immediately destroy it. This will stop the sound playing, so you won't hear anything.

    In the second version, QSound::play(const QString &) is a static method. It will play the sound in the background. That's why you hear something. With the static method, the calls to setLoops and isFinished will not work. Also, the busy loop (while (!sound.isFinished()) ;) is very bad, as it will consume 100% CPU, and probably block playing the sound.

    For the sound to work, you should create it on the heap, and regulary check the isFinished() on a timer event. However, I suggest QSoundEffect, as it gives you more control. Most importantly, the playingChanged() signal, that will inform you when the playing has finished without the need to constantly check.

    Outline:

    void MyObject::playSomeSound() {
       QSoundEffect *s = new QSoundEffect(this);
       connect(s, SIGNAL(playingChanged()), this, SLOT(soundPlayingChanged()));
       s->setSource("C:/Users/mvdelft/Documents/Reverb_configurator/output.wav");
       s->setLoopCount(10);
       s->play();
    }
    
    void MyObject::soundPlayingChanged() {
       QSoundEffect *s = qobject_cast<QSoundEffect *> (sender());
       // Will also be called when playing was started, so check if really finished
       if (!s->isPlaying()) {
          s->deleteLater();
    
          // Do what you need to do when playing finished
       }
    }