From 056b2a59d5cb28042926dab61f56e49917c8eec4 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Tue, 28 Aug 2007 17:48:37 +0000 Subject: Split MidiModel::Note out to ARDOUR::Note in it's own file (midi_model.h was getting fat). Initial work on MidiModel iterator. git-svn-id: svn://localhost/ardour2/trunk@2355 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ardour/automation_event.h | 4 +- libs/ardour/ardour/midi_event.h | 14 ++++++- libs/ardour/ardour/midi_model.h | 78 +++++++++++++++++------------------ libs/ardour/ardour/note.h | 71 +++++++++++++++++++++++++++++++ libs/ardour/ardour/parameter.h | 3 +- 5 files changed, 126 insertions(+), 44 deletions(-) create mode 100644 libs/ardour/ardour/note.h (limited to 'libs/ardour/ardour') diff --git a/libs/ardour/ardour/automation_event.h b/libs/ardour/ardour/automation_event.h index 1675dbc822..e2a98e50b0 100644 --- a/libs/ardour/ardour/automation_event.h +++ b/libs/ardour/ardour/automation_event.h @@ -84,8 +84,8 @@ class AutomationList : public PBD::StatefulDestructible AutomationList& operator= (const AutomationList&); bool operator== (const AutomationList&); - Parameter parameter() const { return _parameter; } - void set_parameter(Parameter p) { _parameter = p; } + const Parameter& parameter() const { return _parameter; } + void set_parameter(Parameter p) { _parameter = p; } void freeze(); void thaw (); diff --git a/libs/ardour/ardour/midi_event.h b/libs/ardour/ardour/midi_event.h index 61e6b8af6e..a04a19cec8 100644 --- a/libs/ardour/ardour/midi_event.h +++ b/libs/ardour/ardour/midi_event.h @@ -21,7 +21,9 @@ #ifndef __ardour_midi_event_h__ #define __ardour_midi_event_h__ +#include #include +#include /** If this is not defined, all methods of MidiEvent are RT safe * but MidiEvent will never deep copy and (depending on the scenario) @@ -38,7 +40,7 @@ namespace ARDOUR { */ struct MidiEvent { #ifdef MIDI_EVENT_ALLOW_ALLOC - MidiEvent(double t=0, size_t s=0, Byte* b=NULL, bool owns_buffer=false) + MidiEvent(double t=0, uint32_t s=0, Byte* b=NULL, bool owns_buffer=false) : _time(t) , _size(s) , _buffer(b) @@ -96,7 +98,15 @@ struct MidiEvent { } inline bool owns_buffer() const { return _owns_buffer; } - inline void set_buffer(Byte* buf) { assert(!_owns_buffer); _buffer = buf; } + + inline void set_buffer(Byte* buf) { + if (_owns_buffer) { + free(_buffer); + _buffer = NULL; + } + _buffer = buf; + _owns_buffer = false; + } #else diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h index 27a11fa9fc..41382b1be3 100644 --- a/libs/ardour/ardour/midi_model.h +++ b/libs/ardour/ardour/midi_model.h @@ -22,6 +22,7 @@ #define __ardour_midi_model_h__ #include +#include #include #include #include @@ -29,11 +30,16 @@ #include #include #include +#include namespace ARDOUR { class Session; class MidiSource; + +// x , y +typedef std::pair, std::pair > + MidiControlIterator; /** This is a slightly higher level (than MidiBuffer) model of MIDI note data. @@ -44,45 +50,13 @@ class MidiSource; */ class MidiModel : public boost::noncopyable, public Automatable { public: - struct Note { - Note(double time=0, double dur=0, uint8_t note=0, uint8_t vel=0x40); - Note(const Note& copy); - - const MidiModel::Note& operator=(const MidiModel::Note& copy); - - inline bool operator==(const Note& other) - { return time() == other.time() && note() == other.note(); } - - inline double time() const { return _on_event.time(); } - inline double end_time() const { return _off_event.time(); } - inline uint8_t note() const { return _on_event.note(); } - inline uint8_t velocity() const { return _on_event.velocity(); } - inline double duration() const { return _off_event.time() - _on_event.time(); } - - inline void set_time(double t) { _off_event.time() = t + duration(); _on_event.time() = t; } - 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 MidiEvent& on_event() { return _on_event; } - inline MidiEvent& off_event() { return _off_event; } - - inline const MidiEvent& on_event() const { return _on_event; } - inline const MidiEvent& off_event() const { return _off_event; } - - private: - // Event buffers are self-contained - MidiEvent _on_event; - MidiEvent _off_event; - }; - MidiModel(Session& s, size_t size=0); // This is crap. - void write_lock() { _lock.writer_lock(); _automation_lock.lock(); } - void write_unlock() { _lock.writer_unlock(); _automation_lock.unlock(); } - void read_lock() { _lock.reader_lock(); _automation_lock.lock(); } - void read_unlock() { _lock.reader_unlock(); _automation_lock.unlock(); } + void write_lock() { _lock.writer_lock(); _automation_lock.lock(); } + void write_unlock() { _lock.writer_unlock(); _automation_lock.unlock(); } + void read_lock() const { _lock.reader_lock(); _automation_lock.lock(); } + void read_unlock() const { _lock.reader_unlock(); _automation_lock.unlock(); } void clear() { _notes.clear(); } @@ -90,7 +64,7 @@ public: void set_note_mode(NoteMode mode) { _note_mode = mode; } void start_write(); - bool currently_writing() const { return _writing; } + bool writing() const { return _writing; } void end_write(bool delete_stuck=false); size_t read (MidiRingBuffer& dst, nframes_t start, nframes_t nframes, nframes_t stamp_offset) const; @@ -99,7 +73,6 @@ public: void append(const MidiBuffer& data); /** Resizes vector if necessary (NOT realtime safe) */ - //void append(double time, size_t size, const Byte* in_buffer); void append(const MidiEvent& ev); inline const Note& note_at(unsigned i) const { return _notes[i]; } @@ -164,11 +137,37 @@ public: sigc::signal ContentsChanged; + /** Read iterator */ + class const_iterator { + public: + const_iterator(MidiModel& model, double t); + ~const_iterator(); + + const MidiEvent& operator*() const { return _event; } + + const const_iterator& operator++(); // prefix only + + private: + const MidiModel& _model; + MidiEvent _event; + + typedef std::priority_queue, LaterNoteEndComparator> + ActiveNotes; + mutable ActiveNotes _active_notes; + + Notes::iterator _note_iter; + + std::vector _control_iters; + }; + private: friend class DeltaCommand; void add_note_unlocked(const Note& note); void remove_note_unlocked(const Note& note); + friend class const_iterator; + bool control_to_midi_event(MidiEvent& ev, const MidiControlIterator& iter); + #ifndef NDEBUG bool is_sorted() const; #endif @@ -177,7 +176,7 @@ private: void append_note_off_unlocked(double time, uint8_t note); void append_cc_unlocked(double time, uint8_t number, uint8_t value); - Glib::RWLock _lock; + mutable Glib::RWLock _lock; Notes _notes; NoteMode _note_mode; @@ -188,6 +187,7 @@ private: bool _edited; // note state for read(): + // (TODO: Remove and replace with iterator) typedef std::priority_queue, LaterNoteEndComparator> ActiveNotes; diff --git a/libs/ardour/ardour/note.h b/libs/ardour/ardour/note.h new file mode 100644 index 0000000000..d88ecd05b0 --- /dev/null +++ b/libs/ardour/ardour/note.h @@ -0,0 +1,71 @@ +/* + Copyright (C) 2007 Paul Davis + Author: Dave Robillard + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __ardour_note_h__ +#define __ardour_note_h__ + +#include +#include + +namespace ARDOUR { + + +/** A MIDI Note. + * + * A note is (unfortunately) special and not just another MidiEvent as it + * has a duration and two separate MIDI events (on and off). + */ +class Note { +public: + Note(double time=0, double dur=0, uint8_t note=0, uint8_t vel=0x40); + Note(const Note& copy); + + const Note& operator=(const Note& copy); + + inline bool operator==(const Note& other) + { return time() == other.time() && note() == other.note(); } + + inline double time() const { return _on_event.time(); } + inline double end_time() const { return _off_event.time(); } + inline uint8_t note() const { return _on_event.note(); } + inline uint8_t velocity() const { return _on_event.velocity(); } + inline double duration() const { return _off_event.time() - _on_event.time(); } + + inline void set_time(double t) { _off_event.time() = t + duration(); _on_event.time() = t; } + 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 MidiEvent& on_event() { return _on_event; } + inline MidiEvent& off_event() { return _off_event; } + + inline const MidiEvent& on_event() const { return _on_event; } + inline const MidiEvent& off_event() const { return _off_event; } + +private: + // Event buffers are self-contained + MidiEvent _on_event; + MidiEvent _off_event; +}; + + +} // namespace ARDOUR + +#endif /* __ardour_note_h__ */ diff --git a/libs/ardour/ardour/parameter.h b/libs/ardour/ardour/parameter.h index 803bd889cb..d56124ee53 100644 --- a/libs/ardour/ardour/parameter.h +++ b/libs/ardour/ardour/parameter.h @@ -90,9 +90,10 @@ public: /** Arbitrary but fixed ordering, so we're comparable (usable in std::map) */ inline bool operator<(const Parameter& id) const { - // FIXME: branch a performance problem? #ifdef DEBUG? +#ifndef NDEBUG if (_type == NullAutomation) PBD::warning << "Uninitialized Parameter compared." << endmsg; +#endif return (_type < id._type || _id < id._id); } -- cgit v1.2.3