13
0

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; 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 /* 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. * 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); new_bpm = std::min (new_bpm, 1000.0);
} }
std::cerr << "new bpm: " << new_bpm << std::endl;
/* don't clamp and proceed here. /* don't clamp and proceed here.
testing has revealed that this can go negative, testing has revealed that this can go negative,
which is an entirely different thing to just being too low. 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); reset_starting_at (ts->sclock() + 1);
} }
#endif
void void
TempoMap::stretch_tempo_end (TempoPoint* ts, samplepos_t sample, samplepos_t end_sample) 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()); reset_starting_at (prev_t->sclock());
} }
void void
TempoMap::twist_tempi (TempoPoint& prev, TempoPoint& focus, TempoPoint& next, double tempo_value) 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 int set_state (XMLNode const&, int version);
LIBTEMPORAL_API void twist_tempi (TempoPoint& prev, TempoPoint& focus, TempoPoint& next, double tempo_delta); 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); LIBTEMPORAL_API void stretch_tempo_end (TempoPoint* ts, samplepos_t sample, samplepos_t end_sample);
/* END OF MODIFYING METHODS */ /* END OF MODIFYING METHODS */