Eliminate excessive allocation (for every event) during MidiModel iteration.
git-svn-id: svn://localhost/ardour2/branches/3.0@3351 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
@@ -12,19 +12,16 @@ CanvasProgramChange::CanvasProgramChange(
|
||||
double height,
|
||||
double x,
|
||||
double y)
|
||||
: Group(parent, x, y),
|
||||
_region(region),
|
||||
_event(event),
|
||||
_text(0),
|
||||
_line(0),
|
||||
_rect(0),
|
||||
_widget(0)
|
||||
: Group(parent, x, y)
|
||||
, _region(region)
|
||||
, _event(event)
|
||||
, _text(0)
|
||||
, _line(0)
|
||||
, _rect(0)
|
||||
{
|
||||
_text = new Text(*this);
|
||||
assert(_text);
|
||||
ostringstream pgm(ios::ate);
|
||||
pgm << int(event->pgm_number());
|
||||
_text->property_text() = pgm.str();
|
||||
char pgm_str[4];
|
||||
snprintf(pgm_str, 4, "%d", (int)event->pgm_number());
|
||||
_text = new Text(*this, 0.0, 0.0, pgm_str);
|
||||
_text->property_justification() = Gtk::JUSTIFY_CENTER;
|
||||
_text->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_MidiProgramChangeOutline.get();
|
||||
double flagwidth = _text->property_text_width() + 10.0;
|
||||
@@ -39,22 +36,12 @@ CanvasProgramChange::CanvasProgramChange(
|
||||
_rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_MidiProgramChangeFill.get();
|
||||
_text->lower_to_bottom();
|
||||
_text->raise(2);
|
||||
assert(_widget == 0);
|
||||
assert(_text != 0);
|
||||
assert(_line != 0);
|
||||
assert(_rect != 0);
|
||||
}
|
||||
|
||||
CanvasProgramChange::~CanvasProgramChange()
|
||||
{
|
||||
if(_line)
|
||||
delete _line;
|
||||
if(_rect)
|
||||
delete _rect;
|
||||
if(_text)
|
||||
delete _text;
|
||||
if(_widget)
|
||||
delete _widget;
|
||||
delete _line;
|
||||
delete _rect;
|
||||
delete _text;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ private:
|
||||
Text* _text;
|
||||
SimpleLine* _line;
|
||||
SimpleRect* _rect;
|
||||
Widget* _widget;
|
||||
};
|
||||
|
||||
} // namespace Canvas
|
||||
|
||||
@@ -466,29 +466,28 @@ MidiRegionView::redisplay_model()
|
||||
<< " velocity: " << int((*i)->velocity())
|
||||
<< endl;
|
||||
}*/
|
||||
|
||||
|
||||
for (size_t i = 0; i < _model->n_notes(); ++i) {
|
||||
for (size_t i = 0; i < _model->n_notes(); ++i)
|
||||
add_note(_model->note_at(i));
|
||||
}
|
||||
|
||||
for (Automatable::Controls::iterator
|
||||
control = _model->controls().begin();
|
||||
// Draw program change 'flags'
|
||||
for (Automatable::Controls::iterator control = _model->controls().begin();
|
||||
control != _model->controls().end(); ++control) {
|
||||
|
||||
if ( control->first.type() == MidiPgmChangeAutomation ) {
|
||||
if (control->first.type() == MidiPgmChangeAutomation) {
|
||||
Glib::Mutex::Lock list_lock (control->second->list()->lock());
|
||||
|
||||
for (AutomationList::const_iterator event = control->second->list()->begin();
|
||||
event != control->second->list()->end(); ++event) {
|
||||
event != control->second->list()->end(); ++event) {
|
||||
MidiControlIterator iter(control->second->list(), (*event)->when, (*event)->value);
|
||||
add_pgm_change(_model->control_to_midi_event(iter));
|
||||
boost::shared_ptr<MIDI::Event> event(new MIDI::Event());
|
||||
_model->control_to_midi_event(event, iter);
|
||||
add_pgm_change(event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Is this necessary ??????????
|
||||
// Is this necessary?
|
||||
/*for (Automatable::Controls::const_iterator i = _model->controls().begin();
|
||||
i != _model->controls().end(); ++i) {
|
||||
|
||||
@@ -821,12 +820,8 @@ MidiRegionView::add_pgm_change(boost::shared_ptr<MIDI::Event> event)
|
||||
assert(event->time() >= 0);
|
||||
|
||||
// dont display notes beyond the region bounds
|
||||
if (
|
||||
event->time() - _region->start() >= _region->length() ||
|
||||
event->time() < _region->start()
|
||||
) {
|
||||
if (event->time() - _region->start() >= _region->length() || event->time() < _region->start())
|
||||
return;
|
||||
}
|
||||
|
||||
ArdourCanvas::Group* const group = (ArdourCanvas::Group*)get_canvas_group();
|
||||
const double x = trackview.editor.frame_to_pixel((nframes_t)event->time() - _region->start());
|
||||
|
||||
@@ -200,7 +200,7 @@ public:
|
||||
|
||||
const MidiSource* midi_source() const { return _midi_source; }
|
||||
void set_midi_source(MidiSource* source) { _midi_source = source; }
|
||||
boost::shared_ptr<MIDI::Event> control_to_midi_event(const MidiControlIterator& iter) const;
|
||||
bool control_to_midi_event(boost::shared_ptr<MIDI::Event> ev, const MidiControlIterator& iter) const;
|
||||
|
||||
private:
|
||||
friend class DeltaCommand;
|
||||
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
inline void set_note(uint8_t n) { _on_event.buffer()[1] = n; _off_event.buffer()[1] = n; }
|
||||
inline void set_velocity(uint8_t n) { _on_event.buffer()[2] = n; }
|
||||
inline void set_duration(double d) { _off_event.time() = _on_event.time() + d; }
|
||||
inline void set_channel(uint8_t channel) { _on_event.set_channel(channel); _off_event.set_channel(channel); }
|
||||
inline void set_channel(uint8_t c) { _on_event.set_channel(c); _off_event.set_channel(c); }
|
||||
|
||||
inline MIDI::Event& on_event() { return _on_event; }
|
||||
inline MIDI::Event& off_event() { return _off_event; }
|
||||
|
||||
@@ -145,7 +145,7 @@ MidiBuffer::push_back(const MIDI::Event& ev)
|
||||
|
||||
memcpy(write_loc, ev.buffer(), ev.size());
|
||||
_events[_size] = ev;
|
||||
_events[_size].set_buffer(write_loc, false);
|
||||
_events[_size].set_buffer(ev.size(), write_loc, false);
|
||||
++_size;
|
||||
|
||||
//cerr << "MidiBuffer: pushed, size = " << _size << endl;
|
||||
@@ -173,8 +173,7 @@ MidiBuffer::push_back(const jack_midi_event_t& ev)
|
||||
|
||||
memcpy(write_loc, ev.buffer, ev.size);
|
||||
_events[_size].time() = (double)ev.time;
|
||||
_events[_size].size() = ev.size;
|
||||
_events[_size].set_buffer(write_loc, false);
|
||||
_events[_size].set_buffer(ev.size, write_loc, false);
|
||||
++_size;
|
||||
|
||||
//cerr << "MidiBuffer: pushed, size = " << _size << endl;
|
||||
@@ -206,8 +205,7 @@ MidiBuffer::reserve(double time, size_t size)
|
||||
Byte* const write_loc = _data + (_size * MAX_EVENT_SIZE);
|
||||
|
||||
_events[_size].time() = time;
|
||||
_events[_size].size() = size;
|
||||
_events[_size].set_buffer(write_loc, false);
|
||||
_events[_size].set_buffer(size, write_loc, false);
|
||||
++_size;
|
||||
|
||||
//cerr << "MidiBuffer: reserved, size = " << _size << endl;
|
||||
|
||||
@@ -59,6 +59,7 @@ void MidiModel::read_unlock() const {
|
||||
|
||||
MidiModel::const_iterator::const_iterator(const MidiModel& model, double t)
|
||||
: _model(&model)
|
||||
, _event(new MIDI::Event(0.0, 4, NULL, true))
|
||||
, _is_end( (t == DBL_MAX) || model.empty())
|
||||
, _locked( !_is_end)
|
||||
{
|
||||
@@ -120,9 +121,7 @@ MidiModel::const_iterator::const_iterator(const MidiModel& model, double t)
|
||||
}
|
||||
|
||||
if (_note_iter != model.notes().end()) {
|
||||
MIDI::Event *new_event = new MIDI::Event((*_note_iter)->on_event(), true);
|
||||
assert(new_event);
|
||||
_event = boost::shared_ptr<MIDI::Event>(new_event);
|
||||
*_event = (*_note_iter)->on_event();
|
||||
}
|
||||
|
||||
double time = DBL_MAX;
|
||||
@@ -138,7 +137,7 @@ MidiModel::const_iterator::const_iterator(const MidiModel& model, double t)
|
||||
|
||||
// <=, because we probably would want to send control events first
|
||||
if (earliest_control.automation_list.get() && earliest_control.x <= time) {
|
||||
_event = model.control_to_midi_event(earliest_control);
|
||||
model.control_to_midi_event(_event, earliest_control);
|
||||
} else {
|
||||
_control_iter = _control_iters.end();
|
||||
}
|
||||
@@ -238,20 +237,16 @@ const MidiModel::const_iterator& MidiModel::const_iterator::operator++()
|
||||
|
||||
if (type == NOTE_ON) {
|
||||
//cerr << "********** MIDI Iterator = note on" << endl;
|
||||
MIDI::Event *new_event = new MIDI::Event((*_note_iter)->on_event(), true);
|
||||
assert(new_event);
|
||||
_event = boost::shared_ptr<MIDI::Event>(new_event);
|
||||
*_event = (*_note_iter)->on_event();
|
||||
_active_notes.push(*_note_iter);
|
||||
++_note_iter;
|
||||
} else if (type == NOTE_OFF) {
|
||||
//cerr << "********** MIDI Iterator = note off" << endl;
|
||||
MIDI::Event *new_event = new MIDI::Event(_active_notes.top()->off_event(), true);
|
||||
assert(new_event);
|
||||
_event = boost::shared_ptr<MIDI::Event>(new_event);
|
||||
*_event = (*_note_iter)->off_event();
|
||||
_active_notes.pop();
|
||||
} else if (type == AUTOMATION) {
|
||||
//cerr << "********** MIDI Iterator = Automation" << endl;
|
||||
_event = _model->control_to_midi_event(*_control_iter);
|
||||
_model->control_to_midi_event(_event, *_control_iter);
|
||||
} else {
|
||||
//cerr << "********** MIDI Iterator = End" << endl;
|
||||
_is_end = true;
|
||||
@@ -278,7 +273,7 @@ MidiModel::const_iterator& MidiModel::const_iterator::operator=(const const_iter
|
||||
}
|
||||
|
||||
_model = other._model;
|
||||
_event = other._event;
|
||||
_event = boost::shared_ptr<MIDI::Event>(new MIDI::Event(*other._event, true));
|
||||
_active_notes = other._active_notes;
|
||||
_is_end = other._is_end;
|
||||
_locked = other._locked;
|
||||
@@ -349,15 +344,14 @@ size_t MidiModel::read(MidiRingBuffer& dst, nframes_t start, nframes_t nframes,
|
||||
}
|
||||
|
||||
/** Write the controller event pointed to by \a iter to \a ev.
|
||||
* Ev will have a newly allocated buffer containing the event.
|
||||
* The buffer of \a ev will be allocated or resized as necessary.
|
||||
* \return true on success
|
||||
*/
|
||||
boost::shared_ptr<MIDI::Event>
|
||||
MidiModel::control_to_midi_event(const MidiControlIterator& iter) const
|
||||
bool
|
||||
MidiModel::control_to_midi_event(boost::shared_ptr<MIDI::Event> ev, const MidiControlIterator& iter) const
|
||||
{
|
||||
assert(iter.automation_list.get());
|
||||
|
||||
boost::shared_ptr<MIDI::Event> ev;
|
||||
|
||||
switch (iter.automation_list->parameter().type()) {
|
||||
case MidiCCAutomation:
|
||||
assert(iter.automation_list.get());
|
||||
@@ -365,7 +359,8 @@ MidiModel::control_to_midi_event(const MidiControlIterator& iter) const
|
||||
assert(iter.automation_list->parameter().id() <= INT8_MAX);
|
||||
assert(iter.y <= INT8_MAX);
|
||||
|
||||
ev = boost::shared_ptr<MIDI::Event>(new MIDI::Event(iter.x, 3, (uint8_t *)malloc(3), true));
|
||||
ev->time() = iter.x;
|
||||
ev->realloc(3);
|
||||
ev->buffer()[0] = MIDI_CMD_CONTROL + iter.automation_list->parameter().channel();
|
||||
ev->buffer()[1] = (Byte)iter.automation_list->parameter().id();
|
||||
ev->buffer()[2] = (Byte)iter.y;
|
||||
@@ -377,7 +372,8 @@ MidiModel::control_to_midi_event(const MidiControlIterator& iter) const
|
||||
assert(iter.automation_list->parameter().id() == 0);
|
||||
assert(iter.y <= INT8_MAX);
|
||||
|
||||
ev = boost::shared_ptr<MIDI::Event>(new MIDI::Event(iter.x, 2, (uint8_t *)malloc(2), true));
|
||||
ev->time() = iter.x;
|
||||
ev->realloc(2);
|
||||
ev->buffer()[0] = MIDI_CMD_PGM_CHANGE + iter.automation_list->parameter().channel();
|
||||
ev->buffer()[1] = (Byte)iter.y;
|
||||
break;
|
||||
@@ -388,7 +384,8 @@ MidiModel::control_to_midi_event(const MidiControlIterator& iter) const
|
||||
assert(iter.automation_list->parameter().id() == 0);
|
||||
assert(iter.y < (1<<14));
|
||||
|
||||
ev = boost::shared_ptr<MIDI::Event>(new MIDI::Event(iter.x, 3, (uint8_t *)malloc(3), true));
|
||||
ev->time() = iter.x;
|
||||
ev->realloc(3);
|
||||
ev->buffer()[0] = MIDI_CMD_BENDER + iter.automation_list->parameter().channel();
|
||||
ev->buffer()[1] = ((Byte)iter.y) & 0x7F; // LSB
|
||||
ev->buffer()[2] = (((Byte)iter.y) >> 7) & 0x7F; // MSB
|
||||
@@ -400,18 +397,18 @@ MidiModel::control_to_midi_event(const MidiControlIterator& iter) const
|
||||
assert(iter.automation_list->parameter().id() == 0);
|
||||
assert(iter.y <= INT8_MAX);
|
||||
|
||||
ev = boost::shared_ptr<MIDI::Event>(new MIDI::Event(iter.x, 2, (uint8_t *)malloc(2), true));
|
||||
ev->time() = iter.x;
|
||||
ev->realloc(2);
|
||||
ev->buffer()[0]
|
||||
= MIDI_CMD_CHANNEL_PRESSURE + iter.automation_list->parameter().channel();
|
||||
ev->buffer()[1] = (Byte)iter.y;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(ev.get());
|
||||
return ev;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -93,9 +93,8 @@ struct Event {
|
||||
_time = copy._time;
|
||||
if (_owns_buffer) {
|
||||
if (copy._buffer) {
|
||||
if (!_buffer || _size < copy._size) {
|
||||
if (copy._size > _size)
|
||||
_buffer = (uint8_t*)::realloc(_buffer, copy._size);
|
||||
}
|
||||
memcpy(_buffer, copy._buffer, copy._size);
|
||||
} else {
|
||||
free(_buffer);
|
||||
@@ -108,19 +107,31 @@ struct Event {
|
||||
_size = copy._size;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void set (uint8_t* msg, size_t msglen, timestamp_t t) {
|
||||
|
||||
inline void shallow_copy(const Event& copy) {
|
||||
if (_owns_buffer) {
|
||||
if (_size < msglen) {
|
||||
free (_buffer);
|
||||
_buffer = (uint8_t*) malloc (msglen);
|
||||
free(_buffer);
|
||||
_buffer = false;
|
||||
_owns_buffer = false;
|
||||
}
|
||||
|
||||
_time = copy._time;
|
||||
_size = copy._size;
|
||||
_buffer = copy._buffer;
|
||||
}
|
||||
|
||||
inline void set(uint8_t* buf, size_t size, double t) {
|
||||
if (_owns_buffer) {
|
||||
if (_size < size) {
|
||||
_buffer = (uint8_t*) ::realloc(_buffer, size);
|
||||
}
|
||||
} else {
|
||||
_buffer = (uint8_t*) malloc (msglen);
|
||||
_buffer = (uint8_t*) malloc(size);
|
||||
_owns_buffer = true;
|
||||
}
|
||||
|
||||
memcpy (_buffer, msg, msglen);
|
||||
_size = size;
|
||||
memcpy (_buffer, buf, size);
|
||||
_time = t;
|
||||
}
|
||||
|
||||
@@ -145,18 +156,20 @@ struct Event {
|
||||
|
||||
inline bool owns_buffer() const { return _owns_buffer; }
|
||||
|
||||
inline void set_buffer(uint8_t* buf, bool own) {
|
||||
inline void set_buffer(size_t size, uint8_t* buf, bool own) {
|
||||
if (_owns_buffer) {
|
||||
free(_buffer);
|
||||
_buffer = NULL;
|
||||
}
|
||||
_size = size;
|
||||
_buffer = buf;
|
||||
_owns_buffer = own;
|
||||
}
|
||||
|
||||
inline void realloc(size_t size) {
|
||||
if (_owns_buffer) {
|
||||
_buffer = (uint8_t*) ::realloc(_buffer, size);
|
||||
if (size > _size)
|
||||
_buffer = (uint8_t*) ::realloc(_buffer, size);
|
||||
} else {
|
||||
_buffer = (uint8_t*) ::malloc(size);
|
||||
_owns_buffer = true;
|
||||
@@ -176,7 +189,7 @@ struct Event {
|
||||
inline uint32_t size() const { return _size; }
|
||||
inline uint32_t& size() { return _size; }
|
||||
inline uint8_t type() const { return (_buffer[0] & 0xF0); }
|
||||
inline void set_type(uint8_t type ) { _buffer[0] = (0x0F & _buffer[0]) | (0xF0 & type); }
|
||||
inline void set_type(uint8_t type) { _buffer[0] = (0x0F & _buffer[0]) | (0xF0 & type); }
|
||||
inline uint8_t channel() const { return (_buffer[0] & 0x0F); }
|
||||
inline void set_channel(uint8_t channel) { _buffer[0] = (0xF0 & _buffer[0]) | (0x0F & channel); }
|
||||
inline bool is_note_on() const { return (type() == MIDI_CMD_NOTE_ON); }
|
||||
|
||||
Reference in New Issue
Block a user