summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Baier <hansfbaier@googlemail.com>2009-06-23 09:50:02 +0000
committerHans Baier <hansfbaier@googlemail.com>2009-06-23 09:50:02 +0000
commitf42f577bedbffcd2465341e033afac0a0326a491 (patch)
tree3499d135da2d870010a8231389fb040a22c02218
parentdef335e427f46513436884bf81d10caf96d7c482 (diff)
Interpolation: First working but buggy version using libsamplerate
git-svn-id: svn://localhost/ardour2/branches/3.0@5255 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--libs/ardour/ardour/audio_diskstream.h2
-rw-r--r--libs/ardour/ardour/interpolation.h37
-rw-r--r--libs/ardour/ardour/session.h6
-rw-r--r--libs/ardour/audio_diskstream.cc14
-rw-r--r--libs/ardour/interpolation.cc93
-rw-r--r--libs/ardour/session_process.cc6
-rw-r--r--libs/ardour/tests/interpolation-test.cc62
-rw-r--r--libs/ardour/tests/interpolation-test.h3
-rw-r--r--libs/ardour/wscript2
9 files changed, 137 insertions, 88 deletions
diff --git a/libs/ardour/ardour/audio_diskstream.h b/libs/ardour/ardour/audio_diskstream.h
index 401ed9ec19..ad3b1adde2 100644
--- a/libs/ardour/ardour/audio_diskstream.h
+++ b/libs/ardour/ardour/audio_diskstream.h
@@ -146,7 +146,7 @@ class AudioDiskstream : public Diskstream
}
}
- LinearInterpolation interpolation;
+ Interpolation interpolation;
XMLNode* deprecated_io_node;
diff --git a/libs/ardour/ardour/interpolation.h b/libs/ardour/ardour/interpolation.h
index fc75451707..d0ba3c48bc 100644
--- a/libs/ardour/ardour/interpolation.h
+++ b/libs/ardour/ardour/interpolation.h
@@ -1,4 +1,6 @@
#include <math.h>
+#include <samplerate.h>
+
#include "ardour/types.h"
#ifndef __interpolation_h__
@@ -8,26 +10,29 @@ namespace ARDOUR {
class Interpolation {
protected:
- double _speed, _target_speed;
-
+ double _speed;
+
+ SRC_STATE* state;
+ std::vector<SRC_DATA> data;
+
+ int error;
+
+ void reset_state ();
+
public:
- Interpolation () : _speed(0.0L) {}
+ Interpolation ();
+ ~Interpolation ();
- void set_speed (double new_speed) { _speed = new_speed; }
- void set_target_speed (double new_speed) { _target_speed = new_speed; }
-
- double target_speed() const { return _target_speed; }
- double speed() const { return _speed; }
+ void set_speed (double new_speed);
+ void set_target_speed (double new_speed) {}
+ double speed () const { return _speed; }
+
+ void add_channel_to (int input_buffer_size, int output_buffer_size);
+ void remove_channel_from ();
- virtual nframes_t interpolate (nframes_t nframes, Sample* input, Sample* output) = 0;
-};
-
-class LinearInterpolation : public Interpolation {
-public:
- nframes_t interpolate (nframes_t nframes, Sample* input, Sample* output);
+ nframes_t interpolate (int channel, nframes_t nframes, Sample* input, Sample* output);
};
} // namespace ARDOUR
-#endif
-
+#endif \ No newline at end of file
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index 18bc22ce87..5c2c32655f 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -1006,11 +1006,13 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
Location* start_location;
Slave* _slave;
bool _silent;
+
+ // varispeed playback
volatile double _transport_speed;
double _last_transport_speed;
- // varispeed playback
double _target_transport_speed;
- LinearInterpolation interpolation;
+ Interpolation interpolation;
+
bool auto_play_legal;
nframes_t _last_slave_transport_frame;
nframes_t maximum_output_latency;
diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
index 9ff030678a..47d7b5c6e6 100644
--- a/libs/ardour/audio_diskstream.cc
+++ b/libs/ardour/audio_diskstream.cc
@@ -821,11 +821,12 @@ AudioDiskstream::process_varispeed_playback(nframes_t nframes, boost::shared_ptr
interpolation.set_target_speed (_target_speed);
interpolation.set_speed (_speed);
- for (chan = c->begin(); chan != c->end(); ++chan) {
+ int channel = 0;
+ for (chan = c->begin(); chan != c->end(); ++chan, ++channel) {
ChannelInfo* chaninfo (*chan);
playback_distance = interpolation.interpolate (
- nframes, chaninfo->current_playback_buffer, chaninfo->speed_buffer);
+ channel, nframes, chaninfo->current_playback_buffer, chaninfo->speed_buffer);
}
}
@@ -2204,12 +2205,14 @@ AudioDiskstream::set_align_style_from_io ()
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;
}
@@ -2226,8 +2229,11 @@ int
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?)
+ // 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());
diff --git a/libs/ardour/interpolation.cc b/libs/ardour/interpolation.cc
index 066507283b..a4a4b08872 100644
--- a/libs/ardour/interpolation.cc
+++ b/libs/ardour/interpolation.cc
@@ -1,41 +1,76 @@
#include <stdint.h>
+
#include "ardour/interpolation.h"
using namespace ARDOUR;
-nframes_t
-LinearInterpolation::interpolate (nframes_t nframes, Sample *input, Sample *output)
+Interpolation::Interpolation() : _speed (1.0L), state (0)
+{
+}
+
+Interpolation::~Interpolation()
+{
+ state = src_delete (state);
+}
+
+void
+Interpolation::set_speed (double new_speed)
+{
+ _speed = new_speed;
+ src_set_ratio (state, 1.0/_speed);
+}
+
+void
+Interpolation::reset_state ()
+{
+ if (state) {
+ src_reset (state);
+ } else {
+ state = src_new (SRC_LINEAR, 1, &error);
+ }
+}
+
+void
+Interpolation::add_channel_to (int input_buffer_size, int output_buffer_size)
{
- // the idea 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
+ SRC_DATA newdata;
- // index in the input buffers
- nframes_t i = 0;
+ /* Set up sample rate converter info. */
+ newdata.end_of_input = 0 ;
+
+ newdata.input_frames = input_buffer_size;
+ newdata.output_frames = output_buffer_size;
+
+ newdata.input_frames_used = 0 ;
+ newdata.output_frames_gen = 0 ;
+
+ newdata.src_ratio = 1.0/_speed;
- double acceleration;
- double distance = 0.0;
+ data.push_back (newdata);
- if (_speed != _target_speed) {
- acceleration = _target_speed - _speed;
- } else {
- acceleration = 0.0;
- }
+ reset_state ();
+}
- for (nframes_t outsample = 0; outsample < nframes; ++outsample) {
- i = distance;
- Sample fractional_phase_part = distance - i;
-
- if (input && output) {
- // Linearly interpolate into the output buffer
- output[outsample] =
- input[i] * (1.0f - fractional_phase_part) +
- input[i+1] * fractional_phase_part;
- }
- distance += _speed + acceleration;
- }
+void
+Interpolation::remove_channel_from ()
+{
+ data.pop_back ();
+ reset_state ();
+}
+
+nframes_t
+Interpolation::interpolate (int channel, nframes_t nframes, Sample *input, Sample *output)
+{
+ data[channel].data_in = input;
+ data[channel].data_out = output;
- i = (distance + 0.5L);
- // playback distance
- return i;
+ data[channel].output_frames = nframes;
+ data[channel].src_ratio = 1.0/_speed;
+
+ if ((error = src_process (state, &data[channel]))) {
+ printf ("\nError : %s\n\n", src_strerror (error));
+ exit (1);
+ }
+
+ return data[channel].input_frames_used;
}
diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc
index d389f32696..e7f2ad416f 100644
--- a/libs/ardour/session_process.cc
+++ b/libs/ardour/session_process.cc
@@ -327,7 +327,8 @@ Session::process_with_events (nframes_t nframes)
} else {
interpolation.set_target_speed (_target_transport_speed);
interpolation.set_speed (_transport_speed);
- frames_moved = (long) interpolation.interpolate (nframes, 0, 0);
+ //FIXME frames_moved = (long) interpolation.interpolate (nframes, 0, 0);
+ frames_moved = _transport_speed * nframes;
}
end_frame = _transport_frame + (nframes_t)frames_moved;
@@ -848,7 +849,8 @@ Session::process_without_events (nframes_t nframes)
} else {
interpolation.set_target_speed (_target_transport_speed);
interpolation.set_speed (_transport_speed);
- frames_moved = (long) interpolation.interpolate (nframes, 0, 0);
+ //FIXME frames_moved = (long) interpolation.interpolate (nframes, 0, 0);
+ frames_moved = _transport_speed * nframes;
}
if (process_routes (nframes)) {
diff --git a/libs/ardour/tests/interpolation-test.cc b/libs/ardour/tests/interpolation-test.cc
index 5a559cc830..3ec7910e1b 100644
--- a/libs/ardour/tests/interpolation-test.cc
+++ b/libs/ardour/tests/interpolation-test.cc
@@ -11,56 +11,54 @@ InterpolationTest::linearInterpolationTest ()
{
cout << "\nLinear Interpolation Test\n";
cout << "\nSpeed: 1.0";
- linear.set_speed (1.0);
- linear.set_target_speed (linear.speed());
- nframes_t result = linear.interpolate (NUM_SAMPLES, input, output);
- CPPUNIT_ASSERT_EQUAL ((uint32_t)(NUM_SAMPLES * linear.speed()), result);
+ interpolation.set_speed (1.0);
+ nframes_t result = interpolation.interpolate (0, NUM_SAMPLES, input, output);
+ CPPUNIT_ASSERT_EQUAL ((uint32_t)(NUM_SAMPLES * interpolation.speed()), result);
+/*
+*/
+ for (int i=0; i < NUM_SAMPLES; ++i) {
+ cout << "input[" << i << "] = " << input[i] << " output[" << i << "] = " << output[i] << endl;
+ }
for (int i = 0; i < NUM_SAMPLES; i += INTERVAL) {
- CPPUNIT_ASSERT_EQUAL (1.0f, output[i]);
+ CPPUNIT_ASSERT_EQUAL (1.0f, output[i+1]);
}
cout << "\nSpeed: 0.5";
- linear.set_speed (0.5);
- linear.set_target_speed (linear.speed());
- result = linear.interpolate (NUM_SAMPLES, input, output);
- CPPUNIT_ASSERT_EQUAL ((uint32_t)(NUM_SAMPLES * linear.speed()), result);
- for (int i = 0; i < NUM_SAMPLES; i += (INTERVAL / linear.speed() +0.5)) {
+ interpolation.set_speed (0.5);
+ result = interpolation.interpolate (0, NUM_SAMPLES, input, output);
+ CPPUNIT_ASSERT_EQUAL ((uint32_t)(NUM_SAMPLES * interpolation.speed()), result);
+ for (int i = 0; i < NUM_SAMPLES; i += (INTERVAL / interpolation.speed() +0.5)) {
CPPUNIT_ASSERT_EQUAL (1.0f, output[i]);
}
cout << "\nSpeed: 0.2";
- linear.set_speed (0.2);
- linear.set_target_speed (linear.speed());
- result = linear.interpolate (NUM_SAMPLES, input, output);
- CPPUNIT_ASSERT_EQUAL ((uint32_t)(NUM_SAMPLES * linear.speed()), result);
+ interpolation.set_speed (0.2);
+ result = interpolation.interpolate (0, NUM_SAMPLES, input, output);
+ CPPUNIT_ASSERT_EQUAL ((uint32_t)(NUM_SAMPLES * interpolation.speed()), result);
cout << "\nSpeed: 0.02";
- linear.set_speed (0.02);
- linear.set_target_speed (linear.speed());
- result = linear.interpolate (NUM_SAMPLES, input, output);
- CPPUNIT_ASSERT_EQUAL ((uint32_t)(NUM_SAMPLES * linear.speed()), result);
+ interpolation.set_speed (0.02);
+ result = interpolation.interpolate (0, NUM_SAMPLES, input, output);
+ CPPUNIT_ASSERT_EQUAL ((uint32_t)(NUM_SAMPLES * interpolation.speed()), result);
cout << "\nSpeed: 0.002";
- linear.set_speed (0.002);
- linear.set_target_speed (linear.speed());
- result = linear.interpolate (NUM_SAMPLES, input, output);
- CPPUNIT_ASSERT_EQUAL ((uint32_t)(NUM_SAMPLES * linear.speed()), result);
+ interpolation.set_speed (0.002);
+ result = interpolation.interpolate (0, NUM_SAMPLES, input, output);
+ CPPUNIT_ASSERT_EQUAL ((uint32_t)(NUM_SAMPLES * interpolation.speed()), result);
cout << "\nSpeed: 2.0";
- linear.set_speed (2.0);
- linear.set_target_speed (linear.speed());
- result = linear.interpolate (NUM_SAMPLES / 2, input, output);
- CPPUNIT_ASSERT_EQUAL ((uint32_t)(NUM_SAMPLES / 2 * linear.speed()), result);
- for (int i = 0; i < NUM_SAMPLES / 2; i += (INTERVAL / linear.speed() +0.5)) {
+ interpolation.set_speed (2.0);
+ result = interpolation.interpolate (0, NUM_SAMPLES / 2, input, output);
+ CPPUNIT_ASSERT_EQUAL ((uint32_t)(NUM_SAMPLES / 2 * interpolation.speed()), result);
+ for (int i = 0; i < NUM_SAMPLES / 2; i += (INTERVAL / interpolation.speed() +0.5)) {
CPPUNIT_ASSERT_EQUAL (1.0f, output[i]);
}
cout << "\nSpeed: 10.0";
- linear.set_speed (10.0);
- linear.set_target_speed (linear.speed());
- result = linear.interpolate (NUM_SAMPLES / 10, input, output);
- CPPUNIT_ASSERT_EQUAL ((uint32_t)(NUM_SAMPLES / 10 * linear.speed()), result);
- for (int i = 0; i < NUM_SAMPLES / 10; i += (INTERVAL / linear.speed() +0.5)) {
+ interpolation.set_speed (10.0);
+ result = interpolation.interpolate (0, NUM_SAMPLES / 10, input, output);
+ CPPUNIT_ASSERT_EQUAL ((uint32_t)(NUM_SAMPLES / 10 * interpolation.speed()), result);
+ for (int i = 0; i < NUM_SAMPLES / 10; i += (INTERVAL / interpolation.speed() +0.5)) {
CPPUNIT_ASSERT_EQUAL (1.0f, output[i]);
}
/*
diff --git a/libs/ardour/tests/interpolation-test.h b/libs/ardour/tests/interpolation-test.h
index 3231f32464..0c1b0de6c2 100644
--- a/libs/ardour/tests/interpolation-test.h
+++ b/libs/ardour/tests/interpolation-test.h
@@ -35,7 +35,7 @@ class InterpolationTest : public CppUnit::TestFixture
ARDOUR::Sample input[NUM_SAMPLES];
ARDOUR::Sample output[NUM_SAMPLES];
- ARDOUR::LinearInterpolation linear;
+ ARDOUR::Interpolation interpolation;
public:
@@ -48,6 +48,7 @@ class InterpolationTest : public CppUnit::TestFixture
}
output[i] = 0.0f;
}
+ interpolation.add_channel_to (NUM_SAMPLES, NUM_SAMPLES);
}
void tearDown() {
diff --git a/libs/ardour/wscript b/libs/ardour/wscript
index fc08dfde0d..172047bde3 100644
--- a/libs/ardour/wscript
+++ b/libs/ardour/wscript
@@ -255,7 +255,7 @@ def build(bld):
tests/testrunner.cpp
'''
testobj.includes = obj.includes + ['../pbd/']
- testobj.uselib = 'CPPUNIT SIGCPP JACK GLIBMM'
+ testobj.uselib = 'CPPUNIT SIGCPP JACK GLIBMM SAMPLERATE'
testobj.target = 'run-tests'
testobj.install_path = ''