Make (MIDI) event time stamp type a template parameter.
git-svn-id: svn://localhost/ardour2/branches/3.0@4473 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
ead5dd4568
commit
166ef64e3d
|
@ -29,11 +29,13 @@ namespace Canvas {
|
|||
|
||||
class CanvasHit : public Diamond, public CanvasNoteEvent {
|
||||
public:
|
||||
typedef Evoral::Note<double> NoteType;
|
||||
|
||||
CanvasHit(
|
||||
MidiRegionView& region,
|
||||
Group& group,
|
||||
double size,
|
||||
const boost::shared_ptr<Evoral::Note> note = boost::shared_ptr<Evoral::Note>())
|
||||
MidiRegionView& region,
|
||||
Group& group,
|
||||
double size,
|
||||
const boost::shared_ptr<NoteType> note = boost::shared_ptr<NoteType>())
|
||||
|
||||
: Diamond(group, size), CanvasNoteEvent(region, this, note)
|
||||
{
|
||||
|
|
|
@ -39,7 +39,7 @@ const uint32_t CanvasNoteEvent::midi_channel_colors[16] = {
|
|||
};
|
||||
|
||||
CanvasNoteEvent::CanvasNoteEvent(MidiRegionView& region, Item* item,
|
||||
const boost::shared_ptr<Evoral::Note> note)
|
||||
const boost::shared_ptr<NoteType> note)
|
||||
: _region(region)
|
||||
, _item(item)
|
||||
, _text(0)
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
class Editor;
|
||||
class MidiRegionView;
|
||||
|
||||
namespace Evoral { class Note; }
|
||||
namespace Evoral { template<typename T> class Note; }
|
||||
|
||||
namespace Gnome {
|
||||
namespace Canvas {
|
||||
|
@ -51,10 +51,11 @@ namespace Canvas {
|
|||
*/
|
||||
class CanvasNoteEvent : public sigc::trackable, public InteractiveItem {
|
||||
public:
|
||||
typedef Evoral::Note<double> NoteType;
|
||||
CanvasNoteEvent(
|
||||
MidiRegionView& region,
|
||||
Item* item,
|
||||
const boost::shared_ptr<Evoral::Note> note = boost::shared_ptr<Evoral::Note>());
|
||||
MidiRegionView& region,
|
||||
Item* item,
|
||||
const boost::shared_ptr<NoteType> note = boost::shared_ptr<NoteType>());
|
||||
|
||||
virtual ~CanvasNoteEvent();
|
||||
|
||||
|
@ -87,7 +88,7 @@ public:
|
|||
virtual double x2() = 0;
|
||||
virtual double y2() = 0;
|
||||
|
||||
const boost::shared_ptr<Evoral::Note> note() const { return _note; }
|
||||
const boost::shared_ptr<NoteType> note() const { return _note; }
|
||||
|
||||
inline static uint32_t meter_style_fill_color(uint8_t vel)
|
||||
{
|
||||
|
@ -116,14 +117,14 @@ public:
|
|||
protected:
|
||||
enum State { None, Pressed, Dragging };
|
||||
|
||||
MidiRegionView& _region;
|
||||
Item* const _item;
|
||||
InteractiveText* _text;
|
||||
Widget* _channel_selector_widget;
|
||||
State _state;
|
||||
const boost::shared_ptr<Evoral::Note> _note;
|
||||
bool _own_note;
|
||||
bool _selected;
|
||||
MidiRegionView& _region;
|
||||
Item* const _item;
|
||||
InteractiveText* _text;
|
||||
Widget* _channel_selector_widget;
|
||||
State _state;
|
||||
const boost::shared_ptr<NoteType> _note;
|
||||
bool _own_note;
|
||||
bool _selected;
|
||||
};
|
||||
|
||||
} // namespace Gnome
|
||||
|
|
|
@ -31,6 +31,8 @@ namespace Canvas {
|
|||
|
||||
class CanvasNote : public SimpleRect, public CanvasNoteEvent {
|
||||
public:
|
||||
typedef Evoral::Note<double> NoteType;
|
||||
|
||||
double x1() { return property_x1(); }
|
||||
double y1() { return property_y1(); }
|
||||
double x2() { return property_x2(); }
|
||||
|
@ -53,9 +55,9 @@ public:
|
|||
};
|
||||
|
||||
CanvasNote(
|
||||
MidiRegionView& region,
|
||||
Group& group,
|
||||
const boost::shared_ptr<Evoral::Note> note = boost::shared_ptr<Evoral::Note>())
|
||||
MidiRegionView& region,
|
||||
Group& group,
|
||||
const boost::shared_ptr<NoteType> note = boost::shared_ptr<NoteType>())
|
||||
|
||||
: SimpleRect(group), CanvasNoteEvent(region, this, note), _note_state(None)
|
||||
{
|
||||
|
|
|
@ -456,7 +456,7 @@ MidiRegionView::create_note_at(double x, double y, double length)
|
|||
new_note_length = snap_to_frame(new_note_time_position_relative + new_note_length) + _region->start()
|
||||
- new_note_time;
|
||||
|
||||
const boost::shared_ptr<Evoral::Note> new_note(new Evoral::Note(
|
||||
const boost::shared_ptr<NoteType> new_note(new NoteType(
|
||||
0, new_note_time, new_note_length, (uint8_t)note, 0x40));
|
||||
view->update_note_range(new_note->note());
|
||||
|
||||
|
@ -504,7 +504,7 @@ MidiRegionView::start_delta_command(string name)
|
|||
}
|
||||
|
||||
void
|
||||
MidiRegionView::command_add_note(const boost::shared_ptr<Evoral::Note> note, bool selected)
|
||||
MidiRegionView::command_add_note(const boost::shared_ptr<NoteType> note, bool selected)
|
||||
{
|
||||
if (_delta_command)
|
||||
_delta_command->add(note);
|
||||
|
@ -889,7 +889,7 @@ MidiRegionView::extend_active_notes()
|
|||
}
|
||||
|
||||
void
|
||||
MidiRegionView::play_midi_note(boost::shared_ptr<Evoral::Note> note)
|
||||
MidiRegionView::play_midi_note(boost::shared_ptr<NoteType> note)
|
||||
{
|
||||
if (!trackview.editor().sound_notes()) {
|
||||
return;
|
||||
|
@ -907,7 +907,7 @@ MidiRegionView::play_midi_note(boost::shared_ptr<Evoral::Note> note)
|
|||
}
|
||||
|
||||
bool
|
||||
MidiRegionView::play_midi_note_off(boost::shared_ptr<Evoral::Note> note)
|
||||
MidiRegionView::play_midi_note_off(boost::shared_ptr<NoteType> note)
|
||||
{
|
||||
RouteUI* route_ui = dynamic_cast<RouteUI*> (&trackview);
|
||||
assert(route_ui);
|
||||
|
@ -925,7 +925,7 @@ MidiRegionView::play_midi_note_off(boost::shared_ptr<Evoral::Note> note)
|
|||
* event arrives, to properly display the note.
|
||||
*/
|
||||
void
|
||||
MidiRegionView::add_note(const boost::shared_ptr<Evoral::Note> note)
|
||||
MidiRegionView::add_note(const boost::shared_ptr<NoteType> note)
|
||||
{
|
||||
assert(note->time() >= 0);
|
||||
assert(midi_view()->note_mode() == Sustained || midi_view()->note_mode() == Percussive);
|
||||
|
@ -967,7 +967,7 @@ MidiRegionView::add_note(const boost::shared_ptr<Evoral::Note> note)
|
|||
// finish the old note rectangle
|
||||
if (_active_notes[note->note()]) {
|
||||
CanvasNote* const old_rect = _active_notes[note->note()];
|
||||
boost::shared_ptr<Evoral::Note> old_note = old_rect->note();
|
||||
boost::shared_ptr<NoteType> old_note = old_rect->note();
|
||||
cerr << "MidiModel: WARNING: Note has length 0: chan " << old_note->channel()
|
||||
<< "note " << (int)old_note->note() << " @ " << old_note->time() << endl;
|
||||
/* FIXME: How large to make it? Make it a diamond? */
|
||||
|
@ -1338,7 +1338,7 @@ MidiRegionView::note_dropped(CanvasNoteEvent* ev, double dt, uint8_t dnote)
|
|||
Selection::iterator next = i;
|
||||
++next;
|
||||
|
||||
const boost::shared_ptr<Evoral::Note> copy(new Evoral::Note(*(*i)->note().get()));
|
||||
const boost::shared_ptr<NoteType> copy(new NoteType(*(*i)->note().get()));
|
||||
|
||||
// we need to snap here again in nframes64_t in order to be sample accurate
|
||||
double new_note_time = (*i)->note()->time();
|
||||
|
@ -1530,7 +1530,7 @@ MidiRegionView::commit_resizing(CanvasNote::NoteEnd note_end, double event_x, bo
|
|||
// transform to region start relative
|
||||
current_frame += _region->start();
|
||||
|
||||
const boost::shared_ptr<Evoral::Note> copy(new Evoral::Note(*(canvas_note->note().get())));
|
||||
const boost::shared_ptr<NoteType> copy(new NoteType(*(canvas_note->note().get())));
|
||||
|
||||
// resize beginning of note
|
||||
if (note_end == CanvasNote::NOTE_ON && current_frame < copy->end_time()) {
|
||||
|
@ -1556,7 +1556,7 @@ MidiRegionView::commit_resizing(CanvasNote::NoteEnd note_end, double event_x, bo
|
|||
void
|
||||
MidiRegionView::change_note_velocity(CanvasNoteEvent* event, int8_t velocity, bool relative)
|
||||
{
|
||||
const boost::shared_ptr<Evoral::Note> copy(new Evoral::Note(*(event->note().get())));
|
||||
const boost::shared_ptr<NoteType> copy(new NoteType(*(event->note().get())));
|
||||
|
||||
if (relative) {
|
||||
uint8_t new_velocity = copy->velocity() + velocity;
|
||||
|
@ -1598,7 +1598,7 @@ MidiRegionView::change_channel(uint8_t channel)
|
|||
++next;
|
||||
|
||||
CanvasNoteEvent* event = *i;
|
||||
const boost::shared_ptr<Evoral::Note> copy(new Evoral::Note(*(event->note().get())));
|
||||
const boost::shared_ptr<NoteType> copy(new NoteType(*(event->note().get())));
|
||||
|
||||
copy->set_channel(channel);
|
||||
|
||||
|
|
|
@ -58,6 +58,8 @@ class AutomationRegionView;
|
|||
class MidiRegionView : public RegionView
|
||||
{
|
||||
public:
|
||||
typedef Evoral::Note<ARDOUR::MidiModel::TimeType> NoteType;
|
||||
|
||||
MidiRegionView (ArdourCanvas::Group *,
|
||||
RouteTimeAxisView&,
|
||||
boost::shared_ptr<ARDOUR::MidiRegion>,
|
||||
|
@ -91,7 +93,7 @@ class MidiRegionView : public RegionView
|
|||
|
||||
GhostRegion* add_ghost (TimeAxisView&);
|
||||
|
||||
void add_note(const boost::shared_ptr<Evoral::Note> note);
|
||||
void add_note(const boost::shared_ptr<NoteType> note);
|
||||
void resolve_note(uint8_t note_num, double end_time);
|
||||
|
||||
struct ControlEvent
|
||||
|
@ -159,7 +161,7 @@ class MidiRegionView : public RegionView
|
|||
void display_model(boost::shared_ptr<ARDOUR::MidiModel> model);
|
||||
|
||||
void start_delta_command(string name = "midi edit");
|
||||
void command_add_note(const boost::shared_ptr<Evoral::Note> note, bool selected);
|
||||
void command_add_note(const boost::shared_ptr<NoteType> note, bool selected);
|
||||
void command_remove_note(ArdourCanvas::CanvasNoteEvent* ev);
|
||||
|
||||
void apply_command();
|
||||
|
@ -264,12 +266,12 @@ class MidiRegionView : public RegionView
|
|||
/** Play the NoteOn event of the given note immediately
|
||||
* and schedule the playback of the corresponding NoteOff event.
|
||||
*/
|
||||
void play_midi_note(boost::shared_ptr<Evoral::Note> note);
|
||||
void play_midi_note(boost::shared_ptr<NoteType> note);
|
||||
|
||||
/** Play the NoteOff-Event of the given note immediately
|
||||
* (scheduled by @ref play_midi_note()).
|
||||
*/
|
||||
bool play_midi_note_off(boost::shared_ptr<Evoral::Note> note);
|
||||
bool play_midi_note_off(boost::shared_ptr<NoteType> note);
|
||||
|
||||
void clear_events();
|
||||
void switch_source(boost::shared_ptr<ARDOUR::Source> src);
|
||||
|
@ -317,7 +319,7 @@ class MidiRegionView : public RegionView
|
|||
|
||||
/** New notes (created in the current command) which should be selected
|
||||
* when they appear after the command is applied. */
|
||||
std::set< boost::shared_ptr<Evoral::Note> > _marked_for_selection;
|
||||
std::set< boost::shared_ptr<NoteType> > _marked_for_selection;
|
||||
|
||||
std::vector<NoteResizeData *> _resize_data;
|
||||
};
|
||||
|
|
|
@ -605,7 +605,7 @@ MidiStreamView::update_rec_regions (boost::shared_ptr<MidiModel> data, nframes_t
|
|||
|
||||
// FIXME: slooooooooow!
|
||||
|
||||
const boost::shared_ptr<Evoral::Note> note = data->note_at(i);
|
||||
const boost::shared_ptr<MidiRegionView::NoteType> note = data->note_at(i);
|
||||
|
||||
if (note->length() > 0 && note->end_time() + region->position() > start)
|
||||
mrv->resolve_note(note->note(), note->end_time());
|
||||
|
|
|
@ -114,12 +114,13 @@ public:
|
|||
|
||||
|
||||
/** Contains notes and controllers */
|
||||
class AutomatableSequence : public Automatable, public Evoral::Sequence {
|
||||
template<typename T>
|
||||
class AutomatableSequence : public Automatable, public Evoral::Sequence<T> {
|
||||
public:
|
||||
AutomatableSequence(Session& s, size_t size)
|
||||
: Evoral::ControlSet()
|
||||
, Automatable(s)
|
||||
, Evoral::Sequence(EventTypeMap::instance())
|
||||
, Evoral::Sequence<T>(EventTypeMap::instance())
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -143,7 +143,8 @@ class Diskstream : public SessionObject
|
|||
|
||||
void remove_region_from_last_capture (boost::weak_ptr<Region> wregion);
|
||||
|
||||
void move_processor_automation (boost::weak_ptr<Processor>, Evoral::RangeMoveList const &);
|
||||
void move_processor_automation (boost::weak_ptr<Processor>,
|
||||
list< Evoral::RangeMove<nframes_t> > const &);
|
||||
|
||||
sigc::signal<void> RecordEnableChanged;
|
||||
sigc::signal<void> SpeedChanged;
|
||||
|
@ -209,7 +210,7 @@ class Diskstream : public SessionObject
|
|||
|
||||
virtual void playlist_changed (Change);
|
||||
virtual void playlist_deleted (boost::weak_ptr<Playlist>);
|
||||
virtual void playlist_ranges_moved (Evoral::RangeMoveList const &);
|
||||
virtual void playlist_ranges_moved (list< Evoral::RangeMove<nframes_t> > const &);
|
||||
|
||||
virtual void transport_stopped (struct tm&, time_t, bool abort) = 0;
|
||||
virtual void transport_looped (nframes_t transport_frame) = 0;
|
||||
|
|
|
@ -32,6 +32,8 @@ namespace ARDOUR {
|
|||
class MidiBuffer : public Buffer
|
||||
{
|
||||
public:
|
||||
typedef double TimeType;
|
||||
|
||||
MidiBuffer(size_t capacity);
|
||||
~MidiBuffer();
|
||||
|
||||
|
@ -41,7 +43,7 @@ public:
|
|||
|
||||
void copy(const MidiBuffer& copy);
|
||||
|
||||
bool push_back(const Evoral::MIDIEvent& event);
|
||||
bool push_back(const Evoral::MIDIEvent<TimeType>& event);
|
||||
bool push_back(const jack_midi_event_t& event);
|
||||
uint8_t* reserve(double time, size_t size);
|
||||
|
||||
|
@ -54,14 +56,14 @@ public:
|
|||
struct iterator_base {
|
||||
iterator_base<B,E>(B& b, size_t o) : buffer(b), offset(o) {}
|
||||
inline E operator*() const {
|
||||
uint8_t* ev_start = buffer._data + offset + sizeof(Evoral::EventTime);
|
||||
uint8_t* ev_start = buffer._data + offset + sizeof(TimeType);
|
||||
return E(EventTypeMap::instance().midi_event_type(*ev_start),
|
||||
*(Evoral::EventTime*)(buffer._data + offset),
|
||||
*(TimeType*)(buffer._data + offset),
|
||||
Evoral::midi_event_size(*ev_start) + 1, ev_start);
|
||||
}
|
||||
inline iterator_base<B,E>& operator++() {
|
||||
uint8_t* ev_start = buffer._data + offset + sizeof(Evoral::EventTime);
|
||||
offset += sizeof(Evoral::EventTime) + Evoral::midi_event_size(*ev_start) + 1;
|
||||
uint8_t* ev_start = buffer._data + offset + sizeof(TimeType);
|
||||
offset += sizeof(TimeType) + Evoral::midi_event_size(*ev_start) + 1;
|
||||
return *this;
|
||||
}
|
||||
inline bool operator!=(const iterator_base<B,E>& other) const {
|
||||
|
@ -71,8 +73,8 @@ public:
|
|||
size_t offset;
|
||||
};
|
||||
|
||||
typedef iterator_base<MidiBuffer, Evoral::MIDIEvent> iterator;
|
||||
typedef iterator_base<const MidiBuffer, const Evoral::MIDIEvent> const_iterator;
|
||||
typedef iterator_base< MidiBuffer, Evoral::MIDIEvent<TimeType> > iterator;
|
||||
typedef iterator_base< const MidiBuffer, const Evoral::MIDIEvent<TimeType> > const_iterator;
|
||||
|
||||
iterator begin() { return iterator(*this, 0); }
|
||||
iterator end() { return iterator(*this, _size); }
|
||||
|
@ -81,8 +83,8 @@ public:
|
|||
const_iterator end() const { return const_iterator(*this, _size); }
|
||||
|
||||
private:
|
||||
friend class iterator_base<MidiBuffer, Evoral::MIDIEvent>;
|
||||
friend class iterator_base<const MidiBuffer, const Evoral::MIDIEvent>;
|
||||
friend class iterator_base< MidiBuffer, Evoral::MIDIEvent<TimeType> >;
|
||||
friend class iterator_base< const MidiBuffer, const Evoral::MIDIEvent<TimeType> >;
|
||||
|
||||
size_t _size; ///< Size in bytes of used portion of _data
|
||||
uint8_t* _data; ///< timestamp, event, timestamp, event, ...
|
||||
|
|
|
@ -170,18 +170,18 @@ class MidiDiskstream : public Diskstream
|
|||
|
||||
void engage_record_enable ();
|
||||
void disengage_record_enable ();
|
||||
void check_note_onoffs(Evoral::MIDIEvent &event);
|
||||
void check_note_onoffs(Evoral::MIDIEvent<MidiBuffer::TimeType> &event);
|
||||
void emit_pending_note_offs(MidiBuffer &dst, nframes_t time);
|
||||
|
||||
MidiRingBuffer* _playback_buf;
|
||||
MidiRingBuffer* _capture_buf;
|
||||
MidiPort* _source_port;
|
||||
boost::shared_ptr<SMFSource> _write_source;
|
||||
nframes_t _last_flush_frame;
|
||||
NoteMode _note_mode;
|
||||
MidiStateTracker _midistate_tracker;
|
||||
volatile gint _frames_written_to_ringbuffer;
|
||||
volatile gint _frames_read_from_ringbuffer;
|
||||
MidiRingBuffer<MidiBuffer::TimeType>* _playback_buf;
|
||||
MidiRingBuffer<MidiBuffer::TimeType>* _capture_buf;
|
||||
MidiPort* _source_port;
|
||||
boost::shared_ptr<SMFSource> _write_source;
|
||||
nframes_t _last_flush_frame;
|
||||
NoteMode _note_mode;
|
||||
MidiStateTracker _midistate_tracker;
|
||||
volatile gint _frames_written_to_ringbuffer;
|
||||
volatile gint _frames_read_from_ringbuffer;
|
||||
};
|
||||
|
||||
}; /* namespace ARDOUR */
|
||||
|
|
|
@ -47,8 +47,10 @@ class MidiSource;
|
|||
* Because of this MIDI controllers and automatable controllers/widgets/etc
|
||||
* are easily interchangeable.
|
||||
*/
|
||||
class MidiModel : public AutomatableSequence {
|
||||
class MidiModel : public AutomatableSequence<double> {
|
||||
public:
|
||||
typedef double TimeType;
|
||||
|
||||
MidiModel(MidiSource* s, size_t size=0);
|
||||
|
||||
NoteMode note_mode() const { return (percussive() ? Percussive : Sustained); }
|
||||
|
@ -71,17 +73,17 @@ public:
|
|||
int set_state (const XMLNode&);
|
||||
XMLNode& get_state ();
|
||||
|
||||
void add(const boost::shared_ptr<Evoral::Note> note);
|
||||
void remove(const boost::shared_ptr<Evoral::Note> note);
|
||||
void add(const boost::shared_ptr< Evoral::Note<TimeType> > note);
|
||||
void remove(const boost::shared_ptr< Evoral::Note<TimeType> > note);
|
||||
|
||||
private:
|
||||
XMLNode &marshal_note(const boost::shared_ptr<Evoral::Note> note);
|
||||
boost::shared_ptr<Evoral::Note> unmarshal_note(XMLNode *xml_note);
|
||||
XMLNode &marshal_note(const boost::shared_ptr< Evoral::Note<TimeType> > note);
|
||||
boost::shared_ptr< Evoral::Note<TimeType> > unmarshal_note(XMLNode *xml_note);
|
||||
|
||||
boost::shared_ptr<MidiModel> _model;
|
||||
const std::string _name;
|
||||
|
||||
typedef std::list< boost::shared_ptr<Evoral::Note> > NoteList;
|
||||
typedef std::list< boost::shared_ptr< Evoral::Note<TimeType> > > NoteList;
|
||||
|
||||
NoteList _added_notes;
|
||||
NoteList _removed_notes;
|
||||
|
|
|
@ -34,7 +34,7 @@ class Session;
|
|||
class Region;
|
||||
class MidiRegion;
|
||||
class Source;
|
||||
class MidiRingBuffer;
|
||||
template<typename T> class MidiRingBuffer;
|
||||
|
||||
class MidiPlaylist : public ARDOUR::Playlist
|
||||
{
|
||||
|
@ -47,7 +47,7 @@ public:
|
|||
|
||||
~MidiPlaylist ();
|
||||
|
||||
nframes_t read (MidiRingBuffer& buf,
|
||||
nframes_t read (MidiRingBuffer<double>& buf,
|
||||
nframes_t start, nframes_t cnt, uint32_t chan_n=0);
|
||||
|
||||
int set_state (const XMLNode&);
|
||||
|
|
|
@ -43,11 +43,13 @@ class Playlist;
|
|||
class Session;
|
||||
class MidiFilter;
|
||||
class MidiSource;
|
||||
class MidiRingBuffer;
|
||||
template<typename T> class MidiRingBuffer;
|
||||
|
||||
class MidiRegion : public Region
|
||||
{
|
||||
public:
|
||||
typedef double TimeType;
|
||||
|
||||
~MidiRegion();
|
||||
|
||||
boost::shared_ptr<MidiSource> midi_source (uint32_t n=0) const;
|
||||
|
@ -56,13 +58,13 @@ class MidiRegion : public Region
|
|||
virtual nframes64_t read (Sample*, nframes64_t pos, nframes64_t cnt, int channel) const { return 0; }
|
||||
virtual nframes64_t readable_length() const { return length(); }
|
||||
|
||||
nframes_t read_at (MidiRingBuffer& dst,
|
||||
nframes_t read_at (MidiRingBuffer<TimeType>& dst,
|
||||
nframes_t position,
|
||||
nframes_t dur,
|
||||
uint32_t chan_n = 0,
|
||||
NoteMode mode = Sustained) const;
|
||||
|
||||
nframes_t master_read_at (MidiRingBuffer& dst,
|
||||
nframes_t master_read_at (MidiRingBuffer<TimeType>& dst,
|
||||
nframes_t position,
|
||||
nframes_t dur,
|
||||
uint32_t chan_n = 0,
|
||||
|
@ -106,7 +108,7 @@ class MidiRegion : public Region
|
|||
MidiRegion (const SourceList &, const XMLNode&);
|
||||
|
||||
private:
|
||||
nframes_t _read_at (const SourceList&, MidiRingBuffer& dst,
|
||||
nframes_t _read_at (const SourceList&, MidiRingBuffer<TimeType>& dst,
|
||||
nframes_t position,
|
||||
nframes_t dur,
|
||||
uint32_t chan_n = 0,
|
||||
|
|
|
@ -37,16 +37,17 @@ class MidiBuffer;
|
|||
*
|
||||
* [timestamp][type][size][size bytes of raw MIDI][timestamp][type][size](etc...)
|
||||
*/
|
||||
class MidiRingBuffer : public Evoral::EventRingBuffer {
|
||||
template<typename T>
|
||||
class MidiRingBuffer : public Evoral::EventRingBuffer<T> {
|
||||
public:
|
||||
/** @param size Size in bytes.
|
||||
*/
|
||||
MidiRingBuffer(size_t size)
|
||||
: Evoral::EventRingBuffer(size)
|
||||
: Evoral::EventRingBuffer<T>(size)
|
||||
, _channel_mask(0x0000FFFF)
|
||||
{}
|
||||
|
||||
inline bool read_prefix(Evoral::EventTime* time, Evoral::EventType* type, uint32_t* size);
|
||||
inline bool read_prefix(T* time, Evoral::EventType* type, uint32_t* size);
|
||||
inline bool read_contents(uint32_t size, uint8_t* buf);
|
||||
|
||||
size_t read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t offset=0);
|
||||
|
@ -86,14 +87,15 @@ private:
|
|||
/** Read the time and size of an event. This call MUST be immediately proceeded
|
||||
* by a call to read_contents (or the read pointer will be garbage).
|
||||
*/
|
||||
template<typename T>
|
||||
inline bool
|
||||
MidiRingBuffer::read_prefix(Evoral::EventTime* time, Evoral::EventType* type, uint32_t* size)
|
||||
MidiRingBuffer<T>::read_prefix(T* time, Evoral::EventType* type, uint32_t* size)
|
||||
{
|
||||
bool success = Evoral::EventRingBuffer::full_read(sizeof(Evoral::EventTime), (uint8_t*)time);
|
||||
bool success = Evoral::EventRingBuffer<T>::full_read(sizeof(T), (uint8_t*)time);
|
||||
if (success)
|
||||
success = Evoral::EventRingBuffer::full_read(sizeof(Evoral::EventType), (uint8_t*)type);
|
||||
success = Evoral::EventRingBuffer<T>::full_read(sizeof(Evoral::EventType), (uint8_t*)type);
|
||||
if (success)
|
||||
success = Evoral::EventRingBuffer::full_read(sizeof(uint32_t), (uint8_t*)size);
|
||||
success = Evoral::EventRingBuffer<T>::full_read(sizeof(uint32_t), (uint8_t*)size);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
@ -102,10 +104,11 @@ MidiRingBuffer::read_prefix(Evoral::EventTime* time, Evoral::EventType* type, ui
|
|||
/** Read the content of an event. This call MUST be immediately preceded
|
||||
* by a call to read_prefix (or the returned even will be garbage).
|
||||
*/
|
||||
template<typename T>
|
||||
inline bool
|
||||
MidiRingBuffer::read_contents(uint32_t size, uint8_t* buf)
|
||||
MidiRingBuffer<T>::read_contents(uint32_t size, uint8_t* buf)
|
||||
{
|
||||
return Evoral::EventRingBuffer::full_read(size, buf);
|
||||
return Evoral::EventRingBuffer<T>::full_read(size, buf);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -39,12 +39,14 @@ using std::string;
|
|||
|
||||
namespace ARDOUR {
|
||||
|
||||
class MidiRingBuffer;
|
||||
template<typename T> class MidiRingBuffer;
|
||||
|
||||
/** Source for MIDI data */
|
||||
class MidiSource : public Source
|
||||
{
|
||||
public:
|
||||
typedef double TimeType;
|
||||
|
||||
MidiSource (Session& session, string name);
|
||||
MidiSource (Session& session, const XMLNode&);
|
||||
virtual ~MidiSource ();
|
||||
|
@ -55,10 +57,10 @@ class MidiSource : public Source
|
|||
virtual uint32_t n_channels () const { return 1; }
|
||||
|
||||
// FIXME: integrate this with the Readable::read interface somehow
|
||||
virtual nframes_t midi_read (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const;
|
||||
virtual nframes_t midi_write (MidiRingBuffer& src, nframes_t cnt);
|
||||
virtual nframes_t midi_read (MidiRingBuffer<TimeType>& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const;
|
||||
virtual nframes_t midi_write (MidiRingBuffer<TimeType>& src, nframes_t cnt);
|
||||
|
||||
virtual void append_event_unlocked(EventTimeUnit unit, const Evoral::Event& ev) = 0;
|
||||
virtual void append_event_unlocked(EventTimeUnit unit, const Evoral::Event<TimeType>& ev) = 0;
|
||||
|
||||
virtual void mark_for_remove() = 0;
|
||||
virtual void mark_streaming_midi_write_started (NoteMode mode, nframes_t start_time);
|
||||
|
@ -99,8 +101,8 @@ class MidiSource : public Source
|
|||
//virtual int flush_header() = 0;
|
||||
//virtual int flush_footer() = 0;
|
||||
|
||||
virtual nframes_t read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const = 0;
|
||||
virtual nframes_t write_unlocked (MidiRingBuffer& dst, nframes_t cnt) = 0;
|
||||
virtual nframes_t read_unlocked (MidiRingBuffer<TimeType>& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const = 0;
|
||||
virtual nframes_t write_unlocked (MidiRingBuffer<TimeType>& dst, nframes_t cnt) = 0;
|
||||
|
||||
mutable Glib::Mutex _lock;
|
||||
string _captured_for;
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
void resolve_notes (MidiBuffer& buffer, nframes_t time);
|
||||
|
||||
private:
|
||||
void track_note_onoffs(const Evoral::MIDIEvent& event);
|
||||
void track_note_onoffs(const Evoral::MIDIEvent<MidiBuffer::TimeType>& event);
|
||||
|
||||
std::bitset<128*16> _active_notes;
|
||||
};
|
||||
|
|
|
@ -104,8 +104,8 @@ private:
|
|||
void set_state_part_two ();
|
||||
void set_state_part_three ();
|
||||
|
||||
MidiRingBuffer _immediate_events;
|
||||
NoteMode _note_mode;
|
||||
MidiRingBuffer<double> _immediate_events;
|
||||
NoteMode _note_mode;
|
||||
};
|
||||
|
||||
} /* namespace ARDOUR*/
|
||||
|
|
|
@ -128,7 +128,7 @@ class Playlist : public SessionObject, public boost::enable_shared_from_this<Pla
|
|||
sigc::signal<void> Modified;
|
||||
sigc::signal<void> NameChanged;
|
||||
sigc::signal<void> LengthChanged;
|
||||
sigc::signal<void, Evoral::RangeMoveList const &> RangesMoved;
|
||||
sigc::signal<void, list< Evoral::RangeMove<nframes_t> > const &> RangesMoved;
|
||||
|
||||
static string bump_name (string old_name, Session&);
|
||||
|
||||
|
@ -190,7 +190,7 @@ class Playlist : public SessionObject, public boost::enable_shared_from_this<Pla
|
|||
RegionList pending_bounds;
|
||||
bool pending_modified;
|
||||
bool pending_length;
|
||||
Evoral::RangeMoveList pending_range_moves;
|
||||
list< Evoral::RangeMove<nframes_t> > pending_range_moves;
|
||||
bool save_on_thaw;
|
||||
string last_save_reason;
|
||||
uint32_t in_set_state;
|
||||
|
|
|
@ -27,14 +27,14 @@
|
|||
#include <ardour/midi_source.h>
|
||||
#include <evoral/SMF.hpp>
|
||||
|
||||
namespace Evoral { class Event; }
|
||||
namespace Evoral { template<typename T> class Event; }
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
class MidiRingBuffer;
|
||||
template<typename T> class MidiRingBuffer;
|
||||
|
||||
/** Standard Midi File (Type 0) Source */
|
||||
class SMFSource : public MidiSource, public Evoral::SMF {
|
||||
class SMFSource : public MidiSource, public Evoral::SMF<double> {
|
||||
public:
|
||||
enum Flag {
|
||||
Writable = 0x1,
|
||||
|
@ -74,7 +74,7 @@ class SMFSource : public MidiSource, public Evoral::SMF {
|
|||
void set_allow_remove_if_empty (bool yn);
|
||||
void mark_for_remove();
|
||||
|
||||
void append_event_unlocked(EventTimeUnit unit, const Evoral::Event& ev);
|
||||
void append_event_unlocked(EventTimeUnit unit, const Evoral::Event<double>& ev);
|
||||
|
||||
int move_to_trash (const string trash_dir_name);
|
||||
|
||||
|
@ -100,14 +100,14 @@ class SMFSource : public MidiSource, public Evoral::SMF {
|
|||
int init (string idstr, bool must_exist);
|
||||
|
||||
nframes_t read_unlocked (
|
||||
MidiRingBuffer& dst,
|
||||
MidiRingBuffer<double>& dst,
|
||||
nframes_t start,
|
||||
nframes_t cn,
|
||||
nframes_t stamp_offset,
|
||||
nframes_t negative_stamp_offset) const;
|
||||
|
||||
nframes_t write_unlocked (
|
||||
MidiRingBuffer& src,
|
||||
MidiRingBuffer<double>& src,
|
||||
nframes_t cnt);
|
||||
|
||||
bool find (std::string path, bool must_exist, bool& is_new);
|
||||
|
|
|
@ -418,12 +418,18 @@ Diskstream::remove_region_from_last_capture (boost::weak_ptr<Region> wregion)
|
|||
}
|
||||
|
||||
void
|
||||
Diskstream::playlist_ranges_moved (Evoral::RangeMoveList const & movements)
|
||||
Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<nframes_t> > const & movements_frames)
|
||||
{
|
||||
if (Config->get_automation_follows_regions () == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
list< Evoral::RangeMove<double> > movements;
|
||||
for (list< Evoral::RangeMove<nframes_t> >::const_iterator i = movements_frames.begin();
|
||||
i != movements_frames.end(); ++i) {
|
||||
movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
|
||||
}
|
||||
|
||||
/* move gain automation */
|
||||
boost::shared_ptr<AutomationList> gain_alist = _io->gain_control()->alist();
|
||||
XMLNode & before = gain_alist->get_state ();
|
||||
|
@ -452,18 +458,25 @@ Diskstream::playlist_ranges_moved (Evoral::RangeMoveList const & movements)
|
|||
/* XXX: ewww */
|
||||
Route * route = dynamic_cast<Route*> (_io);
|
||||
if (route) {
|
||||
route->foreach_processor (sigc::bind (sigc::mem_fun (*this, &Diskstream::move_processor_automation), movements));
|
||||
route->foreach_processor (sigc::bind (sigc::mem_fun (*this, &Diskstream::move_processor_automation), movements_frames));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Diskstream::move_processor_automation (boost::weak_ptr<Processor> p, Evoral::RangeMoveList const & movements)
|
||||
Diskstream::move_processor_automation (boost::weak_ptr<Processor> p,
|
||||
list< Evoral::RangeMove<nframes_t> > const & movements_frames)
|
||||
{
|
||||
boost::shared_ptr<Processor> processor (p.lock ());
|
||||
if (!processor) {
|
||||
return;
|
||||
}
|
||||
|
||||
list< Evoral::RangeMove<double> > movements;
|
||||
for (list< Evoral::RangeMove<nframes_t> >::const_iterator i = movements_frames.begin();
|
||||
i != movements_frames.end(); ++i) {
|
||||
movements.push_back(Evoral::RangeMove<double>(i->from, i->length, i->to));
|
||||
}
|
||||
|
||||
set<Evoral::Parameter> const a = processor->what_can_be_automated ();
|
||||
|
||||
for (set<Evoral::Parameter>::iterator i = a.begin (); i != a.end (); ++i) {
|
||||
|
|
|
@ -312,7 +312,7 @@ static void
|
|||
write_midi_data_to_new_files (Evoral::SMFReader* source, Session::import_status& status,
|
||||
vector<boost::shared_ptr<Source> >& newfiles)
|
||||
{
|
||||
Evoral::Event ev(0, 0.0, 4, NULL, true);
|
||||
Evoral::Event<double> ev(0, 0.0, 4, NULL, true);
|
||||
|
||||
status.progress = 0.0f;
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ PeakMeter::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_f
|
|||
// GUI needs a better MIDI meter, not much information can be
|
||||
// expressed through peaks alone
|
||||
for (MidiBuffer::iterator i = bufs.get_midi(n).begin(); i != bufs.get_midi(n).end(); ++i) {
|
||||
const Evoral::MIDIEvent ev(*i, false);
|
||||
const Evoral::MIDIEvent<double> ev(*i, false);
|
||||
if (ev.is_note_on()) {
|
||||
const float this_vel = log(ev.buffer()[2] / 127.0 * (M_E*M_E-M_E) + M_E) - 1.0;
|
||||
//printf("V %d -> %f\n", (int)((Byte)ev.buffer[2]), this_vel);
|
||||
|
|
|
@ -99,7 +99,7 @@ MidiBuffer::read_from(const Buffer& src, nframes_t nframes, nframes_t offset)
|
|||
}
|
||||
|
||||
for (MidiBuffer::const_iterator i = msrc.begin(); i != msrc.end(); ++i) {
|
||||
const Evoral::MIDIEvent ev(*i, false);
|
||||
const Evoral::MIDIEvent<TimeType> ev(*i, false);
|
||||
/*cout << this << " MidiBuffer::read_from event type: " << int(ev.type())
|
||||
<< " time: " << ev.time() << " size: " << ev.size()
|
||||
<< " status: " << (int)*ev.buffer() << " buffer size: " << _size << endl;*/
|
||||
|
@ -126,16 +126,16 @@ MidiBuffer::read_from(const Buffer& src, nframes_t nframes, nframes_t offset)
|
|||
* @return false if operation failed (not enough room)
|
||||
*/
|
||||
bool
|
||||
MidiBuffer::push_back(const Evoral::MIDIEvent& ev)
|
||||
MidiBuffer::push_back(const Evoral::MIDIEvent<TimeType>& ev)
|
||||
{
|
||||
const size_t stamp_size = sizeof(Evoral::EventTime);
|
||||
const size_t stamp_size = sizeof(TimeType);
|
||||
if (_size + stamp_size + ev.size() >= _capacity) {
|
||||
cerr << "MidiBuffer::push_back failed (buffer is full)" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t* const write_loc = _data + _size;
|
||||
*((Evoral::EventTime*)write_loc) = ev.time();
|
||||
*((TimeType*)write_loc) = ev.time();
|
||||
memcpy(write_loc + stamp_size, ev.buffer(), ev.size());
|
||||
|
||||
_size += stamp_size + ev.size();
|
||||
|
@ -155,14 +155,14 @@ MidiBuffer::push_back(const Evoral::MIDIEvent& ev)
|
|||
bool
|
||||
MidiBuffer::push_back(const jack_midi_event_t& ev)
|
||||
{
|
||||
const size_t stamp_size = sizeof(Evoral::EventTime);
|
||||
const size_t stamp_size = sizeof(TimeType);
|
||||
if (_size + stamp_size + ev.size >= _capacity) {
|
||||
cerr << "MidiBuffer::push_back failed (buffer is full)" << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t* const write_loc = _data + _size;
|
||||
*((Evoral::EventTime*)write_loc) = ev.time;
|
||||
*((TimeType*)write_loc) = ev.time;
|
||||
memcpy(write_loc + stamp_size, ev.buffer, ev.size);
|
||||
|
||||
_size += stamp_size + ev.size;
|
||||
|
@ -180,15 +180,15 @@ MidiBuffer::push_back(const jack_midi_event_t& ev)
|
|||
* location, or the buffer will be corrupted and very nasty things will happen.
|
||||
*/
|
||||
uint8_t*
|
||||
MidiBuffer::reserve(Evoral::EventTime time, size_t size)
|
||||
MidiBuffer::reserve(TimeType time, size_t size)
|
||||
{
|
||||
const size_t stamp_size = sizeof(Evoral::EventTime);
|
||||
const size_t stamp_size = sizeof(TimeType);
|
||||
if (_size + stamp_size + size >= _capacity) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t* const write_loc = _data + _size;
|
||||
*((Evoral::EventTime*)write_loc) = time;
|
||||
*((TimeType*)write_loc) = time;
|
||||
|
||||
_size += stamp_size + size;
|
||||
_silent = false;
|
||||
|
|
|
@ -121,8 +121,9 @@ MidiDiskstream::init (Diskstream::Flag f)
|
|||
set_block_size (_session.get_block_size());
|
||||
allocate_temporary_buffers ();
|
||||
|
||||
_playback_buf = new MidiRingBuffer (_session.midi_diskstream_buffer_size());
|
||||
_capture_buf = new MidiRingBuffer (_session.midi_diskstream_buffer_size());
|
||||
const size_t size = _session.midi_diskstream_buffer_size();
|
||||
_playback_buf = new MidiRingBuffer<MidiBuffer::TimeType> (size);
|
||||
_capture_buf = new MidiRingBuffer<MidiBuffer::TimeType> (size);
|
||||
|
||||
_n_channels = ChanCount(DataType::MIDI, 1);
|
||||
|
||||
|
@ -521,7 +522,7 @@ MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_t
|
|||
// Pump entire port buffer into the ring buffer (FIXME: split cycles?)
|
||||
MidiBuffer& buf = _source_port->get_midi_buffer(nframes, offset);
|
||||
for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
|
||||
const Evoral::MIDIEvent ev(*i, false);
|
||||
const Evoral::MIDIEvent<MidiBuffer::TimeType> ev(*i, false);
|
||||
assert(ev.buffer());
|
||||
_capture_buf->write(ev.time() + transport_frame, ev.type(), ev.size(), ev.buffer());
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ using namespace ARDOUR;
|
|||
using namespace PBD;
|
||||
|
||||
MidiModel::MidiModel(MidiSource *s, size_t size)
|
||||
: AutomatableSequence(s->session(), size)
|
||||
: AutomatableSequence<TimeType>(s->session(), size)
|
||||
, _midi_source(s)
|
||||
{
|
||||
cerr << "MidiModel \"" << s->name() << "\" constructed: " << this << endl;
|
||||
|
@ -90,7 +90,7 @@ MidiModel::DeltaCommand::DeltaCommand(boost::shared_ptr<MidiModel> m,
|
|||
}
|
||||
|
||||
void
|
||||
MidiModel::DeltaCommand::add(const boost::shared_ptr<Evoral::Note> note)
|
||||
MidiModel::DeltaCommand::add(const boost::shared_ptr< Evoral::Note<TimeType> > note)
|
||||
{
|
||||
//cerr << "MEC: apply" << endl;
|
||||
_removed_notes.remove(note);
|
||||
|
@ -98,7 +98,7 @@ MidiModel::DeltaCommand::add(const boost::shared_ptr<Evoral::Note> note)
|
|||
}
|
||||
|
||||
void
|
||||
MidiModel::DeltaCommand::remove(const boost::shared_ptr<Evoral::Note> note)
|
||||
MidiModel::DeltaCommand::remove(const boost::shared_ptr< Evoral::Note<TimeType> > note)
|
||||
{
|
||||
//cerr << "MEC: remove" << endl;
|
||||
_added_notes.remove(note);
|
||||
|
@ -156,7 +156,7 @@ MidiModel::DeltaCommand::undo()
|
|||
}
|
||||
|
||||
XMLNode&
|
||||
MidiModel::DeltaCommand::marshal_note(const boost::shared_ptr<Evoral::Note> note)
|
||||
MidiModel::DeltaCommand::marshal_note(const boost::shared_ptr< Evoral::Note<TimeType> > note)
|
||||
{
|
||||
XMLNode *xml_note = new XMLNode("note");
|
||||
ostringstream note_str(ios::ate);
|
||||
|
@ -182,7 +182,7 @@ MidiModel::DeltaCommand::marshal_note(const boost::shared_ptr<Evoral::Note> note
|
|||
return *xml_note;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Evoral::Note>
|
||||
boost::shared_ptr< Evoral::Note<double> >
|
||||
MidiModel::DeltaCommand::unmarshal_note(XMLNode *xml_note)
|
||||
{
|
||||
unsigned int note;
|
||||
|
@ -232,7 +232,8 @@ MidiModel::DeltaCommand::unmarshal_note(XMLNode *xml_note)
|
|||
velocity = 127;
|
||||
}
|
||||
|
||||
boost::shared_ptr<Evoral::Note> note_ptr(new Evoral::Note(channel, time, length, note, velocity));
|
||||
boost::shared_ptr< Evoral::Note<TimeType> > note_ptr(new Evoral::Note<TimeType>(
|
||||
channel, time, length, note, velocity));
|
||||
return note_ptr;
|
||||
}
|
||||
|
||||
|
@ -296,7 +297,7 @@ MidiModel::write_to(boost::shared_ptr<MidiSource> source)
|
|||
const bool old_percussive = percussive();
|
||||
set_percussive(false);
|
||||
|
||||
for (Evoral::Sequence::const_iterator i = begin(); i != end(); ++i) {
|
||||
for (Evoral::Sequence<TimeType>::const_iterator i = begin(); i != end(); ++i) {
|
||||
source->append_event_unlocked(Frames, *i);
|
||||
}
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ struct RegionSortByLayer {
|
|||
|
||||
/** Returns the number of frames in time duration read (eg could be large when 0 events are read) */
|
||||
nframes_t
|
||||
MidiPlaylist::read (MidiRingBuffer& dst, nframes_t start,
|
||||
MidiPlaylist::read (MidiRingBuffer<MidiBuffer::TimeType>& dst, nframes_t start,
|
||||
nframes_t dur, unsigned chan_n)
|
||||
{
|
||||
/* this function is never called from a realtime thread, so
|
||||
|
|
|
@ -147,7 +147,7 @@ MidiPort::flush_buffers (nframes_t nframes, nframes_t offset)
|
|||
void* jack_buffer = jack_port_get_buffer (_jack_port, nframes);
|
||||
|
||||
for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) {
|
||||
const Evoral::Event& ev = *i;
|
||||
const Evoral::Event<double>& ev = *i;
|
||||
// event times should be frames, relative to cycle start
|
||||
assert(ev.time() >= 0);
|
||||
assert(ev.time() < (nframes+offset));
|
||||
|
|
|
@ -117,19 +117,19 @@ MidiRegion::~MidiRegion ()
|
|||
}
|
||||
|
||||
nframes_t
|
||||
MidiRegion::read_at (MidiRingBuffer& out, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const
|
||||
MidiRegion::read_at (MidiRingBuffer<TimeType>& out, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const
|
||||
{
|
||||
return _read_at (_sources, out, position, dur, chan_n, mode);
|
||||
}
|
||||
|
||||
nframes_t
|
||||
MidiRegion::master_read_at (MidiRingBuffer& out, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const
|
||||
MidiRegion::master_read_at (MidiRingBuffer<TimeType>& out, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const
|
||||
{
|
||||
return _read_at (_master_sources, out, position, dur, chan_n, mode);
|
||||
}
|
||||
|
||||
nframes_t
|
||||
MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer& dst, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const
|
||||
MidiRegion::_read_at (const SourceList& srcs, MidiRingBuffer<TimeType>& dst, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const
|
||||
{
|
||||
/*cerr << "MidiRegion " << _name << "._read_at(" << position << ") - "
|
||||
<< position << " duration: " << dur << endl;*/
|
||||
|
|
|
@ -29,14 +29,15 @@ namespace ARDOUR {
|
|||
* Timestamps of events returned are relative to start (i.e. event with stamp 0
|
||||
* occurred at start), with offset added.
|
||||
*/
|
||||
template<typename T>
|
||||
size_t
|
||||
MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t offset)
|
||||
MidiRingBuffer<T>::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t offset)
|
||||
{
|
||||
if (read_space() == 0) {
|
||||
if (this->read_space() == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Evoral::EventTime ev_time;
|
||||
T ev_time;
|
||||
Evoral::EventType ev_type;
|
||||
uint32_t ev_size;
|
||||
|
||||
|
@ -44,9 +45,9 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t
|
|||
|
||||
//cerr << "MRB read " << start << " .. " << end << " + " << offset << endl;
|
||||
|
||||
while (read_space() >= sizeof(Evoral::EventTime) + sizeof(Evoral::EventType) + sizeof(uint32_t)) {
|
||||
while (this->read_space() >= sizeof(T) + sizeof(Evoral::EventType) + sizeof(uint32_t)) {
|
||||
|
||||
full_peek(sizeof(Evoral::EventTime), (uint8_t*)&ev_time);
|
||||
this->full_peek(sizeof(T), (uint8_t*)&ev_time);
|
||||
|
||||
if (ev_time > end) {
|
||||
//cerr << "MRB: PAST END (" << ev_time << " : " << end << ")" << endl;
|
||||
|
@ -67,7 +68,7 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t
|
|||
if (ev_type == LoopEventType) {
|
||||
ev_time -= start;
|
||||
ev_time += offset;
|
||||
Evoral::MIDIEvent loopevent(LoopEventType, ev_time);
|
||||
Evoral::MIDIEvent<T> loopevent(LoopEventType, ev_time);
|
||||
dst.push_back(loopevent);
|
||||
|
||||
// We can safely return, without reading the data, because
|
||||
|
@ -76,7 +77,7 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t
|
|||
}
|
||||
|
||||
uint8_t status;
|
||||
success = full_peek(sizeof(uint8_t), &status);
|
||||
success = this->full_peek(sizeof(uint8_t), &status);
|
||||
assert(success); // If this failed, buffer is corrupt, all hope is lost
|
||||
|
||||
// Ignore event if it doesn't match channel filter
|
||||
|
@ -84,7 +85,7 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t
|
|||
const uint8_t channel = status & 0x0F;
|
||||
if ( !(get_channel_mask() & (1L << channel)) ) {
|
||||
//cerr << "MRB skipping event due to channel mask" << endl;
|
||||
skip(ev_size); // Advance read pointer to next event
|
||||
this->skip(ev_size); // Advance read pointer to next event
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +104,7 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t
|
|||
continue;
|
||||
}
|
||||
|
||||
success = Evoral::EventRingBuffer::full_read(ev_size, write_loc);
|
||||
success = Evoral::EventRingBuffer<T>::full_read(ev_size, write_loc);
|
||||
|
||||
if (success) {
|
||||
if (is_channel_event(status) && get_channel_mode() == ForceChannel) {
|
||||
|
@ -121,6 +122,7 @@ MidiRingBuffer::read(MidiBuffer& dst, nframes_t start, nframes_t end, nframes_t
|
|||
return count;
|
||||
}
|
||||
|
||||
template class MidiRingBuffer<double>;
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ MidiSource::set_state (const XMLNode& node)
|
|||
}
|
||||
|
||||
nframes_t
|
||||
MidiSource::midi_read (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const
|
||||
MidiSource::midi_read (MidiRingBuffer<MidiBuffer::TimeType>& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const
|
||||
{
|
||||
Glib::Mutex::Lock lm (_lock);
|
||||
if (_model) {
|
||||
|
@ -115,7 +115,7 @@ MidiSource::midi_read (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nfra
|
|||
}
|
||||
|
||||
nframes_t
|
||||
MidiSource::midi_write (MidiRingBuffer& dst, nframes_t cnt)
|
||||
MidiSource::midi_write (MidiRingBuffer<MidiBuffer::TimeType>& dst, nframes_t cnt)
|
||||
{
|
||||
Glib::Mutex::Lock lm (_lock);
|
||||
return write_unlocked (dst, cnt);
|
||||
|
|
|
@ -31,7 +31,7 @@ MidiStateTracker::MidiStateTracker ()
|
|||
}
|
||||
|
||||
void
|
||||
MidiStateTracker::track_note_onoffs (const Evoral::MIDIEvent &event)
|
||||
MidiStateTracker::track_note_onoffs (const Evoral::MIDIEvent<MidiBuffer::TimeType>& event)
|
||||
{
|
||||
if (event.is_note_on()) {
|
||||
_active_notes [event.note() + 128 * event.channel()] = true;
|
||||
|
@ -46,7 +46,7 @@ MidiStateTracker::track (const MidiBuffer::iterator &from, const MidiBuffer::ite
|
|||
bool ret = false;
|
||||
|
||||
for (MidiBuffer::iterator i = from; i != to; ++i) {
|
||||
const Evoral::MIDIEvent ev(*i, false);
|
||||
const Evoral::MIDIEvent<MidiBuffer::TimeType> ev(*i, false);
|
||||
if (ev.event_type() == LoopEventType) {
|
||||
ret = true;
|
||||
continue;
|
||||
|
@ -68,7 +68,8 @@ MidiStateTracker::resolve_notes (MidiBuffer &dst, nframes_t time)
|
|||
for (int note = 0; note < 128; ++note) {
|
||||
if (_active_notes[channel * 128 + note]) {
|
||||
uint8_t buffer[3] = { MIDI_CMD_NOTE_OFF | channel, note, 0 };
|
||||
Evoral::MIDIEvent noteoff (time, MIDI_CMD_NOTE_OFF, 3, buffer, false);
|
||||
Evoral::MIDIEvent<MidiBuffer::TimeType> noteoff
|
||||
(time, MIDI_CMD_NOTE_OFF, 3, buffer, false);
|
||||
|
||||
dst.push_back (noteoff);
|
||||
|
||||
|
|
|
@ -87,11 +87,12 @@ MidiStretch::run (boost::shared_ptr<Region> r)
|
|||
boost::shared_ptr<MidiModel> new_model = new_src->model();
|
||||
new_model->start_write();
|
||||
|
||||
for (Evoral::Sequence::const_iterator i = old_model->begin(); i != old_model->end(); ++i) {
|
||||
for (Evoral::Sequence<MidiModel::TimeType>::const_iterator i = old_model->begin();
|
||||
i != old_model->end(); ++i) {
|
||||
const double new_time = i->time() * _request.time_fraction;
|
||||
|
||||
// FIXME: double copy
|
||||
Evoral::Event ev = Evoral::Event(*i, true);
|
||||
Evoral::Event<MidiModel::TimeType> ev(*i, true);
|
||||
ev.time() = new_time;
|
||||
new_model->append(ev);
|
||||
}
|
||||
|
|
|
@ -363,7 +363,7 @@ Playlist::notify_region_removed (boost::shared_ptr<Region> r)
|
|||
void
|
||||
Playlist::notify_region_moved (boost::shared_ptr<Region> r)
|
||||
{
|
||||
Evoral::RangeMove const move (r->last_position (), r->length (), r->position ());
|
||||
Evoral::RangeMove<nframes_t> const move (r->last_position (), r->length (), r->position ());
|
||||
|
||||
if (holding_state ()) {
|
||||
|
||||
|
@ -371,7 +371,7 @@ Playlist::notify_region_moved (boost::shared_ptr<Region> r)
|
|||
|
||||
} else {
|
||||
|
||||
Evoral::RangeMoveList m;
|
||||
list< Evoral::RangeMove<nframes_t> > m;
|
||||
m.push_back (move);
|
||||
RangesMoved (m);
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ Quantize::run (boost::shared_ptr<Region> r)
|
|||
|
||||
double q_frames = _q * (m.frames_per_bar(t, session.frame_rate()) / (double)m.beats_per_bar());
|
||||
|
||||
for (Evoral::Sequence::Notes::iterator i = model->notes().begin();
|
||||
for (Evoral::Sequence<MidiModel::TimeType>::Notes::iterator i = model->notes().begin();
|
||||
i != model->notes().end(); ++i) {
|
||||
const double new_time = lrint((*i)->time() / q_frames) * q_frames;
|
||||
double new_dur = lrint((*i)->length() / q_frames) * q_frames;
|
||||
|
|
|
@ -55,7 +55,7 @@ uint64_t SMFSource::header_position_offset;
|
|||
|
||||
SMFSource::SMFSource (Session& s, std::string path, Flag flags)
|
||||
: MidiSource (s, region_name_from_path(path, false))
|
||||
, SMF ()
|
||||
, Evoral::SMF<double> ()
|
||||
, _flags (Flag(flags | Writable)) // FIXME: this needs to be writable for now
|
||||
, _allow_remove_if_empty(true)
|
||||
{
|
||||
|
@ -128,7 +128,7 @@ SMFSource::init (string pathstr, bool must_exist)
|
|||
|
||||
/** All stamps in audio frames */
|
||||
nframes_t
|
||||
SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const
|
||||
SMFSource::read_unlocked (MidiRingBuffer<double>& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset, nframes_t negative_stamp_offset) const
|
||||
{
|
||||
//cerr << "SMF read_unlocked " << name() << " read " << start << ", count=" << cnt << ", offset=" << stamp_offset << endl;
|
||||
|
||||
|
@ -146,7 +146,7 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, n
|
|||
size_t scratch_size = 0; // keep track of scratch to minimize reallocs
|
||||
|
||||
// FIXME: don't seek to start and search every read (brutal!)
|
||||
SMF::seek_to_start();
|
||||
Evoral::SMF<double>::seek_to_start();
|
||||
|
||||
// FIXME: assumes tempo never changes after start
|
||||
const double frames_per_beat = _session.tempo_map().tempo_at(_timeline_position).frames_per_beat(
|
||||
|
@ -155,7 +155,7 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, n
|
|||
|
||||
const uint64_t start_ticks = (uint64_t)((start / frames_per_beat) * ppqn());
|
||||
|
||||
while (!SMF::eof()) {
|
||||
while (!Evoral::SMF<double>::eof()) {
|
||||
int ret = read_event(&ev_delta_t, &ev_size, &ev_buffer);
|
||||
if (ret == -1) { // EOF
|
||||
//cerr << "SMF - EOF\n";
|
||||
|
@ -194,11 +194,11 @@ SMFSource::read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, n
|
|||
|
||||
/** All stamps in audio frames */
|
||||
nframes_t
|
||||
SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
|
||||
SMFSource::write_unlocked (MidiRingBuffer<double>& src, nframes_t cnt)
|
||||
{
|
||||
_write_data_count = 0;
|
||||
|
||||
Evoral::EventTime time;
|
||||
double time;
|
||||
Evoral::EventType type;
|
||||
uint32_t size;
|
||||
|
||||
|
@ -208,7 +208,7 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
|
|||
if (_model && ! _model->writing())
|
||||
_model->start_write();
|
||||
|
||||
Evoral::MIDIEvent ev(0, 0.0, 4, NULL, true);
|
||||
Evoral::MIDIEvent<double> ev(0, 0.0, 4, NULL, true);
|
||||
|
||||
while (true) {
|
||||
bool ret = src.peek_time(&time);
|
||||
|
@ -251,7 +251,7 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
|
|||
make_sure_controls_have_the_right_interpolation();
|
||||
}
|
||||
|
||||
SMF::flush();
|
||||
Evoral::SMF<double>::flush();
|
||||
free(buf);
|
||||
|
||||
const nframes_t oldlen = _length;
|
||||
|
@ -264,7 +264,7 @@ SMFSource::write_unlocked (MidiRingBuffer& src, nframes_t cnt)
|
|||
|
||||
|
||||
void
|
||||
SMFSource::append_event_unlocked(EventTimeUnit unit, const Evoral::Event& ev)
|
||||
SMFSource::append_event_unlocked(EventTimeUnit unit, const Evoral::Event<double>& ev)
|
||||
{
|
||||
if (ev.size() == 0) {
|
||||
cerr << "SMFSource: Warning: skipping empty event" << endl;
|
||||
|
@ -299,7 +299,7 @@ SMFSource::append_event_unlocked(EventTimeUnit unit, const Evoral::Event& ev)
|
|||
delta_time = (uint32_t)((ev.time() - last_event_time()) * ppqn());
|
||||
}
|
||||
|
||||
SMF::append_event_unlocked(delta_time, ev);
|
||||
Evoral::SMF<double>::append_event_unlocked(delta_time, ev);
|
||||
|
||||
_write_data_count += ev.size();
|
||||
}
|
||||
|
@ -354,7 +354,7 @@ void
|
|||
SMFSource::mark_streaming_midi_write_started (NoteMode mode, nframes_t start_frame)
|
||||
{
|
||||
MidiSource::mark_streaming_midi_write_started (mode, start_frame);
|
||||
SMF::begin_write (start_frame);
|
||||
Evoral::SMF<double>::begin_write (start_frame);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -367,7 +367,7 @@ SMFSource::mark_streaming_write_completed ()
|
|||
}
|
||||
|
||||
_model->set_edited(false);
|
||||
SMF::end_write ();
|
||||
Evoral::SMF<double>::end_write ();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -632,10 +632,10 @@ SMFSource::load_model(bool lock, bool force_reload)
|
|||
}
|
||||
|
||||
_model->start_write();
|
||||
SMF::seek_to_start();
|
||||
Evoral::SMF<double>::seek_to_start();
|
||||
|
||||
uint64_t time = 0; /* in SMF ticks */
|
||||
Evoral::Event ev;
|
||||
Evoral::Event<double> ev;
|
||||
|
||||
size_t scratch_size = 0; // keep track of scratch and minimize reallocs
|
||||
|
||||
|
@ -655,7 +655,7 @@ SMFSource::load_model(bool lock, bool force_reload)
|
|||
|
||||
if (ret > 0) { // didn't skip (meta) event
|
||||
// make ev.time absolute time in frames
|
||||
ev.time() = time * frames_per_beat / (Evoral::EventTime)ppqn();
|
||||
ev.time() = time * frames_per_beat / (double)ppqn();
|
||||
ev.set_event_type(EventTypeMap::instance().midi_event_type(buf[0]));
|
||||
_model->append(ev);
|
||||
}
|
||||
|
@ -704,6 +704,6 @@ SMFSource::destroy_model()
|
|||
void
|
||||
SMFSource::flush_midi()
|
||||
{
|
||||
SMF::end_write();
|
||||
Evoral::SMF<double>::end_write();
|
||||
}
|
||||
|
||||
|
|
|
@ -120,7 +120,7 @@ public:
|
|||
void erase_range (double start, double end);
|
||||
void erase (iterator);
|
||||
void erase (iterator, iterator);
|
||||
void move_ranges (RangeMoveList const &);
|
||||
void move_ranges (std::list< RangeMove<double> > const &);
|
||||
void modify (iterator, double, double);
|
||||
|
||||
boost::shared_ptr<ControlList> cut (double, double);
|
||||
|
|
|
@ -38,12 +38,12 @@ namespace Evoral {
|
|||
|
||||
/** An event (much like a type generic jack_midi_event_t)
|
||||
*
|
||||
* time is either a frame time (from/to Jack) or a beat time (internal
|
||||
* tempo time, used in MidiModel) depending on context.
|
||||
* Template parameter T is the type of the time stamp used for this event.
|
||||
*/
|
||||
template<typename T>
|
||||
struct Event {
|
||||
#ifdef EVORAL_EVENT_ALLOC
|
||||
Event(EventType type=0, EventTime t=0, uint32_t s=0, uint8_t* b=NULL, bool alloc=false);
|
||||
Event(EventType type=0, T t=0, uint32_t s=0, uint8_t* b=NULL, bool alloc=false);
|
||||
|
||||
/** Copy \a copy.
|
||||
*
|
||||
|
@ -58,18 +58,18 @@ struct Event {
|
|||
inline const Event& operator=(const Event& copy) {
|
||||
_type = copy._type;
|
||||
_time = copy._time;
|
||||
if (_owns_buffer) {
|
||||
if (copy._buffer) {
|
||||
if (_owns_buf) {
|
||||
if (copy._buf) {
|
||||
if (copy._size > _size) {
|
||||
_buffer = (uint8_t*)::realloc(_buffer, copy._size);
|
||||
_buf = (uint8_t*)::realloc(_buf, copy._size);
|
||||
}
|
||||
memcpy(_buffer, copy._buffer, copy._size);
|
||||
memcpy(_buf, copy._buf, copy._size);
|
||||
} else {
|
||||
free(_buffer);
|
||||
_buffer = NULL;
|
||||
free(_buf);
|
||||
_buf = NULL;
|
||||
}
|
||||
} else {
|
||||
_buffer = copy._buffer;
|
||||
_buf = copy._buf;
|
||||
}
|
||||
|
||||
_size = copy._size;
|
||||
|
@ -77,26 +77,26 @@ struct Event {
|
|||
}
|
||||
|
||||
inline void shallow_copy(const Event& copy) {
|
||||
if (_owns_buffer) {
|
||||
free(_buffer);
|
||||
_buffer = false;
|
||||
_owns_buffer = false;
|
||||
if (_owns_buf) {
|
||||
free(_buf);
|
||||
_buf = false;
|
||||
_owns_buf = false;
|
||||
}
|
||||
|
||||
_type = copy._type;
|
||||
_time = copy._time;
|
||||
_size = copy._size;
|
||||
_buffer = copy._buffer;
|
||||
_buf = copy._buf;
|
||||
}
|
||||
|
||||
inline void set(uint8_t* buf, uint32_t size, EventTime t) {
|
||||
if (_owns_buffer) {
|
||||
inline void set(uint8_t* buf, uint32_t size, T t) {
|
||||
if (_owns_buf) {
|
||||
if (_size < size) {
|
||||
_buffer = (uint8_t*) ::realloc(_buffer, size);
|
||||
_buf = (uint8_t*) ::realloc(_buf, size);
|
||||
}
|
||||
memcpy (_buffer, buf, size);
|
||||
memcpy (_buf, buf, size);
|
||||
} else {
|
||||
_buffer = buf;
|
||||
_buf = buf;
|
||||
}
|
||||
|
||||
_time = t;
|
||||
|
@ -113,11 +113,11 @@ struct Event {
|
|||
if (_size != other._size)
|
||||
return false;
|
||||
|
||||
if (_buffer == other._buffer)
|
||||
if (_buf == other._buf)
|
||||
return true;
|
||||
|
||||
for (uint32_t i=0; i < _size; ++i)
|
||||
if (_buffer[i] != other._buffer[i])
|
||||
if (_buf[i] != other._buf[i])
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -125,25 +125,25 @@ struct Event {
|
|||
|
||||
inline bool operator!=(const Event& other) const { return ! operator==(other); }
|
||||
|
||||
inline bool owns_buffer() const { return _owns_buffer; }
|
||||
inline bool owns_buffer() const { return _owns_buf; }
|
||||
|
||||
inline void set_buffer(uint32_t size, uint8_t* buf, bool own) {
|
||||
if (_owns_buffer) {
|
||||
free(_buffer);
|
||||
_buffer = NULL;
|
||||
if (_owns_buf) {
|
||||
free(_buf);
|
||||
_buf = NULL;
|
||||
}
|
||||
_size = size;
|
||||
_buffer = buf;
|
||||
_owns_buffer = own;
|
||||
_size = size;
|
||||
_buf = buf;
|
||||
_owns_buf = own;
|
||||
}
|
||||
|
||||
inline void realloc(uint32_t size) {
|
||||
if (_owns_buffer) {
|
||||
if (_owns_buf) {
|
||||
if (size > _size)
|
||||
_buffer = (uint8_t*) ::realloc(_buffer, size);
|
||||
_buf = (uint8_t*) ::realloc(_buf, size);
|
||||
} else {
|
||||
_buffer = (uint8_t*) ::malloc(size);
|
||||
_owns_buffer = true;
|
||||
_buf = (uint8_t*) ::malloc(size);
|
||||
_owns_buf = true;
|
||||
}
|
||||
|
||||
_size = size;
|
||||
|
@ -153,33 +153,33 @@ struct Event {
|
|||
_type = 0;
|
||||
_time = 0;
|
||||
_size = 0;
|
||||
_buffer = NULL;
|
||||
_buf = NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline void set_buffer(uint8_t* buf) { _buffer = buf; }
|
||||
inline void set_buffer(uint8_t* buf) { _buf = buf; }
|
||||
|
||||
#endif // EVORAL_EVENT_ALLOC
|
||||
|
||||
inline EventType event_type() const { return _type; }
|
||||
inline void set_event_type(EventType t) { _type = t; }
|
||||
inline EventTime time() const { return _time; }
|
||||
inline EventTime& time() { return _time; }
|
||||
inline T time() const { return _time; }
|
||||
inline T& time() { return _time; }
|
||||
inline uint32_t size() const { return _size; }
|
||||
inline uint32_t& size() { return _size; }
|
||||
|
||||
inline const uint8_t* buffer() const { return _buffer; }
|
||||
inline uint8_t*& buffer() { return _buffer; }
|
||||
inline const uint8_t* buffer() const { return _buf; }
|
||||
inline uint8_t*& buffer() { return _buf; }
|
||||
|
||||
protected:
|
||||
EventType _type; /**< Type of event (application relative, NOT MIDI 'type') */
|
||||
EventTime _time; /**< Sample index (or beat time) at which event is valid */
|
||||
uint32_t _size; /**< Number of uint8_ts of data in \a buffer */
|
||||
uint8_t* _buffer; /**< Raw MIDI data */
|
||||
EventType _type; /**< Type of event (application relative, NOT MIDI 'type') */
|
||||
T _time; /**< Sample index (or beat time) at which event is valid */
|
||||
uint32_t _size; /**< Number of uint8_ts of data in \a buffer */
|
||||
uint8_t* _buf; /**< Raw MIDI data */
|
||||
|
||||
#ifdef EVORAL_EVENT_ALLOC
|
||||
bool _owns_buffer; /**< Whether buffer is locally allocated */
|
||||
bool _owns_buf; /**< Whether buffer is locally allocated */
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -34,7 +34,8 @@ namespace Evoral {
|
|||
* This packs a timestamp, size, and size bytes of data flat into the buffer.
|
||||
* Useful for MIDI events, OSC messages, etc.
|
||||
*/
|
||||
class EventRingBuffer : public Evoral::RingBuffer<uint8_t>, public Evoral::EventSink {
|
||||
template<typename T>
|
||||
class EventRingBuffer : public Evoral::RingBuffer<uint8_t>, public Evoral::EventSink<T> {
|
||||
public:
|
||||
|
||||
/** @param capacity Ringbuffer capacity in bytes.
|
||||
|
@ -44,25 +45,27 @@ public:
|
|||
|
||||
size_t capacity() const { return _size; }
|
||||
|
||||
bool peek_time(EventTime* time);
|
||||
bool peek_time(T* time);
|
||||
|
||||
uint32_t write(EventTime time, EventType type, uint32_t size, const uint8_t* buf);
|
||||
bool read (EventTime* time, EventType* type, uint32_t* size, uint8_t* buf);
|
||||
uint32_t write(T time, EventType type, uint32_t size, const uint8_t* buf);
|
||||
bool read (T* time, EventType* type, uint32_t* size, uint8_t* buf);
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
EventRingBuffer::peek_time(EventTime* time)
|
||||
EventRingBuffer<T>::peek_time(T* time)
|
||||
{
|
||||
bool success = RingBuffer<uint8_t>::full_peek(sizeof(EventTime), (uint8_t*)time);
|
||||
bool success = RingBuffer<uint8_t>::full_peek(sizeof(T), (uint8_t*)time);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
EventRingBuffer::read(EventTime* time, EventType* type, uint32_t* size, uint8_t* buf)
|
||||
EventRingBuffer<T>::read(T* time, EventType* type, uint32_t* size, uint8_t* buf)
|
||||
{
|
||||
bool success = RingBuffer<uint8_t>::full_read(sizeof(EventTime), (uint8_t*)time);
|
||||
bool success = RingBuffer<uint8_t>::full_read(sizeof(T), (uint8_t*)time);
|
||||
if (success)
|
||||
success = RingBuffer<uint8_t>::full_read(sizeof(EventType), (uint8_t*)type);
|
||||
if (success)
|
||||
|
@ -74,13 +77,14 @@ EventRingBuffer::read(EventTime* time, EventType* type, uint32_t* size, uint8_t*
|
|||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline uint32_t
|
||||
EventRingBuffer::write(EventTime time, EventType type, uint32_t size, const uint8_t* buf)
|
||||
EventRingBuffer<T>::write(T time, EventType type, uint32_t size, const uint8_t* buf)
|
||||
{
|
||||
if (write_space() < (sizeof(EventTime) + sizeof(EventType) + sizeof(uint32_t) + size)) {
|
||||
if (write_space() < (sizeof(T) + sizeof(EventType) + sizeof(uint32_t) + size)) {
|
||||
return 0;
|
||||
} else {
|
||||
RingBuffer<uint8_t>::write(sizeof(EventTime), (uint8_t*)&time);
|
||||
RingBuffer<uint8_t>::write(sizeof(T), (uint8_t*)&time);
|
||||
RingBuffer<uint8_t>::write(sizeof(EventType), (uint8_t*)&type);
|
||||
RingBuffer<uint8_t>::write(sizeof(uint32_t), (uint8_t*)&size);
|
||||
RingBuffer<uint8_t>::write(size, buf);
|
||||
|
|
|
@ -26,10 +26,11 @@ namespace Evoral {
|
|||
|
||||
/** Pure virtual base for anything you can write events to.
|
||||
*/
|
||||
template<typename T>
|
||||
class EventSink {
|
||||
public:
|
||||
virtual ~EventSink() {}
|
||||
virtual uint32_t write(EventTime time, EventType type, uint32_t size, const uint8_t* buf) = 0;
|
||||
virtual uint32_t write(T time, EventType type, uint32_t size, const uint8_t* buf) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -19,10 +19,11 @@
|
|||
#ifndef EVORAL_MIDI_EVENT_HPP
|
||||
#define EVORAL_MIDI_EVENT_HPP
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include "evoral/Event.hpp"
|
||||
#include "evoral/midi_events.h"
|
||||
#ifdef EVORAL_MIDI_XML
|
||||
#include <pbd/xml++.h>
|
||||
class XMLNode;
|
||||
#endif
|
||||
|
||||
namespace Evoral {
|
||||
|
@ -33,13 +34,14 @@ namespace Evoral {
|
|||
* but the application must make sure the event actually contains
|
||||
* valid MIDI data for these functions to make sense.
|
||||
*/
|
||||
struct MIDIEvent : public Event {
|
||||
MIDIEvent(EventType type=0, EventTime t=0, uint32_t s=0, uint8_t* b=NULL, bool alloc=false)
|
||||
: Event(type, t, s, b, alloc)
|
||||
template<typename T>
|
||||
struct MIDIEvent : public Event<T> {
|
||||
MIDIEvent(EventType type=0, T t=0, uint32_t s=0, uint8_t* b=NULL, bool alloc=false)
|
||||
: Event<T>(type, t, s, b, alloc)
|
||||
{}
|
||||
|
||||
MIDIEvent(const Event& copy, bool alloc)
|
||||
: Event(copy, alloc)
|
||||
MIDIEvent(const Event<T>& copy, bool alloc)
|
||||
: Event<T>(copy, alloc)
|
||||
{}
|
||||
|
||||
#ifdef EVORAL_MIDI_XML
|
||||
|
@ -52,12 +54,12 @@ struct MIDIEvent : public Event {
|
|||
boost::shared_ptr<XMLNode> to_xml() const;
|
||||
#endif
|
||||
|
||||
inline uint8_t type() const { return (_buffer[0] & 0xF0); }
|
||||
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 uint8_t type() const { return (this->_buf[0] & 0xF0); }
|
||||
inline void set_type(uint8_t type) { this->_buf[0] = (0x0F & this->_buf[0])
|
||||
| (0xF0 & type); }
|
||||
inline uint8_t channel() const { return (this->_buf[0] & 0x0F); }
|
||||
inline void set_channel(uint8_t channel) { this->_buf[0] = (0xF0 & this->_buf[0])
|
||||
| (0x0F & channel); }
|
||||
inline bool is_note_on() const { return (type() == MIDI_CMD_NOTE_ON); }
|
||||
inline bool is_note_off() const { return (type() == MIDI_CMD_NOTE_OFF); }
|
||||
inline bool is_cc() const { return (type() == MIDI_CMD_CONTROL); }
|
||||
|
@ -66,24 +68,24 @@ struct MIDIEvent : public Event {
|
|||
inline bool is_note() const { return (is_note_on() || is_note_off()); }
|
||||
inline bool is_aftertouch() const { return (type() == MIDI_CMD_NOTE_PRESSURE); }
|
||||
inline bool is_channel_pressure() const { return (type() == MIDI_CMD_CHANNEL_PRESSURE); }
|
||||
inline uint8_t note() const { return (_buffer[1]); }
|
||||
inline uint8_t velocity() const { return (_buffer[2]); }
|
||||
inline uint8_t cc_number() const { return (_buffer[1]); }
|
||||
inline void set_cc_number(uint8_t number) { _buffer[1] = number; }
|
||||
inline uint8_t cc_value() const { return (_buffer[2]); }
|
||||
inline void set_cc_value(uint8_t value) { _buffer[2] = value; }
|
||||
inline uint8_t pitch_bender_lsb() const { return (_buffer[1]); }
|
||||
inline uint8_t pitch_bender_msb() const { return (_buffer[2]); }
|
||||
inline uint16_t pitch_bender_value() const { return ( ((0x7F & _buffer[2]) << 7)
|
||||
| (0x7F & _buffer[1]) ); }
|
||||
inline uint8_t pgm_number() const { return (_buffer[1]); }
|
||||
inline void set_pgm_number(uint8_t number){ _buffer[1] = number; }
|
||||
inline uint8_t aftertouch() const { return (_buffer[1]); }
|
||||
inline uint8_t channel_pressure() const { return (_buffer[1]); }
|
||||
inline uint8_t note() const { return (this->_buf[1]); }
|
||||
inline uint8_t velocity() const { return (this->_buf[2]); }
|
||||
inline uint8_t cc_number() const { return (this->_buf[1]); }
|
||||
inline void set_cc_number(uint8_t number) { this->_buf[1] = number; }
|
||||
inline uint8_t cc_value() const { return (this->_buf[2]); }
|
||||
inline void set_cc_value(uint8_t value) { this->_buf[2] = value; }
|
||||
inline uint8_t pitch_bender_lsb() const { return (this->_buf[1]); }
|
||||
inline uint8_t pitch_bender_msb() const { return (this->_buf[2]); }
|
||||
inline uint16_t pitch_bender_value() const { return ( ((0x7F & this->_buf[2]) << 7)
|
||||
| (0x7F & this->_buf[1]) ); }
|
||||
inline uint8_t pgm_number() const { return (this->_buf[1]); }
|
||||
inline void set_pgm_number(uint8_t number){ this->_buf[1] = number; }
|
||||
inline uint8_t aftertouch() const { return (this->_buf[1]); }
|
||||
inline uint8_t channel_pressure() const { return (this->_buf[1]); }
|
||||
inline bool is_channel_event() const { return (0x80 <= type()) && (type() <= 0xE0); }
|
||||
inline bool is_smf_meta_event() const { return _buffer[0] == 0xFF; }
|
||||
inline bool is_sysex() const { return _buffer[0] == 0xF0
|
||||
|| _buffer[0] == 0xF7; }
|
||||
inline bool is_smf_meta_event() const { return this->_buf[0] == 0xFF; }
|
||||
inline bool is_sysex() const { return this->_buf[0] == 0xF0
|
||||
|| this->_buf[0] == 0xF7; }
|
||||
};
|
||||
|
||||
} // namespace Evoral
|
||||
|
|
|
@ -29,15 +29,16 @@ namespace Evoral {
|
|||
*
|
||||
* Currently a note is defined as (on event, length, off event).
|
||||
*/
|
||||
template<typename T>
|
||||
class Note {
|
||||
public:
|
||||
Note(uint8_t chan=0, EventTime time=0, EventLength len=0, uint8_t note=0, uint8_t vel=0x40);
|
||||
Note(const Note& copy);
|
||||
Note(uint8_t chan=0, T time=0, EventLength len=0, uint8_t note=0, uint8_t vel=0x40);
|
||||
Note(const Note<T>& copy);
|
||||
~Note();
|
||||
|
||||
const Note& operator=(const Note& copy);
|
||||
const Note<T>& operator=(const Note<T>& copy);
|
||||
|
||||
inline bool operator==(const Note& other) {
|
||||
inline bool operator==(const Note<T>& other) {
|
||||
return time() == other.time() &&
|
||||
note() == other.note() &&
|
||||
length() == other.length() &&
|
||||
|
@ -45,8 +46,8 @@ public:
|
|||
channel() == other.channel();
|
||||
}
|
||||
|
||||
inline EventTime time() const { return _on_event.time(); }
|
||||
inline EventTime end_time() const { return _off_event.time(); }
|
||||
inline T time() const { return _on_event.time(); }
|
||||
inline T 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 EventLength length() const { return _off_event.time() - _on_event.time(); }
|
||||
|
@ -55,21 +56,21 @@ public:
|
|||
return _on_event.channel();
|
||||
}
|
||||
|
||||
inline void set_time(EventTime t) { _off_event.time() = t + length(); _on_event.time() = t; }
|
||||
inline void set_time(T t) { _off_event.time() = t + length(); _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_length(EventLength l) { _off_event.time() = _on_event.time() + l; }
|
||||
inline void set_channel(uint8_t c) { _on_event.set_channel(c); _off_event.set_channel(c); }
|
||||
|
||||
inline Event& on_event() { return _on_event; }
|
||||
inline const Event& on_event() const { return _on_event; }
|
||||
inline Event& off_event() { return _off_event; }
|
||||
inline const Event& off_event() const { return _off_event; }
|
||||
inline Event<T>& on_event() { return _on_event; }
|
||||
inline const Event<T>& on_event() const { return _on_event; }
|
||||
inline Event<T>& off_event() { return _off_event; }
|
||||
inline const Event<T>& off_event() const { return _off_event; }
|
||||
|
||||
private:
|
||||
// Event buffers are self-contained
|
||||
MIDIEvent _on_event;
|
||||
MIDIEvent _off_event;
|
||||
MIDIEvent<T> _on_event;
|
||||
MIDIEvent<T> _off_event;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -24,12 +24,13 @@
|
|||
|
||||
namespace Evoral {
|
||||
|
||||
class Event;
|
||||
class EventRingBuffer;
|
||||
template<typename T> class Event;
|
||||
template<typename T> class EventRingBuffer;
|
||||
|
||||
|
||||
/** Standard Midi File (Type 0)
|
||||
*/
|
||||
template<typename T>
|
||||
class SMF {
|
||||
public:
|
||||
SMF();
|
||||
|
@ -37,14 +38,14 @@ public:
|
|||
|
||||
void seek_to_start() const;
|
||||
|
||||
uint16_t ppqn() const { return _ppqn; }
|
||||
uint16_t ppqn() const { return _ppqn; }
|
||||
bool is_empty() const { return _empty; }
|
||||
bool eof() const { return feof(_fd); }
|
||||
bool eof() const { return feof(_fd); }
|
||||
|
||||
EventTime last_event_time() const { return _last_ev_time; }
|
||||
T last_event_time() const { return _last_ev_time; }
|
||||
|
||||
void begin_write(FrameTime start_time);
|
||||
void append_event_unlocked(uint32_t delta_t, const Evoral::Event& ev);
|
||||
void append_event_unlocked(uint32_t delta_t, const Event<T>& ev);
|
||||
void end_write();
|
||||
|
||||
void flush();
|
||||
|
@ -70,11 +71,11 @@ protected:
|
|||
private:
|
||||
static const uint16_t _ppqn = 19200;
|
||||
|
||||
FILE* _fd;
|
||||
EventTime _last_ev_time; ///< last frame time written, relative to source start
|
||||
uint32_t _track_size;
|
||||
uint32_t _header_size; ///< size of SMF header, including MTrk chunk header
|
||||
bool _empty; ///< true iff file contains(non-empty) events
|
||||
FILE* _fd;
|
||||
T _last_ev_time; ///< last frame time written, relative to source start
|
||||
uint32_t _track_size;
|
||||
uint32_t _header_size; ///< size of SMF header, including MTrk chunk header
|
||||
bool _empty; ///< true iff file contains(non-empty) events
|
||||
};
|
||||
|
||||
}; /* namespace Evoral */
|
||||
|
|
|
@ -35,9 +35,9 @@
|
|||
namespace Evoral {
|
||||
|
||||
class TypeMap;
|
||||
class EventSink;
|
||||
class Note;
|
||||
class Event;
|
||||
template<typename T> class EventSink;
|
||||
template<typename T> class Note;
|
||||
template<typename T> class Event;
|
||||
|
||||
/** An iterator over (the x axis of) a 2-d double coordinate space.
|
||||
*/
|
||||
|
@ -58,6 +58,7 @@ public:
|
|||
/** This is a higher level view of events, with separate representations for
|
||||
* notes (instead of just unassociated note on/off events) and controller data.
|
||||
* Controller data is represented as a list of time-stamped float values. */
|
||||
template<typename T>
|
||||
class Sequence : virtual public ControlSet {
|
||||
public:
|
||||
Sequence(const TypeMap& type_map, size_t size=0);
|
||||
|
@ -79,49 +80,49 @@ public:
|
|||
bool writing() const { return _writing; }
|
||||
void end_write(bool delete_stuck=false);
|
||||
|
||||
size_t read(EventSink& dst,
|
||||
timestamp_t start,
|
||||
timedur_t length,
|
||||
timestamp_t stamp_offset) const;
|
||||
size_t read(EventSink<T>& dst,
|
||||
timestamp_t start,
|
||||
timedur_t length,
|
||||
timestamp_t stamp_offset) const;
|
||||
|
||||
/** Resizes vector if necessary (NOT realtime safe) */
|
||||
void append(const Event& ev);
|
||||
void append(const Event<T>& ev);
|
||||
|
||||
inline const boost::shared_ptr<const Note> note_at(unsigned i) const { return _notes[i]; }
|
||||
inline const boost::shared_ptr<Note> note_at(unsigned i) { return _notes[i]; }
|
||||
inline const boost::shared_ptr< const Note<T> > note_at(unsigned i) const { return _notes[i]; }
|
||||
inline const boost::shared_ptr< Note<T> > note_at(unsigned i) { return _notes[i]; }
|
||||
|
||||
inline size_t n_notes() const { return _notes.size(); }
|
||||
inline bool empty() const { return _notes.size() == 0 && ControlSet::empty(); }
|
||||
|
||||
inline static bool note_time_comparator(const boost::shared_ptr<const Note>& a,
|
||||
const boost::shared_ptr<const Note>& b) {
|
||||
inline static bool note_time_comparator(const boost::shared_ptr< const Note<T> >& a,
|
||||
const boost::shared_ptr< const Note<T> >& b) {
|
||||
return a->time() < b->time();
|
||||
}
|
||||
|
||||
struct LaterNoteEndComparator {
|
||||
typedef const Note* value_type;
|
||||
inline bool operator()(const boost::shared_ptr<const Note> a,
|
||||
const boost::shared_ptr<const Note> b) const {
|
||||
typedef const Note<T>* value_type;
|
||||
inline bool operator()(const boost::shared_ptr< const Note<T> > a,
|
||||
const boost::shared_ptr< const Note<T> > b) const {
|
||||
return a->end_time() > b->end_time();
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::vector< boost::shared_ptr<Note> > Notes;
|
||||
typedef std::vector< boost::shared_ptr< Note<T> > > Notes;
|
||||
inline Notes& notes() { return _notes; }
|
||||
inline const Notes& notes() const { return _notes; }
|
||||
|
||||
/** Read iterator */
|
||||
class const_iterator {
|
||||
public:
|
||||
const_iterator(const Sequence& seq, EventTime t);
|
||||
const_iterator(const Sequence<T>& seq, T t);
|
||||
~const_iterator();
|
||||
|
||||
inline bool valid() const { return !_is_end && _event; }
|
||||
inline bool locked() const { return _locked; }
|
||||
|
||||
const Event& operator*() const { return *_event; }
|
||||
const boost::shared_ptr<Event> operator->() const { return _event; }
|
||||
const boost::shared_ptr<Event> get_event_pointer() { return _event; }
|
||||
const Event<T>& operator*() const { return *_event; }
|
||||
const boost::shared_ptr< Event<T> > operator->() const { return _event; }
|
||||
const boost::shared_ptr< Event<T> > get_event_pointer() { return _event; }
|
||||
|
||||
const const_iterator& operator++(); // prefix only
|
||||
bool operator==(const const_iterator& other) const;
|
||||
|
@ -130,13 +131,13 @@ public:
|
|||
const_iterator& operator=(const const_iterator& other);
|
||||
|
||||
private:
|
||||
friend class Sequence;
|
||||
friend class Sequence<T>;
|
||||
|
||||
const Sequence* _seq;
|
||||
boost::shared_ptr<Event> _event;
|
||||
const Sequence<T>* _seq;
|
||||
boost::shared_ptr< Event<T> > _event;
|
||||
|
||||
typedef std::priority_queue< boost::shared_ptr<Note>,
|
||||
std::deque< boost::shared_ptr<Note> >,
|
||||
typedef std::priority_queue< boost::shared_ptr< Note<T> >,
|
||||
std::deque< boost::shared_ptr< Note<T> > >,
|
||||
LaterNoteEndComparator >
|
||||
ActiveNotes;
|
||||
|
||||
|
@ -144,21 +145,21 @@ public:
|
|||
|
||||
typedef std::vector<ControlIterator> ControlIterators;
|
||||
|
||||
bool _is_end;
|
||||
bool _locked;
|
||||
Notes::const_iterator _note_iter;
|
||||
ControlIterators _control_iters;
|
||||
ControlIterators::iterator _control_iter;
|
||||
bool _is_end;
|
||||
bool _locked;
|
||||
typename Notes::const_iterator _note_iter;
|
||||
ControlIterators _control_iters;
|
||||
ControlIterators::iterator _control_iter;
|
||||
};
|
||||
|
||||
const_iterator begin(EventTime t=0) const { return const_iterator(*this, t); }
|
||||
const const_iterator& end() const { return _end_iter; }
|
||||
const_iterator begin(T t=0) const { return const_iterator(*this, t); }
|
||||
const const_iterator& end() const { return _end_iter; }
|
||||
|
||||
void read_seek(EventTime t) { _read_iter = begin(t); }
|
||||
EventTime read_time() const { return _read_iter.valid() ? _read_iter->time() : 0.0; }
|
||||
void read_seek(T t) { _read_iter = begin(t); }
|
||||
T read_time() const { return _read_iter.valid() ? _read_iter->time() : 0.0; }
|
||||
|
||||
bool control_to_midi_event(boost::shared_ptr<Event>& ev,
|
||||
const ControlIterator& iter) const;
|
||||
bool control_to_midi_event(boost::shared_ptr< Event<T> >& ev,
|
||||
const ControlIterator& iter) const;
|
||||
|
||||
bool edited() const { return _edited; }
|
||||
void set_edited(bool yn) { _edited = yn; }
|
||||
|
@ -167,8 +168,8 @@ public:
|
|||
bool is_sorted() const;
|
||||
#endif
|
||||
|
||||
void add_note_unlocked(const boost::shared_ptr<Note> note);
|
||||
void remove_note_unlocked(const boost::shared_ptr<const Note> note);
|
||||
void add_note_unlocked(const boost::shared_ptr< Note<T> > note);
|
||||
void remove_note_unlocked(const boost::shared_ptr< const Note<T> > note);
|
||||
|
||||
uint8_t lowest_note() const { return _lowest_note; }
|
||||
uint8_t highest_note() const { return _highest_note; }
|
||||
|
@ -180,9 +181,9 @@ protected:
|
|||
private:
|
||||
friend class const_iterator;
|
||||
|
||||
void append_note_on_unlocked(uint8_t chan, EventTime time, uint8_t note, uint8_t velocity);
|
||||
void append_note_off_unlocked(uint8_t chan, EventTime time, uint8_t note);
|
||||
void append_control_unlocked(const Parameter& param, EventTime time, double value);
|
||||
void append_note_on_unlocked(uint8_t chan, T time, uint8_t note, uint8_t velocity);
|
||||
void append_note_off_unlocked(uint8_t chan, T time, uint8_t note);
|
||||
void append_control_unlocked(const Parameter& param, T time, double value);
|
||||
|
||||
mutable Glib::RWLock _lock;
|
||||
|
||||
|
@ -205,7 +206,7 @@ private:
|
|||
uint8_t _highest_note;
|
||||
|
||||
typedef std::priority_queue<
|
||||
boost::shared_ptr<Note>, std::deque< boost::shared_ptr<Note> >,
|
||||
boost::shared_ptr< Note<T> >, std::deque< boost::shared_ptr< Note<T> > >,
|
||||
LaterNoteEndComparator>
|
||||
ActiveNotes;
|
||||
};
|
||||
|
|
|
@ -33,9 +33,6 @@ typedef double timestamp_t;
|
|||
/** Duration of time in timestamp_t units */
|
||||
typedef timestamp_t timedur_t;
|
||||
|
||||
/** Time stamp of an event */
|
||||
typedef double EventTime;
|
||||
|
||||
/** Time stamp of an event */
|
||||
typedef double EventLength;
|
||||
|
||||
|
@ -43,15 +40,14 @@ typedef double EventLength;
|
|||
typedef uint32_t EventType;
|
||||
|
||||
/** Type to describe the movement of a time range */
|
||||
template<typename T>
|
||||
struct RangeMove {
|
||||
RangeMove (EventTime f, FrameTime l, EventTime t) : from (f), length (l), to (t) {}
|
||||
EventTime from; ///< start of the range
|
||||
RangeMove (T f, FrameTime l, T t) : from (f), length (l), to (t) {}
|
||||
T from; ///< start of the range
|
||||
FrameTime length; ///< length of the range
|
||||
EventTime to; ///< new start of the range
|
||||
T to; ///< new start of the range
|
||||
};
|
||||
|
||||
typedef std::list<RangeMove> RangeMoveList;
|
||||
|
||||
} // namespace Evoral
|
||||
|
||||
#endif // EVORAL_TYPES_HPP
|
||||
|
|
|
@ -1285,8 +1285,10 @@ ControlList::paste (ControlList& alist, double pos, float times)
|
|||
|
||||
/** Move automation around according to a list of region movements */
|
||||
void
|
||||
ControlList::move_ranges (RangeMoveList const & movements)
|
||||
ControlList::move_ranges (const list< RangeMove<double> >& movements)
|
||||
{
|
||||
typedef list< RangeMove<double> > RangeMoveList;
|
||||
|
||||
{
|
||||
Glib::Mutex::Lock lm (_lock);
|
||||
|
||||
|
@ -1304,8 +1306,8 @@ ControlList::move_ranges (RangeMoveList const & movements)
|
|||
/* copy the events into the new list */
|
||||
for (RangeMoveList::const_iterator i = movements.begin (); i != movements.end (); ++i) {
|
||||
iterator j = old_events.begin ();
|
||||
EventTime const limit = i->from + i->length;
|
||||
EventTime const dx = i->to - i->from;
|
||||
const double limit = i->from + i->length;
|
||||
const double dx = i->to - i->from;
|
||||
while (j != old_events.end () && (*j)->when <= limit) {
|
||||
if ((*j)->when >= i->from) {
|
||||
ControlEvent* ev = new ControlEvent (**j);
|
||||
|
|
|
@ -22,47 +22,52 @@ namespace Evoral {
|
|||
|
||||
#ifdef EVORAL_EVENT_ALLOC
|
||||
|
||||
Event::Event(uint32_t tid, EventTime t, uint32_t s, uint8_t* b, bool owns_buffer)
|
||||
template<typename T>
|
||||
Event<T>::Event(uint32_t tid, T t, uint32_t s, uint8_t* b, bool owns_buf)
|
||||
: _type(tid)
|
||||
, _time(t)
|
||||
, _size(s)
|
||||
, _buffer(b)
|
||||
, _owns_buffer(owns_buffer)
|
||||
, _buf(b)
|
||||
, _owns_buf(owns_buf)
|
||||
{
|
||||
if (owns_buffer) {
|
||||
_buffer = (uint8_t*)malloc(_size);
|
||||
if (owns_buf) {
|
||||
_buf = (uint8_t*)malloc(_size);
|
||||
if (b) {
|
||||
memcpy(_buffer, b, _size);
|
||||
memcpy(_buf, b, _size);
|
||||
} else {
|
||||
memset(_buffer, 0, _size);
|
||||
memset(_buf, 0, _size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Event::Event(const Event& copy, bool owns_buffer)
|
||||
template<typename T>
|
||||
Event<T>::Event(const Event& copy, bool owns_buf)
|
||||
: _type(copy._type)
|
||||
, _time(copy._time)
|
||||
, _size(copy._size)
|
||||
, _buffer(copy._buffer)
|
||||
, _owns_buffer(owns_buffer)
|
||||
, _buf(copy._buf)
|
||||
, _owns_buf(owns_buf)
|
||||
{
|
||||
if (owns_buffer) {
|
||||
_buffer = (uint8_t*)malloc(_size);
|
||||
if (copy._buffer) {
|
||||
memcpy(_buffer, copy._buffer, _size);
|
||||
if (owns_buf) {
|
||||
_buf = (uint8_t*)malloc(_size);
|
||||
if (copy._buf) {
|
||||
memcpy(_buf, copy._buf, _size);
|
||||
} else {
|
||||
memset(_buffer, 0, _size);
|
||||
memset(_buf, 0, _size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Event::~Event() {
|
||||
if (_owns_buffer) {
|
||||
free(_buffer);
|
||||
template<typename T>
|
||||
Event<T>::~Event() {
|
||||
if (_owns_buf) {
|
||||
free(_buf);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // EVORAL_EVENT_ALLOC
|
||||
|
||||
} // namespace MIDI
|
||||
template class Event<double>;
|
||||
|
||||
} // namespace Evoral
|
||||
|
||||
|
|
|
@ -16,27 +16,34 @@
|
|||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include "evoral/MIDIEvent.hpp"
|
||||
#ifdef EVORAL_MIDI_XML
|
||||
#include <pbd/xml++.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Evoral {
|
||||
|
||||
#ifdef EVORAL_MIDI_XML
|
||||
|
||||
MIDIEvent::MIDIEvent(const XMLNode& event)
|
||||
: Event()
|
||||
template<typename T>
|
||||
MIDIEvent<T>::MIDIEvent(const XMLNode& event)
|
||||
: Event<T>()
|
||||
{
|
||||
string name = event.name();
|
||||
|
||||
if (name == "ControlChange") {
|
||||
_buffer = (uint8_t*) ::malloc(3);
|
||||
_owns_buffer = true;
|
||||
this->_buf = (uint8_t*) ::malloc(3);
|
||||
this->_owns_buf = true;
|
||||
set_type(MIDI_CMD_CONTROL);
|
||||
|
||||
set_cc_number(atoi(event.property("Control")->value().c_str()));
|
||||
set_cc_value (atoi(event.property("Value")->value().c_str()));
|
||||
} else if (name == "ProgramChange") {
|
||||
_buffer = (uint8_t*) ::malloc(2);
|
||||
_owns_buffer = true;
|
||||
this->_buf = (uint8_t*) ::malloc(2);
|
||||
this->_owns_buf = true;
|
||||
set_type(MIDI_CMD_PGM_CHANGE);
|
||||
|
||||
set_pgm_number(atoi(event.property("Number")->value().c_str()));
|
||||
|
@ -44,8 +51,9 @@ MIDIEvent::MIDIEvent(const XMLNode& event)
|
|||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
boost::shared_ptr<XMLNode>
|
||||
MIDIEvent::to_xml() const
|
||||
MIDIEvent<T>::to_xml() const
|
||||
{
|
||||
XMLNode *result = 0;
|
||||
|
||||
|
@ -73,5 +81,7 @@ MIDIEvent::to_xml() const
|
|||
|
||||
#endif // EVORAL_MIDI_XML
|
||||
|
||||
} // namespace MIDI
|
||||
template class MIDIEvent<double>;
|
||||
|
||||
} // namespace Evoral
|
||||
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
|
||||
namespace Evoral {
|
||||
|
||||
Note::Note(uint8_t chan, EventTime t, EventLength l, uint8_t n, uint8_t v)
|
||||
template<typename T>
|
||||
Note<T>::Note(uint8_t chan, T t, EventLength l, uint8_t n, uint8_t v)
|
||||
// FIXME: types?
|
||||
: _on_event(0xDE, t, 3, NULL, true)
|
||||
, _off_event(0xAD, t + l, 3, NULL, true)
|
||||
|
@ -45,7 +46,8 @@ Note::Note(uint8_t chan, EventTime t, EventLength l, uint8_t n, uint8_t v)
|
|||
}
|
||||
|
||||
|
||||
Note::Note(const Note& copy)
|
||||
template<typename T>
|
||||
Note<T>::Note(const Note<T>& copy)
|
||||
: _on_event(copy._on_event, true)
|
||||
, _off_event(copy._off_event, true)
|
||||
{
|
||||
|
@ -71,13 +73,15 @@ Note::Note(const Note& copy)
|
|||
}
|
||||
|
||||
|
||||
Note::~Note()
|
||||
template<typename T>
|
||||
Note<T>::~Note()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
const Note&
|
||||
Note::operator=(const Note& copy)
|
||||
template<typename T>
|
||||
const Note<T>&
|
||||
Note<T>::operator=(const Note<T>& copy)
|
||||
{
|
||||
_on_event = copy._on_event;
|
||||
_off_event = copy._off_event;
|
||||
|
@ -93,4 +97,6 @@ Note::operator=(const Note& copy)
|
|||
return *this;
|
||||
}
|
||||
|
||||
template class Note<double>;
|
||||
|
||||
} // namespace Evoral
|
||||
|
|
|
@ -32,7 +32,8 @@ using namespace std;
|
|||
|
||||
namespace Evoral {
|
||||
|
||||
SMF::SMF()
|
||||
template<typename T>
|
||||
SMF<T>::SMF()
|
||||
: _fd(0)
|
||||
, _last_ev_time(0)
|
||||
, _track_size(4) // 4 bytes for the ever-present EOT event
|
||||
|
@ -41,7 +42,8 @@ SMF::SMF()
|
|||
{
|
||||
}
|
||||
|
||||
SMF::~SMF()
|
||||
template<typename T>
|
||||
SMF<T>::~SMF()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -53,8 +55,9 @@ SMF::~SMF()
|
|||
* -1 if the file can not be opened for reading,
|
||||
* -2 if the file can not be opened for writing
|
||||
*/
|
||||
template<typename T>
|
||||
int
|
||||
SMF::open(const std::string& path)
|
||||
SMF<T>::open(const std::string& path)
|
||||
{
|
||||
//cerr << "Opening SMF file " << path() << " writeable: " << writable() << endl;
|
||||
_fd = fopen(path.c_str(), "r+");
|
||||
|
@ -87,8 +90,9 @@ SMF::open(const std::string& path)
|
|||
return (_fd == 0) ? -1 : 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
SMF::close()
|
||||
SMF<T>::close()
|
||||
{
|
||||
if (_fd) {
|
||||
flush_header();
|
||||
|
@ -98,14 +102,16 @@ SMF::close()
|
|||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
SMF::seek_to_start() const
|
||||
SMF<T>::seek_to_start() const
|
||||
{
|
||||
fseek(_fd, _header_size, SEEK_SET);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
SMF::seek_to_footer_position()
|
||||
SMF<T>::seek_to_footer_position()
|
||||
{
|
||||
uint8_t buffer[4];
|
||||
|
||||
|
@ -126,14 +132,16 @@ SMF::seek_to_footer_position()
|
|||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
SMF::flush()
|
||||
SMF<T>::flush()
|
||||
{
|
||||
fflush(_fd);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int
|
||||
SMF::flush_header()
|
||||
SMF<T>::flush_header()
|
||||
{
|
||||
// FIXME: write timeline position somehow?
|
||||
|
||||
|
@ -161,8 +169,9 @@ SMF::flush_header()
|
|||
return 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int
|
||||
SMF::flush_footer()
|
||||
SMF<T>::flush_footer()
|
||||
{
|
||||
//cerr << path() << " SMF Flushing footer\n";
|
||||
seek_to_footer_position();
|
||||
|
@ -172,8 +181,9 @@ SMF::flush_footer()
|
|||
return 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
SMF::write_footer()
|
||||
SMF<T>::write_footer()
|
||||
{
|
||||
write_var_len(0);
|
||||
char eot[3] = { 0xFF, 0x2F, 0x00 }; // end-of-track meta-event
|
||||
|
@ -196,8 +206,9 @@ SMF::write_footer()
|
|||
* Returns event length (including status byte) on success, 0 if event was
|
||||
* skipped (eg a meta event), or -1 on EOF (or end of track).
|
||||
*/
|
||||
template<typename T>
|
||||
int
|
||||
SMF::read_event(uint32_t* delta_t, uint32_t* size, uint8_t** buf) const
|
||||
SMF<T>::read_event(uint32_t* delta_t, uint32_t* size, uint8_t** buf) const
|
||||
{
|
||||
if (feof(_fd)) {
|
||||
return -1;
|
||||
|
@ -263,8 +274,9 @@ SMF::read_event(uint32_t* delta_t, uint32_t* size, uint8_t** buf) const
|
|||
return (int)*size;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
SMF::append_event_unlocked(uint32_t delta_t, const Evoral::Event& ev)
|
||||
SMF<T>::append_event_unlocked(uint32_t delta_t, const Event<T>& ev)
|
||||
{
|
||||
if (ev.size() == 0)
|
||||
return;
|
||||
|
@ -279,22 +291,25 @@ SMF::append_event_unlocked(uint32_t delta_t, const Evoral::Event& ev)
|
|||
_empty = false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
SMF::begin_write(FrameTime start_frame)
|
||||
SMF<T>::begin_write(FrameTime start_frame)
|
||||
{
|
||||
_last_ev_time = 0;
|
||||
fseek(_fd, _header_size, SEEK_SET);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
SMF::end_write()
|
||||
SMF<T>::end_write()
|
||||
{
|
||||
flush_header();
|
||||
flush_footer();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
SMF::write_chunk_header(const char id[4], uint32_t length)
|
||||
SMF<T>::write_chunk_header(const char id[4], uint32_t length)
|
||||
{
|
||||
const uint32_t length_be = GUINT32_TO_BE(length);
|
||||
|
||||
|
@ -302,8 +317,9 @@ SMF::write_chunk_header(const char id[4], uint32_t length)
|
|||
fwrite(&length_be, 4, 1, _fd);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
SMF::write_chunk(const char id[4], uint32_t length, void* data)
|
||||
SMF<T>::write_chunk(const char id[4], uint32_t length, void* data)
|
||||
{
|
||||
write_chunk_header(id, length);
|
||||
|
||||
|
@ -311,8 +327,9 @@ SMF::write_chunk(const char id[4], uint32_t length, void* data)
|
|||
}
|
||||
|
||||
/** Returns the size (in bytes) of the value written. */
|
||||
template<typename T>
|
||||
size_t
|
||||
SMF::write_var_len(uint32_t value)
|
||||
SMF<T>::write_var_len(uint32_t value)
|
||||
{
|
||||
size_t ret = 0;
|
||||
|
||||
|
@ -336,4 +353,6 @@ SMF::write_var_len(uint32_t value)
|
|||
return ret;
|
||||
}
|
||||
|
||||
template class SMF<double>;
|
||||
|
||||
} // namespace Evoral
|
||||
|
|
|
@ -35,21 +35,25 @@ using namespace std;
|
|||
|
||||
namespace Evoral {
|
||||
|
||||
void Sequence::write_lock() {
|
||||
template<typename T>
|
||||
void Sequence<T>::write_lock() {
|
||||
_lock.writer_lock();
|
||||
_control_lock.lock();
|
||||
}
|
||||
|
||||
void Sequence::write_unlock() {
|
||||
template<typename T>
|
||||
void Sequence<T>::write_unlock() {
|
||||
_lock.writer_unlock();
|
||||
_control_lock.unlock();
|
||||
}
|
||||
|
||||
void Sequence::read_lock() const {
|
||||
template<typename T>
|
||||
void Sequence<T>::read_lock() const {
|
||||
_lock.reader_lock();
|
||||
}
|
||||
|
||||
void Sequence::read_unlock() const {
|
||||
template<typename T>
|
||||
void Sequence<T>::read_unlock() const {
|
||||
_lock.reader_unlock();
|
||||
}
|
||||
|
||||
|
@ -64,7 +68,8 @@ static ostream& errorout = cerr;
|
|||
|
||||
// Read iterator (const_iterator)
|
||||
|
||||
Sequence::const_iterator::const_iterator(const Sequence& seq, EventTime t)
|
||||
template<typename T>
|
||||
Sequence<T>::const_iterator::const_iterator(const Sequence<T>& seq, T t)
|
||||
: _seq(&seq)
|
||||
, _is_end( (t == DBL_MAX) || seq.empty() )
|
||||
, _locked( !_is_end )
|
||||
|
@ -79,7 +84,8 @@ Sequence::const_iterator::const_iterator(const Sequence& seq, EventTime t)
|
|||
|
||||
// find first note which begins after t
|
||||
_note_iter = seq.notes().end();
|
||||
for (Sequence::Notes::const_iterator i = seq.notes().begin(); i != seq.notes().end(); ++i) {
|
||||
for (typename Sequence<T>::Notes::const_iterator i = seq.notes().begin();
|
||||
i != seq.notes().end(); ++i) {
|
||||
if ((*i)->time() >= t) {
|
||||
_note_iter = i;
|
||||
break;
|
||||
|
@ -130,7 +136,7 @@ Sequence::const_iterator::const_iterator(const Sequence& seq, EventTime t)
|
|||
&& (!earliest_control.list
|
||||
|| (*_note_iter)->on_event().time() < earliest_control.x)) {
|
||||
debugout << "Reading note on event @ " << (*_note_iter)->on_event().time() << endl;
|
||||
_event = boost::shared_ptr<Event>(new Event((*_note_iter)->on_event(), true));
|
||||
_event = boost::shared_ptr< Event<T> >(new Event<T>((*_note_iter)->on_event(), true));
|
||||
_active_notes.push(*_note_iter);
|
||||
++_note_iter;
|
||||
_control_iter = _control_iters.end();
|
||||
|
@ -152,22 +158,24 @@ Sequence::const_iterator::const_iterator(const Sequence& seq, EventTime t)
|
|||
}
|
||||
} else {
|
||||
debugout << "New Iterator = " << _event->event_type();
|
||||
debugout << " : " << hex << (int)((MIDIEvent*)_event.get())->type();
|
||||
debugout << " : " << hex << (int)((MIDIEvent<T>*)_event.get())->type();
|
||||
debugout << " @ " << _event->time() << endl;
|
||||
}
|
||||
|
||||
//assert(_is_end || (_event->buffer() && _event->buffer()[0] != '\0'));
|
||||
}
|
||||
|
||||
Sequence::const_iterator::~const_iterator()
|
||||
template<typename T>
|
||||
Sequence<T>::const_iterator::~const_iterator()
|
||||
{
|
||||
if (_locked) {
|
||||
_seq->read_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
const
|
||||
Sequence::const_iterator& Sequence::const_iterator::operator++()
|
||||
template<typename T>
|
||||
const typename Sequence<T>::const_iterator&
|
||||
Sequence<T>::const_iterator::operator++()
|
||||
{
|
||||
if (_is_end) {
|
||||
throw std::logic_error("Attempt to iterate past end of Sequence");
|
||||
|
@ -176,7 +184,7 @@ Sequence::const_iterator& Sequence::const_iterator::operator++()
|
|||
debugout << "Iterator ++" << endl;
|
||||
assert(_event->buffer() && _event->size() > 0);
|
||||
|
||||
const MIDIEvent& ev = *((MIDIEvent*)_event.get());
|
||||
const MIDIEvent<T>& ev = *((MIDIEvent<T>*)_event.get());
|
||||
|
||||
//debugout << "const_iterator::operator++: " << _event->to_string() << endl;
|
||||
|
||||
|
@ -214,10 +222,10 @@ Sequence::const_iterator& Sequence::const_iterator::operator++()
|
|||
}
|
||||
}
|
||||
|
||||
enum Type {NIL, NOTE_ON, NOTE_OFF, CONTROL};
|
||||
enum Type { NIL, NOTE_ON, NOTE_OFF, CONTROL };
|
||||
|
||||
Type type = NIL;
|
||||
EventTime t = 0;
|
||||
T t = 0;
|
||||
|
||||
// Next earliest note on
|
||||
if (_note_iter != _seq->notes().end()) {
|
||||
|
@ -262,8 +270,9 @@ Sequence::const_iterator& Sequence::const_iterator::operator++()
|
|||
return *this;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool
|
||||
Sequence::const_iterator::operator==(const const_iterator& other) const
|
||||
Sequence<T>::const_iterator::operator==(const const_iterator& other) const
|
||||
{
|
||||
if (_is_end || other._is_end) {
|
||||
return (_is_end == other._is_end);
|
||||
|
@ -272,8 +281,9 @@ Sequence::const_iterator::operator==(const const_iterator& other) const
|
|||
}
|
||||
}
|
||||
|
||||
Sequence::const_iterator&
|
||||
Sequence::const_iterator::operator=(const const_iterator& other)
|
||||
template<typename T>
|
||||
typename Sequence<T>::const_iterator&
|
||||
Sequence<T>::const_iterator::operator=(const const_iterator& other)
|
||||
{
|
||||
if (_locked && _seq != other._seq) {
|
||||
_seq->read_unlock();
|
||||
|
@ -292,7 +302,7 @@ Sequence::const_iterator::operator=(const const_iterator& other)
|
|||
if (_event) {
|
||||
*_event = *other._event.get();
|
||||
} else {
|
||||
_event = boost::shared_ptr<Event>(new Event(*other._event, true));
|
||||
_event = boost::shared_ptr< Event<T> >(new Event<T>(*other._event, true));
|
||||
}
|
||||
} else {
|
||||
if (_event) {
|
||||
|
@ -305,7 +315,8 @@ Sequence::const_iterator::operator=(const const_iterator& other)
|
|||
|
||||
// Sequence
|
||||
|
||||
Sequence::Sequence(const TypeMap& type_map, size_t size)
|
||||
template<typename T>
|
||||
Sequence<T>::Sequence(const TypeMap& type_map, size_t size)
|
||||
: _read_iter(*this, DBL_MAX)
|
||||
, _edited(false)
|
||||
, _type_map(type_map)
|
||||
|
@ -326,8 +337,9 @@ Sequence::Sequence(const TypeMap& type_map, size_t size)
|
|||
* adding \a offset to each event's timestamp.
|
||||
* \return number of events written to \a dst
|
||||
*/
|
||||
template<typename T>
|
||||
size_t
|
||||
Sequence::read(EventSink& dst, timestamp_t start, timedur_t nframes, timestamp_t offset) const
|
||||
Sequence<T>::read(EventSink<T>& dst, timestamp_t start, timedur_t nframes, timestamp_t offset) const
|
||||
{
|
||||
debugout << this << " read @ " << start << " * " << nframes << " + " << offset << endl;
|
||||
debugout << this << " # notes: " << n_notes() << endl;
|
||||
|
@ -370,13 +382,14 @@ Sequence::read(EventSink& dst, timestamp_t start, timedur_t nframes, timestamp_t
|
|||
* The event_type of \a ev should be set to the expected output type.
|
||||
* \return true on success
|
||||
*/
|
||||
template<typename T>
|
||||
bool
|
||||
Sequence::control_to_midi_event(boost::shared_ptr<Event>& ev, const ControlIterator& iter) const
|
||||
Sequence<T>::control_to_midi_event(boost::shared_ptr< Event<T> >& ev, const ControlIterator& iter) const
|
||||
{
|
||||
assert(iter.list.get());
|
||||
const uint32_t event_type = iter.list->parameter().type();
|
||||
if (!ev) {
|
||||
ev = boost::shared_ptr<Event>(new Event(event_type, 0, 3, NULL, true));
|
||||
ev = boost::shared_ptr< Event<T> >(new Event<T>(event_type, 0, 3, NULL, true));
|
||||
}
|
||||
|
||||
uint8_t midi_type = _type_map.parameter_midi_type(iter.list->parameter());
|
||||
|
@ -438,8 +451,9 @@ Sequence::control_to_midi_event(boost::shared_ptr<Event>& ev, const ControlItera
|
|||
|
||||
/** Clear all events from the model.
|
||||
*/
|
||||
template<typename T>
|
||||
void
|
||||
Sequence::clear()
|
||||
Sequence<T>::clear()
|
||||
{
|
||||
_lock.writer_lock();
|
||||
_notes.clear();
|
||||
|
@ -457,8 +471,9 @@ Sequence::clear()
|
|||
* stored; note off events are discarded entirely and all contained notes will
|
||||
* have length 0.
|
||||
*/
|
||||
template<typename T>
|
||||
void
|
||||
Sequence::start_write()
|
||||
Sequence<T>::start_write()
|
||||
{
|
||||
debugout << this << " START WRITE, PERCUSSIVE = " << _percussive << endl;
|
||||
write_lock();
|
||||
|
@ -476,8 +491,9 @@ Sequence::start_write()
|
|||
* that were never resolved with a corresonding note off will be deleted.
|
||||
* Otherwise they will remain as notes with length 0.
|
||||
*/
|
||||
template<typename T>
|
||||
void
|
||||
Sequence::end_write(bool delete_stuck)
|
||||
Sequence<T>::end_write(bool delete_stuck)
|
||||
{
|
||||
write_lock();
|
||||
assert(_writing);
|
||||
|
@ -485,7 +501,7 @@ Sequence::end_write(bool delete_stuck)
|
|||
debugout << this << " END WRITE: " << _notes.size() << " NOTES\n";
|
||||
|
||||
if (!_percussive && delete_stuck) {
|
||||
for (Notes::iterator n = _notes.begin(); n != _notes.end() ;) {
|
||||
for (typename Notes::iterator n = _notes.begin(); n != _notes.end() ;) {
|
||||
if ((*n)->length() == 0) {
|
||||
errorout << "WARNING: Stuck note lost: " << (*n)->note() << endl;
|
||||
n = _notes.erase(n);
|
||||
|
@ -499,7 +515,7 @@ Sequence::end_write(bool delete_stuck)
|
|||
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
if (!_write_notes[i].empty()) {
|
||||
errorout << "WARNING: Sequence::end_write: Channel " << i << " has "
|
||||
errorout << "WARNING: Sequence<T>::end_write: Channel " << i << " has "
|
||||
<< _write_notes[i].size() << " stuck notes" << endl;
|
||||
}
|
||||
_write_notes[i].clear();
|
||||
|
@ -519,13 +535,14 @@ Sequence::end_write(bool delete_stuck)
|
|||
* the start of this model (t=0) and MUST be monotonically increasing
|
||||
* and MUST be >= the latest event currently in the model.
|
||||
*/
|
||||
template<typename T>
|
||||
void
|
||||
Sequence::append(const Event& event)
|
||||
Sequence<T>::append(const Event<T>& event)
|
||||
{
|
||||
write_lock();
|
||||
_edited = true;
|
||||
|
||||
const MIDIEvent& ev = (const MIDIEvent&)event;
|
||||
const MIDIEvent<T>& ev = (const MIDIEvent<T>&)event;
|
||||
|
||||
assert(_notes.empty() || ev.time() >= _notes.back()->time());
|
||||
assert(_writing);
|
||||
|
@ -565,8 +582,9 @@ Sequence::append(const Event& event)
|
|||
write_unlock();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
Sequence::append_note_on_unlocked(uint8_t chan, EventTime time, uint8_t note_num, uint8_t velocity)
|
||||
Sequence<T>::append_note_on_unlocked(uint8_t chan, T time, uint8_t note_num, uint8_t velocity)
|
||||
{
|
||||
debugout << this << " c" << (int)chan << " note " << (int)note_num << " off @ " << time << endl;
|
||||
assert(note_num <= 127);
|
||||
|
@ -579,7 +597,7 @@ Sequence::append_note_on_unlocked(uint8_t chan, EventTime time, uint8_t note_num
|
|||
if (note_num > _highest_note)
|
||||
_highest_note = note_num;
|
||||
|
||||
boost::shared_ptr<Note> new_note(new Note(chan, time, 0, note_num, velocity));
|
||||
boost::shared_ptr< Note<T> > new_note(new Note<T>(chan, time, 0, note_num, velocity));
|
||||
_notes.push_back(new_note);
|
||||
if (!_percussive) {
|
||||
debugout << "Sustained: Appending active note on " << (unsigned)(uint8_t)note_num << endl;
|
||||
|
@ -589,8 +607,9 @@ Sequence::append_note_on_unlocked(uint8_t chan, EventTime time, uint8_t note_num
|
|||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
Sequence::append_note_off_unlocked(uint8_t chan, EventTime time, uint8_t note_num)
|
||||
Sequence<T>::append_note_off_unlocked(uint8_t chan, T time, uint8_t note_num)
|
||||
{
|
||||
debugout << this << " c" << (int)chan << " note " << (int)note_num << " off @ " << time << endl;
|
||||
assert(note_num <= 127);
|
||||
|
@ -612,7 +631,7 @@ Sequence::append_note_off_unlocked(uint8_t chan, EventTime time, uint8_t note_nu
|
|||
|
||||
for (WriteNotes::iterator n = _write_notes[chan].begin(); n
|
||||
!= _write_notes[chan].end(); ++n) {
|
||||
Note& note = *_notes[*n].get();
|
||||
Note<T>& note = *_notes[*n].get();
|
||||
if (note.note() == note_num) {
|
||||
assert(time >= note.time());
|
||||
note.set_length(time - note.time());
|
||||
|
@ -629,8 +648,9 @@ Sequence::append_note_off_unlocked(uint8_t chan, EventTime time, uint8_t note_nu
|
|||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
Sequence::append_control_unlocked(const Parameter& param, EventTime time, double value)
|
||||
Sequence<T>::append_control_unlocked(const Parameter& param, T time, double value)
|
||||
{
|
||||
debugout << this << " " << _type_map.to_symbol(param) << " @ " << time << " \t= \t" << value
|
||||
<< " # controls: " << _controls.size() << endl;
|
||||
|
@ -638,25 +658,26 @@ Sequence::append_control_unlocked(const Parameter& param, EventTime time, double
|
|||
c->list()->rt_add(time, value);
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
Sequence::add_note_unlocked(const boost::shared_ptr<Note> note)
|
||||
Sequence<T>::add_note_unlocked(const boost::shared_ptr< Note<T> > note)
|
||||
{
|
||||
debugout << this << " add note " << (int)note->note() << " @ " << note->time() << endl;
|
||||
_edited = true;
|
||||
Notes::iterator i = upper_bound(_notes.begin(), _notes.end(), note,
|
||||
typename Notes::iterator i = upper_bound(_notes.begin(), _notes.end(), note,
|
||||
note_time_comparator);
|
||||
_notes.insert(i, note);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
Sequence::remove_note_unlocked(const boost::shared_ptr<const Note> note)
|
||||
Sequence<T>::remove_note_unlocked(const boost::shared_ptr< const Note<T> > note)
|
||||
{
|
||||
_edited = true;
|
||||
debugout << this << " remove note " << (int)note->note() << " @ " << note->time() << endl;
|
||||
for (Notes::iterator n = _notes.begin(); n != _notes.end(); ++n) {
|
||||
Note& _n = *(*n);
|
||||
const Note& _note = *note;
|
||||
for (typename Notes::iterator n = _notes.begin(); n != _notes.end(); ++n) {
|
||||
Note<T>& _n = *(*n);
|
||||
const Note<T>& _note = *note;
|
||||
// TODO: There is still the issue, that after restarting ardour
|
||||
// persisted undo does not work, because of rounding errors in the
|
||||
// event times after saving/restoring to/from MIDI files
|
||||
|
@ -675,10 +696,11 @@ Sequence::remove_note_unlocked(const boost::shared_ptr<const Note> note)
|
|||
|
||||
/** Slow! for debugging only. */
|
||||
#ifndef NDEBUG
|
||||
template<typename T>
|
||||
bool
|
||||
Sequence::is_sorted() const {
|
||||
Sequence<T>::is_sorted() const {
|
||||
bool t = 0;
|
||||
for (Notes::const_iterator n = _notes.begin(); n != _notes.end(); ++n)
|
||||
for (typename Notes::const_iterator n = _notes.begin(); n != _notes.end(); ++n)
|
||||
if ((*n)->time() < t)
|
||||
return false;
|
||||
else
|
||||
|
@ -688,5 +710,7 @@ Sequence::is_sorted() const {
|
|||
}
|
||||
#endif
|
||||
|
||||
template class Sequence<double>;
|
||||
|
||||
} // namespace Evoral
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ JACK_MidiPort::write(byte * msg, size_t msglen, timestamp_t timestamp)
|
|||
if (!is_process_thread()) {
|
||||
|
||||
Glib::Mutex::Lock lm (non_process_thread_fifo_lock);
|
||||
RingBuffer<Evoral::Event>::rw_vector vec;
|
||||
RingBuffer< Evoral::Event<double> >::rw_vector vec;
|
||||
|
||||
non_process_thread_fifo.get_write_vector (&vec);
|
||||
|
||||
|
@ -161,7 +161,7 @@ JACK_MidiPort::write(byte * msg, size_t msglen, timestamp_t timestamp)
|
|||
void
|
||||
JACK_MidiPort::flush (void* jack_port_buffer)
|
||||
{
|
||||
RingBuffer<Evoral::Event>::rw_vector vec;
|
||||
RingBuffer< Evoral::Event<double> >::rw_vector vec;
|
||||
size_t written;
|
||||
|
||||
non_process_thread_fifo.get_read_vector (&vec);
|
||||
|
@ -171,7 +171,7 @@ JACK_MidiPort::flush (void* jack_port_buffer)
|
|||
}
|
||||
|
||||
if (vec.len[0]) {
|
||||
Evoral::Event* evp = vec.buf[0];
|
||||
Evoral::Event<double>* evp = vec.buf[0];
|
||||
|
||||
for (size_t n = 0; n < vec.len[0]; ++n, ++evp) {
|
||||
jack_midi_event_write (jack_port_buffer,
|
||||
|
@ -180,7 +180,7 @@ JACK_MidiPort::flush (void* jack_port_buffer)
|
|||
}
|
||||
|
||||
if (vec.len[1]) {
|
||||
Evoral::Event* evp = vec.buf[1];
|
||||
Evoral::Event<double>* evp = vec.buf[1];
|
||||
|
||||
for (size_t n = 0; n < vec.len[1]; ++n, ++evp) {
|
||||
jack_midi_event_write (jack_port_buffer,
|
||||
|
|
|
@ -82,9 +82,8 @@ private:
|
|||
void flush (void* jack_port_buffer);
|
||||
|
||||
static pthread_t _process_thread;
|
||||
|
||||
|
||||
RingBuffer<Evoral::Event> non_process_thread_fifo;
|
||||
RingBuffer< Evoral::Event<double> > non_process_thread_fifo;
|
||||
Glib::Mutex non_process_thread_fifo_lock;
|
||||
};
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ public:
|
|||
|
||||
class PatchBank;
|
||||
|
||||
typedef std::list<boost::shared_ptr<Evoral::MIDIEvent> > PatchMidiCommands;
|
||||
typedef std::list< boost::shared_ptr< Evoral::MIDIEvent<double> > > PatchMidiCommands;
|
||||
|
||||
class Patch : public PBD::Stateful
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue