#include <ardour/panner.h>
#include <ardour/utils.h>
#include <ardour/buffer_set.h>
+#include <ardour/audio_buffer.h>
+#include <ardour/internal_send.h>
#include "i18n.h"
using namespace std;
_session.add_diskstream (ds);
+ _session.RouteAdded.connect (mem_fun (*this, &AudioTrack::catch_up_on_busses));
+
set_diskstream (boost::dynamic_pointer_cast<AudioDiskstream> (ds), this);
}
: Track (sess, node)
{
_set_state (node, false);
+
+ _session.RouteAdded.connect (mem_fun (*this, &AudioTrack::catch_up_on_busses));
}
AudioTrack::~AudioTrack ()
{
}
+void
+AudioTrack::catch_up_on_busses (RouteList& added)
+{
+ if (is_hidden()) {
+ return;
+ }
+
+ for (RouteList::iterator x = added.begin(); x != added.end(); ++x) {
+ if (boost::dynamic_pointer_cast<Track>(*x) == 0 && (*x)->default_type() == DataType::AUDIO) {
+ /* Audio bus */
+ if (!(*x)->is_master() && !(*x)->is_control()) {
+ add_internal_send (*x);
+ }
+ }
+ }
+}
+
+void
+AudioTrack::add_internal_send (boost::shared_ptr<Route> r)
+{
+ boost::shared_ptr<InternalSend> is (new InternalSend (_session, PreFader, r));
+
+ cerr << name() << " Adding processor\n";
+
+ add_processor (is, 0);
+
+ cerr << "After add, we have " << _processors.size() << endl;
+
+ /* note: if adding failed, the InternalSend will be cleaned up automatically when
+ the shared_ptr goes out of scope.
+ */
+}
+
int
AudioTrack::set_mode (TrackMode m)
{
transport_frame = _session.transport_frame();
+ prepare_inputs( nframes, offset );
+
if ((nframes = check_initial_delay (nframes, offset, transport_frame)) == 0) {
/* need to do this so that the diskstream sets its
playback distance to zero, thus causing diskstream::commit
/* copy the diskstream data to all output buffers */
-
- const size_t limit = n_process_buffers().n_audio();
- BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers());
-
+
+ size_t limit = n_process_buffers().n_audio();
+ BufferSet& bufs = _session.get_scratch_buffers ();
+ const size_t blimit = bufs.count().n_audio();
+
uint32_t n;
uint32_t i;
- 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;
+ 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 (nframes_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 < blimit; ++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;
+ }
}
}
}
/* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
if (!diskstream->record_enabled() && _session.transport_rolling()) {
- Glib::Mutex::Lock am (_automation_lock, Glib::TRY_LOCK);
+ Glib::Mutex::Lock am (data().control_lock(), Glib::TRY_LOCK);
- if (am.locked() && gain_control()->list()->automation_playback()) {
+ if (am.locked() && gain_control()->automation_playback()) {
apply_gain_automation = gain_control()->list()->curve().rt_safe_get_vector (start_frame, end_frame, _session.gain_automation_buffer(), nframes);
}
}
}
}
- if (gain_control()->list()->automation_state() == Play) {
+ if (gain_control()->automation_state() == Play) {
gain_control()->list()->curve().get_vector (start, start + nframes, gain_automation, nframes);
/* now deactivate the processor */
- processor->set_active (false);
+ processor->deactivate ();
_session.set_dirty ();
}
}
}
new_playlist = PlaylistFactory::create (DataType::AUDIO, _session, new_playlist_name, false);
+
+ _freeze_record.gain = _gain;
+ _freeze_record.gain_automation_state = _gain_control->automation_state();
+ _freeze_record.pan_automation_state = _panner->automation_state();
+
region_name = new_playlist_name;
/* create a new region from all filesources, keep it private */
diskstream->use_playlist (boost::dynamic_pointer_cast<AudioPlaylist>(new_playlist));
diskstream->set_record_enabled (false);
+ /* reset stuff that has already been accounted for in the freeze process */
+
+ set_gain (1.0, this);
+ _gain_control->set_automation_state (Off);
+ _panner->set_automation_state (Off);
+
_freeze_record.state = Frozen;
FreezeChange(); /* EMIT SIGNAL */
}
}
_freeze_record.playlist.reset ();
+ set_gain (_freeze_record.gain, this);
+ _gain_control->set_automation_state (_freeze_record.gain_automation_state);
+ _panner->set_automation_state (_freeze_record.pan_automation_state);
}
_freeze_record.state = UnFrozen;