diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2013-03-27 21:50:18 -0400 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2013-03-27 21:50:18 -0400 |
commit | 4abbabdcf9c6d6d98ba261d91846577a2fa2f05e (patch) | |
tree | 5a7134ccc9508a6f1da25ef3dc6d432bdc25a04f /libs/ardour/audio_track.cc | |
parent | 78aa7a13fd5e5abac70637ce6641b7d2e73dd541 (diff) |
Squashed commit of the following:
commit fdbae82077db53add90df7448a06869dac89acc6
Author: Paul Davis <paul@linuxaudiosystems.com>
Date: Wed Mar 27 21:45:28 2013 -0400
mammoth changes in basic signal flow, total redesign of MIDI channel filtering and more.
commit 59343a8283698e02bc0f622313b29e98f449e4c8
Author: Paul Davis <paul@linuxaudiosystems.com>
Date: Wed Mar 27 01:58:53 2013 -0400
initial working version after changes to MIDI channel filtering. may affect metering input too. testing not yet finished
this commit merges many deep changes in ardour's internal architecture,
combined with a total redesign of how MIDI channel filtering works.
data in a track used to flow from JACK port buffers to diskstream's ringbuffers
and was then copied from the ringbuffers into a BufferSet for use during
Route::process_output_buffers(). The butler thread would handle the movement of
data between the ringbuffers and disk.
with this commit, data now flows from JACK port buffers into the BufferSet used
for Route processing, and is copied from the BufferSet into the diskstream's
ringbuffers (the butler thread continues to handle interactions with disk as
usual).
this change allowed a dramatic consolidation of code and simplification of most
aspects of Track/Route::roll() and Track/Route::no_roll(). in particular, see
Route::fill_buffers_with_input() which now concisely describes how we move data
from JACK port buffers into the BufferSet for all Route types (including Tracks).
this work was initially motivated by changing MIDI channel filtering so that we
can process capture and playback independently. there is now a very clean
pathway for this - see MidiTrack::roll() (NOTE: This needs implementing in the
no-roll case too - a TODO item).
the channel selector for MIDI tracks has been moved out of the track header and
is now accessible via the context menu. more work is likely here, to make it
(more) obvious to the user when filtering is going on.
Diffstat (limited to 'libs/ardour/audio_track.cc')
-rw-r--r-- | libs/ardour/audio_track.cc | 128 |
1 files changed, 12 insertions, 116 deletions
diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 90439f46e9..070a7453fb 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -316,8 +316,6 @@ AudioTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_fram return 0; } - Sample* b; - Sample* tmpb; framepos_t transport_frame; boost::shared_ptr<AudioDiskstream> diskstream = audio_diskstream(); @@ -342,7 +340,9 @@ AudioTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_fram to do nothing. */ - dret = diskstream->process (transport_frame, 0, playback_distance); + BufferSet bufs; /* empty set, no matter - nothing will happen */ + + dret = diskstream->process (bufs, transport_frame, 0, playback_distance, false); need_butler = diskstream->commit (playback_distance); return dret; } @@ -350,126 +350,22 @@ AudioTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_fram _silent = false; _amp->apply_gain_automation(false); - if ((dret = diskstream->process (transport_frame, nframes, playback_distance)) != 0) { - need_butler = diskstream->commit (playback_distance); - silence (nframes); - return dret; - } - - /* special condition applies */ + BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers ()); + fill_buffers_with_input (bufs, _input, nframes); + if (_meter_point == MeterInput) { - _input->process_input (_meter, start_frame, end_frame, nframes); + _meter->run (bufs, start_frame, end_frame, nframes, true); } - if (monitoring_state() == MonitoringInput) { - - passthru (start_frame, end_frame, nframes, false); - - } else if ((b = diskstream->playback_buffer(0)) != 0) { - - /* - XXX is it true that the earlier test on n_outputs() - means that we can avoid checking it again here? i think - so, because changing the i/o configuration of an IO - requires holding the AudioEngine lock, which we hold - while in the process() tree. - */ - - - /* copy the diskstream data to all output buffers */ - - size_t limit = input_streams ().n_audio(); - BufferSet& bufs = _session.get_scratch_buffers (); - const size_t blimit = bufs.count().n_audio(); - - uint32_t n; - uint32_t i; - - if (limit > blimit) { - - /* example case: auditioner configured for stereo output, - but loaded with an 8 channel file. there are only - 2 passthrough buffers, but n_process_buffers() will - return 8. - - arbitrary decision: map all channels in the diskstream - to the outputs available. - */ - - float scaling = limit/blimit; - - for (i = 0, n = 1; i < blimit; ++i, ++n) { - - /* first time through just copy a channel into - the output buffer. - */ - - Sample* bb = bufs.get_audio (i).data(); - - for (pframes_t xx = 0; xx < nframes; ++xx) { - bb[xx] = b[xx] * scaling; - } - - if (n < diskstream->n_channels().n_audio()) { - tmpb = diskstream->playback_buffer(n); - if (tmpb!=0) { - b = tmpb; - } - } - } - - for (;i < limit; ++i, ++n) { - - /* for all remaining channels, sum with existing - data in the output buffers - */ - - bufs.get_audio (i%blimit).accumulate_with_gain_from (b, nframes, 0, scaling); - - if (n < diskstream->n_channels().n_audio()) { - tmpb = diskstream->playback_buffer(n); - if (tmpb!=0) { - b = tmpb; - } - } - - } - - limit = blimit; - - } else { - for (i = 0, n = 1; i < limit; ++i, ++n) { - memcpy (bufs.get_audio (i).data(), b, sizeof (Sample) * nframes); - if (n < diskstream->n_channels().n_audio()) { - tmpb = diskstream->playback_buffer(n); - if (tmpb!=0) { - b = tmpb; - } - } - } - - /* try to leave any MIDI buffers alone */ - - ChanCount chn; - chn.set_audio (limit); - chn.set_midi (_input->n_ports().n_midi()); - bufs.set_count (chn); - } - - /* final argument: don't waste time with automation if we're recording or we've just stopped (yes it can happen) */ - - process_output_buffers ( - bufs, start_frame, end_frame, nframes, - declick, - (!diskstream->record_enabled() && _session.transport_rolling()) - ); - - } else { - /* problem with the diskstream; just be quiet for a bit */ + if ((dret = diskstream->process (bufs, transport_frame, nframes, playback_distance, (monitoring_state() == MonitoringDisk))) != 0) { + need_butler = diskstream->commit (playback_distance); silence (nframes); + return dret; } + process_output_buffers (bufs, start_frame, end_frame, nframes, declick, (!diskstream->record_enabled() && _session.transport_rolling())); + need_butler = diskstream->commit (playback_distance); return 0; |