diff --git a/libs/ardour/ardour/smf_source.h b/libs/ardour/ardour/smf_source.h index a478b98c90..7842264233 100644 --- a/libs/ardour/ardour/smf_source.h +++ b/libs/ardour/ardour/smf_source.h @@ -76,6 +76,9 @@ public: void prevent_deletion (); void set_path (const std::string& newpath); + /** Query the smf file for its channel info */ + SMF::UsedChannels used_midi_channels(); + protected: void close (); void flush_midi (const Lock& lock); diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index f952bcbb63..187e60475c 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -670,6 +670,11 @@ SMFSource::load_model (const Glib::Threads::Mutex::Lock& lock, bool force_reload Evoral::event_id_t event_id; bool have_event_id; + _num_channels = 0; + _n_note_on_events = 0; + _has_pgm_change = false; + _used_channels.reset (); + // TODO simplify event allocation std::list< std::pair< Evoral::Event*, gint > > eventlist; @@ -691,6 +696,23 @@ SMFSource::load_model (const Glib::Threads::Mutex::Lock& lock, bool force_reload continue; } + /* aggregate information about channels and pgm-changes */ + uint8_t type = buf[0] & 0xf0; + uint8_t chan = buf[0] & 0x0f; + if (type >= 0x80 && type <= 0xE0) { + _used_channels.set(chan); + switch (type) { + case MIDI_CMD_NOTE_ON: + ++_n_note_on_events; + break; + case MIDI_CMD_PGM_CHANGE: + _has_pgm_change = true; + break; + default: + break; + } + } + if (ret > 0) { /* not a meta-event */ @@ -730,6 +752,8 @@ SMFSource::load_model (const Glib::Threads::Mutex::Lock& lock, bool force_reload } } + _num_channels = _used_channels.size(); + eventlist.sort(compare_eventlist); std::list< std::pair< Evoral::Event*, gint > >::iterator it; @@ -749,6 +773,12 @@ SMFSource::load_model (const Glib::Threads::Mutex::Lock& lock, bool force_reload free(buf); } +Evoral::SMF::UsedChannels +SMFSource::used_midi_channels() +{ + return _used_channels; +} + void SMFSource::destroy_model (const Glib::Threads::Mutex::Lock& lock) { diff --git a/libs/evoral/SMF.cc b/libs/evoral/SMF.cc index db62d07a3a..48263e178c 100644 --- a/libs/evoral/SMF.cc +++ b/libs/evoral/SMF.cc @@ -125,11 +125,6 @@ SMF::open(const std::string& path, int track) { Glib::Threads::Mutex::Lock lm (_smf_lock); - _num_channels = 0; - _n_note_on_events = 0; - _has_pgm_change = false; - _used_channels.clear (); - assert(track >= 1); if (_smf) { smf_delete(_smf); @@ -157,57 +152,11 @@ SMF::open(const std::string& path, int track) fclose(f); - bool type0 = _smf->format==0; - lm.release (); if (!_empty) { - - for (int i = 1; i <= _smf->number_of_tracks; ++i) { - - // scan file for used channels. - int ret; - uint32_t delta_t = 0; - uint32_t size = 0; - uint8_t* buf = NULL; - event_id_t event_id = 0; - - if (type0) { - seek_to_start (); //type0 files have no 'track' concept, just seek_to_start - } else { - seek_to_track (i); - } - - std::set used; - while ((ret = read_event (&delta_t, &size, &buf, &event_id)) >= 0) { - if (ret == 0) { - continue; - } - if (size == 0) { - break; - } - uint8_t type = buf[0] & 0xf0; - uint8_t chan = buf[0] & 0x0f; - - if (type >= 0x80 && type <= 0xE0) { - _used_channels.insert(chan); - switch (type) { - case MIDI_CMD_NOTE_ON: - ++_n_note_on_events; - break; - case MIDI_CMD_PGM_CHANGE: - _has_pgm_change = true; - break; - default: - break; - } - } - } - _num_channels += _used_channels.size(); - free (buf); - } - seek_to_start(); } + return 0; } diff --git a/libs/evoral/evoral/SMF.h b/libs/evoral/evoral/SMF.h index 4000ee359b..591647922c 100644 --- a/libs/evoral/evoral/SMF.h +++ b/libs/evoral/evoral/SMF.h @@ -89,7 +89,9 @@ public: int smf_format () const; int num_channels () const { return _num_channels; } - std::set const& used_channels () const { return _used_channels; } + typedef std::bitset<16> UsedChannels; + UsedChannels const& used_channels () const { return _used_channels; } + void set_used_channels (UsedChannels used) { _used_channels = used; } uint64_t n_note_on_events () const { return _n_note_on_events; } bool has_pgm_change () const { return _has_pgm_change; } @@ -134,18 +136,20 @@ public: Markers const & markers() const { return _markers; } void load_markers (); + protected: + + uint64_t _n_note_on_events; + bool _has_pgm_change; + + int _num_channels; + UsedChannels _used_channels; + private: smf_t* _smf; smf_track_t* _smf_track; bool _empty; ///< true iff file contains(non-empty) events mutable Glib::Threads::Mutex _smf_lock; - int _num_channels; - std::set _used_channels; - - uint64_t _n_note_on_events; - bool _has_pgm_change; - mutable Markers _markers; };