Issues creating a metronome

Hello,

I’m trying to build a video game to measure the rhythm accuracy of a player. The program should display rhythms, the player has to play them in sync with a metronome.

I’ve been trying to build a sketch that would play a “tick” to give the tempo. I’ve tried different strategies for it but I can’t get something that suits what I need :

1 - I’ve tried to use delay() inside a “timer” function : it is not stable enough, varying around 4ms each other beat…

2 - I’ve read about “threading” the timer() function that would give it its own planification in Processing, and using a while loop

Blockquote
void timer() {
while (isEnabled) {
tick = millis();
if (tick == nextPuls) {
clave.play();
Puls = tick;
nextPuls = tick + int(Interval);
println(tick);
}
}}
This works great, the timer is perfectly stable and accurate, but this method is heavy on the CPU, and Processing can’t seem do be able to get keypressed or display things smoothly.

3 - So, I’ve tried to add a delay() inside my timer() thread, which seems to be better at first but the time stops working after a few beats.

Blockquote
void timer() {
while (isEnabled) {
tick = millis();
if (tick == nextPuls) {
clave.play();
Puls = tick;
nextPuls = tick + int(Interval);
println(tick);
}
delay(1);
}}

I told myself the sound didn’t work because of the delay() function but even when creating a separate sound playing function the tempo seemed to stop after a few beats.

I really don’t get what I miss. There must be a way to have events being tempo-synced but being at the same time able to process UI display and keyboard presses…

If anone can help me see what I’m doing wrong this would be really really cool for me.

Thank you very much !

1 Like

Don’t use delay(). It is not the function you want. It does not do what you think it does. Do not feel bad - so many people have run into this issue. So many. :tired_face:

Instead, use millis(). It gives you the number of milliseconds that have elapsed since the sketch started. You can use this to write a metronome easily:

int time;

void setup(){
  size(200,200);
  time = millis() + 1000;
}

void draw(){
  background(0);
  if( millis() > time ){
    time = millis() + 1000; // Flash every second.
    background(255);
  }
}
1 Like

Hey TfGuy44,

Thanks for your help ! This is what I tried to do at first, my problem with this method is that it’s related to draw() function, and this appears to be quite unstable. For example, when printing time in the console, the beat seems to vary from 2 to 40 ms on my computer…

int time;

void setup(){
  size(200,200);
  time = millis() + 1000;
}

void draw(){
  background(0);
  if( millis() > time ){
    time = millis() + 1000; // Flash every second.
    background(255);
    println(time);
  }
}

This is why I tried to separate this measure and move it to a thread function, but then it’s using the CPU like crazy, even though it gets absolutely very steady.

How can I find a compromise ? :slight_smile:

Thanks !

println() is very slow! Don’t rely on the values it prints out to give you a good indication of how often the tick is triggering.

You can check the value of millis() anywhere - in keyPressed() to know when a key was pressed, in draw() to know i it’s time to draw a tick… or in a timer() function that’s running in a second thread.

Example game:

int time;
int click_time = -1;

void setup(){
  size(200,200);
  time = millis() + 1000;
}

void draw(){
  background(0);
  if( millis() > time ){
    if( click_time > time - 200 ){
      background(0,200,0);
    } else {
      background(200,0,0);
    }
    time = millis() + 1000; // Flash every second.
  }
}

void mousePressed(){
  click_time = millis();
}
1 Like

That’s really interesting, thank you !

Didn’t know println was slow, I thought it was a good way to get feedback even for timing purposes. I’ll know better next time :wink:

I’ve been struggling with this for a long time, so thank you very much, I’ll try this !

As an alternative to millis(), there’s this library I’ve made which is a wrapper for Java’s Timer class:

2 Likes

If you want a metronome implementation in a timer library, you may also be interested in checking out the code of this timing library:

…in particular, the way it implements “tick()” as a configurable period that is attached to a callback function – this is an interesting model if you want a variable-speed metronome … or multiple metronomes.

2 Likes

Thank you, I will try this :slight_smile:

Whoah that’s great ! It seems to do exactly what I’m looking for. Thanks a lot !