Calculating BPM/Sync rate from a gate/trigger input

Post Reply
User avatar
AndyMac
Posts: 98
Joined: Wed Sep 05, 2018 6:16 pm
Location: Wirral UK
Contact:

Sat Feb 09, 2019 12:11 pm

I am trying to work out the best way to do this accurately so that some of my modules can use this, as well as the host BPM, to control their speed. I am currently using System.nanoTime() on the leading edge of the gates, but seems to have quite a bit of drift this way and so am using averaging (but this has its own issues).

Is there an example of how best to do this, or even some code snippets to help with this?

Knowing that you have some modules which appear to be using this capability, it would be great if the process could be made available in the Library so that this capability could be easily used consistently across modules.
Andrew Macaulay
Cherry Dan
Site Admin
Posts: 103
Joined: Fri Jul 27, 2018 5:36 pm

Mon Feb 18, 2019 6:18 pm

I am currently using System.nanoTime() on the leading edge of the gates
That's not the right approach. Audio processing in a computer is done one buffer at a time, not one sample at a time, so the actual processing of samples is not done in real time. If a buffer of 480 samples is being processed, we process them as fast as possible, return the results, and wait for the next buffer to come along. As a result, you can't accurately use real-time functions like nanoTime() to calculate BPM.

Instead, all you really need to know is that Voltage Modular works internally at 48 kHz. Therefore, every sample is 1/48000th of a second. If you receive two trigger pulses 1000 samples apart, then you can calculate that 1/48th of a second has passed, or 20.83 milliseconds. Based on that, and knowing that a sync signal is generated at 96 pulses per quarter note, and there are 60,000 milliseconds per minute, you should be able to calculate the tempo. Let us know if you need more help!

Thanks,
Dan
User avatar
AndyMac
Posts: 98
Joined: Wed Sep 05, 2018 6:16 pm
Location: Wirral UK
Contact:

Mon Feb 18, 2019 9:27 pm

Thanks Dan, that makes complete sense.... but how do you work out how many samples apart the two trigger pulses are? I've looked in the library and also at the objects visible in the debug window but can't see anything that would provide this.
Andrew Macaulay
Cherry Dan
Site Admin
Posts: 103
Joined: Fri Jul 27, 2018 5:36 pm

Mon Feb 18, 2019 9:39 pm

AndyMac wrote:
Mon Feb 18, 2019 9:27 pm
Thanks Dan, that makes complete sense.... but how do you work out how many samples apart the two trigger pulses are? I've looked in the library and also at the objects visible in the debug window but can't see anything that would provide this.
Keep a running count of samples since your last trigger. e.g.:

public long samplesSinceTrigger = 0;

Every time a trigger occurs, set this back to 0. Every time ProcessSample() gets called, and there's no trigger, increment this value:

samplesSinceTrigger++;

So the code would be something along the lines of:

if (bTriggerOn)
{
[ Convert samplesSinceTrigger to bpm ]

samplesSinceTrigger = 0;
}
else
{
samplesSinceTrigger++;
}

Dan
User avatar
AndyMac
Posts: 98
Joined: Wed Sep 05, 2018 6:16 pm
Location: Wirral UK
Contact:

Mon Feb 18, 2019 9:51 pm

Brilliant. Thanks for that. Will try this tomorrow. Simple when you know how :-)
Andrew Macaulay
User avatar
AndyMac
Posts: 98
Joined: Wed Sep 05, 2018 6:16 pm
Location: Wirral UK
Contact:

Tue Feb 19, 2019 7:58 am

Just reread that explanation - brilliant --- that simple!

Makes a lot of sense.

I (rather stupidly) had not realised that ProcessSample() was going to be such an accurate "time source" in this way!

:lol:
Andrew Macaulay
Post Reply