13
0

Fix absolutely atrocious memory leak on MIDI recording. I meeean... move along now, nothing to see here.

Fix SMFSource to realloc a scratch read buffer as necessary, removing upper limit on single raw event size.
Remove public exposure of MidiBuffer::max_event_size (though it still exists internally).
Fix crash bug on MIDI record completion (transport stop).


git-svn-id: svn://localhost/ardour2/trunk@2157 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
David Robillard 2007-07-20 03:18:36 +00:00
parent 6a4bd8e926
commit f9717abf01
4 changed files with 35 additions and 12 deletions

View File

@ -46,8 +46,6 @@ public:
const MidiEvent& operator[](size_t i) const { assert(i < _size); return _events[i]; }
MidiEvent& operator[](size_t i) { assert(i < _size); return _events[i]; }
static size_t max_event_size() { return MAX_EVENT_SIZE; }
bool merge(const MidiBuffer& a, const MidiBuffer& b);
private:

View File

@ -63,7 +63,7 @@ public:
void append(const MidiBuffer& data);
/** Resizes vector if necessary (NOT realtime safe) */
void append(double time, size_t size, Byte* in_buffer);
void append(double time, size_t size, const Byte* in_buffer);
inline const Note& note_at(unsigned i) const { return _notes[i]; }

View File

@ -104,7 +104,7 @@ MidiModel::append(const MidiBuffer& buf)
* and MUST be >= the latest event currently in the model.
*/
void
MidiModel::append(double time, size_t size, Byte* buf)
MidiModel::append(double time, size_t size, const Byte* buf)
{
assert(_notes.empty() || time >= _notes.back().start);

View File

@ -275,11 +275,17 @@ SMFSource::read_event(jack_midi_event_t& ev) const
}
}
size_t event_size = midi_event_size((unsigned char)status) + 1;
// Make sure we have enough scratch buffer
if (ev.size < event_size)
ev.buffer = (Byte*)realloc(ev.buffer, event_size);
ev.time = delta_time;
ev.size = midi_event_size((unsigned char)status) + 1;
ev.size = event_size;
if (ev.buffer == NULL)
ev.buffer = (Byte*)malloc(sizeof(Byte) * ev.size);
/*if (ev.buffer == NULL)
ev.buffer = (Byte*)malloc(sizeof(Byte) * ev.size);*/
ev.buffer[0] = (unsigned char)status;
fread(ev.buffer+1, 1, ev.size - 1, _fd);
@ -305,12 +311,12 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, n
_read_data_count = 0;
// FIXME: ugh
unsigned char ev_buf[MidiBuffer::max_event_size()];
jack_midi_event_t ev; // time in SMF ticks
ev.time = 0;
ev.size = MidiBuffer::max_event_size();
ev.buffer = ev_buf;
ev.size = 0;
ev.buffer = NULL; // read_event will allocate scratch as needed
size_t scratch_size = 0; // keep track of scratch and minimize reallocs
// FIXME: don't seek to start every read
fseek(_fd, _header_size, 0);
@ -348,6 +354,11 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, n
}
_read_data_count += ev.size;
if (ev.size > scratch_size)
scratch_size = ev.size;
else
ev.size = scratch_size;
}
return cnt;
@ -786,8 +797,12 @@ SMFSource::load_model(bool lock, bool force_reload)
return;
}
if (! _model)
if (! _model) {
_model = new MidiModel(_session);
} else {
cerr << "SMFSource: Reloading model." << endl;
_model->clear();
}
_model->start_write();
@ -799,12 +814,15 @@ SMFSource::load_model(bool lock, bool force_reload)
ev.size = 0;
ev.buffer = NULL;
size_t scratch_size = 0; // keep track of scratch and minimize reallocs
// FIXME: assumes tempo never changes after start
const double frames_per_beat = _session.tempo_map().tempo_at(_timeline_position).frames_per_beat(
_session.engine().frame_rate());
int ret;
while ((ret = read_event(ev)) >= 0) {
time += ev.time;
const double ev_time = (double)(time * frames_per_beat / (double)_ppqn); // in frames
@ -813,10 +831,17 @@ SMFSource::load_model(bool lock, bool force_reload)
//cerr << "ADDING EVENT TO MODEL: " << ev.time << endl;
_model->append(ev_time, ev.size, ev.buffer);
}
if (ev.size > scratch_size)
scratch_size = ev.size;
else
ev.size = scratch_size;
}
_model->end_write(false); /* FIXME: delete stuck notes iff percussion? */
free(ev.buffer);
_model_loaded = true;
}