From 799b6ec97d2dea160ae11326fda8f50ae6c34faf Mon Sep 17 00:00:00 2001 From: Hans Baier Date: Fri, 9 Jan 2009 09:18:24 +0000 Subject: [PATCH] * changed transport speed in session and slaves from float to double * added some comments git-svn-id: svn://localhost/ardour2/branches/3.0@4394 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/ardour/ardour/diskstream.h | 10 ++++++--- libs/ardour/ardour/session.h | 22 +++++++++---------- libs/ardour/ardour/slave.h | 16 +++++++------- libs/ardour/audio_diskstream.cc | 19 +++++++++++----- libs/ardour/diskstream.cc | 1 + libs/ardour/jack_slave.cc | 4 ++-- libs/ardour/midi_clock_slave.cc | 11 +++++----- libs/ardour/mtc_slave.cc | 8 +++---- libs/ardour/session_process.cc | 2 +- libs/ardour/session_transport.cc | 20 ++++++++--------- libs/surfaces/control_protocol/basic_ui.cc | 4 ++-- .../control_protocol/basic_ui.h | 4 ++-- 12 files changed, 67 insertions(+), 54 deletions(-) diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h index 955f2ed8e7..24655a1d41 100644 --- a/libs/ardour/ardour/diskstream.h +++ b/libs/ardour/ardour/diskstream.h @@ -277,9 +277,13 @@ class Diskstream : public SessionObject nframes_t wrap_buffer_size; nframes_t speed_buffer_size; - uint64_t last_phase; - uint64_t phi; - uint64_t target_phi; + uint64_t last_phase; + + /// diskstream speed in 40.24 fixed point math + uint64_t phi; + + /// target diskstream speed in 40.24 fixed point math + uint64_t target_phi; nframes_t file_frame; nframes_t playback_sample; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 81134d16fd..9d12aa79b8 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -170,9 +170,9 @@ class Session : public PBD::StatefulDestructible Type type; Action action; - nframes_t action_frame; - nframes_t target_frame; - float speed; + nframes_t action_frame; + nframes_t target_frame; + double speed; union { void* ptr; @@ -187,7 +187,7 @@ class Session : public PBD::StatefulDestructible list audio_range; list music_range; - Event(Type t, Action a, nframes_t when, nframes_t where, float spd, bool yn = false) + Event(Type t, Action a, nframes_t when, nframes_t where, double spd, bool yn = false) : type (t), action (a), action_frame (when), @@ -388,9 +388,9 @@ class Session : public PBD::StatefulDestructible void set_session_end (nframes_t end) { end_location->set_start(end); _end_location_is_free = false; } void use_rf_shuttle_speed (); void allow_auto_play (bool yn); - void request_transport_speed (float speed); + void request_transport_speed (double speed); void request_overwrite_buffer (Diskstream*); - void request_diskstream_speed (Diskstream&, float speed); + void request_diskstream_speed (Diskstream&, double speed); void request_input_change_handling (); bool locate_pending() const { return static_cast(post_transport_work&PostTransportLocate); } @@ -572,7 +572,7 @@ class Session : public PBD::StatefulDestructible void request_slave_source (SlaveSource); bool synced_to_jack() const { return Config->get_slave_source() == JACK; } - float transport_speed() const { return _transport_speed; } + double transport_speed() const { return _transport_speed; } bool transport_stopped() const { return _transport_speed == 0.0f; } bool transport_rolling() const { return _transport_speed != 0.0f; } @@ -1023,8 +1023,8 @@ class Session : public PBD::StatefulDestructible Location* start_location; Slave* _slave; bool _silent; - volatile float _transport_speed; - float _last_transport_speed; + volatile double _transport_speed; + double _last_transport_speed; bool auto_play_legal; nframes_t _last_slave_transport_frame; nframes_t maximum_output_latency; @@ -1419,8 +1419,8 @@ class Session : public PBD::StatefulDestructible void locate (nframes_t, bool with_roll, bool with_flush, bool with_loop=false); void start_locate (nframes_t, bool with_roll, bool with_flush, bool with_loop=false); void force_locate (nframes_t frame, bool with_roll = false); - void set_diskstream_speed (Diskstream*, float speed); - void set_transport_speed (float speed, bool abort = false); + void set_diskstream_speed (Diskstream*, double speed); + void set_transport_speed (double speed, bool abort = false); void stop_transport (bool abort = false); void start_transport (); void realtime_stop (bool abort); diff --git a/libs/ardour/ardour/slave.h b/libs/ardour/ardour/slave.h index 07d7a4cf6a..1f2610e028 100644 --- a/libs/ardour/ardour/slave.h +++ b/libs/ardour/ardour/slave.h @@ -105,7 +105,7 @@ class Slave { * @param position - The transport position requested * @return - The return value is currently ignored (see Session::follow_slave) */ - virtual bool speed_and_position (float& speed, nframes_t& position) = 0; + virtual bool speed_and_position (double& speed, nframes_t& position) = 0; /** * reports to ARDOUR whether the Slave is currently synced to its external @@ -174,7 +174,7 @@ class MTC_Slave : public Slave, public sigc::trackable { ~MTC_Slave (); void rebind (MIDI::Port&); - bool speed_and_position (float&, nframes_t&); + bool speed_and_position (double&, nframes_t&); bool locked() const; bool ok() const; @@ -194,12 +194,12 @@ class MTC_Slave : public Slave, public sigc::trackable { nframes_t last_inbound_frame; /* when we got it; audio clocked */ MIDI::byte last_mtc_fps_byte; - float mtc_speed; + double mtc_speed; nframes_t first_mtc_frame; nframes_t first_mtc_time; static const int32_t accumulator_size = 128; - float accumulator[accumulator_size]; + double accumulator[accumulator_size]; int32_t accumulator_index; bool have_first_accumulated_speed; @@ -216,7 +216,7 @@ class MIDIClock_Slave : public Slave, public sigc::trackable { ~MIDIClock_Slave (); void rebind (MIDI::Port&); - bool speed_and_position (float&, nframes_t&); + bool speed_and_position (double&, nframes_t&); bool locked() const; bool ok() const; @@ -289,7 +289,7 @@ class ADAT_Slave : public Slave ADAT_Slave () {} ~ADAT_Slave () {} - bool speed_and_position (float& speed, nframes_t& pos) { + bool speed_and_position (double& speed, nframes_t& pos) { speed = 0; pos = 0; return false; @@ -307,7 +307,7 @@ class JACK_Slave : public Slave JACK_Slave (jack_client_t*); ~JACK_Slave (); - bool speed_and_position (float& speed, nframes_t& pos); + bool speed_and_position (double& speed, nframes_t& pos); bool starting() const { return _starting; } bool locked() const; @@ -319,7 +319,7 @@ class JACK_Slave : public Slave private: jack_client_t* jack; - float speed; + double speed; bool _starting; }; diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index 8ba1825759..dbd16e920b 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -785,8 +785,17 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_ nframes_t i = 0; // Linearly interpolate into the alt buffer - // using 40.24 fixp maths (swh) + // 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) + // phi = fixed point speed if (phi != target_phi) { phi_delta = ((int64_t)(target_phi - phi)) / nframes; } else { @@ -795,7 +804,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_ for (chan = c->begin(); chan != c->end(); ++chan) { - float fr; + Sample fractional_part; ChannelInfo* chaninfo (*chan); i = 0; @@ -803,10 +812,10 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, nframes_ for (nframes_t outsample = 0; outsample < nframes; ++outsample) { i = phase >> 24; - fr = (phase & 0xFFFFFF) / 16777216.0f; + fractional_part = (phase & 0xFFFFFF) / 16777216.0f; chaninfo->speed_buffer[outsample] = - chaninfo->current_playback_buffer[i] * (1.0f - fr) + - chaninfo->current_playback_buffer[i+1] * fr; + chaninfo->current_playback_buffer[i] * (1.0f - fractional_part) + + chaninfo->current_playback_buffer[i+1] * fractional_part; phase += phi + phi_delta; } diff --git a/libs/ardour/diskstream.cc b/libs/ardour/diskstream.cc index 334e4336af..afd5d21470 100644 --- a/libs/ardour/diskstream.cc +++ b/libs/ardour/diskstream.cc @@ -109,6 +109,7 @@ Diskstream::init (Flag f) wrap_buffer_size = 0; speed_buffer_size = 0; last_phase = 0; + // speed = 1 in 40.24 fixed point math phi = (uint64_t) (0x1000000); target_phi = phi; file_frame = 0; diff --git a/libs/ardour/jack_slave.cc b/libs/ardour/jack_slave.cc index 40729d3370..b7160489ff 100644 --- a/libs/ardour/jack_slave.cc +++ b/libs/ardour/jack_slave.cc @@ -34,7 +34,7 @@ using namespace sigc; JACK_Slave::JACK_Slave (jack_client_t* j) : jack (j) { - float x; + double x; nframes_t p; /* call this to initialize things */ speed_and_position (x, p); @@ -63,7 +63,7 @@ JACK_Slave::ok() const } bool -JACK_Slave::speed_and_position (float& sp, nframes_t& position) +JACK_Slave::speed_and_position (double& sp, nframes_t& position) { jack_position_t pos; jack_transport_state_t state; diff --git a/libs/ardour/midi_clock_slave.cc b/libs/ardour/midi_clock_slave.cc index ec5dc3e5c9..f1ec1ad924 100644 --- a/libs/ardour/midi_clock_slave.cc +++ b/libs/ardour/midi_clock_slave.cc @@ -133,8 +133,8 @@ MIDIClock_Slave::update_midi_clock (Parser& parser, nframes_t timestamp) // calculate loop error // we use session.transport_frame() instead of t1 here - // because t1 is used to calculate the transport speed, and since this - // is float, the loop will compensate for accumulating rounding errors + // because t1 is used to calculate the transport speed, + // so the loop will compensate for accumulating rounding errors e = (double(last_position) - double(session.transport_frame())) / double(session.frame_rate()); @@ -242,7 +242,7 @@ MIDIClock_Slave::stop_if_no_more_clock_events(nframes_t& pos, nframes_t now) } bool -MIDIClock_Slave::speed_and_position (float& speed, nframes_t& pos) +MIDIClock_Slave::speed_and_position (double& speed, nframes_t& pos) { if (!_started || _starting) { speed = 0.0; @@ -257,15 +257,14 @@ MIDIClock_Slave::speed_and_position (float& speed, nframes_t& pos) } // calculate speed - double speed_double = ((t1 - t0) * session.frame_rate()) / one_ppqn_in_frames; - speed = float(speed_double); + speed = ((t1 - t0) * session.frame_rate()) / one_ppqn_in_frames; // calculate position if (engine_now > last_timestamp) { // we are in between MIDI clock messages // so we interpolate position according to speed nframes_t elapsed = engine_now - last_timestamp; - pos = nframes_t (last_position + double(elapsed) * speed_double); + pos = nframes_t (last_position + double(elapsed) * speed); } else { // A new MIDI clock message has arrived this cycle pos = last_position; diff --git a/libs/ardour/mtc_slave.cc b/libs/ardour/mtc_slave.cc index 1a8cd589da..e45e760251 100644 --- a/libs/ardour/mtc_slave.cc +++ b/libs/ardour/mtc_slave.cc @@ -257,13 +257,13 @@ MTC_Slave::ok() const } bool -MTC_Slave::speed_and_position (float& speed, nframes_t& pos) +MTC_Slave::speed_and_position (double& speed, nframes_t& pos) { nframes_t now = session.engine().frame_time(); SafeTime last; nframes_t frame_rate; nframes_t elapsed; - float speed_now; + double speed_now; read_current (&last); @@ -287,7 +287,7 @@ MTC_Slave::speed_and_position (float& speed, nframes_t& pos) frame_rate = session.frame_rate(); - speed_now = (float) ((last.position - first_mtc_frame) / (double) (now - first_mtc_time)); + speed_now = (double) ((last.position - first_mtc_frame) / (double) (now - first_mtc_time)); accumulator[accumulator_index++] = speed_now; @@ -297,7 +297,7 @@ MTC_Slave::speed_and_position (float& speed, nframes_t& pos) } if (have_first_accumulated_speed) { - float total = 0; + double total = 0; for (int32_t i = 0; i < accumulator_size; ++i) { total += accumulator[i]; diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc index 08f614db07..6247a4d654 100644 --- a/libs/ardour/session_process.cc +++ b/libs/ardour/session_process.cc @@ -465,7 +465,7 @@ Session::transport_locked () const bool Session::follow_slave (nframes_t nframes, nframes_t offset) { - float slave_speed; + double slave_speed; nframes_t slave_transport_frame; nframes_t this_delta; int dir; diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc index 9163dfd5ea..0649d16848 100644 --- a/libs/ardour/session_transport.cc +++ b/libs/ardour/session_transport.cc @@ -74,14 +74,14 @@ Session::request_slave_source (SlaveSource src) } void -Session::request_transport_speed (float speed) +Session::request_transport_speed (double speed) { Event* ev = new Event (Event::SetTransportSpeed, Event::Add, Event::Immediate, 0, speed); queue_event (ev); } void -Session::request_diskstream_speed (Diskstream& ds, float speed) +Session::request_diskstream_speed (Diskstream& ds, double speed) { Event* ev = new Event (Event::SetDiskstreamSpeed, Event::Add, Event::Immediate, 0, speed); ev->set_ptr (&ds); @@ -628,7 +628,7 @@ Session::start_locate (nframes_t target_frame, bool with_roll, bool with_flush, { if (synced_to_jack()) { - float sp; + double sp; nframes_t pos; _slave->speed_and_position (sp, pos); @@ -799,16 +799,16 @@ Session::locate (nframes_t target_frame, bool with_roll, bool with_flush, bool w * @param abort */ void -Session::set_transport_speed (float speed, bool abort) +Session::set_transport_speed (double speed, bool abort) { if (_transport_speed == speed) { return; } if (speed > 0) { - speed = min (8.0f, speed); + speed = min (8.0, speed); } else if (speed < 0) { - speed = max (-8.0f, speed); + speed = max (-8.0, speed); } if (transport_rolling() && speed == 0.0) { @@ -875,11 +875,11 @@ Session::set_transport_speed (float speed, bool abort) return; } - if (speed > 0.0f && _transport_frame == current_end_frame()) { + if (speed > 0.0 && _transport_frame == current_end_frame()) { return; } - if (speed < 0.0f && _transport_frame == 0) { + if (speed < 0.0 && _transport_frame == 0) { return; } @@ -889,7 +889,7 @@ Session::set_transport_speed (float speed, bool abort) before the last stop, then we have to do extra work. */ - if ((_transport_speed && speed * _transport_speed < 0.0f) || (_last_transport_speed * speed < 0.0f) || (_last_transport_speed == 0.0f && speed < 0.0f)) { + if ((_transport_speed && speed * _transport_speed < 0.0) || (_last_transport_speed * speed < 0.0) || (_last_transport_speed == 0.0f && speed < 0.0f)) { post_transport_work = PostTransportWork (post_transport_work | PostTransportReverse); last_stop_frame = _transport_frame; } @@ -1144,7 +1144,7 @@ Session::reverse_diskstream_buffers () } void -Session::set_diskstream_speed (Diskstream* stream, float speed) +Session::set_diskstream_speed (Diskstream* stream, double speed) { if (stream->realtime_set_speed (speed, false)) { post_transport_work = PostTransportWork (post_transport_work | PostTransportSpeed); diff --git a/libs/surfaces/control_protocol/basic_ui.cc b/libs/surfaces/control_protocol/basic_ui.cc index b88e002374..a0eeda5a96 100644 --- a/libs/surfaces/control_protocol/basic_ui.cc +++ b/libs/surfaces/control_protocol/basic_ui.cc @@ -184,12 +184,12 @@ BasicUI::next_marker () } void -BasicUI::set_transport_speed (float speed) +BasicUI::set_transport_speed (double speed) { session->request_transport_speed (speed); } -float +double BasicUI::get_transport_speed () { return session->transport_speed (); diff --git a/libs/surfaces/control_protocol/control_protocol/basic_ui.h b/libs/surfaces/control_protocol/control_protocol/basic_ui.h index c8b5a2a0b6..279d1c6394 100644 --- a/libs/surfaces/control_protocol/control_protocol/basic_ui.h +++ b/libs/surfaces/control_protocol/control_protocol/basic_ui.h @@ -50,8 +50,8 @@ class BasicUI { void ffwd (); void transport_stop (); void transport_play (bool jump_back = true); - void set_transport_speed (float speed); - float get_transport_speed (); + void set_transport_speed (double speed); + double get_transport_speed (); jack_nframes_t transport_frame (); void locate (jack_nframes_t frame, bool play = false);