Coupling signal into slot
-
Hello programmers,
I have a problem which i can't find a solution to. The situation is as follows:
I am writing a program for sound visualisation. In my class which inherits QThread I am getting samples from my sound card, store them in a QVector and then I emit them for further processing. It look something like this:
void AUDIO::run() { while(1){ //funktions for getting the samples from the audio device emit amplitude_samples_signal(*bufferqt); //*bufferqt is a pointer to a QVector } }
And in my MainWindow constructor I connect this signal to a slot, which is a function that takes a QVector as an argument and then I do the visualisation from the data obtained in QVector. It looks like this:
Constructor:
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { in = new AUDIO(); connect(in,SIGNAL(amplitude_samples_signal(QVector<double>)),this,SLOT(amplitude_samples_slot(QVector<double>)),Qt::QueuedConnection); }
Slot
void MainWindow::amplitude_samples_slot(QVector<double> value) { //take the QVector and do the visualisation }
This solution works fine, however it takes a lot of computing power since I am using while(1) in AUDIO::run(). I want to use QTimer to get rid of the while and to trigger the recording lets say every 16ms. But then I can't propagate the Qtimer into a slot since I am already propagating the QVector. Is there any way how to propagate a couple of signals (in my example a signal from QTimer and a QVector) into one slot?
Thank you very much for your answers.
Ondra
[edit: koahnig] code tags added
-
If I understand you correctly, you assume that you can have only one slot. However, you can have as many signal slot connections as you need. In principle each signal will be collected and stored until it can be processed. In some cases this might create a problem when you are creating lots of signals and/or the slot routines may take a lot of cpu power, but otherwise it should work.
In your case you are putting a complete vector as parameter into the signal. Depending on the size of your vector this might create a problem, because your vector with all elements are copied. You might think of a different method here (e.g. a pointer).
-
I´m not sure this will solve your problem but take a short look at
QSignalMapper
-
Hi,
How are you getting your data from the sound card ?
How are you doing the processing ?
Depending on what you want, there are audio libraries that do a lot of the heavy lifting, however, it might be wiser to use a secondary thread for your audio processing and then only send the result to your GUI
-
@SGaist Thanks for your reply. I am using ALSA library in Linux to get the data and QCustomPlot for the data visualisation. The actual function in ALSA is called
snd_pcm_readi()
. I am using two threads, at least I thing so (I am not an experienced programmer). But when I test the thread ID's withQThread::currentThreadId()
, I get:From AUDIO thread: 0x7f13cffff700 From GUI thread: 0x7f13f152f780
So I am guessing that the GUI and audio processing run in a separate thread. However, the two threads are doing some heavy computing all the time because of the while loop I mentioned. And I want all the actions (first action is read the data from the sound card, next is visualise the data) to be triggered with a 16ms interval. And I don't know how to do it.
Thank you for your replies! I really appreciate it.
-
Any while loop will tie up your processor if you don't put protections in, such as a sleep. An empty while loop will peg your processor even if it is doing nothing.
In your main application, set a single-shot timer which is handled by the AUDIO::run method of your sampling thread. There, set up any signal/slot connections you want and then emit a signal which will be picked up by a slot on the audio thread to sample your card and exit the ::run method. When the signal is picked up by the slot, sample your data, and set a QTimer event which is handled by the same slot definition, emit a signal with your QVector payload with a slot to handle it on the visualization thread and exit. The visualization thread will pick up the signal and process the data. No timer is needed here since it will be slaved to the Audio event which is firing every 16ms
When the Qtimer hits again, your audio thread will sample, and the process will repeat indefinitely until you signal a shutdown.
You will need to take care to disable your timers when the application is about to terminate, or you could end up trying to process an event while the application is shutting down.
-
Why 16ms ? And why not use QAudioInput ?
-
@SGaist I'm reading batches of data - 256 samples (one frame) with a 16 kHz sampling frequency. The length of the frame is then 16ms. And I'm using ALSA because it's a requirement from a school for this project and I need to manually set all the HW audio parameters.
Thank you for all your answers. It helped me a lot.