From 0cfbc64e54caf4dfdb9c8f8007334ffed1314948 Mon Sep 17 00:00:00 2001 From: Ben Loftis Date: Sat, 14 May 2022 14:12:24 -0500 Subject: [PATCH] triggerbox: given no other info, assume a clip is 1,2,4,8 or 16 bars at 4/4 this solves the oft-recurring problem where we assign a beat-count of '3' or '7' because minipm mis-detected the tempo, and that situation is vanishingly rare. it's better to assume 4 or 8 the user always has the option to change the number of beats (and therefore the detected tempo) manually, for those clips that are in a different time signature. but minibpm cannot be expected to help us there. NOTE: this is a fallback to make things 'just work' lacking any other context. * if the tempo is detected in the filename, we use that instead * clips that were recorded to the timeline use that bpm+timesig * in the future we can use file-metadata (acidized wave?) instead * this is audio-only: midi files can have an embedded timesignature but... given no other information, experience says the vast majority of downloaded/purchased clips will be 1,2 or 4 bars at 4/4. --- libs/ardour/triggerbox.cc | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/libs/ardour/triggerbox.cc b/libs/ardour/triggerbox.cc index fe177919d0..578602136c 100644 --- a/libs/ardour/triggerbox.cc +++ b/libs/ardour/triggerbox.cc @@ -1612,18 +1612,10 @@ AudioTrigger::estimate_tempo () } } - /* We don't have too many good choices here. Triggers can fire at any - * time, so there's no special place on the tempo map that we can use - * to get the meter from and thus compute an estimated bar count for - * this region. Our solution for now: just use the first meter. - */ - if (text_tempo < 0) { breakfastquay::MiniBPM mbpm (_box.session().sample_rate()); - mbpm.setBPMRange (metric.tempo().quarter_notes_per_minute () * 0.75, metric.tempo().quarter_notes_per_minute() * 1.5); - _estimated_tempo = mbpm.estimateTempoOfSamples (data[0], data.length); //cerr << name() << "MiniBPM Estimated: " << _estimated_tempo << " bpm from " << (double) data.length / _box.session().sample_rate() << " seconds\n"; @@ -1642,6 +1634,24 @@ AudioTrigger::estimate_tempo () /* fractional beatcnt */ double maybe_beats = (seconds / 60.) * _estimated_tempo; double beatcount = round (maybe_beats); + + /* the vast majority of third-party clips are 1,2,4,8, or 16-bar 'beats'. + * Given no other metadata, it makes things 'just work' if we assume 4/4 time signature, and power-of-2 bars (1,2,4,8 or 16) + * TODO: someday we could provide a widget for users who have unlabeled, un-metadata'd, clips that they *know* are 3/4 or 5/4 or 11/4 */ + { + double barcount = round (beatcount/4); + if (barcount <= 18) { /* why not 16 here? fuzzy logic allows minibpm to misjudge the clip a bit */ + for (int pwr = 0; pwr <= 4; pwr++) { + float bc = pow(2,pwr); + if (barcount <= bc) { + barcount = bc; + break; + } + } + } + beatcount = round(barcount * 4); + } + double est = _estimated_tempo; _estimated_tempo = beatcount / (seconds/60.); DEBUG_TRACE (DEBUG::Triggers, string_compose ("given original estimated tempo %1, rounded beatcnt is %2 : resulting in working bpm = %3\n", est, _beatcnt, _estimated_tempo)); @@ -1650,8 +1660,6 @@ AudioTrigger::estimate_tempo () set_follow_length(Temporal::BBT_Offset( 0, rint(beatcount), 0)); } - /* use initial tempo in map (assumed for now to be the only one */ - #if 0 cerr << "estimated tempo: " << _estimated_tempo << endl; const samplecnt_t one_beat = tm->bbt_duration_at (timepos_t (AudioTime), BBT_Offset (0, 1, 0)).samples();