mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-08 07:45:00 +01:00
track notes at the region level in MidiPlaylist; resolve them (deliver note offs) if a note spans the end of the region
git-svn-id: svn://localhost/ardour2/branches/3.0@5804 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
a86b994c68
commit
539a692b0e
11 changed files with 139 additions and 41 deletions
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include "ardour/ardour.h"
|
#include "ardour/ardour.h"
|
||||||
#include "ardour/playlist.h"
|
#include "ardour/playlist.h"
|
||||||
|
#include "ardour/midi_state_tracker.h"
|
||||||
#include "evoral/Parameter.hpp"
|
#include "evoral/Parameter.hpp"
|
||||||
|
|
||||||
namespace ARDOUR
|
namespace ARDOUR
|
||||||
|
|
@ -74,6 +75,10 @@ private:
|
||||||
bool region_changed (Change, boost::shared_ptr<Region>);
|
bool region_changed (Change, boost::shared_ptr<Region>);
|
||||||
|
|
||||||
NoteMode _note_mode;
|
NoteMode _note_mode;
|
||||||
|
|
||||||
|
typedef std::map<Region*,MidiStateTracker*> NoteTrackers;
|
||||||
|
NoteTrackers _note_trackers;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} /* namespace ARDOUR */
|
} /* namespace ARDOUR */
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ class Playlist;
|
||||||
class Session;
|
class Session;
|
||||||
class MidiFilter;
|
class MidiFilter;
|
||||||
class MidiSource;
|
class MidiSource;
|
||||||
|
class MidiStateTracker;
|
||||||
template<typename T> class MidiRingBuffer;
|
template<typename T> class MidiRingBuffer;
|
||||||
|
|
||||||
class MidiRegion : public Region
|
class MidiRegion : public Region
|
||||||
|
|
@ -56,10 +57,11 @@ class MidiRegion : public Region
|
||||||
virtual sframes_t readable_length() const { return length(); }
|
virtual sframes_t readable_length() const { return length(); }
|
||||||
|
|
||||||
nframes_t read_at (MidiRingBuffer<nframes_t>& dst,
|
nframes_t read_at (MidiRingBuffer<nframes_t>& dst,
|
||||||
sframes_t position,
|
sframes_t position,
|
||||||
nframes_t dur,
|
nframes_t dur,
|
||||||
uint32_t chan_n = 0,
|
uint32_t chan_n = 0,
|
||||||
NoteMode mode = Sustained) const;
|
NoteMode mode = Sustained,
|
||||||
|
MidiStateTracker* tracker = 0) const;
|
||||||
|
|
||||||
nframes_t master_read_at (MidiRingBuffer<nframes_t>& dst,
|
nframes_t master_read_at (MidiRingBuffer<nframes_t>& dst,
|
||||||
sframes_t position,
|
sframes_t position,
|
||||||
|
|
@ -104,10 +106,11 @@ class MidiRegion : public Region
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nframes_t _read_at (const SourceList&, MidiRingBuffer<nframes_t>& dst,
|
nframes_t _read_at (const SourceList&, MidiRingBuffer<nframes_t>& dst,
|
||||||
nframes_t position,
|
sframes_t position,
|
||||||
nframes_t dur,
|
nframes_t dur,
|
||||||
uint32_t chan_n = 0,
|
uint32_t chan_n = 0,
|
||||||
NoteMode mode = Sustained) const;
|
NoteMode mode = Sustained,
|
||||||
|
MidiStateTracker* tracker = 0) const;
|
||||||
|
|
||||||
void recompute_at_start ();
|
void recompute_at_start ();
|
||||||
void recompute_at_end ();
|
void recompute_at_end ();
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
class MidiStateTracker;
|
||||||
class MidiModel;
|
class MidiModel;
|
||||||
template<typename T> class MidiRingBuffer;
|
template<typename T> class MidiRingBuffer;
|
||||||
|
|
||||||
|
|
@ -55,11 +56,12 @@ class MidiSource : virtual public Source
|
||||||
* \param cnt Length of range to be read (in audio frames)
|
* \param cnt Length of range to be read (in audio frames)
|
||||||
* \param stamp_offset Offset to add to event times written to dst
|
* \param stamp_offset Offset to add to event times written to dst
|
||||||
* \param negative_stamp_offset Offset to subtract from event times written to dst
|
* \param negative_stamp_offset Offset to subtract from event times written to dst
|
||||||
|
* \param tracker an optional pointer to MidiStateTracker object, for note on/off tracking
|
||||||
*/
|
*/
|
||||||
virtual nframes_t midi_read (MidiRingBuffer<nframes_t>& dst,
|
virtual nframes_t midi_read (MidiRingBuffer<nframes_t>& dst,
|
||||||
sframes_t source_start,
|
sframes_t source_start,
|
||||||
sframes_t start, nframes_t cnt,
|
sframes_t start, nframes_t cnt,
|
||||||
sframes_t stamp_offset, sframes_t negative_stamp_offset) const;
|
sframes_t stamp_offset, sframes_t negative_stamp_offset, MidiStateTracker*) const;
|
||||||
|
|
||||||
virtual nframes_t midi_write (MidiRingBuffer<nframes_t>& src,
|
virtual nframes_t midi_write (MidiRingBuffer<nframes_t>& src,
|
||||||
sframes_t source_start,
|
sframes_t source_start,
|
||||||
|
|
@ -113,9 +115,10 @@ class MidiSource : virtual public Source
|
||||||
virtual void flush_midi() = 0;
|
virtual void flush_midi() = 0;
|
||||||
|
|
||||||
virtual nframes_t read_unlocked (MidiRingBuffer<nframes_t>& dst,
|
virtual nframes_t read_unlocked (MidiRingBuffer<nframes_t>& dst,
|
||||||
sframes_t position,
|
sframes_t position,
|
||||||
sframes_t start, nframes_t cnt,
|
sframes_t start, nframes_t cnt,
|
||||||
sframes_t stamp_offset, sframes_t negative_stamp_offset) const = 0;
|
sframes_t stamp_offset, sframes_t negative_stamp_offset,
|
||||||
|
MidiStateTracker* tracker) const = 0;
|
||||||
|
|
||||||
virtual nframes_t write_unlocked (MidiRingBuffer<nframes_t>& dst,
|
virtual nframes_t write_unlocked (MidiRingBuffer<nframes_t>& dst,
|
||||||
sframes_t position,
|
sframes_t position,
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,11 @@
|
||||||
#define __ardour_midi_state_tracker_h__
|
#define __ardour_midi_state_tracker_h__
|
||||||
|
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
|
||||||
#include "ardour/midi_buffer.h"
|
#include "ardour/midi_buffer.h"
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
template <typename T> class MidiRingBuffer;
|
||||||
|
|
||||||
/** Tracks played notes, so they can be resolved in potential stuck note
|
/** Tracks played notes, so they can be resolved in potential stuck note
|
||||||
* situations (e.g. looping, transport stop, etc).
|
* situations (e.g. looping, transport stop, etc).
|
||||||
|
|
@ -36,7 +36,10 @@ public:
|
||||||
MidiStateTracker();
|
MidiStateTracker();
|
||||||
|
|
||||||
void track (const MidiBuffer::iterator& from, const MidiBuffer::iterator& to, bool& looped);
|
void track (const MidiBuffer::iterator& from, const MidiBuffer::iterator& to, bool& looped);
|
||||||
|
void add (uint8_t note, uint8_t chn);
|
||||||
|
void remove (uint8_t note, uint8_t chn);
|
||||||
void resolve_notes (MidiBuffer& buffer, nframes64_t time);
|
void resolve_notes (MidiBuffer& buffer, nframes64_t time);
|
||||||
|
void resolve_notes (MidiRingBuffer<nframes_t>& buffer, nframes64_t time);
|
||||||
void dump (std::ostream&);
|
void dump (std::ostream&);
|
||||||
void reset ();
|
void reset ();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include "ardour/track.h"
|
#include "ardour/track.h"
|
||||||
#include "ardour/midi_ring_buffer.h"
|
#include "ardour/midi_ring_buffer.h"
|
||||||
|
#include "ardour/midi_state_tracker.h"
|
||||||
|
|
||||||
namespace ARDOUR
|
namespace ARDOUR
|
||||||
{
|
{
|
||||||
|
|
@ -96,8 +97,7 @@ protected:
|
||||||
int _set_state (const XMLNode&, int, bool call_base);
|
int _set_state (const XMLNode&, int, bool call_base);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void write_out_of_band_data (
|
void write_out_of_band_data (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
|
||||||
BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
|
|
||||||
|
|
||||||
int set_diskstream (boost::shared_ptr<MidiDiskstream> ds);
|
int set_diskstream (boost::shared_ptr<MidiDiskstream> ds);
|
||||||
void use_new_diskstream ();
|
void use_new_diskstream ();
|
||||||
|
|
@ -111,7 +111,6 @@ private:
|
||||||
uint8_t _default_channel;
|
uint8_t _default_channel;
|
||||||
bool _midi_thru;
|
bool _midi_thru;
|
||||||
|
|
||||||
|
|
||||||
int no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
|
int no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
|
||||||
bool state_changing, bool can_record, bool rec_monitors_input);
|
bool state_changing, bool can_record, bool rec_monitors_input);
|
||||||
void push_midi_input_to_step_edit_ringbuffer (nframes_t nframes);
|
void push_midi_input_to_step_edit_ringbuffer (nframes_t nframes);
|
||||||
|
|
|
||||||
|
|
@ -71,12 +71,13 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nframes_t read_unlocked (MidiRingBuffer<nframes_t>& dst,
|
nframes_t read_unlocked (MidiRingBuffer<nframes_t>& dst,
|
||||||
sframes_t position,
|
sframes_t position,
|
||||||
sframes_t start,
|
sframes_t start,
|
||||||
nframes_t cnt,
|
nframes_t cnt,
|
||||||
sframes_t stamp_offset,
|
sframes_t stamp_offset,
|
||||||
sframes_t negative_stamp_offset) const;
|
sframes_t negative_stamp_offset,
|
||||||
|
MidiStateTracker* tracker) const;
|
||||||
|
|
||||||
nframes_t write_unlocked (MidiRingBuffer<nframes_t>& src,
|
nframes_t write_unlocked (MidiRingBuffer<nframes_t>& src,
|
||||||
sframes_t position,
|
sframes_t position,
|
||||||
nframes_t cnt);
|
nframes_t cnt);
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,16 @@ MidiPlaylist::read (MidiRingBuffer<nframes_t>& dst, nframes_t start, nframes_t d
|
||||||
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
|
for (RegionList::iterator i = regions.begin(); i != regions.end(); ++i) {
|
||||||
if ((*i)->coverage (start, end) != OverlapNone) {
|
if ((*i)->coverage (start, end) != OverlapNone) {
|
||||||
regs.push_back(*i);
|
regs.push_back(*i);
|
||||||
|
} else {
|
||||||
|
/* region does not cover the current read boundaries, so make
|
||||||
|
sure that we silence any notes that it had turned on
|
||||||
|
*/
|
||||||
|
NoteTrackers::iterator t = _note_trackers.find ((*i).get());
|
||||||
|
if (t != _note_trackers.end()) {
|
||||||
|
t->second->resolve_notes (dst, (*i)->last_frame());
|
||||||
|
delete t->second;
|
||||||
|
_note_trackers.erase (t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -151,7 +161,20 @@ MidiPlaylist::read (MidiRingBuffer<nframes_t>& dst, nframes_t start, nframes_t d
|
||||||
for (vector<boost::shared_ptr<Region> >::iterator i = regs.begin(); i != regs.end(); ++i) {
|
for (vector<boost::shared_ptr<Region> >::iterator i = regs.begin(); i != regs.end(); ++i) {
|
||||||
boost::shared_ptr<MidiRegion> mr = boost::dynamic_pointer_cast<MidiRegion>(*i);
|
boost::shared_ptr<MidiRegion> mr = boost::dynamic_pointer_cast<MidiRegion>(*i);
|
||||||
if (mr) {
|
if (mr) {
|
||||||
mr->read_at (dst, start, dur, chan_n, _note_mode);
|
|
||||||
|
NoteTrackers::iterator t = _note_trackers.find ((*i).get());
|
||||||
|
MidiStateTracker* tracker;
|
||||||
|
|
||||||
|
if (t == _note_trackers.end()) {
|
||||||
|
pair<Region*,MidiStateTracker*> newpair;
|
||||||
|
newpair.first = (*i).get();
|
||||||
|
tracker = newpair.second = new MidiStateTracker;
|
||||||
|
_note_trackers.insert (newpair);
|
||||||
|
} else {
|
||||||
|
tracker = t->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
mr->read_at (dst, start, dur, chan_n, _note_mode, tracker);
|
||||||
_read_data_count += mr->read_data_count();
|
_read_data_count += mr->read_data_count();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -159,11 +182,18 @@ MidiPlaylist::read (MidiRingBuffer<nframes_t>& dst, nframes_t start, nframes_t d
|
||||||
return dur;
|
return dur;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiPlaylist::remove_dependents (boost::shared_ptr<Region> /*region*/)
|
MidiPlaylist::remove_dependents (boost::shared_ptr<Region> region)
|
||||||
{
|
{
|
||||||
/* MIDI regions have no dependents (crossfades) */
|
/* MIDI regions have no dependents (crossfades) but we might be tracking notes */
|
||||||
|
NoteTrackers::iterator t = _note_trackers.find (region.get());
|
||||||
|
|
||||||
|
/* GACK! THREAD SAFETY! */
|
||||||
|
|
||||||
|
if (t != _note_trackers.end()) {
|
||||||
|
delete t->second;
|
||||||
|
_note_trackers.erase (t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -130,19 +130,20 @@ MidiRegion::set_position_internal (nframes_t pos, bool allow_bbt_recompute)
|
||||||
}
|
}
|
||||||
|
|
||||||
nframes_t
|
nframes_t
|
||||||
MidiRegion::read_at (MidiRingBuffer<nframes_t>& out, sframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const
|
MidiRegion::read_at (MidiRingBuffer<nframes_t>& out, sframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode, MidiStateTracker* tracker) const
|
||||||
{
|
{
|
||||||
return _read_at (_sources, out, position, dur, chan_n, mode);
|
return _read_at (_sources, out, position, dur, chan_n, mode, tracker);
|
||||||
}
|
}
|
||||||
|
|
||||||
nframes_t
|
nframes_t
|
||||||
MidiRegion::master_read_at (MidiRingBuffer<nframes_t>& out, sframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const
|
MidiRegion::master_read_at (MidiRingBuffer<nframes_t>& out, sframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const
|
||||||
{
|
{
|
||||||
return _read_at (_master_sources, out, position, dur, chan_n, mode);
|
return _read_at (_master_sources, out, position, dur, chan_n, mode); /* no tracker */
|
||||||
}
|
}
|
||||||
|
|
||||||
nframes_t
|
nframes_t
|
||||||
MidiRegion::_read_at (const SourceList& /*srcs*/, MidiRingBuffer<nframes_t>& dst, nframes_t position, nframes_t dur, uint32_t chan_n, NoteMode mode) const
|
MidiRegion::_read_at (const SourceList& /*srcs*/, MidiRingBuffer<nframes_t>& dst, sframes_t position, nframes_t dur, uint32_t chan_n,
|
||||||
|
NoteMode mode, MidiStateTracker* tracker) const
|
||||||
{
|
{
|
||||||
nframes_t internal_offset = 0;
|
nframes_t internal_offset = 0;
|
||||||
nframes_t src_offset = 0;
|
nframes_t src_offset = 0;
|
||||||
|
|
@ -207,8 +208,9 @@ MidiRegion::_read_at (const SourceList& /*srcs*/, MidiRingBuffer<nframes_t>& dst
|
||||||
_start + internal_offset, // where to start reading in the source
|
_start + internal_offset, // where to start reading in the source
|
||||||
to_read, // read duration in frames
|
to_read, // read duration in frames
|
||||||
output_buffer_position, // the offset in the output buffer
|
output_buffer_position, // the offset in the output buffer
|
||||||
negative_output_buffer_position // amount to substract from note times
|
negative_output_buffer_position, // amount to substract from note times
|
||||||
) != to_read) {
|
tracker
|
||||||
|
) != to_read) {
|
||||||
return 0; /* "read nothing" */
|
return 0; /* "read nothing" */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
#include "ardour/audioengine.h"
|
#include "ardour/audioengine.h"
|
||||||
#include "ardour/midi_model.h"
|
#include "ardour/midi_model.h"
|
||||||
#include "ardour/midi_ring_buffer.h"
|
#include "ardour/midi_ring_buffer.h"
|
||||||
|
#include "ardour/midi_state_tracker.h"
|
||||||
#include "ardour/midi_source.h"
|
#include "ardour/midi_source.h"
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
#include "ardour/session_directory.h"
|
#include "ardour/session_directory.h"
|
||||||
|
|
@ -126,8 +127,9 @@ MidiSource::invalidate ()
|
||||||
|
|
||||||
nframes_t
|
nframes_t
|
||||||
MidiSource::midi_read (MidiRingBuffer<nframes_t>& dst, sframes_t source_start,
|
MidiSource::midi_read (MidiRingBuffer<nframes_t>& dst, sframes_t source_start,
|
||||||
sframes_t start, nframes_t cnt,
|
sframes_t start, nframes_t cnt,
|
||||||
sframes_t stamp_offset, sframes_t negative_stamp_offset) const
|
sframes_t stamp_offset, sframes_t negative_stamp_offset,
|
||||||
|
MidiStateTracker* tracker) const
|
||||||
{
|
{
|
||||||
Glib::Mutex::Lock lm (_lock);
|
Glib::Mutex::Lock lm (_lock);
|
||||||
|
|
||||||
|
|
@ -152,13 +154,21 @@ MidiSource::midi_read (MidiRingBuffer<nframes_t>& dst, sframes_t source_start,
|
||||||
const sframes_t time_frames = BEATS_TO_FRAMES(i->time());
|
const sframes_t time_frames = BEATS_TO_FRAMES(i->time());
|
||||||
if (time_frames < source_start + start + cnt) {
|
if (time_frames < source_start + start + cnt) {
|
||||||
dst.write(time_frames, i->event_type(), i->size(), i->buffer());
|
dst.write(time_frames, i->event_type(), i->size(), i->buffer());
|
||||||
|
if (tracker) {
|
||||||
|
Evoral::MIDIEvent<Evoral::MusicalTime>& ev (*(Evoral::MIDIEvent<Evoral::MusicalTime>*) (&(*i)));
|
||||||
|
if (ev.is_note_on()) {
|
||||||
|
tracker->add (ev.note(), ev.channel());
|
||||||
|
} else if (ev.is_note_off()) {
|
||||||
|
tracker->remove (ev.note(), ev.channel());
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cnt;
|
return cnt;
|
||||||
} else {
|
} else {
|
||||||
return read_unlocked (dst, source_start, start, cnt, stamp_offset, negative_stamp_offset);
|
return read_unlocked (dst, source_start, start, cnt, stamp_offset, negative_stamp_offset, tracker);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "ardour/event_type_map.h"
|
#include "ardour/event_type_map.h"
|
||||||
|
#include "ardour/midi_ring_buffer.h"
|
||||||
#include "ardour/midi_state_tracker.h"
|
#include "ardour/midi_state_tracker.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
@ -47,6 +48,21 @@ MidiStateTracker::track_note_onoffs (const Evoral::MIDIEvent<MidiBuffer::TimeTyp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void
|
||||||
|
MidiStateTracker::add (uint8_t note, uint8_t chn)
|
||||||
|
{
|
||||||
|
cerr << "Added note " << note << " chan " << chn << endl;
|
||||||
|
_active_notes[note + 128 * chn]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MidiStateTracker::remove (uint8_t note, uint8_t chn)
|
||||||
|
{
|
||||||
|
if (_active_notes[note + 128 * chn]) {
|
||||||
|
cerr << "Removed note " << note << " chan " << chn << endl;
|
||||||
|
_active_notes[note + 128 * chn]--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiStateTracker::track (const MidiBuffer::iterator &from, const MidiBuffer::iterator &to, bool& looped)
|
MidiStateTracker::track (const MidiBuffer::iterator &from, const MidiBuffer::iterator &to, bool& looped)
|
||||||
|
|
@ -81,6 +97,23 @@ MidiStateTracker::resolve_notes (MidiBuffer &dst, nframes64_t time)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MidiStateTracker::resolve_notes (MidiRingBuffer<nframes_t> &dst, nframes64_t time)
|
||||||
|
{
|
||||||
|
uint8_t buf[3];
|
||||||
|
for (int channel = 0; channel < 16; ++channel) {
|
||||||
|
for (int note = 0; note < 128; ++note) {
|
||||||
|
while (_active_notes[channel * 128 + note]) {
|
||||||
|
buf[0] = MIDI_CMD_NOTE_OFF|channel;
|
||||||
|
buf[1] = note;
|
||||||
|
buf[2] = 0;
|
||||||
|
dst.write (time, EventTypeMap::instance().midi_event_type (buf[0]), 3, buf);
|
||||||
|
_active_notes[channel * 128 + note]--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiStateTracker::dump (ostream& o)
|
MidiStateTracker::dump (ostream& o)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@
|
||||||
#include "ardour/event_type_map.h"
|
#include "ardour/event_type_map.h"
|
||||||
#include "ardour/midi_model.h"
|
#include "ardour/midi_model.h"
|
||||||
#include "ardour/midi_ring_buffer.h"
|
#include "ardour/midi_ring_buffer.h"
|
||||||
|
#include "ardour/midi_state_tracker.h"
|
||||||
#include "ardour/session.h"
|
#include "ardour/session.h"
|
||||||
#include "ardour/smf_source.h"
|
#include "ardour/smf_source.h"
|
||||||
|
|
||||||
|
|
@ -98,8 +99,9 @@ SMFSource::~SMFSource ()
|
||||||
/** All stamps in audio frames */
|
/** All stamps in audio frames */
|
||||||
nframes_t
|
nframes_t
|
||||||
SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& destination, sframes_t source_start,
|
SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& destination, sframes_t source_start,
|
||||||
sframes_t start, nframes_t duration,
|
sframes_t start, nframes_t duration,
|
||||||
sframes_t stamp_offset, sframes_t negative_stamp_offset) const
|
sframes_t stamp_offset, sframes_t negative_stamp_offset,
|
||||||
|
MidiStateTracker* tracker) const
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
uint64_t time = 0; // in SMF ticks, 1 tick per _ppqn
|
uint64_t time = 0; // in SMF ticks, 1 tick per _ppqn
|
||||||
|
|
@ -166,11 +168,18 @@ SMFSource::read_unlocked (MidiRingBuffer<nframes_t>& destination, sframes_t sour
|
||||||
|
|
||||||
if (ev_frame_time < start + duration) {
|
if (ev_frame_time < start + duration) {
|
||||||
destination.write(ev_frame_time - negative_stamp_offset, ev_type, ev_size, ev_buffer);
|
destination.write(ev_frame_time - negative_stamp_offset, ev_type, ev_size, ev_buffer);
|
||||||
|
|
||||||
|
if (tracker) {
|
||||||
|
if (ev_buffer[0] & MIDI_CMD_NOTE_ON) {
|
||||||
|
tracker->add (ev_buffer[1], ev_buffer[0] & 0xf);
|
||||||
|
} else if (ev_buffer[0] & MIDI_CMD_NOTE_OFF) {
|
||||||
|
tracker->remove (ev_buffer[1], ev_buffer[0] & 0xf);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_read_data_count += ev_size;
|
_read_data_count += ev_size;
|
||||||
|
|
||||||
if (ev_size > scratch_size) {
|
if (ev_size > scratch_size) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue