Fix corrupt MIDI file writing when meta events are present (fixes missing first note issue on some imported files).

Reduce number of buffer allocations on MIDI read/write.


git-svn-id: svn://localhost/ardour2/branches/3.0@3395 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
David Robillard 2008-05-22 21:36:27 +00:00
parent 39b2e2b572
commit 54bec37b5a
3 changed files with 18 additions and 11 deletions

View file

@ -545,6 +545,7 @@ void MidiModel::append_note_on_unlocked(uint8_t chan, double time,
/*cerr << "MidiModel " << this << " chan " << (int)chan << /*cerr << "MidiModel " << this << " chan " << (int)chan <<
" note " << (int)note_num << " on @ " << time << endl;*/ " note " << (int)note_num << " on @ " << time << endl;*/
assert(note_num <= 127);
assert(chan < 16); assert(chan < 16);
assert(_writing); assert(_writing);
_edited = true; _edited = true;
@ -565,6 +566,7 @@ void MidiModel::append_note_off_unlocked(uint8_t chan, double time,
/*cerr << "MidiModel " << this << " chan " << (int)chan << /*cerr << "MidiModel " << this << " chan " << (int)chan <<
" note " << (int)note_num << " off @ " << time << endl;*/ " note " << (int)note_num << " off @ " << time << endl;*/
assert(note_num <= 127);
assert(chan < 16); assert(chan < 16);
assert(_writing); assert(_writing);
_edited = true; _edited = true;

View file

@ -406,15 +406,14 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, n
//cerr << "SMF - EOF\n"; //cerr << "SMF - EOF\n";
break; break;
} }
time += ev_delta_t; // accumulate delta time
if (ret == 0) { // meta-event (skipped) if (ret == 0) { // meta-event (skipped, just accumulate time)
//cerr << "SMF - META\n"; //cerr << "SMF - META\n";
time += ev_delta_t; // just accumulate delta time and ignore event
continue; continue;
} }
time += ev_delta_t; // accumulate delta time
if (time >= start_ticks) { if (time >= start_ticks) {
const nframes_t ev_frame_time = (nframes_t)( const nframes_t ev_frame_time = (nframes_t)(
((time / (double)_ppqn) * frames_per_beat)) + stamp_offset; ((time / (double)_ppqn) * frames_per_beat)) + stamp_offset;
@ -451,6 +450,8 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
if (_model && ! _model->writing()) if (_model && ! _model->writing())
_model->start_write(); _model->start_write();
MIDI::Event ev(0.0, 4, NULL, true);
while (true) { while (true) {
bool ret = src.full_peek(sizeof(double), (Byte*)&time); bool ret = src.full_peek(sizeof(double), (Byte*)&time);
if (!ret || time - _timeline_position > _length + cnt) if (!ret || time - _timeline_position > _length + cnt)
@ -474,7 +475,7 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
assert(time >= _timeline_position); assert(time >= _timeline_position);
time -= _timeline_position; time -= _timeline_position;
const MIDI::Event ev(time, size, buf); ev.set(buf, size, time);
if (! (ev.is_channel_event() || ev.is_smf_meta_event() || ev.is_sysex()) ) { if (! (ev.is_channel_event() || ev.is_smf_meta_event() || ev.is_sysex()) ) {
//cerr << "SMFSource: WARNING: caller tried to write non SMF-Event of type " << std::hex << int(ev.buffer()[0]) << endl; //cerr << "SMFSource: WARNING: caller tried to write non SMF-Event of type " << std::hex << int(ev.buffer()[0]) << endl;
continue; continue;
@ -501,6 +502,9 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
void void
SMFSource::append_event_unlocked(EventTimeUnit unit, const MIDI::Event& ev) SMFSource::append_event_unlocked(EventTimeUnit unit, const MIDI::Event& ev)
{ {
if (ev.size() == 0)
return;
/*printf("SMFSource: %s - append_event_unlocked chan = %u, time = %lf, size = %u, data = ", /*printf("SMFSource: %s - append_event_unlocked chan = %u, time = %lf, size = %u, data = ",
name().c_str(), (unsigned)ev.channel(), ev.time(), ev.size()); name().c_str(), (unsigned)ev.channel(), ev.time(), ev.size());
for (size_t i=0; i < ev.size(); ++i) { for (size_t i=0; i < ev.size(); ++i) {
@ -931,15 +935,17 @@ SMFSource::load_model(bool lock, bool force_reload)
_session.tempo_map().meter_at(_timeline_position)); _session.tempo_map().meter_at(_timeline_position));
uint32_t delta_t = 0; uint32_t delta_t = 0;
uint32_t size = 0;
uint8_t* buf = NULL;
int ret; int ret;
while ((ret = read_event(&delta_t, &ev.size(), &ev.buffer())) >= 0) { while ((ret = read_event(&delta_t, &size, &buf)) >= 0) {
ev.set(buf, size, 0.0);
time += delta_t; time += delta_t;
if (ret > 0) { // didn't skip (meta) event if (ret > 0) { // didn't skip (meta) event
// make ev.time absolute time in frames // make ev.time absolute time in frames
ev.time() = (double)time * frames_per_beat / (double)_ppqn; ev.time() = (double)time * frames_per_beat / (double)_ppqn;
_model->append(ev); _model->append(ev);
} }
@ -952,7 +958,7 @@ SMFSource::load_model(bool lock, bool force_reload)
_model->end_write(false); _model->end_write(false);
_model->set_edited(false); _model->set_edited(false);
free(ev.buffer()); free(buf);
} }

View file

@ -125,13 +125,12 @@ struct Event {
if (_size < size) { if (_size < size) {
_buffer = (uint8_t*) ::realloc(_buffer, size); _buffer = (uint8_t*) ::realloc(_buffer, size);
} }
memcpy (_buffer, buf, size);
} else { } else {
_buffer = (uint8_t*) malloc(size); _buffer = buf;
_owns_buffer = true;
} }
_size = size; _size = size;
memcpy (_buffer, buf, size);
_time = t; _time = t;
} }