cliprec: a bit more work on the skeleton of the ClipRecProcessor
This commit is contained in:
parent
9652789e22
commit
7f1890ff95
|
@ -28,18 +28,49 @@ namespace ARDOUR {
|
|||
|
||||
class AudioFileSource;
|
||||
class Session;
|
||||
class Track;
|
||||
|
||||
template<typename T> class MidiRingBuffer;
|
||||
|
||||
class LIBARDOUR_API ClipRecProcessor : public Processor
|
||||
{
|
||||
public:
|
||||
ClipRecProcessor (Session&, std::string const & name);
|
||||
ClipRecProcessor (Session&, Track&, std::string const & name);
|
||||
void run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, double speed, pframes_t nframes, bool result_required);
|
||||
bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
|
||||
|
||||
private:
|
||||
Track& _track;
|
||||
|
||||
/** Information about one audio channel, playback or capture
|
||||
* (depending on the derived class)
|
||||
*/
|
||||
struct ChannelInfo : public boost::noncopyable {
|
||||
|
||||
ChannelInfo (samplecnt_t buffer_size);
|
||||
virtual ~ChannelInfo ();
|
||||
|
||||
/** A ringbuffer for data to be recorded back, written to in the
|
||||
* process thread, read from in the butler thread.
|
||||
*/
|
||||
PBD::RingBufferNPT<Sample>* buf;
|
||||
PBD::RingBufferNPT<Sample>::rw_vector rw_vector;
|
||||
|
||||
/* used only by capture */
|
||||
boost::shared_ptr<AudioFileSource> write_source;
|
||||
|
||||
/* used in the butler thread only */
|
||||
samplecnt_t curr_capture_cnt;
|
||||
|
||||
virtual void resize (samplecnt_t) = 0;
|
||||
};
|
||||
|
||||
typedef std::vector<ChannelInfo*> ChannelList;
|
||||
SerializedRCUManager<ChannelList> channels;
|
||||
|
||||
/* The MIDI stuff */
|
||||
|
||||
MidiRingBuffer<samplepos_t>* _midi_buf;
|
||||
};
|
||||
|
||||
} /* namespace */
|
||||
|
|
|
@ -16,12 +16,21 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "pbd/compose.h"
|
||||
#include "pbd/debug.h"
|
||||
|
||||
#include "ardour/audio_buffer.h"
|
||||
#include "ardour/cliprec.h"
|
||||
#include "ardour/debug.h"
|
||||
#include "ardour/midi_track.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
ClipRecProcessor::ClipRecProcessor (Session& s, std::string const & name)
|
||||
ClipRecProcessor::ClipRecProcessor (Session& s, Track& t, std::string const & name)
|
||||
: Processor (s, name, Temporal::BeatTime)
|
||||
, _track (t)
|
||||
, channels (new ChannelList)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -42,6 +51,85 @@ ClipRecProcessor::can_support_io_configuration (const ChanCount& in, ChanCount&
|
|||
void
|
||||
ClipRecProcessor::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_sample, double speed, pframes_t nframes, bool result_required)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!check_active()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t n_buffers = bufs.count().n_audio();
|
||||
boost::shared_ptr<ChannelList> c = channels.reader();
|
||||
ChannelList::iterator chan;
|
||||
size_t n;
|
||||
|
||||
if (n_buffers) {
|
||||
|
||||
/* AUDIO */
|
||||
|
||||
for (chan = c->begin(), n = 0; chan != c->end(); ++chan, ++n) {
|
||||
|
||||
ChannelInfo* chaninfo (*chan);
|
||||
AudioBuffer& buf (bufs.get_audio (n%n_buffers));
|
||||
|
||||
chaninfo->buf->get_write_vector (&chaninfo->rw_vector);
|
||||
|
||||
if (nframes <= (samplecnt_t) chaninfo->rw_vector.len[0]) {
|
||||
|
||||
Sample *incoming = buf.data ();
|
||||
memcpy (chaninfo->rw_vector.buf[0], incoming, sizeof (Sample) * nframes);
|
||||
|
||||
} else {
|
||||
|
||||
samplecnt_t total = chaninfo->rw_vector.len[0] + chaninfo->rw_vector.len[1];
|
||||
|
||||
if (nframes > total) {
|
||||
DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 overrun in %2, rec_nframes = %3 total space = %4\n",
|
||||
DEBUG_THREAD_SELF, name(), nframes, total));
|
||||
return;
|
||||
}
|
||||
|
||||
Sample *incoming = buf.data ();
|
||||
samplecnt_t first = chaninfo->rw_vector.len[0];
|
||||
|
||||
memcpy (chaninfo->rw_vector.buf[0], incoming, sizeof (Sample) * first);
|
||||
memcpy (chaninfo->rw_vector.buf[1], incoming + first, sizeof (Sample) * (nframes - first));
|
||||
}
|
||||
|
||||
chaninfo->buf->increment_write_ptr (nframes);
|
||||
}
|
||||
}
|
||||
|
||||
/* MIDI */
|
||||
|
||||
if (_midi_buf) {
|
||||
|
||||
// Pump entire port buffer into the ring buffer (TODO: split cycles?)
|
||||
MidiBuffer& buf = bufs.get_midi (0);
|
||||
MidiTrack* mt = dynamic_cast<MidiTrack*>(&_track);
|
||||
MidiChannelFilter* filter = mt ? &mt->capture_filter() : 0;
|
||||
|
||||
assert (buf.size() == 0 || _midi_buf);
|
||||
|
||||
for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) {
|
||||
Evoral::Event<MidiBuffer::TimeType> ev (*i, false);
|
||||
if (ev.time() > nframes) {
|
||||
break;
|
||||
}
|
||||
|
||||
bool skip_event = false;
|
||||
|
||||
if (mt) {
|
||||
/* skip injected immediate/out-of-band events */
|
||||
MidiBuffer const& ieb (mt->immediate_event_buffer());
|
||||
for (MidiBuffer::const_iterator j = ieb.begin(); j != ieb.end(); ++j) {
|
||||
if (*j == ev) {
|
||||
skip_event = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!skip_event && (!filter || !filter->filter(ev.buffer(), ev.size()))) {
|
||||
const samplepos_t event_time = start_sample + ev.time();
|
||||
_midi_buf->write (event_time, ev.event_type(), ev.size(), ev.buffer());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ libardour_sources = [
|
|||
'chan_mapping.cc',
|
||||
'circular_buffer.cc',
|
||||
'clip_library.cc',
|
||||
'cliprec.cc',
|
||||
'config_text.cc',
|
||||
'control_group.cc',
|
||||
'control_protocol_manager.cc',
|
||||
|
|
Loading…
Reference in New Issue