PDA

View Full Version : QAudioOutput in a QThread - problem.



_franko_
22nd November 2010, 19:10
Hi there!

This is my first post on this great forum ;)
I found here many good answers and examples. But I cannot find solution for this one...

I'm writing a quite big project with network programming and i have to play sound when my client connect and send some message to server.
First step which i made was to create an object of my class which encapsulate QAudioOutput and just use function (QAudioOutput::start()) from examples which shows how to play sound using this Qt class. That works ok but when client send more same message in short time not all sounds were played. So i decided to use QThread subclass to hear multiple sounds at once. Unfortunately the sound wasn't heard.

Can someone could help me with this problem?

I post here en example of my other short app in which i tried join thread and QAudioOutput. Same result - i don't hear sound as if file wasn't played or not send to audio device from the thread.



PlayFile::PlayFile(QString fn) : format(0), info(new QAudioDeviceInfo(QAudioDeviceInfo::defaultOutputDe vice())), ao(0), file(0) {
filename = fn;
setQuality();
printSupportedFeatures();
// setObjectName("mythread");
}

void PlayFile::setQuality() {
if(!format)
format = new QAudioFormat();
format->setCodec("audio/pcm");
format->setChannels(1);
format->setFrequency(11025);
// format->setFrequency(22050);
format->setSampleSize(8);
}

void PlayFile::sPlayFile() {
// qDebug("Odtwarzanie dzwieku...");
if(!file) {
file = new QFile(filename);
file->open(QIODevice::ReadOnly);
}
if(!ao)
ao = new QAudioOutput(*info, *format);
ao->start(file);
qDebug("error: %d", ao->error());
}

void PlayFile::run() {
// qDebug("Watek %s", this->objectName().toStdString().c_str());
sPlayFile();
// qDebug("buffer %d", ao->bufferSize());
// qDebug("bytes %d", ao->bytesFree());
}

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
PlayFile* pf = new PlayFile("./alarm.wav");
// using this slot to start thread doesn't produce sound on output.. why?
pf->start();
// when i use this fuction (slot) i hear the sound
// pf->sPlayFile();
MainWindow w;
w.show();
return a.exec();
}



Please help me to correct this problem.

high_flyer
23rd November 2010, 10:12
I have a theory, but I am not sure its correct.
But we can test it easy:
put 2 seconds sleep in your run function before sPlayFile();.

Do you get the sound played then?

wysota
23rd November 2010, 10:56
I would probably first check if the audio format is supported by your backend.

high_flyer
23rd November 2010, 11:05
I would probably first check if the audio format is supported by your backend.
Well, he said he gets sound when he plays the function outside the thread... so...

wysota
23rd November 2010, 11:07
Oh, I missed that... After reading the post again carefully I have a strong doubt using threads would solve the problem at all. If the audio output is busy playing one sound, pushing more data to it from another thread won't cause two sounds to play simoultaneously, one needs a mixer for that. Otherwise the second sound will play only after the first one will have finished playing.

^NyAw^
23rd November 2010, 11:17
Hi,

Maybe you can stop the current playing sound and reproduce the new sound.

high_flyer
23rd November 2010, 11:24
If the audio output is busy playing one sound, pushing more data to it from another thread won't cause two sounds to play simoultaneously, one needs a mixer for that.
True, but that is still not his problem, since he only plays the sound once, over a thread.
I have a suspition, that it has to do with the fact the thread runs (and probably finishes) before QApplication::exec() is called.
My guess is, that there are some events that need the QApplication event loop... but as I said, this is only a guess.
This is why I suggested the sleep.
Another way to test it would be to start the thread after QApplication::exec() has been called.

When this is solved, the problem with multiple sounds on the sound system with out a mixer problem will still be there though...

_franko_
23rd November 2010, 11:34
Thanks to all for your responds.

Yes it's true that it has something to do with main event loop.
I check in debug and I hear a sound only when QApplication::exec() was processing.
So maybe I need do something with local event loop.
I'll still searching though.

high_flyer
23rd November 2010, 11:38
So maybe I need do something with local event loop.
I thought as much.
Nothing special to do, just start the thread after QApplication::exec() has been called, from your widget for example.

_franko_
23rd November 2010, 12:04
@high_flyer:
Thanks for your replies.
Pause between calling my function didn't change anything.
I tried to play a sound in separate thread when i press the QButton widget but it doesn't help neither.

I really don't know what to do next.
I start to thinking that is not possible to play sound in different threads than GUI's one...

high_flyer
23rd November 2010, 12:20
Have a look at QEventLoop, maybe you could do something with that.

But I think playing sound in threads is more a design problem, if you design properly, you probably wont need this.

wysota
23rd November 2010, 14:33
True, but that is still not his problem, since he only plays the sound once, over a thread.
I don't think so, look:

That works ok but when client send more same message in short time not all sounds were played.

Sound is played asynchronously so there is no benefit in doing that in a thread. You can run the event loop of the thread and the sound will probably play fine but it won't change the fact that sounds won't be able to mix. It could even crash the application.

high_flyer
23rd November 2010, 15:00
You can run the event loop of the thread and the sound will probably play fine but it won't change the fact that sounds won't be able to mix.
Yes, as I said before, I agree with that too.
These were to separate problems - one getting the events through, the other - parallel audio with out mixing.

danjiun
14th June 2012, 00:45
So. Somebody now have a solution for use QAudioOutput within a QThread ?
Somebody speek about Events but how and which events ?
Please somebody help me.

Daniel

danjiun
17th June 2012, 03:05
Hi.
I write for other people, because i already found a solution.
The key is : from the thread you create a QAudioOutput and start it, you need to enter the event loop, and this is only possible after executing exec().
So after start you QAudioOutput, in the run() function you need to write :
exec()
This is new for me, because i come from the World of MFC, and there for calling to IDirectSound, where i engage a sound without need to enter a event loop.
In fact, now i transport everything i do before with MFC, (for Windows), a project from before 10 years ago, to QT.
I am already 8 years Linux-user, but i want compatibility with every operativ system.
Greatings. Daniel