13
0
Commit Graph

416 Commits

Author SHA1 Message Date
0ff2c746f7 prevent crash if tempo or meter are dragged back to zero 2022-10-25 12:52:30 -06:00
3efb488629 when moving tempo markers, do nothing unless the marker is moved at least 1 beat
Since tempo markers are always on-beat, this enforces a minumum distance of 1 beat while remaining on-beat.
2022-10-25 11:10:36 -06:00
b5d7754a26
Fix MIDI Clock generator
MIDI clock start at the next beat (round_up_to_beat), so
here we have to round the current tick, rather than fall
back to a tick that is not yet complete, as 14da117bc8 does.

Reproduced with the Session from #9027
Start loop at bar 40 with MClk generator enabled.

```
#3  in __GI___assert_fail (assertion=0x7fedd86c4fd5 "clk_pos >= pos", file=0x7fedd86c38b7 "../libs/temporal/tempo.cc", line=3336, function=0x7fedd86c4f60 "void Temporal::TempoMap::midi_clock_beat_at_or_after(Temporal::samplepos_t, Temporal::samplepos_t&, uint32_t&) const") at assert.c:101
#4  in Temporal::TempoMap::midi_clock_beat_at_or_after(long, long&, unsigned int&) const (this= 0x560187e92c00, pos=20691033, clk_pos=@0x7fedc02178b8: 20691032, clk_beat=@0x7fedc02178c4: 11472) at ../libs/temporal/tempo.cc:3336
#5  in ARDOUR::MidiClockTicker::tick(long, long, unsigned int, long) (this=0x56018eed6db0, start_sample=20691033, end_sample=20692057, n_samples=1024, pre_roll=0) at ../libs/ardour/ticker.cc:170
#6  in ARDOUR::Session::send_mclk_for_cycle(long, long, unsigned int, long) (this=0x56018a216340, start_sample=20691033, end_sample=20692057, n_samples=1024, pre_roll=0) at ../libs/ardour/session.cc:7495
#7  in ARDOUR::AudioEngine::process_callback(unsigned int) (this=0x5601881a4f20, nframes=1024) at ../libs/ardour/audioengine.cc:563
```
2022-10-24 06:18:30 +02:00
30ec62a953 This is clearly broken
Partially revert previous commit. Otherwise snap to bar/beat
clocks-displays display rounded down X|Y|1919 instead of X|Y+1|0
2022-10-22 03:09:32 +02:00
14da117bc8 Add explicit round/floor integer multiply/divide
This fixes various rounding issues. Notably superclock to sample
conversion must always round down when playing forward.

`::process (start, end, speed = 1)` uses exclusive end.
Processing begins at `start` and end ends just before `end`.
Next cycle will begin with the current end.

One example where this failed:
 - New session at 48kHz
 - Change tempo to 130 BPM
 - Enable snap to 1/8 note
 - Snap playhead to 1|3|0
 - Enable Metronome
 - Play

`assert (superclock_to_samples ((*i).sclock(), sample_rate()) < end);`

end = 177231 samples == superclock 1042118280
A grid point is found at superclock 1042116920 (that is < 1042118280).
However converting it back to samples rounded it to sample 177231 == end,
while actual location is 1360 super-clock ticks before end.

The metronome click has to be started this cycle, since the same
position will not be found at the beginning of the next cycle, with
start = 177232.

Similarly a samplecnt_t t, converted to music-time and back must not be
later than the given sample.

```
timepos_t tsc (t);
assert (timepos_t::from_ticks (tsc.ticks ()).samples () <= t);
```

IOW. When playing forward, all super-clock time between 1|1|0 and 1|1|1
should round down to 1|1|0. "We have not yet reached the first tick".
2022-10-22 02:10:05 +02:00
23010a910d
Be liberal about what to accept
This addressee a bug where ardour 6 was able to write negative
duration `length="-1"` `length-beats="-3.3650500597559585e-05"`

Ideally timecnt_t::string_to should check for invalid,
negative, duration. But this also catches a more generic case.

```
exception at str.substr (1)
#3 Temporal::timepos_t::string_to (this=0x7fffffff7bb0, str="") at libs/temporal/timeline.cc:904
#4 Temporal::timecnt_t::string_to (this=0x7fffffff7ba0, str="-2") at libs/temporal/timeline.cc:294
#5 PBD::string_to<Temporal::timecnt_t> (str="-2") at libs/ardour/ardour/types_convert.h:131
```
2022-10-16 22:30:35 +02:00
8240875379
Prevent overflow for huge time values (fix 99h clock limit @96kHz)
The default clock-limit is 99:59:59:00, just under 360000 seconds
(see ARDOUR_UI::parameter_changed, clock-display-limit).

AudioClock calculates this limit pos as
`timepos_t (limit_sec * _session->sample_rate())`

This caused an overflow leading to a negative value:
```
   timepos_t (359999 * 96000)
   samples_to_superclock (359999 * 96000, 96000)
   int_div_round (359999 * 96000 * 282240000, 96000)
```

Ideally this will be optimized, here the sample-rate cancels out,
so we could use a c'tor usin seconds.
In other cases we could cache the pre-calculated sc_per_sample:
`superclock_ticks_per_second() / superclock_t (sr)` which is an
integer for all commonly used sample-rates.
2022-10-16 18:46:36 +02:00
a7a8783bb4 increase superclock_ticks_per_second to provide integer handling for NTSC (following Facebook "flicks") 2022-10-13 18:05:49 -06:00
88396347e6 increment/decrement name changes ... out with old in with the new (libs 2022-10-07 17:30:35 -06:00
27d5843f7a temporal: replace Range::extent() with Range::length()
We want to encourage/enforce the use of exclusive-end conventions
everywhere in the libraries that make up ardour
2022-10-07 16:16:14 -06:00
c4d737dd87 temporal: provide ::decrement_by_domain() methods for time{pos,cnt}_t
audio time nominally uses superclocks as its canonical unit. However
many things at a higher level only understand samples. If we
increment or decrement a superclock value by 1, the vast majority of
the time we will still get the same sample value after
conversion. Thus to correctly alter an audio time by an amount
that will manifest as 1 sample's difference, we have to use
samples_to_superclock(1)
2022-10-07 16:16:14 -06:00
617a517a60 temporal: add timecnt_t::increment() and Range::extent() (length+1) 2022-10-07 16:16:14 -06:00
7a0da94ba3 fix RangeTest to account for Range now using exclusive ends, not inclusive 2022-10-05 17:30:45 -06:00
04647d5ae5 More unit-tests updates
* move RangeTest to libtemporal tests
* remove BeatsTest,  already converted from
  Evoral to temporal/BeatTest.cc
2022-10-01 16:57:12 +02:00
2d6e5d4638 Fix building unit-tests on macOS 2022-09-28 23:05:56 +02:00
8b84a0c36f
Add explicit BBT_Offset print function (like timeline.h has) 2022-09-28 18:46:58 +02:00
c8ddfd5637 Fix C++ memory layout for the TempoMap
Usually C++ class instance has the same mem address as its first parent.
LuaBridge uses this to for derived classes. A TemopPoint instance has
the same address as its parent Tempo. However due to virtual inheritance
this was not the case due to a lack of virtual d'tor.

Now the following Lua code works correctly
```
tm = Temporal.TempoMap.read()
tp = Temporal.timepos_t (0)
print (tm:tempo_at(tp):note_type())
```

Previously the last line failed calling Tempo::note_type()
on a TempoPoint instance, due to memory offset e.g.
TempoPoint: 0x600000ff90e0 Tempo: 0x600000ff90e8
2022-09-28 04:12:11 +02:00
28d11df6f6
operator% is a const operation 2022-09-27 13:04:49 +02:00
36aa661a1d
Add explicit BBT/Beat print functions (like timeline.h has)
This is in preparation for Lua bindings to allow print()ing
the value. We cannot use PBD::to_string() here.
2022-09-27 02:23:11 +02:00
f79f3ee301
Remove unused API 2022-09-27 00:40:35 +02:00
0b0f49412d remove some debug output 2022-09-21 09:13:26 -06:00
025dfa6062 tempo map: fix logic error in ::reset_starting_at() relating to tempo/bbt markers 2022-08-17 16:40:14 -06:00
luz paz
47c525315d Fix various typos
Found via `codespell -q 3 -S *.po,./.git,./share/patchfiles,./libs,./msvc_extra_headers,./share/web_surfaces,*.patch  -L ba,buss,busses,discreet,doubleclick,hsi,ontop,ro,scrollin,seh,siz,sord,sur,te,trough,ue`
2022-08-03 12:10:01 -06:00
cc6a437faf temporal: fix a bug in BBT_Time::round_up_to_bar()
Also remove Meter:: versions of related methods, because they are not necessary. We
only need metrical information for operations like ::round_to_bar()
2022-08-03 10:59:29 -06:00
2de84c97d0
Fix Temporal::Range::squish reduced to samples
Loop Location start="a1665678660" end="b145920"
Loop-end (at 122BPM) is a2109859636
at 48kHz this is sample 1794098.32

Now play the loop and play sample 1794098 = a2109859248
Range::squish start: a1665678660 end: a2109859636 squish: a2109859248

squish() does nothing, since there are still 388 superclock-ticks
until the end of the loop.

However, DiskReader::get_midi_playback convertes the value back
to samples(), this leads to effective_start == loop_end;
resulting in an endless loop.

Thanks to MikeLupe to provide a session to reproduce this issue.
2022-07-15 19:54:21 +02:00
0d70be3a05 miscellaneous fixes for warnings from -Wconversion 2022-07-04 22:01:48 -06:00
1f6abbb756
Comment-out unused timepos_t modulo operator which is not implemented 2022-06-30 01:47:42 +02:00
3bcf75a35a
Remove Range::squish debug information, used fixed modulo operation 2022-06-30 01:07:32 +02:00
2c1f36201c
Fix timecnt_t modulo operation when mixing time-domains 2022-06-30 01:07:32 +02:00
ee350362d3
Debug loop range squishing
When the loop-range is defined in BeatTime, the disk-reader encounters
rounding issues due to time-domain mismatches.

With a simple session fixed BPM at 120,  48kHz.
looping 1 bar exactly 2 sec at the start of the session:
```
 Range::squish start: b0 end: b7680 squish: a113554560
 Range::squish using modulo:       b45 = a661500
 Range::squish using modulo in TD: a5760
 Range::squish using earlier():    a658560
```
The correct answer is a113554560 - 2 * 56448000 [SC/sec] = a658560

Calculating the modulo iteratively is not great, however usually
only one iteration is required.
2022-06-28 03:01:41 +02:00
046cdf1295 fix unused variable warning by removing it. 2022-06-22 13:31:08 -06:00
e2ef135161 remove unused warning 2022-06-21 17:30:59 -06:00
f679da4e1e simplify implementation of Beats::operator%= (Beats) 2022-06-21 14:46:20 -06:00
5d81535588 remember to use muldiv() when doing a*b/c; also no need to call to_ticks(), just use _ticks 2022-06-21 14:46:20 -06:00
1be136adbd allow construction of Beats with a beat count that exceeds INT32_MAX 2022-06-21 14:46:20 -06:00
d6d9792dcb fix construction of Beats from an int64_t that exceeds INT32_MAX 2022-06-21 14:46:20 -06:00
696e05c3e5 convert internal implementation of Temporal::Beats to just use a 64 bit tick value
This expands significantly the maximum number of Beats that can be represented, which is a good
thing in itself. It slightly speeds up some Beats::operator methods, and slightly slows down
::get_beats() and ::get_ticks().

One minor change in an API user was required, and several tweaks to the unit tests due to the
macros being used by cppunit creating possible type confusion.

Units test pass
2022-06-21 12:26:54 -06:00
4dbdaf7fe9 fix possible negative return from TempoPoint::quarters_at_superclock() 2022-06-21 11:39:10 -06:00
f60b35483d temporal: fix major conceptual error managing Point reference to owner map
When TempoMap::copy_points() is called, the new points are intended to belong
to the (nascent) new map. But the copy constructor for the points leaves the
_map member of a Point unchanged, and so the new points reference the old
map (forever!). ::copy_points() must reset each Point to reference the new map.

Refactored the object that has the _map member, so that we could limit access
to its ::set_map() method to TempoMap.
2022-06-16 22:11:56 -06:00
32096afc90 temporal: remve debug output 2022-06-16 10:36:02 -06:00
2cfc013b0c temporal: fix loading tempo map from XML
We need to clear out all 4 intrusive lists before we start, not just the 3 typed ones
2022-06-16 10:18:37 -06:00
477b136e97 temporal: if requested via -Dtemporalmap, dump tempo map after any update 2022-06-16 10:18:37 -06:00
637971a7df
Fix Beat duration calculation
bbt_duration_at() calls bbtwalk_to_quarters() which already
subtracts the origin's position. Previously `pos` was subtracted twice.
2022-06-04 04:33:48 +02:00
88a035b000 temporal: changes in API to better support BBT markers 2022-06-03 13:19:56 -06:00
531db75a27 temporal: when dragging tempo/meter, move in points list as well
We spliced the point back into the tempo and meter lists correctly, but failed
to do the same thing for the same object's position in the points list.
2022-06-03 10:53:01 -06:00
7dadb1407b temporal: when copying points between TempoMaps do not double-count MusicTimePoints
They were counted as tempos, and meters, and bartimes individually, which
generated new tempo and meter points in the map, which is incorrect.
2022-06-03 10:53:01 -06:00
1b904285be temporal: improve utility of TempoMap::dump() output 2022-06-03 10:53:01 -06:00
2d24bcdf4a temporal: add operator== and operator!= for ratio_t 2022-05-31 12:36:54 -06:00
192b2fd839 temporal: fixes for TempoMap::move_meter() 2022-05-30 21:14:57 -06:00
710cca9ccf change logic for memory management when adding tempo,meter,bartime points
Because a bartime point IS-A tempo point and IS-A meter point, we cannot just delete the tempo
point passed into core_add_tempo() if the new point replaces an existing one. Ditto for meter.

So, leave that logic up to the caller
2022-05-29 15:01:54 -06:00