Hello !
I'm encountering quite a big problem, and I'm having a very hard time finding a good solution.

I have written an amp/cabinet model for bela, which runs on my pedalboard. The program in itself runs fine. The big issue is that, when used standalone (aka not connect to a computer) the build process is messed up by some file date problems. In practice, the audio part works fine, but all the midi message are ignored, which is highly problematic.

As soon as the bela is wired to a computer, and the the program is restarted, everything works fine. I've tried to clean and rebuild the project but it only temporarly solve the issue.

I must precise that I'm using a small python script that sync files I edit on my laptop to the bela project folder, so I understand that my date/time stamp issue seen by make comes from here.

Any idea of how I could solve that ?
Thanks !

Are you building the program when running embedded? If you build it beforehand, why would it matter if the date has changed?

Thank you for your answer giuliomoro !

To be honest, I’m not really sure. The Bela get powered on and I assume it follows its default power on cycle. The only thing I’ve setup is the guitar amp project as a startup project using the Bela IDE.

Am I wrong assuming that my MIDI issue is related to this clock skew warning I see ?

I think you are wrong. It may well be related to the midi device not being ready by the time the program starts.

If they program fails to run on boot, connect to the IDE and see the log on the console. That may contain the answer you are looking for.

If it doesn't show enough meaningul lines, run in the console at the bottom.of the IDE:

journalctl -u bela_startup -n10000 --boot

And that should print everything you need

I don't think the log shows any failure from the midi device:

-- Logs begin at Thu 2016-11-03 17:16:43 UTC, end at Sun 2024-09-29 07:58:26 UTC. --
Sep 29 07:50:12 bela systemd[1]: Started Run Bela at boot.
Sep 29 07:50:12 bela stdbuf[220]: make: Entering directory '/root/Bela'
Sep 29 07:50:13 bela stdbuf[220]: make: Warning: File 'libraries/WSServer/build/WSServer.d' has modification time 25311034 s in the future
Sep 29 07:50:14 bela stdbuf[220]: Running /root/Bela/projects/bela.PAM/bela.PAM -p32 -C4 -B2 -N1 -G0 -M0 -H0,0 -H1,0 -H2,-6 -H3,-6 -H4,-6 -H5,-6 -H6,-6 -H7,-6 -I0,-12 -I1,-12 -I2,10 -I3,10 -I4,10 -I5,10 -I6,10 -I7,10 -X0

Is it possible to have a kind of delay before the program gets executed ?
Thanks again !!

That's one way of doing it, but:

  • it seems that the polling is very slow:

    		static int timer = 0;
    		if (++timer != (int)context->audioSampleRate) return;
    
    		timer = 0;
    		if(the_midi.readFrom(MIDI_PORT.c_str()) == 1)
    ...

    if I understand correctly, that results in attempting the_mid.readFrom() once every context->analogFrames seconds, which is a lot of time. Something like this would check every second - which may be what you are aiming for:

    		static int timer = 0;
    		timer += context->audioFrames
    		if (timer < (int)context->audioSampleRate) return;
    
    		timer = 0;
    		if(the_midi.readFrom(MIDI_PORT.c_str()) == 1)
  • however, as you are not processing audio until the MIDI device is connected, something like that is probably best moved to setup():

    		while(the_midi.readFrom(MIDI_PORT.c_str()) != 1)
    			usleep(100000); // 100 ms
  • Either way, the downside of both approaches is that if you never plug the MIDI device, you will not get any sound, which may be suboptimal. I recommend instead that you start a thread and wait for the device there. Above setup() you'd define the thread function (and turn the_midi into a pointer):

    static Midi* the_midi = nullptr; // will be set by midiConnectThread when ready
    void midiConnectThread(void*)
    {
    	Midi* midi = new Midi();
    	while(1 != midi->readFrom(MIDI_PORT.c_str()))
    			usleep(100000); // 100 ms
    	the_midi->writeTo(MIDI_PORT.c_str());
    	the_midi->enableParser(true);
    	the_midi->setParserCallback(&midiCallback, (void *)MIDI_PORT.c_str());
    	the_midi = midi;
    	// thread is done, it will terminate execution
    }

    then from setup you simply start this thread:

    setup( ...)
    {
    ...
    	Bela_runAuxiliaryTask(midiConnectThread);
    ...
    	return true;
    }

    and in cleanup(), delete the global pointer:

    cleanup(...)
    {
    ...
    	delete the_midi;
    ...
    }
    If you ever need to use `the_midi` directly (e.g.: to write to it), make sure you check for it not to be `nullptr` before accessing it.
    
    What you are doing looks like fun, btw :-)

Hello giuliomoro,

First and foremost, thanks a lot for such a detailed answer !

So, from top to bottom 😉

  • Arg !!! Of course, I wanted to count seconds but forgot that the render callback is called every audio blocks...
  • I thought of doing a while loop in the init, but I was afraid that it would just be stucked there with the computer unable to load the midi interface. So, I guess I was wrong 😉
  • Using another thread is indeed super clean ! My concern is that the CPU consumption is very high with this project, around 81-82%, and I know I'm not far from dropping audio buffers. I assume that auxiliary threads do not run with a high priority ? Any way, I'll implement that and see if it works !

Indeed, it is a lot of fun ! It's the best solution I've found to have a silent guitar rig that I like. I'm on the road this week for a couple of gigs, hence my very quick and dirty fixes 😉

Again, thanks a lot !

    jeanlouppecquais Using another thread is indeed super clean ! My concern is that the CPU consumption is very high with this project, around 81-82%, and I know I'm not far from dropping audio buffers. I assume that auxiliary threads do not run with a high priority ?

    As created above, it will run with default priority of 0, which is all it needs and it won't affect your audio processing. It sleeps for 100ms, then wakes up, checks for the device and sleeps again. This type of workload would hardly have any impact on CPU anyhow.

    max changed the title to MIDI initialization failing at boot time .