mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-16 03:36:32 +01:00
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:
parent
6a4bd8e926
commit
f9717abf01
4 changed files with 35 additions and 12 deletions
|
|
@ -46,8 +46,6 @@ public:
|
||||||
const MidiEvent& operator[](size_t i) const { assert(i < _size); return _events[i]; }
|
const MidiEvent& operator[](size_t i) const { assert(i < _size); return _events[i]; }
|
||||||
MidiEvent& operator[](size_t i) { 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);
|
bool merge(const MidiBuffer& a, const MidiBuffer& b);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ public:
|
||||||
void append(const MidiBuffer& data);
|
void append(const MidiBuffer& data);
|
||||||
|
|
||||||
/** Resizes vector if necessary (NOT realtime safe) */
|
/** 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]; }
|
inline const Note& note_at(unsigned i) const { return _notes[i]; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ MidiModel::append(const MidiBuffer& buf)
|
||||||
* and MUST be >= the latest event currently in the model.
|
* and MUST be >= the latest event currently in the model.
|
||||||
*/
|
*/
|
||||||
void
|
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);
|
assert(_notes.empty() || time >= _notes.back().start);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.time = delta_time;
|
||||||
ev.size = midi_event_size((unsigned char)status) + 1;
|
ev.size = event_size;
|
||||||
|
|
||||||
if (ev.buffer == NULL)
|
/*if (ev.buffer == NULL)
|
||||||
ev.buffer = (Byte*)malloc(sizeof(Byte) * ev.size);
|
ev.buffer = (Byte*)malloc(sizeof(Byte) * ev.size);*/
|
||||||
|
|
||||||
ev.buffer[0] = (unsigned char)status;
|
ev.buffer[0] = (unsigned char)status;
|
||||||
fread(ev.buffer+1, 1, ev.size - 1, _fd);
|
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;
|
_read_data_count = 0;
|
||||||
|
|
||||||
// FIXME: ugh
|
|
||||||
unsigned char ev_buf[MidiBuffer::max_event_size()];
|
|
||||||
jack_midi_event_t ev; // time in SMF ticks
|
jack_midi_event_t ev; // time in SMF ticks
|
||||||
ev.time = 0;
|
ev.time = 0;
|
||||||
ev.size = MidiBuffer::max_event_size();
|
ev.size = 0;
|
||||||
ev.buffer = ev_buf;
|
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
|
// FIXME: don't seek to start every read
|
||||||
fseek(_fd, _header_size, 0);
|
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;
|
_read_data_count += ev.size;
|
||||||
|
|
||||||
|
if (ev.size > scratch_size)
|
||||||
|
scratch_size = ev.size;
|
||||||
|
else
|
||||||
|
ev.size = scratch_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cnt;
|
return cnt;
|
||||||
|
|
@ -786,8 +797,12 @@ SMFSource::load_model(bool lock, bool force_reload)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! _model)
|
if (! _model) {
|
||||||
_model = new MidiModel(_session);
|
_model = new MidiModel(_session);
|
||||||
|
} else {
|
||||||
|
cerr << "SMFSource: Reloading model." << endl;
|
||||||
|
_model->clear();
|
||||||
|
}
|
||||||
|
|
||||||
_model->start_write();
|
_model->start_write();
|
||||||
|
|
||||||
|
|
@ -799,12 +814,15 @@ SMFSource::load_model(bool lock, bool force_reload)
|
||||||
ev.size = 0;
|
ev.size = 0;
|
||||||
ev.buffer = NULL;
|
ev.buffer = NULL;
|
||||||
|
|
||||||
|
size_t scratch_size = 0; // keep track of scratch and minimize reallocs
|
||||||
|
|
||||||
// FIXME: assumes tempo never changes after start
|
// FIXME: assumes tempo never changes after start
|
||||||
const double frames_per_beat = _session.tempo_map().tempo_at(_timeline_position).frames_per_beat(
|
const double frames_per_beat = _session.tempo_map().tempo_at(_timeline_position).frames_per_beat(
|
||||||
_session.engine().frame_rate());
|
_session.engine().frame_rate());
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
while ((ret = read_event(ev)) >= 0) {
|
while ((ret = read_event(ev)) >= 0) {
|
||||||
|
|
||||||
time += ev.time;
|
time += ev.time;
|
||||||
|
|
||||||
const double ev_time = (double)(time * frames_per_beat / (double)_ppqn); // in frames
|
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;
|
//cerr << "ADDING EVENT TO MODEL: " << ev.time << endl;
|
||||||
_model->append(ev_time, ev.size, ev.buffer);
|
_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? */
|
_model->end_write(false); /* FIXME: delete stuck notes iff percussion? */
|
||||||
|
|
||||||
|
free(ev.buffer);
|
||||||
|
|
||||||
_model_loaded = true;
|
_model_loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue