12 static_assert (MIN_BPM *
TRANSPORT_PPQN / (60.0 * MAX_SAMPLERATE) > 1.0);
14 static_assert (4503599627370496.0 / (MAX_BPM *
TRANSPORT_PPQN) / (60 * 24) > 363.95);
18constexpr double INVERSE_SEMIQUAVER = 1.0 / SEMIQUAVER_TICKS;
20TickSignature::TickSignature() :
25 TickSignature (other.bpm(), other.beats_per_bar(), other.beat_unit())
28TickSignature::TickSignature (
double bpm,
uint8 beats_per_bar,
uint8 beat_unit)
37 const double bpm = src.bpm();
38 const uint8 beats_per_bar = src.beats_per_bar();
39 const uint8 beat_unit = src.beat_unit();
49 assert_return (samplerate >= MIN_SAMPLERATE && samplerate <= MAX_SAMPLERATE);
54 sample_per_ticks_ = ticks_per_minute_d > 0 ? (60.0 *
samplerate_) / ticks_per_minute_d : 0;
65 ticks_per_minute_ = ticks_per_minute_d;
66 ticks_per_second_ = ticks_per_minute_d * (1.0 / 60.0);
67 inv_ticks_per_second_ =
ISLIKELY (
bpm_ > 0) ? 1.0 / ticks_per_second_ : 0.0;
69 sample_per_ticks_ = ticks_per_minute_d > 0 ? (60.0 *
samplerate_) / ticks_per_minute_d : 0;
78 t.
minutes = divmod (tick - offset_, ticks_per_minute_, &minutereminder);
79 t.
seconds = minutereminder * inv_ticks_per_second_;
88 tick +=
time.minutes * ticks_per_minute_;
89 tick +=
time.seconds * ticks_per_second_;
99 const auto old_offset_ = offset_;
102 if (beat_unit == 1 || beat_unit == 2 || beat_unit == 4 || beat_unit == 8 || beat_unit == 16)
104 const int semiquavers_per_beat = 16 /
beat_unit_;
105 beat_ticks_ = SEMIQUAVER_TICKS * semiquavers_per_beat;
116 b.
bar = divmod (tick - offset_,
int64 (bar_ticks_), &bar_reminder);
118 b.
beat = divmod (
int32 (bar_reminder), beat_ticks_, &beat_reminder);
119 b.
semiquaver = beat_reminder * INVERSE_SEMIQUAVER;
127 int64 tick = offset_;
128 tick += beat.
bar *
int64 (bar_ticks_);
138 return (tick - offset_) / bar_ticks_;
145 int64 tick = offset_;
146 tick += bar *
int64 (bar_ticks_);
157 return __builtin_popcountl (bits);
158 return __builtin_popcountll (bits);
181 case SpeakerArrangement::NONE:
return "-";
190 case SpeakerArrangement::STEREO:
return "Stereo";
191 case SpeakerArrangement::STEREO_21:
return "Stereo-2.1";
192 case SpeakerArrangement::STEREO_30:
return "Stereo-3.0";
193 case SpeakerArrangement::STEREO_31:
return "Stereo-3.1";
194 case SpeakerArrangement::SURROUND_50:
return "Surround-5.0";
195 case SpeakerArrangement::SURROUND_51:
return "Surround-5.1";
197 case SpeakerArrangement::FRONT_LEFT_OF_CENTER:
return "FLC";
198 case SpeakerArrangement::FRONT_RIGHT_OF_CENTER:
return "FRC";
199 case SpeakerArrangement::BACK_CENTER:
return "BC";
200 case SpeakerArrangement::SIDE_LEFT:
return "SL";
201 case SpeakerArrangement::SIDE_RIGHT:
return "SR";
202 case SpeakerArrangement::TOP_CENTER:
return "TC";
203 case SpeakerArrangement::TOP_FRONT_LEFT:
return "TFL";
204 case SpeakerArrangement::TOP_FRONT_CENTER:
return "TFC";
205 case SpeakerArrangement::TOP_FRONT_RIGHT:
return "TFR";
206 case SpeakerArrangement::TOP_BACK_LEFT:
return "TBL";
207 case SpeakerArrangement::TOP_BACK_CENTER:
return "TBC";
208 case SpeakerArrangement::TOP_BACK_RIGHT:
return "TBR";
209 case SpeakerArrangement::SIDE_SURROUND_50:
return "Side-Surround-5.0";
210 case SpeakerArrangement::SIDE_SURROUND_51:
return "Side-Surround-5.1";
219 const bool isaux = speaker_arrangement_is_aux (spa);
230 samplerate (sample_rate), nyquist (sample_rate / 2),
231 isamplerate (1.0 / sample_rate), inyquist (2.0 / sample_rate),
232 speaker_arrangement (speakerarrangement)
234 tick_sig.set_samplerate (sample_rate);
235 assert_return (sample_rate >= MIN_SAMPLERATE && sample_rate <= MAX_SAMPLERATE);
240AudioTransport::running (
bool r)
254AudioTransport::set_tick (
int64 newtick)
256 current_tick = newtick;
257 current_tick_d = current_tick;
262AudioTransport::tempo (
double newbpm,
uint8 numerator,
uint8 denominator)
273 tempo (ticksignature.bpm(), ticksignature.beats_per_bar(), ticksignature.beat_unit());
277AudioTransport::advance (
uint nsamples)
282 current_tick_d += nsamples * tick_sig.ticks_per_sample();
283 current_tick = current_tick_d;
289AudioTransport::update_current ()
295 const auto old_next = next_bar_tick;
297 next_bar_tick = current_bar_tick + tick_sig.bar_ticks();
303 if (old_next != next_bar_tick &&
false)
304 printerr (
"%3d.%2d.%5.2f %02d:%06.3f frame=%d tick=%d next=%d bpm=%d sig=%d/%d ppqn=%d pps=%f rate=%d\n",
308 current_bpm, tick_sig.beats_per_bar(), tick_sig.beat_unit(),
325 static_assert (SEMIQUAVER_TICKS ==
int32 (SEMIQUAVER_TICKS));
329 const int64 max_semiquavers_per_beat = 16;
330 int64 max_beat_ticks = SEMIQUAVER_TICKS * max_semiquavers_per_beat;
331 int64 max_bar_ticks = max_beat_ticks * 64 / 1;
332 TASSERT (max_bar_ticks < 2147483648);
334 int64 testtick = 170000000000077;
337 int32 hminutes, hours = divmod (tt.
minutes, 60, &hminutes);
339 TCMP (ts.bar_from_tick (testtick), ==, tb.
bar);
341 printerr (
"%03d.%02d.%06.3f %02d:%02d:%06.3f tick=%d\n",
343 hours, hminutes, tt.
seconds, testtick);
344 TCMP (ts.beat_to_tick (tb), ==, testtick);
345 TCMP (ts.time_to_tick (tt), ==, testtick);
348 TCMP (ts.bar_to_tick (tb.
bar), ==, ts.beat_to_tick (tb));
#define assert_return(expr,...)
Return from the current function if expr is unmet and issue an assertion warning.
#define return_unless(cond,...)
Return silently if cond does not evaluate to true with return value ...
#define CLAMP(v, mi, ma)
Yield v clamped to [mi … ma].
#define if_constexpr
Indentation helper for editors that cannot (yet) decipher if constexpr
#define TEST_INTEGRITY(FUNC)
Register func as an integrity test.
#define ISLIKELY(cond)
Hint to the compiler to optimize for cond == TRUE.
The Anklang C++ API namespace.
int32_t int32
A 32-bit signed integer.
@ FRONT_LEFT
Stereo Left (FL)
@ FRONT_RIGHT
Stereo Right (FR)
@ AUX
Flag for side chain uses.
@ LOW_FREQUENCY
Low Frequency Effects (LFE)
uint8_t uint8
An 8-bit unsigned integer.
int64_t int64
A 64-bit unsigned integer, use PRI*64 in format strings.
constexpr const int64 TRANSPORT_PPQN
Maximum number of sample frames to calculate in Processor::render().
uint32_t uint
Provide 'uint' as convenience type.
int32 current_bar
Bar of current_tick position.
double current_semiquaver
The sixteenth with fraction within beat.
const uint samplerate
Sample rate (mixing frequency) in Hz used for rendering.
double current_seconds
Seconds of current_tick position.
int64 current_frame
Number of sample frames processed since playback start.
int8 current_beat
Beat within bar of current_tick position.
float current_bpm
Running tempo in beats per minute.
int32 current_minutes
Minute of current_tick position.
Musical time signature and tick conversions.
double seconds
Seconds with fraction after the minute.
Beat beat_from_tick(int64 tick) const
Calculate beat from tick, requires set_signature().
int64 bar_to_tick(int32 bar) const
Calculate tick from bar, requires set_signature().
double bpm_
Current tempo in beats per minute.
void set_samplerate(uint samplerate)
Assign sample rate.
uint8 beats_per_bar_
Upper numeral (numerator), how many beats constitute a bar.
uint8 beat_unit_
Lower numeral (denominator in [1 2 4 8 16]), note value that represents one beat.
double inv_samplerate_
Precalculated 1.0 / samplerate.
int32 minutes
Tick position in minutes.
int32 samplerate_
Sample rate (mixing frequency) in Hz.
int64 time_to_tick(const Time &time) const
Calculate tick from time, requires set_bpm().
int32 bar
Bar of tick position.
int64 beat_to_tick(const Beat &beat) const
Calculate tick from beat, requires set_signature().
double semiquaver
The sixteenth with fraction within beat.
Time time_from_tick(int64 tick) const
Calculate time from tick, requires set_bpm().
bool set_signature(uint8 beats_per_bar, uint8 beat_unit)
Assign time signature and offset for the signature to take effect.
int32 bar_from_tick(int64 tick) const
Calculate bar from tick, requires set_signature().
void set_bpm(double bpm)
Assign tempo in beats per minute.
int8 beat
Beat within bar of tick position.
#define TASSERT(cond)
Unconditional test assertion, enters breakpoint if not fullfilled.
#define TCMP(a, cmp, b)
Compare a and b according to operator cmp, verbose on failiure.