mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-11 17:16:38 +01:00
* Extracted method void AudioDiskstream::process_varispeed_playback(nframes_t nframes, boost::shared_ptr<ChannelList> c)
from AudioDiskstream::process git-svn-id: svn://localhost/ardour2/branches/3.0@4396 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
3d2c1ba3e6
commit
bfbae251be
2 changed files with 68 additions and 55 deletions
|
|
@ -216,6 +216,8 @@ class AudioDiskstream : public Diskstream
|
||||||
|
|
||||||
typedef std::vector<ChannelInfo*> ChannelList;
|
typedef std::vector<ChannelInfo*> ChannelList;
|
||||||
|
|
||||||
|
void process_varispeed_playback(nframes_t nframes, boost::shared_ptr<ChannelList> c);
|
||||||
|
|
||||||
/* The two central butler operations */
|
/* The two central butler operations */
|
||||||
int do_flush (Session::RunContext context, bool force = false);
|
int do_flush (Session::RunContext context, bool force = false);
|
||||||
int do_refill () { return _do_refill(_mixdown_buffer, _gain_buffer); }
|
int do_refill () { return _do_refill(_mixdown_buffer, _gain_buffer); }
|
||||||
|
|
@ -226,6 +228,7 @@ class AudioDiskstream : public Diskstream
|
||||||
nframes_t& start, nframes_t cnt,
|
nframes_t& start, nframes_t cnt,
|
||||||
ChannelInfo* channel_info, int channel, bool reversed);
|
ChannelInfo* channel_info, int channel, bool reversed);
|
||||||
|
|
||||||
|
|
||||||
void finish_capture (bool rec_monitors_input, boost::shared_ptr<ChannelList>);
|
void finish_capture (bool rec_monitors_input, boost::shared_ptr<ChannelList>);
|
||||||
void transport_stopped (struct tm&, time_t, bool abort);
|
void transport_stopped (struct tm&, time_t, bool abort);
|
||||||
void transport_looped (nframes_t transport_frame);
|
void transport_looped (nframes_t transport_frame);
|
||||||
|
|
|
||||||
|
|
@ -779,60 +779,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rec_nframes == 0 && _actual_speed != 1.0f && _actual_speed != -1.0f) {
|
if (rec_nframes == 0 && _actual_speed != 1.0f && _actual_speed != -1.0f) {
|
||||||
|
process_varispeed_playback(nframes, c);
|
||||||
// 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;
|
|
||||||
int64_t phi_delta;
|
|
||||||
nframes_t i = 0;
|
|
||||||
|
|
||||||
// Linearly interpolate into the alt buffer
|
|
||||||
// using 40.24 fixp maths
|
|
||||||
//
|
|
||||||
// Fixedpoint 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]
|
|
||||||
// has no rounding errors and no drift, and just requires a single integer add.
|
|
||||||
// (swh)
|
|
||||||
|
|
||||||
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_part;
|
|
||||||
ChannelInfo* chaninfo (*chan);
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
phase = last_phase;
|
|
||||||
|
|
||||||
for (nframes_t outsample = 0; outsample < nframes; ++outsample) {
|
|
||||||
i = phase >> 24;
|
|
||||||
fractional_part = (phase & fractional_part_mask) / binary_scaling_factor;
|
|
||||||
chaninfo->speed_buffer[outsample] =
|
|
||||||
chaninfo->current_playback_buffer[i] * (1.0f - fractional_part) +
|
|
||||||
chaninfo->current_playback_buffer[i+1] * fractional_part;
|
|
||||||
phase += phi + phi_delta;
|
|
||||||
}
|
|
||||||
|
|
||||||
chaninfo->current_playback_buffer = chaninfo->speed_buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
playback_distance = i; // + 1;
|
|
||||||
last_phase = (phase & fractional_part_mask);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
playback_distance = nframes;
|
playback_distance = nframes;
|
||||||
}
|
}
|
||||||
|
|
@ -859,6 +806,69 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
chaninfo->current_playback_buffer = chaninfo->speed_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
playback_distance = i; // + 1;
|
||||||
|
last_phase = (phase & fractional_part_mask);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AudioDiskstream::commit (nframes_t nframes)
|
AudioDiskstream::commit (nframes_t nframes)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue