mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 15:25:01 +01:00
superclock_ticks_per_second: use an (inline) accessor, change value
We do not want a value as large as the previous one, which limits the time range that can be represented in 62 bits unnecessarily. The new value is 9 times smaller than the previous value, and loses only 384000 as a significant factor. This commit also switches to using an (inline) accessor for superclock_ticks_per_second, making it possible in debug/testing phases to spot early/illegal uses of the value.
This commit is contained in:
parent
641589c56a
commit
a803dd0df8
7 changed files with 40 additions and 30 deletions
|
|
@ -31,6 +31,7 @@
|
||||||
#include "pbd/ringbuffer.h"
|
#include "pbd/ringbuffer.h"
|
||||||
|
|
||||||
#include "temporal/bbt_time.h"
|
#include "temporal/bbt_time.h"
|
||||||
|
#include "temporal/superclock.h
|
||||||
|
|
||||||
#include "ardour/midi_state_tracker.h"
|
#include "ardour/midi_state_tracker.h"
|
||||||
#include "ardour/processor.h"
|
#include "ardour/processor.h"
|
||||||
|
|
@ -43,10 +44,6 @@ class StepSequencer;
|
||||||
|
|
||||||
typedef uint64_t superclock_t;
|
typedef uint64_t superclock_t;
|
||||||
|
|
||||||
static const superclock_t superclock_ticks_per_second = 508032000; // 2^10 * 3^4 * 5^3 * 7^2
|
|
||||||
inline superclock_t superclock_to_samples (superclock_t s, int sr) { return (s * sr) / superclock_ticks_per_second; }
|
|
||||||
inline superclock_t samples_to_superclock (int samples, int sr) { return (samples * superclock_ticks_per_second) / sr; }
|
|
||||||
|
|
||||||
class BeatBox : public ARDOUR::Processor {
|
class BeatBox : public ARDOUR::Processor {
|
||||||
public:
|
public:
|
||||||
BeatBox (ARDOUR::Session& s);
|
BeatBox (ARDOUR::Session& s);
|
||||||
|
|
|
||||||
|
|
@ -561,7 +561,7 @@ LuaBindings::common (lua_State* L)
|
||||||
|
|
||||||
.beginNamespace ("Temporal")
|
.beginNamespace ("Temporal")
|
||||||
|
|
||||||
.addConst ("superclock_ticks_per_second", Temporal::superclock_ticks_per_second)
|
.addFunction ("superclock_ticks_per_second", Temporal::superclock_ticks_per_second)
|
||||||
.addConst ("ticks_per_beat", Temporal::ticks_per_beat)
|
.addConst ("ticks_per_beat", Temporal::ticks_per_beat)
|
||||||
|
|
||||||
.beginClass <Temporal::ratio_t> ("ratio")
|
.beginClass <Temporal::ratio_t> ("ratio")
|
||||||
|
|
|
||||||
|
|
@ -341,15 +341,6 @@ Session::Session (AudioEngine &eng,
|
||||||
g_atomic_int_set (&_seek_counter, 0);
|
g_atomic_int_set (&_seek_counter, 0);
|
||||||
g_atomic_int_set (&_butler_seek_counter, 0);
|
g_atomic_int_set (&_butler_seek_counter, 0);
|
||||||
|
|
||||||
/* create a new "default" tempo map. This maybe reset/overwritten by
|
|
||||||
* the session if it already exists during ::set_state()
|
|
||||||
*/
|
|
||||||
|
|
||||||
TempoMap::SharedPtr tmcopy (TempoMap::write_copy());
|
|
||||||
/* this discards the copy that was made, and installs the new default tempo map */
|
|
||||||
tmcopy.reset (new TempoMap (Tempo (120, 4), Meter (4, 4)));
|
|
||||||
TempoMap::update (tmcopy);
|
|
||||||
|
|
||||||
created_with = string_compose ("%1 %2", PROGRAM_NAME, revision);
|
created_with = string_compose ("%1 %2", PROGRAM_NAME, revision);
|
||||||
|
|
||||||
pthread_mutex_init (&_rt_emit_mutex, 0);
|
pthread_mutex_init (&_rt_emit_mutex, 0);
|
||||||
|
|
|
||||||
|
|
@ -19,13 +19,22 @@
|
||||||
#include "temporal/superclock.h"
|
#include "temporal/superclock.h"
|
||||||
|
|
||||||
#ifndef COMPILER_MSVC
|
#ifndef COMPILER_MSVC
|
||||||
Temporal::superclock_t Temporal::superclock_ticks_per_second = 508032000; // 2^10 * 3^4 * 5^3 * 7^2
|
Temporal::superclock_t Temporal::_superclock_ticks_per_second = 56448000; /* 2^10 * 3^2 * 5^3 * 7^2 */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int Temporal::most_recent_engine_sample_rate = 48000; /* have to pick something as a default */
|
int Temporal::most_recent_engine_sample_rate = 48000; /* have to pick something as a default */
|
||||||
|
|
||||||
|
bool Temporal::scts_set = false;
|
||||||
|
|
||||||
void
|
void
|
||||||
Temporal::set_sample_rate (int sr)
|
Temporal::set_sample_rate (int sr)
|
||||||
{
|
{
|
||||||
most_recent_engine_sample_rate = sr;
|
most_recent_engine_sample_rate = sr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Temporal::set_superclock_ticks_per_second (Temporal::superclock_t sc)
|
||||||
|
{
|
||||||
|
_superclock_ticks_per_second = sc;
|
||||||
|
scts_set = true;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -534,10 +534,10 @@ TempoPoint::quarters_at_superclock (superclock_t sc) const
|
||||||
superclock_t sc_delta = sc - _sclock;
|
superclock_t sc_delta = sc - _sclock;
|
||||||
|
|
||||||
/* convert sc into superbeats, given that sc represents some number of seconds */
|
/* convert sc into superbeats, given that sc represents some number of seconds */
|
||||||
const superclock_t whole_seconds = sc_delta / superclock_ticks_per_second;
|
const superclock_t whole_seconds = sc_delta / superclock_ticks_per_second();
|
||||||
const superclock_t remainder = sc_delta - (whole_seconds * superclock_ticks_per_second);
|
const superclock_t remainder = sc_delta - (whole_seconds * superclock_ticks_per_second());
|
||||||
|
|
||||||
const int64_t supernotes = ((_super_note_type_per_second) * whole_seconds) + int_div_round (superclock_t ((_super_note_type_per_second) * remainder), superclock_ticks_per_second);
|
const int64_t supernotes = ((_super_note_type_per_second) * whole_seconds) + int_div_round (superclock_t ((_super_note_type_per_second) * remainder), superclock_ticks_per_second());
|
||||||
/* multiply after divide to reduce overflow risk */
|
/* multiply after divide to reduce overflow risk */
|
||||||
const int64_t superbeats = int_div_round (supernotes, (superclock_t) _note_type) * 4;
|
const int64_t superbeats = int_div_round (supernotes, (superclock_t) _note_type) * 4;
|
||||||
|
|
||||||
|
|
@ -2186,7 +2186,7 @@ std::operator<<(std::ostream& str, TempoMetric const & tm)
|
||||||
std::ostream&
|
std::ostream&
|
||||||
std::operator<<(std::ostream& str, TempoMapPoint const & tmp)
|
std::operator<<(std::ostream& str, TempoMapPoint const & tmp)
|
||||||
{
|
{
|
||||||
str << '@' << std::setw (12) << tmp.sclock() << ' ' << tmp.sclock() / (double) superclock_ticks_per_second
|
str << '@' << std::setw (12) << tmp.sclock() << ' ' << tmp.sclock() / (double) superclock_ticks_per_second()
|
||||||
<< " secs " << tmp.sample (TEMPORAL_SAMPLE_RATE) << " samples"
|
<< " secs " << tmp.sample (TEMPORAL_SAMPLE_RATE) << " samples"
|
||||||
<< (tmp.is_explicit_tempo() ? " EXP-T" : " imp-t")
|
<< (tmp.is_explicit_tempo() ? " EXP-T" : " imp-t")
|
||||||
<< (tmp.is_explicit_meter() ? " EXP-M" : " imp-m")
|
<< (tmp.is_explicit_meter() ? " EXP-M" : " imp-m")
|
||||||
|
|
@ -2362,7 +2362,7 @@ TempoMap::get_state ()
|
||||||
XMLNode* node = new XMLNode (X_("TempoMap"));
|
XMLNode* node = new XMLNode (X_("TempoMap"));
|
||||||
|
|
||||||
node->set_property (X_("time-domain"), _time_domain);
|
node->set_property (X_("time-domain"), _time_domain);
|
||||||
node->set_property (X_("superclocks-per-second"), superclock_ticks_per_second);
|
node->set_property (X_("superclocks-per-second"), superclock_ticks_per_second());
|
||||||
|
|
||||||
XMLNode* children;
|
XMLNode* children;
|
||||||
|
|
||||||
|
|
@ -2397,7 +2397,9 @@ TempoMap::set_state (XMLNode const & node, int version)
|
||||||
/* global map properties */
|
/* global map properties */
|
||||||
|
|
||||||
/* XXX this should probably be at the global level in the session file because it affects a lot more than just the tempo map, potentially */
|
/* XXX this should probably be at the global level in the session file because it affects a lot more than just the tempo map, potentially */
|
||||||
node.get_property (X_("superclocks-per-second"), superclock_ticks_per_second);
|
superclock_t sc;
|
||||||
|
node.get_property (X_("superclocks-per-second"), sc);
|
||||||
|
set_superclock_ticks_per_second (sc);
|
||||||
|
|
||||||
node.get_property (X_("time-domain"), _time_domain);
|
node.get_property (X_("time-domain"), _time_domain);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,9 @@
|
||||||
#ifndef __ardour_superclock_h__
|
#ifndef __ardour_superclock_h__
|
||||||
#define __ardour_superclock_h__
|
#define __ardour_superclock_h__
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <csignal>
|
||||||
|
|
||||||
#include "pbd/integer_division.h"
|
#include "pbd/integer_division.h"
|
||||||
|
|
||||||
|
|
@ -30,17 +32,26 @@ namespace Temporal {
|
||||||
typedef int64_t superclock_t;
|
typedef int64_t superclock_t;
|
||||||
|
|
||||||
#ifndef COMPILER_MSVC
|
#ifndef COMPILER_MSVC
|
||||||
extern superclock_t superclock_ticks_per_second;
|
extern superclock_t _superclock_ticks_per_second;
|
||||||
#else
|
#else
|
||||||
static superclock_t superclock_ticks_per_second = 508032000; // 2^10 * 3^4 * 5^3 * 7^2
|
static superclock_t _superclock_ticks_per_second = 56448000; /* 2^10 * 3^2 * 5^3 * 7^2 */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline superclock_t superclock_to_samples (superclock_t s, int sr) { return int_div_round (s * sr, superclock_ticks_per_second); }
|
extern bool scts_set;
|
||||||
static inline superclock_t samples_to_superclock (int64_t samples, int sr) { return int_div_round (samples * superclock_ticks_per_second, superclock_t (sr)); }
|
|
||||||
|
#ifdef DEBUG_EARLY_SCTS_USE
|
||||||
|
static inline superclock_t superclock_ticks_per_second() { if (!scts_set) { raise (SIGUSR2); } return _superclock_ticks_per_second; }
|
||||||
|
#else
|
||||||
|
static inline superclock_t superclock_ticks_per_second() { return _superclock_ticks_per_second; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline superclock_t superclock_to_samples (superclock_t s, int sr) { return int_div_round (s * sr, superclock_ticks_per_second()); }
|
||||||
|
static inline superclock_t samples_to_superclock (int64_t samples, int sr) { return int_div_round (samples * superclock_ticks_per_second(), superclock_t (sr)); }
|
||||||
|
|
||||||
extern int most_recent_engine_sample_rate;
|
extern int most_recent_engine_sample_rate;
|
||||||
|
|
||||||
LIBTEMPORAL_API void set_sample_rate (int sr);
|
LIBTEMPORAL_API void set_sample_rate (int sr);
|
||||||
|
LIBTEMPORAL_API void set_superclock_ticks_per_second (superclock_t sc);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -210,9 +210,9 @@ class LIBTEMPORAL_API Tempo : public Rampable {
|
||||||
/* these five methods should only be used to show and collect information to the user (for whom
|
/* these five methods should only be used to show and collect information to the user (for whom
|
||||||
* bpm as a floating point number is the obvious representation)
|
* bpm as a floating point number is the obvious representation)
|
||||||
*/
|
*/
|
||||||
double note_types_per_minute () const { return (superclock_ticks_per_second * 60.0) / _superclocks_per_note_type; }
|
double note_types_per_minute () const { return (superclock_ticks_per_second() * 60.0) / _superclocks_per_note_type; }
|
||||||
double end_note_types_per_minute () const { return (superclock_ticks_per_second * 60.0) / _end_superclocks_per_note_type; }
|
double end_note_types_per_minute () const { return (superclock_ticks_per_second() * 60.0) / _end_superclocks_per_note_type; }
|
||||||
double quarter_notes_per_minute() const { return (superclock_ticks_per_second * 60.0 * 4.0) / (_note_type * _superclocks_per_note_type); }
|
double quarter_notes_per_minute() const { return (superclock_ticks_per_second() * 60.0 * 4.0) / (_note_type * _superclocks_per_note_type); }
|
||||||
double samples_per_note_type(samplecnt_t sr) const { return superclock_to_samples (superclocks_per_note_type (), sr); }
|
double samples_per_note_type(samplecnt_t sr) const { return superclock_to_samples (superclocks_per_note_type (), sr); }
|
||||||
double samples_per_quarter_note(samplecnt_t sr) const { return superclock_to_samples (superclocks_per_quarter_note(), sr); }
|
double samples_per_quarter_note(samplecnt_t sr) const { return superclock_to_samples (superclocks_per_quarter_note(), sr); }
|
||||||
void set_note_types_per_minute (double npm) { _superclocks_per_note_type = double_npm_to_scpn (npm); }
|
void set_note_types_per_minute (double npm) { _superclocks_per_note_type = double_npm_to_scpn (npm); }
|
||||||
|
|
@ -301,7 +301,7 @@ class LIBTEMPORAL_API Tempo : public Rampable {
|
||||||
Type _type;
|
Type _type;
|
||||||
|
|
||||||
static inline uint64_t double_npm_to_snps (double npm) { return (uint64_t) llround (npm * big_numerator / 60); }
|
static inline uint64_t double_npm_to_snps (double npm) { return (uint64_t) llround (npm * big_numerator / 60); }
|
||||||
static inline superclock_t double_npm_to_scpn (double npm) { return (superclock_t) llround ((60./npm) * superclock_ticks_per_second); }
|
static inline superclock_t double_npm_to_scpn (double npm) { return (superclock_t) llround ((60./npm) * superclock_ticks_per_second()); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void set_ramped (bool yn);
|
void set_ramped (bool yn);
|
||||||
|
|
@ -416,7 +416,7 @@ class /*LIBTEMPORAL_API*/ TempoPoint : public Tempo, public tempo_hook, public v
|
||||||
*/
|
*/
|
||||||
|
|
||||||
LIBTEMPORAL_API double note_types_per_minute_at_DOUBLE (timepos_t const & pos) const {
|
LIBTEMPORAL_API double note_types_per_minute_at_DOUBLE (timepos_t const & pos) const {
|
||||||
return (superclock_ticks_per_second * 60.0) / superclocks_per_note_type_at (pos);
|
return (superclock_ticks_per_second() * 60.0) / superclocks_per_note_type_at (pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBTEMPORAL_API double omega() const { return _omega; }
|
LIBTEMPORAL_API double omega() const { return _omega; }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue