mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-10 00:34:59 +01:00
smf_source: implement SMF::UsedChannels, and move midi screening into load_model()
Some MIDI sources (esp immediately after import) are not yet on disk, but are only in memory. So Open() does not properly initalize data like UsedChannels and program info
This commit is contained in:
parent
9266e47558
commit
c83b8396c2
4 changed files with 46 additions and 59 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@
|
|||
#include "ardour/midi_state_tracker.h"
|
||||
#include "ardour/parameter_types.h"
|
||||
#include "ardour/session.h"
|
||||
#include "ardour/segment_descriptor.h"
|
||||
#include "ardour/smf_source.h"
|
||||
|
||||
#include "pbd/i18n.h"
|
||||
|
|
@ -670,6 +671,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<Temporal::Beats>*, gint > > eventlist;
|
||||
|
||||
|
|
@ -691,6 +697,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 +753,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<Temporal::Beats>*, gint > >::iterator it;
|
||||
|
|
@ -749,6 +774,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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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<uint8_t> 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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -89,7 +89,9 @@ public:
|
|||
int smf_format () const;
|
||||
|
||||
int num_channels () const { return _num_channels; }
|
||||
std::set<uint8_t> 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<uint8_t> _used_channels;
|
||||
|
||||
uint64_t _n_note_on_events;
|
||||
bool _has_pgm_change;
|
||||
|
||||
mutable Markers _markers;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue