vector<Sample*>& get_passthru_buffers() { return _passthru_buffers; }
vector<Sample*>& get_silent_buffers (uint32_t howmany);
+ vector<Sample*>& get_send_buffers () { return _send_buffers; }
DiskStream *diskstream_by_id (id_t id);
DiskStream *diskstream_by_name (string name);
jack_nframes_t last_stop_frame;
vector<Sample *> _passthru_buffers;
vector<Sample *> _silent_buffers;
- map<RunContext,char*> _conversion_buffers;
+ vector<Sample *> _send_buffers;
+ map<RunContext,char*> _conversion_buffers;
jack_nframes_t current_block_size;
jack_nframes_t _worst_output_latency;
jack_nframes_t _worst_input_latency;
Sample *buffer;
double fractional_shift;
double fractional_pos;
-
+ gain_t polscale = invert_polarity ? -1.0f : 1.0f;
+
fractional_shift = -1.0/declick;
if (target < initial) {
buffer = bufs[n];
fractional_pos = 1.0;
- if (invert_polarity) {
- for (jack_nframes_t nx = 0; nx < declick; ++nx) {
- buffer[nx] *= -(initial + (delta * (0.5 + 0.5 * cos (M_PI * fractional_pos))));
- fractional_pos += fractional_shift;
- }
- } else {
- for (jack_nframes_t nx = 0; nx < declick; ++nx) {
- buffer[nx] *= (initial + (delta * (0.5 + 0.5 * cos (M_PI * fractional_pos))));
- fractional_pos += fractional_shift;
- }
+ for (jack_nframes_t nx = 0; nx < declick; ++nx) {
+ buffer[nx] *= polscale * (initial + (delta * (0.5 + 0.5 * cos (M_PI * fractional_pos))));
+ fractional_pos += fractional_shift;
}
/* now ensure the rest of the buffer has the target value
gain_t dg;
-
+ gain_t pangain = _gain;
+
{
TentativeLockMonitor dm (declick_lock, __LINE__, __FILE__);
if (dg != _gain) {
apply_declick (bufs, nbufs, nframes, _gain, dg, false);
_gain = dg;
+ pangain = 1.0f;
}
/* simple, non-automation panning to outputs */
if (_session.transport_speed() > 1.5f || _session.transport_speed() < -1.5f) {
- pan (bufs, nbufs, nframes, offset, _gain * speed_quietning);
+ pan (bufs, nbufs, nframes, offset, pangain * speed_quietning);
} else {
- pan (bufs, nbufs, nframes, offset, _gain);
+ pan (bufs, nbufs, nframes, offset, pangain);
}
}
{
if (active()) {
- IO::deliver_output (bufs, nbufs, nframes, offset);
+ // we have to copy the input, because IO::deliver_output may alter the buffers
+ // in-place, which a send must never do.
+
+ vector<Sample*>& sendbufs = _session.get_send_buffers();
+
+ for (size_t i=0; i < nbufs; ++i) {
+ memcpy (sendbufs[i], bufs[i], sizeof (Sample) * nframes);
+ }
+
+
+ IO::deliver_output (sendbufs, nbufs, nframes, offset);
if (_metering) {
uint32_t n;
} else {
for (n = 0; n < no; ++n) {
- _peak_power[n] = Session::compute_peak (output(n)->get_buffer(nframes+offset) + offset, nframes, _peak_power[n]) * _gain;
+ _peak_power[n] = Session::compute_peak (output(n)->get_buffer(nframes) + offset, nframes, _peak_power[n]);
}
}
}
free(*i);
}
+ for (vector<Sample*>::iterator i = _send_buffers.begin(); i != _send_buffers.end(); ++i) {
+ free(*i);
+ }
+
for (map<RunContext,char*>::iterator i = _conversion_buffers.begin(); i != _conversion_buffers.end(); ++i) {
delete [] (i->second);
}
ensure_passthru_buffers (np);
+ for (vector<Sample*>::iterator i = _send_buffers.begin(); i != _send_buffers.end(); ++i) {
+ free(*i);
+
+ Sample *buf;
+#ifdef NO_POSIX_MEMALIGN
+ buf = (Sample *) malloc(current_block_size * sizeof(Sample));
+#else
+ posix_memalign((void **)&buf,16,current_block_size * 4);
+#endif
+ *i = buf;
+
+ memset (*i, 0, sizeof (Sample) * current_block_size);
+ }
+
+
if (_gain_automation_buffer) {
delete [] _gain_automation_buffer;
}
memset (p, 0, sizeof (Sample) * current_block_size);
_silent_buffers.push_back (p);
+ *p = 0;
+
+#ifdef NO_POSIX_MEMALIGN
+ p = (Sample *) malloc(current_block_size * sizeof(Sample));
+#else
+ posix_memalign((void **)&p,16,current_block_size * 4);
+#endif
+ memset (p, 0, sizeof (Sample) * current_block_size);
+ _send_buffers.push_back (p);
+
}
allocate_pan_automation_buffers (current_block_size, howmany, false);
}