temporal: change API for TempoMap::stretch_tempo()

This will likely be modified because it is actually impossible to do
what this code is attempting to do.
This commit is contained in:
Paul Davis 2023-04-07 12:55:37 -06:00
parent 57398b1e5e
commit e9f71824a1
2 changed files with 104 additions and 1 deletions

View File

@ -3180,6 +3180,103 @@ TempoMap::set_continuing (TempoPoint& tp, bool yn)
return true;
}
#if 1
void
TempoMap::stretch_tempo (TempoPoint& focus, double tempo_value)
{
/* Our goal is to alter the outound tempo at @param focus and at the same
* time create & modify a ramp between the previous tempo and @param focus
* so that @param remains in the same location.
*
* The user has placed @param focus at the correct point, but wanfocus to
* adjust the (outbound) tempo without creating an obvious step change
* at @param focus. So we want to ramp from prev to focus
*/
TempoPoint* prev = const_cast<TempoPoint*> (previous_tempo (focus));
TempoPoint old_prev (*prev);
TempoPoint old_focus (focus);
std::cerr << "using " << tempo_value << " working on " << focus << std::endl;
std::cerr << "\twith prev " << *prev << std::endl;
std::cerr << "focus then " << focus << std::endl;
focus.set_note_types_per_minute (tempo_value);
focus.set_end_npm (tempo_value);
std::cerr << "focus now " << focus << std::endl;
prev->set_end_npm (tempo_value);
prev->compute_omega_beats_from_next_tempo (focus);
superclock_t err = prev->superclock_at (focus.beats()) - focus.sclock();
const superclock_t one_sample = superclock_ticks_per_second() / TEMPORAL_SAMPLE_RATE;
const Beats b (focus.beats() - prev->beats());
// const double end_scpqn = focus.superclocks_per_quarter_note();
double scpqn = focus.superclocks_per_quarter_note ();
double new_npm;
int cnt = 0;
std::cerr << "initial error = " << err / (double) one_sample << std::endl;
reset_starting_at (prev->sclock());;
return;
while (std::abs(err) >= one_sample) {
if (err > 0) {
/* estimated > actual: speed end tempo up a little aka
reduce scpqn
*/
scpqn *= 0.99;
} else {
/* estimated < actual: reduce end tempo a little, aka
increase scpqn
*/
scpqn *= 1.01;
}
if (scpqn < 1.0) {
/* mathematically too small, bail out */
*prev = old_prev;
focus = old_focus;
return;
}
/* Convert scpqn to notes-per-minute */
new_npm = ((superclock_ticks_per_second() * 60.0) / scpqn) * (focus.note_type() / 4.0);
/* limit range of possible discovered tempo */
if (new_npm < 4.0 && new_npm > 400) {
/* too low of a tempo for our taste, bail out */
*prev = old_prev;
focus = old_focus;
return;
}
/* set the (initial) tempo, recompute omega and then compute
* the (new) error (distance between the predicted position of
* the next marker and its actual (fixed) position.
*/
focus.set_note_types_per_minute (new_npm);
focus.set_end_npm (new_npm);
prev->set_end_npm (new_npm);
prev->compute_omega_beats_from_next_tempo (focus);
err = prev->superclock_at (focus.beats()) - focus.sclock();
++cnt;
}
std::cerr << "that took " << cnt << " iterations to get to < 1 sample\n";
std::cerr << "final focus: " << focus << std::endl;
std::cerr << "final prev: " << *prev << std::endl;
reset_starting_at (prev->sclock());
// dump (std::cerr);
}
#else
/* Adjusts the outgoing tempo at @p ts so that the next Tempo point is at @p
* end_sample, while keeping the beat time positions of both the same.
*
@ -3259,6 +3356,9 @@ TempoMap::stretch_tempo (TempoPoint* ts, samplepos_t sample, samplepos_t end_sam
new_bpm = std::min (new_bpm, 1000.0);
}
std::cerr << "new bpm: " << new_bpm << std::endl;
/* don't clamp and proceed here.
testing has revealed that this can go negative,
which is an entirely different thing to just being too low.
@ -3280,6 +3380,8 @@ TempoMap::stretch_tempo (TempoPoint* ts, samplepos_t sample, samplepos_t end_sam
reset_starting_at (ts->sclock() + 1);
}
#endif
void
TempoMap::stretch_tempo_end (TempoPoint* ts, samplepos_t sample, samplepos_t end_sample)
{
@ -3328,6 +3430,7 @@ TempoMap::stretch_tempo_end (TempoPoint* ts, samplepos_t sample, samplepos_t end
reset_starting_at (prev_t->sclock());
}
void
TempoMap::twist_tempi (TempoPoint& prev, TempoPoint& focus, TempoPoint& next, double tempo_value)
{

View File

@ -766,7 +766,7 @@ class /*LIBTEMPORAL_API*/ TempoMap : public PBD::StatefulDestructible
LIBTEMPORAL_API int set_state (XMLNode const&, int version);
LIBTEMPORAL_API void twist_tempi (TempoPoint& prev, TempoPoint& focus, TempoPoint& next, double tempo_delta);
LIBTEMPORAL_API void stretch_tempo (TempoPoint* ts, samplepos_t sample, samplepos_t end_sample, Beats const & start_qnote, Beats const & end_qnote);
LIBTEMPORAL_API void stretch_tempo (TempoPoint& ts, double new_npm);
LIBTEMPORAL_API void stretch_tempo_end (TempoPoint* ts, samplepos_t sample, samplepos_t end_sample);
/* END OF MODIFYING METHODS */