diff --git a/libs/evoral/SMF.cc b/libs/evoral/SMF.cc index ece8b49a20..80dc61dbcd 100644 --- a/libs/evoral/SMF.cc +++ b/libs/evoral/SMF.cc @@ -46,7 +46,6 @@ SMF::SMF() : _smf (0) , _smf_track (0) , _empty (true) - , _type0 (false) {}; SMF::~SMF() @@ -54,6 +53,12 @@ SMF::~SMF() close (); } +int +SMF::smf_format () const +{ + return _smf ? _smf->format : 0; +} + uint16_t SMF::num_tracks() const { @@ -120,8 +125,7 @@ SMF::open(const std::string& path, int track) { Glib::Threads::Mutex::Lock lm (_smf_lock); - _type0 = false; - _type0channels.clear (); + _num_channels = 0; assert(track >= 1); if (_smf) { @@ -150,31 +154,44 @@ SMF::open(const std::string& path, int track) fclose(f); + bool type0 = _smf->format==0; + lm.release (); - if (_smf->format == 0 && _smf->number_of_tracks == 1 && !_empty) { - // type-0 file: scan file for # of used channels. - int ret; - uint32_t delta_t = 0; - uint32_t size = 0; - uint8_t* buf = NULL; - event_id_t event_id = 0; - seek_to_start(); - while ((ret = read_event (&delta_t, &size, &buf, &event_id)) >= 0) { - if (ret == 0) { - continue; + 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); } - if (size == 0) { - break; + + 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.insert(chan); + } } - uint8_t type = buf[0] & 0xf0; - uint8_t chan = buf[0] & 0x0f; - if (type < 0x80 || type > 0xE0) { - continue; - } - _type0channels.insert(chan); + _num_channels += used.size(); + free (buf); } - free (buf); - _type0 = true; + seek_to_start(); } return 0; @@ -237,8 +254,7 @@ SMF::create(const std::string& path, int track, uint16_t ppqn) } _empty = true; - _type0 = false; - _type0channels.clear (); + _num_channels = 0; return 0; } @@ -252,8 +268,7 @@ SMF::close() smf_delete(_smf); _smf = 0; _smf_track = 0; - _type0 = false; - _type0channels.clear (); + _num_channels = 0; } } diff --git a/libs/evoral/evoral/SMF.h b/libs/evoral/evoral/SMF.h index 647f02f8b8..641a00f736 100644 --- a/libs/evoral/evoral/SMF.h +++ b/libs/evoral/evoral/SMF.h @@ -86,8 +86,8 @@ public: double round_to_file_precision (double val) const; - bool is_type0 () const { return _type0; } - std::set channels () const { return _type0channels; } + int smf_format () const; + int num_channels () const { return _num_channels; } void track_names (std::vector&) const; void instrument_names (std::vector&) const; @@ -135,8 +135,7 @@ public: bool _empty; ///< true iff file contains(non-empty) events mutable Glib::Threads::Mutex _smf_lock; - bool _type0; - std::set _type0channels; + int _num_channels; mutable Markers _markers; };