factor out code to extract a TempoMap from an SMF

This commit is contained in:
Paul Davis 2024-02-02 10:10:00 -07:00
parent 5509db3b24
commit 7dac2a216d
2 changed files with 58 additions and 0 deletions

View File

@ -33,6 +33,8 @@
#include "libsmf/smf.h"
#include "temporal/tempo.h"
#include "evoral/Event.h"
#include "evoral/SMF.h"
#include "evoral/midi_util.h"
@ -697,4 +699,54 @@ SMF::load_markers ()
}
}
std::shared_ptr<Temporal::TempoMap>
SMF::tempo_map (bool& provided) const
{
/* cannot create an empty TempoMap, so create one with "default" single
values for tempo and meter, then overwrite them.
*/
std::shared_ptr<Temporal::TempoMap> new_map (new Temporal::TempoMap (Temporal::Tempo (120, 4), Temporal::Meter (4, 4)));
const size_t ntempos = num_tempos ();
if (ntempos == 0) {
provided = false;
return new_map;
}
Temporal::Meter last_meter (4, 4);
bool have_initial_meter = false;
for (size_t n = 0; n < ntempos; ++n) {
Evoral::SMF::Tempo* t = nth_tempo (n);
assert (t);
Temporal::Tempo tempo (t->tempo(), 32.0 / (double) t->notes_per_note);
Temporal::Meter meter (t->numerator, t->denominator);
Temporal::BBT_Argument bbt; /* 1|1|0 which is correct for the no-meter case */
if (have_initial_meter) {
bbt = new_map->bbt_at (Temporal::timepos_t (Temporal::Beats (int_div_round (t->time_pulses, (size_t) ppqn()), 0)));
new_map->set_tempo (tempo, bbt);
if (!(meter == last_meter)) {
new_map->set_meter (meter, bbt);
}
} else {
new_map->set_meter (meter, bbt);
new_map->set_tempo (tempo, bbt);
have_initial_meter = true;
}
last_meter = meter;
}
provided = true;
return new_map;
}
} // namespace Evoral

View File

@ -35,6 +35,10 @@ typedef smf_struct smf_t;
typedef smf_track_struct smf_track_t;
typedef smf_tempo_struct smf_tempo_t;
namespace Temporal {
class TempoMap;
}
namespace Evoral {
/** Standard Midi File.
@ -136,6 +140,8 @@ public:
Markers const & markers() const { return _markers; }
void load_markers ();
std::shared_ptr<Temporal::TempoMap> tempo_map (bool& provided) const;
private:
smf_t* _smf;
smf_track_t* _smf_track;