I’m building an audio synthesizer which needs to place audio playing in a thread that isn’t blocking the GUI. I was assuming I’d need to do something like have a worker and controller like the following. Does this work if the controller (Synthesizer) class is used like qmlRegisterType(“de.poetaster.sailsynth”, 1, 0, “Synthesizer”);
class Player : public QObject {
Q_OBJECT
public slots:
void play() {
SoundGenerator::play(m_g);
result(true);
}
signals:
void result(bool r);
};
class Synthesizer : public QObject {
Q_OBJECT
public:
Synth() {
w = new Player;
t = new QThread;
w->moveToThread(t);
connect(this, SIGNAL(start()), w, SLOT(play()));
connect(w, SIGNAL(result(bool)), this, SIGNAL(result(bool)));
t->start();
}
private:
Player * w;
QThread * t;
signals:
void start();
void result(bool r);
};
To answer my own question, yes it does work.
With a ‘thread worker’ like so
class Player : public QObject {
Q_OBJECT
public slots:
void setGenerator(QString generator) {
m_voiceDesc = generator;
}
void setDuration(long time) {
m_duration = time;
}
void play() {
SoundGenerator::setVolume(0); // Avoid sound clicks at start
SoundGenerator::fade_in(10);
SoundGenerator::setVolume(0.6); // Avoid sound clicks at start
// remove old instance first
SoundGenerator::remove(mg);
mg = SoundGenerator::factory(qPrintable(m_voiceDesc));
SoundGenerator::play(mg);
const int fade_time=10; //m_fadeIn;
long duration = m_duration;
if (duration > fade_time) {
SDL_Delay(duration-fade_time);
SoundGenerator::fade_out(fade_time);
SDL_Delay(fade_time);
} else {
SoundGenerator::fade_out(fade_time);
SDL_Delay(fade_time);
}
SDL_Delay(10);
result(true);
}
signals:
void result(bool r);
private:
SoundGenerator* mg;
QString m_voiceDesc;
long m_duration;
};
I can call the the Synthesizer class ‘play()’ from QML like so:
void Synthesizer::play(){
w = new Player;
w->setDuration(m_duration);
w->setGenerator(m_voiceDesc);
t = new QThread;
w->moveToThread(t);
connect(this, SIGNAL(start()), w, SLOT(play()));
connect(w, SIGNAL(result(bool)), this, SIGNAL(result(bool)));
this->start();
t->start();
}
And the gui remains responsive. So far, so good.
4 Likes