Label.setText in getNextAudioBlock - error


#1

Hello,
I have issue that I want display some text every about one second, but I want it to be some avaraged value from all buffer blocks. So I set the buffer blocks counter, and every getNextRenderBlock I make bufferCounter++; And if bufferCounter >= sampleRate/bufferSize I want to make someLabel.setText("some text", dontSendNotification);

But i get that error:

Built-in Output (15): EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)

and that error is next to that code:

void Component::internalRepaintUnchecked (Rectangle<int> area, bool isEntireComponent)
{
     // if component methods are being called from threads other than the message
     // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.
     ASSERT_MESSAGE_MANAGER_IS_LOCKED     // error comes exactly here
     if (flags.visibleFlag)
     ....
     ....

Colud anyone help me to solve that problem?


#2

You must not use GUI objects from the audio thread.


#3

So how to make it what I want?


#4

You can use a timer. If you need to update the label with data from the audio thread, have your audio source/processor object hold onto it as a member and update it in the audio callback.

class MyGui : public Component, public Timer
{
public: 
    MyGui () 
    {
        //...
        startTimerHz (60);
    }
    // ...
    void timerCallback() override
    {
        auto data = otherObject.getData(); // could be a processor, AudioSource, whatever

        label.setText (String (data));
    }
private:
    Label label;
};

#5

Great thanks for your advice. I also thought about timer but I have already one timer in the project. Actually I have the timer in the other class. But I am still learning of programming, and not sure if I can use many timers working simultaneously. I’ve heard normally all code works linear, one by one, but timer calls some parallel process/thread in the application. And I am not sure how many parallel process I can have in one application. Does it depend how many cores is in my computer processor? I would like to ubderstand it.


#6

The JUCE GUI thread timer does not, the callbacks run only in the GUI thread. You can have as many timers as you want, but obviously if the callbacks take a long time to execute, things will start to mess up at some point.


#7

Yes, but as I understand it runs independently to other tasks, like for example getNextAudioBlock. So for example if getNextAudioBlock is in the middle of the process, but at the same moment it’s time to timerCallback and in timeCallback there is some complicated process like for example fourier transform. So what would be first? Or would it be happening together simultaneously with getNextAudioBlock?


#8

The timers run completely independently by default (in relation to the audio thread), so you have no way of knowing what happens when.


#9

Ok, but does that “completely independently running” need some special environment or hardware, like somebody told me that: all code works linear, one by one, and if you want some parallel/independent process you need to use other core of your processor. Is it true in any way? Is it important to understand at all? Maybe I am just bothering with things which are not important?


#10

You are probably confused by how GUI programs work, it’s not so obvious that it’s just linear code execution in one thread.

A simplified model of how the GUI actually works (which you don’t directly see in a framework like JUCE, since it’s all hidden away for your convenience) :

int  main()
{
  GUI thegui;
  while (true)
  {
     auto msg = GetMessage(); // The messages come from the OS by "magic"
     if (msg == WM_QuitMessage)
       break;
     if (msg == WM_PaintMessage)
       thegui.paint(msg);
     if (msg == WM_TimerMessage)
       thegui.timerCallback(msg);
     if (msg == WM_MouseMessage)
       thegui.handleMouseMessage(msg);
     // etc etc, there are dozens of different kinds of messages that could happen
  }
  return 0;
}

So, it all is just running in a kind of an endless loop, linearly, in one thread.


#11

Thanks for your reply. But going deeper with the topic. Is it easy (how to do that :slight_smile: ) to make such independent running/thread/process without using the Timer? For example to make two things parallel, but both of them very fast, fast as possible, so even faster than every one millisecond which I can get with startTimer(1);


#12

I think at your skill level it’s clearly best to stay away from attempting anything like that. It’s complicated enough to understand how a basic audio application with the GUI and the audio thread works and should be implemented. (Many experienced programmers struggle with that already. Adding even more parallelism just makes things even more worse and difficult.)


#13

Why? :slight_smile: but sometimes such option could be very handy.


#14

The saying goes : “I had 1 problem. I tried solving that with an additional thread of execution. I now have 2 problems.”


#15

Yes, you are right, of course you solved my problem with Label.setText with updating data from getNextAudioBlock.
Now I am just asking for satisfy my curiosity :slight_smile:


#16

This is technically right. But you can’t influence that a thread runs on a certain core, you just need your code to be robust against any situation, as it’s not unlikely that your audio processing and gui processing will happen on a different core. And even if it runs on the same core, your OS might even decide to interleave execution of your parallel processes on your cores, so that execution seems parallel. This is how you are actually able to run 10 applications (and much more) in parallel on a dual core cpu!


#17

As @PluginPenguin pointed out, the cores don’t matter. Just to give you an additional hint:
The threads are an abstraction layer of physical cores AND timeslices. When we had single core machines, we still had threads “parallel” running (the term might be justified, since for all other threads the time was frozen). One thread would run for a while and later be put aside (with all registers and cache, which is one piece of the overhead you get for parallelising).

The other problem you have, the audio stream is one entity to produce, so even if several threads would contribute, you rely on the slowest to finish before you can deliver the audio signal to the driver. So most of your threads are waiting for each other.

Last but not least, most of the time, your software is not the only thing running. Especially in a DAW, you have many plugins on several tracks and software instruments. The host is already parallelising these, and it can do it much better by using one thread per track and mixing in one “master” thread, that is triggered by the audio hardware.

About threads in JUCE:
Every application has at least one thread, in console applications it is just the execution of the int main(int, char**), in GUI applications it is the MessageThread, that is run by the OS. Here you get messages, that are handled one after each other. A Timer is simply telling the OS “call me in n msecs”. If the OS is busy, this might arrive a little later. But it is still the message thread, that executes it.

Every audio application has automatically a second thread, that is run by the audio hardware. It is started either by adding an AudioIODeviceCallback to an AudioIODevice, or because we allowed a host to load us, so the host will call as audio thread our processBlock() method.

The challenge is not to use the most patterns and techniques, but to achieve your goal with minimum effort (for you and the CPU).

(Sorry, got a little longer)


#18

Great thanks for explanation.
It’s thread about Label.setText with data updated from getNextAudioBlock. So I would like to move it to other threat.


Parallel processing - is the Timer the best solution?