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:
parent
57398b1e5e
commit
e9f71824a1
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user