Musical Time - Tempo/Measure/Beat etc utility classes?


#1

I am a newbie to JUCE but it looks really good so far.

In the app I am looking to write with JUCE I need to deal with musical time as well as real time.

Is there a library out there that works nicely with JUCE for mapping musical time (mearues/beats/etc) to realtime?

I could write my own but this must be such a common requirement that there must be something out there already…


#2

I had some code knocking around that does this kind of thing. Must try to find time to clean it up and add it to the library…

(But the basics of converting bars/beats to seconds is pretty simple)


#3

That would be cool.

A time line where musical time is constant for the entire time line is easy enough. However, if there were tempo or time signature changes throughout it gets more tricky.

Do your “untidy” classes cover variable time lines?


#4

Yes, I started some classes that were designed to be able to handle irregular timelines, but only got as far as implementing regular ones.


#5

Here’s two functions from my MusicMath class that do the conversions between bar/beat/subdivision and time. Note that tempo is in beats per second.

	void timeToMetricPosition(double tempo, int subdivisionsPerBeat, int beatsPerMeasure, double time,
							int& measure, int& beat, int& subdivision)
	{
		double dblSubdivisions = tempo * subdivisionsPerBeat * time;
		int subdivisions = static_cast<int>(dblSubdivisions);
		int beats = subdivisions / subdivisionsPerBeat;
		subdivision = subdivisions % subdivisionsPerBeat;
		measure = beats / beatsPerMeasure;
		beat = beats % beatsPerMeasure;
	}

	double metricPositionToTime(double tempo, int subdivisionsPerBeat, int beatsPerMeasure,
							int measure, int beat, int subdivision)
	{
		double beats = measure*beatsPerMeasure + beat + static_cast<double>(subdivision)/subdivisionsPerBeat;
		return beats/tempo;
	}

The above can be generalized to handle meter changes by implementing a sequence of triples (time, meter, bar#) to encode at what time and bar a meter change occurs. Note the invariant for this sequence is that both time and bar# are monotonic increasing.

Given a time, t, you can compute the metric position (bar/beat/subdivision) by searching the sequence for the time, t0, of the nearest previous meter change (t0 <= t). You then compute the bars/beats/subdivisions in the span t - t0 using the meter at t0 and a function similiar to timeToMetricPosition, above. You get the final answer by adding the bar# at t0 to the previously computed bars to get bars+bar#/beats/subdivisions.

Given a metric position, bar/beat/subdivision, you can compute the time, t, by searching the sequence for the nearest previous meter change, (t0, meter, bar#) (t0 <= t). You then compute, dt, by using a function similiar to metricPositionToTime, above, passing it bar-bar#/beat/subdivision. You then get the final answer, t = t0 + dt.