diff options
Diffstat (limited to 'libs/ardour/ardour')
-rw-r--r-- | libs/ardour/ardour/audio_track.h | 4 | ||||
-rw-r--r-- | libs/ardour/ardour/buffer.h | 27 | ||||
-rw-r--r-- | libs/ardour/ardour/buffer_set.h | 6 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_diskstream.h | 23 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_playlist.h | 4 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_port.h | 16 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_region.h | 14 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_ring_buffer.h | 242 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_track.h | 4 | ||||
-rw-r--r-- | libs/ardour/ardour/route.h | 5 | ||||
-rw-r--r-- | libs/ardour/ardour/track.h | 3 | ||||
-rw-r--r-- | libs/ardour/ardour/types.h | 3 |
12 files changed, 305 insertions, 46 deletions
diff --git a/libs/ardour/ardour/audio_track.h b/libs/ardour/ardour/audio_track.h index 54a8c19a22..bca79b0d7d 100644 --- a/libs/ardour/ardour/audio_track.h +++ b/libs/ardour/ardour/audio_track.h @@ -64,10 +64,6 @@ class AudioTrack : public Track protected: XMLNode& state (bool full); - void passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, - jack_nframes_t nframes, jack_nframes_t offset, int declick, - bool meter); - ChanCount n_process_buffers (); private: diff --git a/libs/ardour/ardour/buffer.h b/libs/ardour/ardour/buffer.h index df7f57455b..896d6e7616 100644 --- a/libs/ardour/ardour/buffer.h +++ b/libs/ardour/ardour/buffer.h @@ -181,23 +181,36 @@ public: ~MidiBuffer(); - // FIXME: clear events starting at offset in time - void silence(jack_nframes_t len, jack_nframes_t offset=0) { assert(offset == 0); _size = 0; } + void silence(jack_nframes_t dur, jack_nframes_t offset=0); void read_from(const Buffer& src, jack_nframes_t nframes, jack_nframes_t offset); - void set_size(size_t size) { _size = size; } + bool push_back(const MidiEvent& event); + + const MidiEvent& operator[](size_t i) const { assert(i < _size); return _events[i]; } + MidiEvent& operator[](size_t i) { assert(i < _size); return _events[i]; } + + static size_t max_event_size() { return MAX_EVENT_SIZE; } + + //void set_size(size_t size) { _size = size; } - const RawMidi* data() const { return _data; } - RawMidi* data() { return _data; } + //const RawMidi* data() const { return _data; } + //RawMidi* data() { return _data; } private: // These are undefined (prevent copies) MidiBuffer(const MidiBuffer& copy); MidiBuffer& operator=(const MidiBuffer& copy); - bool _owns_data; - RawMidi* _data; ///< Actual buffer contents + // FIXME: Jack needs to tell us this + static const size_t MAX_EVENT_SIZE = 4; // bytes + + /* We use _size as "number of events", so the size of _data is + * (_size * MAX_EVENT_SIZE) + */ + + MidiEvent* _events; ///< Event structs that point to offsets in _data + RawMidi* _data; ///< MIDI, straight up. No time stamps. }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/buffer_set.h b/libs/ardour/ardour/buffer_set.h index dfb5dd3611..43df729e05 100644 --- a/libs/ardour/ardour/buffer_set.h +++ b/libs/ardour/ardour/buffer_set.h @@ -28,6 +28,7 @@ namespace ARDOUR { class Buffer; class AudioBuffer; +class MidiBuffer; class PortSet; @@ -77,6 +78,11 @@ public: { return (AudioBuffer&)get(DataType::AUDIO, i); } + + MidiBuffer& get_midi(size_t i) + { + return (MidiBuffer&)get(DataType::MIDI, i); + } void read_from(BufferSet& in, jack_nframes_t nframes, jack_nframes_t offset=0) { diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h index 901baf3c64..ccff993638 100644 --- a/libs/ardour/ardour/midi_diskstream.h +++ b/libs/ardour/ardour/midi_diskstream.h @@ -45,6 +45,8 @@ #include <ardour/utils.h> #include <ardour/diskstream.h> #include <ardour/midi_playlist.h> +#include <ardour/midi_ring_buffer.h> + struct tm; namespace ARDOUR { @@ -65,8 +67,7 @@ class MidiDiskstream : public Diskstream float playback_buffer_load() const; float capture_buffer_load() const; - RawMidi* playback_buffer () { return _current_playback_buffer; } - RawMidi* capture_buffer () { return _current_capture_buffer; } + void get_playback(MidiBuffer& dst, jack_nframes_t start, jack_nframes_t end); void set_record_enabled (bool yn); @@ -124,7 +125,7 @@ class MidiDiskstream : public Diskstream int do_refill_with_alloc(); - int read (MidiBuffer& dst, jack_nframes_t& start, jack_nframes_t cnt, bool reversed); + int read (jack_nframes_t& start, jack_nframes_t cnt, bool reversed); void finish_capture (bool rec_monitors_input); void transport_stopped (struct tm&, time_t, bool abort); @@ -147,17 +148,17 @@ class MidiDiskstream : public Diskstream void disengage_record_enable (); // FIXME: This is basically a single ChannelInfo.. abstractify that concept? - RingBufferNPT<RawMidi>* _playback_buf; - RingBufferNPT<RawMidi>* _capture_buf; - RawMidi* _current_playback_buffer; - RawMidi* _current_capture_buffer; - RawMidi* _playback_wrap_buffer; - RawMidi* _capture_wrap_buffer; + MidiRingBuffer* _playback_buf; + MidiRingBuffer* _capture_buf; + //RawMidi* _current_playback_buffer; + //RawMidi* _current_capture_buffer; + //RawMidi* _playback_wrap_buffer; + //RawMidi* _capture_wrap_buffer; MidiPort* _source_port; SMFSource* _write_source; ///< aka capturing source RingBufferNPT<CaptureTransition>* _capture_transition_buf; - RingBufferNPT<RawMidi>::rw_vector _playback_vector; - RingBufferNPT<RawMidi>::rw_vector _capture_vector; + //RingBufferNPT<RawMidi>::rw_vector _playback_vector; + //RingBufferNPT<RawMidi>::rw_vector _capture_vector; }; }; /* namespace ARDOUR */ diff --git a/libs/ardour/ardour/midi_playlist.h b/libs/ardour/ardour/midi_playlist.h index 9e9cf250e2..11627b5a07 100644 --- a/libs/ardour/ardour/midi_playlist.h +++ b/libs/ardour/ardour/midi_playlist.h @@ -33,7 +33,7 @@ class Session; class Region; class MidiRegion; class Source; -class MidiBuffer; +class MidiRingBuffer; class MidiPlaylist : public ARDOUR::Playlist { @@ -56,7 +56,7 @@ public: MidiPlaylist (const MidiPlaylist&, jack_nframes_t start, jack_nframes_t cnt, string name, bool hidden = false); - jack_nframes_t read (MidiBuffer& buf, + jack_nframes_t read (MidiRingBuffer& buf, jack_nframes_t start, jack_nframes_t cnt, uint32_t chan_n=0); int set_state (const XMLNode&); diff --git a/libs/ardour/ardour/midi_port.h b/libs/ardour/ardour/midi_port.h index 3c48f0ce9e..f6eafe11bd 100644 --- a/libs/ardour/ardour/midi_port.h +++ b/libs/ardour/ardour/midi_port.h @@ -39,19 +39,23 @@ class MidiPort : public Port { DataType type() const { return DataType(DataType::MIDI); } - MidiBuffer& get_buffer() { - return *_buffer; + Buffer& get_buffer() { + return _buffer; + } + + MidiBuffer& get_midi_buffer() { + return _buffer; } void cycle_start(jack_nframes_t nframes); void cycle_end(); - size_t capacity() { return _buffer->capacity(); } - size_t size() { return _buffer->size(); } + size_t capacity() { return _buffer.capacity(); } + size_t size() { return _buffer.size(); } /** Assumes that the port is an output port */ void silence (jack_nframes_t nframes, jack_nframes_t offset) { - _buffer->silence(nframes, offset); + _buffer.silence(nframes, offset); } protected: @@ -61,7 +65,7 @@ class MidiPort : public Port { /* engine isn't supposed to access below here */ - MidiBuffer* _buffer; + MidiBuffer _buffer; jack_nframes_t _nframes_this_cycle; }; diff --git a/libs/ardour/ardour/midi_region.h b/libs/ardour/ardour/midi_region.h index 0144f52473..745d3fa4a8 100644 --- a/libs/ardour/ardour/midi_region.h +++ b/libs/ardour/ardour/midi_region.h @@ -41,7 +41,7 @@ class Playlist; class Session; class MidiFilter; class MidiSource; -class MidiBuffer; +class MidiRingBuffer; class MidiRegion : public Region { @@ -57,16 +57,16 @@ class MidiRegion : public Region MidiSource& midi_source (uint32_t n=0) const; - jack_nframes_t read_at (MidiBuffer& out, + jack_nframes_t read_at (MidiRingBuffer& dst, jack_nframes_t position, - jack_nframes_t cnt, + jack_nframes_t dur, uint32_t chan_n = 0, jack_nframes_t read_frames = 0, jack_nframes_t skip_frames = 0) const; - jack_nframes_t master_read_at (MidiBuffer& buf, + jack_nframes_t master_read_at (MidiRingBuffer& dst, jack_nframes_t position, - jack_nframes_t cnt, + jack_nframes_t dur, uint32_t chan_n=0) const; XMLNode& state (bool); @@ -83,9 +83,9 @@ class MidiRegion : public Region StateManager::State* state_factory (std::string why) const; Change restore_state (StateManager::State&); - jack_nframes_t _read_at (const SourceList&, MidiBuffer& buf, + jack_nframes_t _read_at (const SourceList&, MidiRingBuffer& dst, jack_nframes_t position, - jack_nframes_t cnt, + jack_nframes_t dur, uint32_t chan_n = 0, jack_nframes_t read_frames = 0, jack_nframes_t skip_frames = 0) const; diff --git a/libs/ardour/ardour/midi_ring_buffer.h b/libs/ardour/ardour/midi_ring_buffer.h new file mode 100644 index 0000000000..53057dbcba --- /dev/null +++ b/libs/ardour/ardour/midi_ring_buffer.h @@ -0,0 +1,242 @@ +/* + Copyright (C) 2006 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __ardour_midi_ring_buffer_h__ +#define __ardour_midi_ring_buffer_h__ + +#include <algorithm> +#include <ardour/types.h> +#include <pbd/ringbufferNPT.h> +#include <ardour/buffer.h> + +namespace ARDOUR { + +/** A MIDI RingBuffer + * (necessary because MIDI events are variable sized so a generic RB won't do). + * + * ALL publically accessible sizes refer to event COUNTS. What actually goes + * on in here is none of the callers business :) + */ +class MidiRingBuffer { +public: + MidiRingBuffer (size_t size) + : _size(size) + , _max_event_size(MidiBuffer::max_event_size()) + , _ev_buf(new MidiEvent[size]) + , _raw_buf(new RawMidi[size * _max_event_size]) + { + reset (); + assert(read_space() == 0); + assert(write_space() == size - 1); + } + + virtual ~MidiRingBuffer() { + delete[] _ev_buf; + delete[] _raw_buf; + } + + void reset () { + /* !!! NOT THREAD SAFE !!! */ + g_atomic_int_set (&_write_ptr, 0); + g_atomic_int_set (&_read_ptr, 0); + } + + size_t write_space () { + size_t w, r; + + w = g_atomic_int_get (&_write_ptr); + r = g_atomic_int_get (&_read_ptr); + + if (w > r) { + return ((r - w + _size) % _size) - 1; + } else if (w < r) { + return (r - w) - 1; + } else { + return _size - 1; + } + } + + size_t read_space () { + size_t w, r; + + w = g_atomic_int_get (&_write_ptr); + r = g_atomic_int_get (&_read_ptr); + + if (w > r) { + return w - r; + } else { + return (w - r + _size) % _size; + } + } + + size_t capacity() const { return _size; } + + /** Read one event and appends it to @a out. */ + //size_t read(MidiBuffer& out); + + /** Write one event (@a in) */ + size_t write(const MidiEvent& in); // deep copies in + + /** Read events all events up to time @a end into @a out, leaving stamps intact. + * Any events before @a start will be dropped. */ + size_t read(MidiBuffer& out, jack_nframes_t start, jack_nframes_t end); + + /** Write all events from @a in, applying @a offset to all time stamps */ + size_t write(const MidiBuffer& in, jack_nframes_t offset = 0); + + inline void clear_event(size_t index); + +private: + + // _event_ indices + mutable gint _write_ptr; + mutable gint _read_ptr; + + size_t _size; // size (capacity) in events + size_t _max_event_size; // ratio of raw_buf size to ev_buf size + MidiEvent* _ev_buf; // these point into... + RawMidi* _raw_buf; // this + +}; + +/** Just for sanity checking */ +inline void +MidiRingBuffer::clear_event(size_t index) +{ + memset(&_ev_buf[index].buffer, 0, _max_event_size); + _ev_buf[index].time = 0; + _ev_buf[index].size = 0; + _ev_buf[index].buffer = 0; + +} +#if 0 +inline size_t +MidiRingBuffer::read (MidiBuffer& buf) +{ + const size_t priv_read_ptr = g_atomic_int_get(&_read_ptr); + + if (read_space() == 0) { + return 0; + } else { + MidiEvent* const read_ev = &_ev_buf[priv_read_ptr]; + assert(read_ev->size > 0); + buf.push_back(*read_ev); + printf("MRB - read %xd %d %d with time %u at index %zu\n", + read_ev->buffer[0], read_ev->buffer[1], read_ev->buffer[2], read_ev->time, + priv_read_ptr); + clear_event(priv_read_ptr); + g_atomic_int_set(&_read_ptr, (priv_read_ptr + 1) % _size); + return 1; + } +} +#endif +inline size_t +MidiRingBuffer::write (const MidiEvent& ev) +{ + //static jack_nframes_t last_write_time = 0; + + assert(ev.size > 0); + + size_t priv_write_ptr = g_atomic_int_get(&_write_ptr); + + if (write_space () == 0) { + return 0; + } else { + //assert(ev.time >= last_write_time); + + const size_t raw_index = priv_write_ptr * _max_event_size; + + MidiEvent* const write_ev = &_ev_buf[priv_write_ptr]; + *write_ev = ev; + + memcpy(&_raw_buf[raw_index], ev.buffer, ev.size); + write_ev->buffer = &_raw_buf[raw_index]; + g_atomic_int_set(&_write_ptr, (priv_write_ptr + 1) % _size); + + printf("MRB - wrote %xd %d %d with time %u at index %zu (raw index %zu)\n", + write_ev->buffer[0], write_ev->buffer[1], write_ev->buffer[2], write_ev->time, + priv_write_ptr, raw_index); + + assert(write_ev->size = ev.size); + + //last_write_time = ev.time; + printf("(W) read space: %zu\n", read_space()); + + return 1; + } +} + +inline size_t +MidiRingBuffer::read(MidiBuffer& dst, jack_nframes_t start, jack_nframes_t end) +{ + if (read_space() == 0) + return 0; + + size_t priv_read_ptr = g_atomic_int_get(&_read_ptr); + jack_nframes_t time = _ev_buf[priv_read_ptr].time; + size_t count = 0; + size_t limit = read_space(); + + while (time <= end && limit > 0) { + MidiEvent* const read_ev = &_ev_buf[priv_read_ptr]; + if (time >= start) { + dst.push_back(*read_ev); + printf("MRB - read %xd %d %d with time %u at index %zu\n", + read_ev->buffer[0], read_ev->buffer[1], read_ev->buffer[2], read_ev->time, + priv_read_ptr); + } else { + cerr << "MRB: LOST EVENT!" << endl; + } + + clear_event(priv_read_ptr); + + ++count; + --limit; + + priv_read_ptr = (priv_read_ptr + 1) % _size; + + assert(read_ev->time <= end); + time = _ev_buf[priv_read_ptr].time; + } + + g_atomic_int_set(&_read_ptr, priv_read_ptr); + printf("(R) read space: %zu\n", read_space()); + + return count; +} + +inline size_t +MidiRingBuffer::write(const MidiBuffer& in, jack_nframes_t offset) +{ + size_t num_events = in.size(); + size_t to_write = std::min(write_space(), num_events); + + // FIXME: double copy :/ + for (size_t i=0; i < to_write; ++i) { + MidiEvent ev = in[i]; + ev.time += offset; + write(ev); + } + + return to_write; +} + +} // namespace ARDOUR + +#endif // __ardour_midi_ring_buffer_h__ + diff --git a/libs/ardour/ardour/midi_track.h b/libs/ardour/ardour/midi_track.h index 654eb98e30..409aa171e9 100644 --- a/libs/ardour/ardour/midi_track.h +++ b/libs/ardour/ardour/midi_track.h @@ -76,10 +76,6 @@ public: protected: XMLNode& state (bool full); - void passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, - jack_nframes_t nframes, jack_nframes_t offset, int declick, - bool meter); - ChanCount n_process_buffers (); private: diff --git a/libs/ardour/ardour/route.h b/libs/ardour/ardour/route.h index db5cddca39..107abb7b48 100644 --- a/libs/ardour/ardour/route.h +++ b/libs/ardour/ardour/route.h @@ -309,10 +309,13 @@ class Route : public IO bool meter); protected: - /* for derived classes */ virtual XMLNode& state(bool); + void passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, + jack_nframes_t nframes, jack_nframes_t offset, int declick, + bool meter); + void silence (jack_nframes_t nframes, jack_nframes_t offset); sigc::connection input_signal_connection; diff --git a/libs/ardour/ardour/track.h b/libs/ardour/ardour/track.h index 15a0a28aab..2b317a0299 100644 --- a/libs/ardour/ardour/track.h +++ b/libs/ardour/ardour/track.h @@ -95,9 +95,6 @@ class Track : public Route virtual XMLNode& state (bool full) = 0; - virtual void passthru_silence (jack_nframes_t start_frame, jack_nframes_t end_frame, - jack_nframes_t nframes, jack_nframes_t offset, int declick, bool meter) = 0; - virtual ChanCount n_process_buffers () = 0; Diskstream *_diskstream; diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h index 00833f6547..d5bfded460 100644 --- a/libs/ardour/ardour/types.h +++ b/libs/ardour/ardour/types.h @@ -50,7 +50,8 @@ namespace ARDOUR { typedef uint32_t layer_t; typedef uint64_t microseconds_t; - typedef jack_midi_event_t RawMidi; + typedef jack_midi_event_t MidiEvent; + typedef unsigned char RawMidi; enum IOChange { NoChange = 0, |