+void
+Panner::distribute_no_automation (BufferSet& inbufs, BufferSet& outbufs, nframes_t nframes, gain_t gain_coeff)
+{
+ if (outbufs.count().n_audio() == 0) {
+ // Don't want to lose audio...
+ assert(inbufs.count().n_audio() == 0);
+ return;
+ }
+
+ // We shouldn't be called in the first place...
+ assert(!bypassed());
+ assert(!empty());
+
+
+ if (outbufs.count().n_audio() == 1) {
+
+ AudioBuffer& dst = outbufs.get_audio(0);
+
+ if (gain_coeff == 0.0f) {
+
+ /* only one output, and gain was zero, so make it silent */
+
+ dst.silence (nframes);
+
+ } else if (gain_coeff == 1.0f){
+
+ /* mix all buffers into the output */
+
+ // copy the first
+ dst.read_from(inbufs.get_audio(0), nframes);
+
+ // accumulate starting with the second
+ if (inbufs.count().n_audio() > 0) {
+ BufferSet::audio_iterator i = inbufs.audio_begin();
+ for (++i; i != inbufs.audio_end(); ++i) {
+ dst.merge_from(*i, nframes);
+ }
+ }
+
+ } else {
+
+ /* mix all buffers into the output, scaling them all by the gain */
+
+ // copy the first
+ dst.read_from(inbufs.get_audio(0), nframes);
+
+ // accumulate (with gain) starting with the second
+ if (inbufs.count().n_audio() > 0) {
+ BufferSet::audio_iterator i = inbufs.audio_begin();
+ for (++i; i != inbufs.audio_end(); ++i) {
+ dst.accumulate_with_gain_from(*i, nframes, gain_coeff);
+ }
+ }
+
+ }
+
+ return;
+ }
+
+ /* the terrible silence ... */
+ for (BufferSet::audio_iterator i = outbufs.audio_begin(); i != outbufs.audio_end(); ++i) {
+ i->silence(nframes);
+ }
+
+ BufferSet::audio_iterator i = inbufs.audio_begin();
+
+ for (vector<StreamPanner*>::iterator pan = _streampanners.begin(); pan != _streampanners.end() && i != inbufs.audio_end(); ++pan, ++i) {
+ (*pan)->distribute (*i, outbufs, gain_coeff, nframes);
+ }
+}
+
+void
+Panner::run (BufferSet& inbufs, BufferSet& outbufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
+{
+ if (outbufs.count().n_audio() == 0) {
+ // Failing to deliver audio we were asked to deliver is a bug
+ assert(inbufs.count().n_audio() == 0);
+ return;
+ }
+
+ // We shouldn't be called in the first place...
+ assert(!bypassed());
+ assert(!empty());
+
+ // If we shouldn't play automation defer to distribute_no_automation
+ if (!(automation_state() & Play || ((automation_state() & Touch) && !touching()))) {
+
+ // Speed quietning
+ gain_t gain_coeff = 1.0;
+
+ if (fabsf(_session.transport_speed()) > 1.5f) {
+ gain_coeff = speed_quietning;
+ }
+
+ distribute_no_automation (inbufs, outbufs, nframes, gain_coeff);
+ return;
+ }
+
+ // Otherwise.. let the automation flow, baby
+
+ if (outbufs.count().n_audio() == 1) {
+
+ AudioBuffer& dst = outbufs.get_audio(0);
+
+ // FIXME: apply gain automation?
+
+ // copy the first
+ dst.read_from(inbufs.get_audio(0), nframes);
+
+ // accumulate starting with the second
+ BufferSet::audio_iterator i = inbufs.audio_begin();
+ for (++i; i != inbufs.audio_end(); ++i) {
+ dst.merge_from(*i, nframes);
+ }
+
+ return;
+ }
+
+ // More than 1 output, we should have 1 panner for each input
+ //assert(_streampanners.size() == inbufs.count().n_audio());
+
+ /* the terrible silence ... */
+ for (BufferSet::audio_iterator i = outbufs.audio_begin(); i != outbufs.audio_end(); ++i) {
+ i->silence(nframes);
+ }
+
+ BufferSet::audio_iterator i = inbufs.audio_begin();
+ for (vector<StreamPanner*>::iterator pan = _streampanners.begin(); pan != _streampanners.end(); ++pan, ++i) {
+ (*pan)->distribute_automated (*i, outbufs, start_frame, end_frame, nframes, _session.pan_automation_buffer());
+ }
+}
+