summaryrefslogtreecommitdiff
path: root/libs/ardour/audio_diskstream.cc
diff options
context:
space:
mode:
authorHans Baier <hansfbaier@googlemail.com>2009-01-10 08:41:51 +0000
committerHans Baier <hansfbaier@googlemail.com>2009-01-10 08:41:51 +0000
commitbfbae251be8b67b33ad1c95b56e30da0cb537ec5 (patch)
tree0775c108745ce39774aff80376e048ca36047450 /libs/ardour/audio_diskstream.cc
parent3d2c1ba3e68b82a0e0f498152a3127599e209c87 (diff)
* 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
Diffstat (limited to 'libs/ardour/audio_diskstream.cc')
-rw-r--r--libs/ardour/audio_diskstream.cc118
1 files changed, 64 insertions, 54 deletions
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index cd2148325a..36903f7699 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -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) {
-
- // 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);
-
+ process_varispeed_playback(nframes, c);
} else {
playback_distance = nframes;
}
@@ -859,6 +806,69 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_
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
AudioDiskstream::commit (nframes_t nframes)
{