Browse Source

Change to use new timing method for main loop

master
cancel 6 years ago
parent
commit
20ec36ba66
  1. 65
      tui_main.c

65
tui_main.c

@ -656,6 +656,7 @@ typedef struct {
Usz ruler_spacing_y, ruler_spacing_x;
Ged_input_mode input_mode;
Usz bpm;
U64 clock;
double accum_secs;
double time_to_next_note_off;
char const* filename;
@ -695,6 +696,7 @@ void ged_init(Ged* a) {
a->ruler_spacing_x = 8;
a->input_mode = Ged_input_mode_normal;
a->bpm = 120;
a->clock = 0;
a->accum_secs = 0.0;
a->time_to_next_note_off = 1.0;
a->filename = NULL;
@ -889,10 +891,12 @@ void send_output_events(Oosc_dev* oosc_dev, Midi_mode const* midi_mode, Usz bpm,
}
}
static double ms_to_sec(double ms) { return ms / 1000.0; }
double ged_secs_to_deadline(Ged const* a) {
if (a->is_playing) {
double secs_span = 60.0 / (double)a->bpm / 4.0;
double rem = secs_span - a->accum_secs;
double rem = secs_span - (stm_sec(stm_since(a->clock)) + a->accum_secs);
double next_note_off = a->time_to_next_note_off;
if (rem < 0.0)
rem = 0.0;
@ -913,28 +917,35 @@ static float float_clamp(float a, float low, float high) {
return a;
}
void ged_apply_delta_secs(Ged* a, double secs) {
if (a->is_playing) {
a->accum_secs += secs;
Oosc_dev* oosc_dev = a->oosc_dev;
Midi_mode const* midi_mode = a->midi_mode;
apply_time_to_sustained_notes(oosc_dev, midi_mode, secs, &a->susnote_list,
&a->time_to_next_note_off);
}
a->meter_level -= (float)secs;
a->meter_level = float_clamp(a->meter_level, 0.0f, 1.0f);
}
void ged_reset_clock(Ged* a) { a->clock = stm_now(); }
void ged_do_stuff(Ged* a) {
double secs_span = 60.0 / (double)a->bpm / 4.0;
Oosc_dev* oosc_dev = a->oosc_dev;
Midi_mode const* midi_mode = a->midi_mode;
// Clamp to 1 second of buffered play time, in case the process get frozen,
// we don't want to play back a ton of steps all at once.
if (a->accum_secs > 1.0)
a->accum_secs = 1.0;
while (a->accum_secs > secs_span) {
a->accum_secs -= secs_span;
double secs = stm_sec(stm_since(a->clock));
a->meter_level -= (float)secs;
a->meter_level = float_clamp(a->meter_level, 0.0f, 1.0f);
apply_time_to_sustained_notes(oosc_dev, midi_mode, secs, &a->susnote_list,
&a->time_to_next_note_off);
if (!a->is_playing)
return;
bool do_play = false;
for (;;) {
U64 now = stm_now();
U64 diff = stm_diff(now, a->clock);
double sdiff = stm_sec(diff) + a->accum_secs;
if (sdiff >= secs_span) {
a->clock = now;
a->accum_secs = sdiff - secs_span;
fprintf(stderr, "err: %f\n", a->accum_secs);
do_play = true;
break;
}
if (secs_span - sdiff > ms_to_sec(2.0))
break;
}
if (do_play) {
orca_run(a->field.buffer, a->markmap_r.buffer, a->field.height,
a->field.width, a->tick_num, &a->bank, &a->oevent_list,
a->piano_bits);
@ -956,8 +967,6 @@ void ged_do_stuff(Ged* a) {
}
}
static double ms_to_sec(double ms) { return ms / 1000.0; }
static inline Isz isz_clamp(Isz x, Isz low, Isz high) {
return x < low ? low : x > high ? high : x;
}
@ -1417,11 +1426,11 @@ void ged_input_cmd(Ged* a, Ged_input_cmd ev) {
if (a->is_playing) {
ged_stop_all_sustained_notes(a);
a->is_playing = false;
a->accum_secs = 0.0;
a->meter_level = 0.0f;
} else {
undo_history_push(&a->undo_hist, &a->field, a->tick_num);
a->is_playing = true;
a->clock = stm_now();
// dumb'n'dirty, get us close to the next step time, but not quite
a->accum_secs = 60.0 / (double)a->bpm / 4.0 - 0.02;
}
@ -1842,14 +1851,11 @@ int main(int argc, char** argv) {
int key = KEY_RESIZE;
wtimeout(stdscr, 0);
U64 last_time = 0;
int cur_timeout = 0;
for (;;) {
switch (key) {
case ERR: {
U64 diff = stm_laptime(&last_time);
ged_apply_delta_secs(&ged_state, stm_sec(diff));
ged_do_stuff(&ged_state);
bool drew_any = false;
if (qnav_stack.stack_changed)
@ -1872,17 +1878,15 @@ int main(int argc, char** argv) {
qnav_stack.stack_changed = false;
if (drew_any)
doupdate();
diff = stm_laptime(&last_time);
ged_apply_delta_secs(&ged_state, stm_sec(diff));
double secs_to_d = ged_secs_to_deadline(&ged_state);
// fprintf(stderr, "to deadline: %f\n", secs_to_d);
int new_timeout;
if (secs_to_d < ms_to_sec(0.5)) {
new_timeout = 0;
} else if (secs_to_d < ms_to_sec(3.0)) {
new_timeout = 1;
} else if (secs_to_d < ms_to_sec(2.0)) {
new_timeout = 0;
} else if (secs_to_d < ms_to_sec(10.0)) {
new_timeout = 5;
new_timeout = 2;
} else if (secs_to_d < ms_to_sec(50.0)) {
new_timeout = 15;
} else {
@ -2107,9 +2111,6 @@ int main(int argc, char** argv) {
ged_input_character(&ged_state, '.');
} else {
ged_input_cmd(&ged_state, Ged_input_cmd_toggle_play_pause);
// flush lap time -- quick hack to prevent time before hitting spacebar
// to play being applied as actual playback time
stm_laptime(&last_time);
}
break;
case 27: // Escape

Loading…
Cancel
Save