Allow to scan midi file during file read
This partially revertseced764480
. In many places Ardour uses SMF directly, without loading the MIDI model in a libardour SMFSource. In this case no information (track, channel-count) was available, aftereced764480
, and worse various members were not initialized and showed random numbers. This fixes various import options.
This commit is contained in:
parent
7428f13e15
commit
0457646387
@ -46,6 +46,9 @@ SMF::SMF()
|
|||||||
: _smf (0)
|
: _smf (0)
|
||||||
, _smf_track (0)
|
, _smf_track (0)
|
||||||
, _empty (true)
|
, _empty (true)
|
||||||
|
, _n_note_on_events (0)
|
||||||
|
, _has_pgm_change (false)
|
||||||
|
, _num_channels (0)
|
||||||
{};
|
{};
|
||||||
|
|
||||||
SMF::~SMF()
|
SMF::~SMF()
|
||||||
@ -121,10 +124,15 @@ SMF::test(const std::string& path)
|
|||||||
* -2 if the file exists but specified track does not exist
|
* -2 if the file exists but specified track does not exist
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
SMF::open(const std::string& path, int track)
|
SMF::open(const std::string& path, int track, bool scan)
|
||||||
{
|
{
|
||||||
Glib::Threads::Mutex::Lock lm (_smf_lock);
|
Glib::Threads::Mutex::Lock lm (_smf_lock);
|
||||||
|
|
||||||
|
_num_channels = 0;
|
||||||
|
_n_note_on_events = 0;
|
||||||
|
_has_pgm_change = false;
|
||||||
|
_used_channels.reset ();
|
||||||
|
|
||||||
assert(track >= 1);
|
assert(track >= 1);
|
||||||
if (_smf) {
|
if (_smf) {
|
||||||
smf_delete(_smf);
|
smf_delete(_smf);
|
||||||
@ -153,6 +161,51 @@ SMF::open(const std::string& path, int track)
|
|||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
lm.release ();
|
lm.release ();
|
||||||
|
if (!_empty && scan) {
|
||||||
|
/* scan the file, set meta-data w/o loading the model */
|
||||||
|
bool type0 = _smf->format==0;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_num_channels += _used_channels.count ();
|
||||||
|
free (buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!_empty) {
|
if (!_empty) {
|
||||||
seek_to_start();
|
seek_to_start();
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ public:
|
|||||||
virtual ~SMF();
|
virtual ~SMF();
|
||||||
|
|
||||||
static bool test(const std::string& path);
|
static bool test(const std::string& path);
|
||||||
int open(const std::string& path, int track=1);
|
int open (const std::string& path, int track = 1, bool scan = true);
|
||||||
// XXX 19200 = 10 * Temporal::ticks_per_beat
|
// XXX 19200 = 10 * Temporal::ticks_per_beat
|
||||||
int create(const std::string& path, int track=1, uint16_t ppqn=19200);
|
int create(const std::string& path, int track=1, uint16_t ppqn=19200);
|
||||||
void close();
|
void close();
|
||||||
@ -136,21 +136,20 @@ public:
|
|||||||
Markers const & markers() const { return _markers; }
|
Markers const & markers() const { return _markers; }
|
||||||
void load_markers ();
|
void load_markers ();
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
uint64_t _n_note_on_events;
|
|
||||||
bool _has_pgm_change;
|
|
||||||
|
|
||||||
int _num_channels;
|
|
||||||
UsedChannels _used_channels;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
smf_t* _smf;
|
smf_t* _smf;
|
||||||
smf_track_t* _smf_track;
|
smf_track_t* _smf_track;
|
||||||
bool _empty; ///< true iff file contains(non-empty) events
|
bool _empty; ///< true iff file contains(non-empty) events
|
||||||
|
|
||||||
mutable Glib::Threads::Mutex _smf_lock;
|
mutable Glib::Threads::Mutex _smf_lock;
|
||||||
|
|
||||||
mutable Markers _markers;
|
mutable Markers _markers;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint64_t _n_note_on_events;
|
||||||
|
bool _has_pgm_change;
|
||||||
|
int _num_channels;
|
||||||
|
UsedChannels _used_channels;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; /* namespace Evoral */
|
}; /* namespace Evoral */
|
||||||
|
Loading…
Reference in New Issue
Block a user