_n_channels.set(DataType::AUDIO, c->size());
- if (_io->n_inputs().n_audio() > _n_channels.n_audio()) {
- add_channel_to (c, _io->n_inputs().n_audio() - _n_channels.n_audio());
- } else if (_io->n_inputs().n_audio() < _n_channels.n_audio()) {
- remove_channel_from (c, _n_channels.n_audio() - _io->n_inputs().n_audio());
+ if (_io->n_ports().n_audio() > _n_channels.n_audio()) {
+ add_channel_to (c, _io->n_ports().n_audio() - _n_channels.n_audio());
+ } else if (_io->n_ports().n_audio() < _n_channels.n_audio()) {
+ remove_channel_from (c, _n_channels.n_audio() - _io->n_ports().n_audio());
}
}
uint32_t n;
ChannelList::iterator chan;
- uint32_t ni = _io->n_inputs().n_audio();
+ uint32_t ni = _io->n_ports().n_audio();
vector<string> connections;
for (n = 0, chan = c->begin(); chan != c->end() && n < ni; ++chan, ++n) {
connections.clear ();
- if (_io->input(n)->get_connections (connections) == 0) {
+ if (_io->nth (n)->get_connections (connections) == 0) {
if ((*chan)->source) {
// _source->disable_metering ();
}
void
-AudioDiskstream::check_record_status (nframes_t transport_frame, nframes_t nframes, bool can_record)
+AudioDiskstream::check_record_status (nframes_t transport_frame, nframes_t /*nframes*/, bool can_record)
{
int possibly_recording;
int rolling;
if (_alignment_style == ExistingMaterial) {
- if (!Config->get_punch_in()) {
+ if (!_session.config.get_punch_in()) {
/* manual punch in happens at the correct transport frame
because the user hit a button. but to get alignment correct
} else {
- if (Config->get_punch_in()) {
+ if (_session.config.get_punch_in()) {
first_recordable_frame += _roll_delay;
} else {
capture_start_frame -= _roll_delay;
(*chan)->current_playback_buffer = 0;
}
- if (nominally_recording || (_session.get_record_enabled() && Config->get_punch_in())) {
+ if (nominally_recording || (_session.get_record_enabled() && _session.config.get_punch_in())) {
OverlapType ot;
// Safeguard against situations where process() goes haywire when autopunching and last_recordable_frame < first_recordable_frame
if (nominally_recording || rec_nframes) {
- uint32_t limit = _io->n_inputs ().n_audio();
+ uint32_t limit = _io->n_ports ().n_audio();
/* one or more ports could already have been removed from _io, but our
channel setup hasn't yet been updated. prevent us from trying to
for recording, and use rec_offset
*/
- AudioPort* const ap = _io->audio_input(n);
+ AudioPort* const ap = _io->audio (n);
assert(ap);
assert(rec_nframes <= ap->get_audio_buffer(nframes).capacity());
memcpy (chaninfo->current_capture_buffer, ap->get_audio_buffer (rec_nframes).data(rec_offset), sizeof (Sample) * rec_nframes);
goto out;
}
- AudioPort* const ap = _io->audio_input(n);
+ AudioPort* const ap = _io->audio (n);
assert(ap);
Sample* buf = ap->get_audio_buffer(nframes).data();
playback_distance = nframes;
}
- phi = target_phi;
+ _speed = _target_speed;
}
void
AudioDiskstream::process_varispeed_playback(nframes_t nframes, boost::shared_ptr<ChannelList> c)
{
- ChannelList::iterator chan;
-
- // the idea behind phase is that when the speed is not 1.0, we have to
- // interpolate between samples and then we have to store where we thought we were.
- // rather than being at sample N or N+1, we were at N+0.8792922
- // so the "phase" element, if you want to think about this way,
- // varies from 0 to 1, representing the "offset" between samples
- uint64_t phase = last_phase;
-
- // acceleration
- int64_t phi_delta;
+ ChannelList::iterator chan;
- // index in the input buffers
- nframes_t i = 0;
-
- // Linearly interpolate into the speed buffer
- // using 40.24 fixed point math
- //
- // Fixed point is just an integer with an implied scaling factor.
- // In 40.24 the scaling factor is 2^24 = 16777216,
- // so a value of 10*2^24 (in integer space) is equivalent to 10.0.
- //
- // The advantage is that addition and modulus [like x = (x + y) % 2^40]
- // have no rounding errors and no drift, and just require a single integer add.
- // (swh)
+ interpolation.set_speed (_target_speed);
+
+ int channel = 0;
+ for (chan = c->begin(); chan != c->end(); ++chan, ++channel) {
+ ChannelInfo* chaninfo (*chan);
- const int64_t fractional_part_mask = 0xFFFFFF;
- const Sample binary_scaling_factor = 16777216.0f;
-
- // phi = fixed point speed
- if (phi != target_phi) {
- phi_delta = ((int64_t)(target_phi - phi)) / nframes;
- } else {
- phi_delta = 0;
- }
-
- for (chan = c->begin(); chan != c->end(); ++chan) {
-
- Sample fractional_phase_part;
- ChannelInfo* chaninfo (*chan);
-
- i = 0;
- phase = last_phase;
-
- for (nframes_t outsample = 0; outsample < nframes; ++outsample) {
- i = phase >> 24;
- fractional_phase_part = (phase & fractional_part_mask) / binary_scaling_factor;
- chaninfo->speed_buffer[outsample] =
- chaninfo->current_playback_buffer[i] * (1.0f - fractional_phase_part) +
- chaninfo->current_playback_buffer[i+1] * fractional_phase_part;
- phase += phi + phi_delta;
+ playback_distance = interpolation.interpolate (
+ channel, nframes, chaninfo->current_playback_buffer, chaninfo->speed_buffer);
+
+ chaninfo->current_playback_buffer = chaninfo->speed_buffer;
}
-
- chaninfo->current_playback_buffer = chaninfo->speed_buffer;
- }
-
- playback_distance = i; // + 1;
- last_phase = (phase & fractional_part_mask);
}
bool
-AudioDiskstream::commit (nframes_t nframes)
+AudioDiskstream::commit (nframes_t /*nframes*/)
{
bool need_butler = false;
int
AudioDiskstream::read (Sample* buf, Sample* mixdown_buffer, float* gain_buffer, nframes_t& start, nframes_t cnt,
- ChannelInfo* channel_info, int channel, bool reversed)
+ ChannelInfo* /*channel_info*/, int channel, bool reversed)
{
nframes_t this_read = 0;
bool reloop = false;
* written at all unless @a force_flush is true.
*/
int
-AudioDiskstream::do_flush (RunContext context, bool force_flush)
+AudioDiskstream::do_flush (RunContext /*context*/, bool force_flush)
{
uint32_t to_write;
int32_t ret = 0;
}
void
-AudioDiskstream::finish_capture (bool rec_monitors_input, boost::shared_ptr<ChannelList> c)
+AudioDiskstream::finish_capture (bool /*rec_monitors_input*/, boost::shared_ptr<ChannelList> c)
{
was_recording = false;
void
AudioDiskstream::set_record_enabled (bool yn)
{
- if (!recordable() || !_session.record_enabling_legal() || _io->n_inputs().n_audio() == 0) {
+ if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_audio() == 0) {
return;
}
for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
if ((*chan)->source) {
- (*chan)->source->ensure_monitor_input (!(Config->get_auto_input() && rolling));
+ (*chan)->source->ensure_monitor_input (!(_session.config.get_auto_input() && rolling));
}
capturing_sources.push_back ((*chan)->write_source);
(*chan)->write_source->mark_streaming_write_started ();
Location* pi;
- if (Config->get_punch_in() && ((pi = _session.locations()->auto_punch_location()) != 0)) {
- snprintf (buf, sizeof (buf), "%" PRIu32, pi->start());
+ if (_session.config.get_punch_in() && ((pi = _session.locations()->auto_punch_location()) != 0)) {
+ snprintf (buf, sizeof (buf), "%" PRId64, pi->start());
} else {
snprintf (buf, sizeof (buf), "%" PRIu32, _session.transport_frame());
}
}
void
-AudioDiskstream::reset_write_sources (bool mark_write_complete, bool force)
+AudioDiskstream::reset_write_sources (bool mark_write_complete, bool /*force*/)
{
ChannelList::iterator chan;
boost::shared_ptr<ChannelList> c = channels.reader();
}
void
-AudioDiskstream::set_block_size (nframes_t nframes)
+AudioDiskstream::set_block_size (nframes_t /*nframes*/)
{
if (_session.get_block_size() > speed_buffer_size) {
speed_buffer_size = _session.get_block_size();
boost::shared_ptr<ChannelList> c = channels.reader();
for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
- if ((*chan)->speed_buffer) delete [] (*chan)->speed_buffer;
+ if ((*chan)->speed_buffer)
+ delete [] (*chan)->speed_buffer;
(*chan)->speed_buffer = new Sample[speed_buffer_size];
}
}
boost::shared_ptr<ChannelList> c = channels.reader();
for (ChannelList::iterator chan = c->begin(); chan != c->end(); ++chan) {
- if ((*chan)->playback_wrap_buffer) delete [] (*chan)->playback_wrap_buffer;
+ if ((*chan)->playback_wrap_buffer)
+ delete [] (*chan)->playback_wrap_buffer;
(*chan)->playback_wrap_buffer = new Sample[required_wrap_size];
- if ((*chan)->capture_wrap_buffer) delete [] (*chan)->capture_wrap_buffer;
+ if ((*chan)->capture_wrap_buffer)
+ delete [] (*chan)->capture_wrap_buffer;
(*chan)->capture_wrap_buffer = new Sample[required_wrap_size];
}
int
AudioDiskstream::add_channel_to (boost::shared_ptr<ChannelList> c, uint32_t how_many)
{
+
while (how_many--) {
c->push_back (new ChannelInfo(_session.audio_diskstream_buffer_size(), speed_buffer_size, wrap_buffer_size));
+ interpolation.add_channel_to (_session.audio_diskstream_buffer_size(), speed_buffer_size);
}
_n_channels.set(DataType::AUDIO, c->size());
-
+
return 0;
}
AudioDiskstream::remove_channel_from (boost::shared_ptr<ChannelList> c, uint32_t how_many)
{
while (how_many-- && !c->empty()) {
- delete c->back();
+ // FIXME: crash (thread safe with RCU?)
+ // memory leak, when disabled.... :(
+ //delete c->back();
c->pop_back();
+ interpolation.remove_channel_from ();
}
_n_channels.set(DataType::AUDIO, c->size());