static void bf_est_update(short fill) { // the rate-matching system needs to decide how full to keep the buffer. // the initial fill is present when the system starts to output samples, // but most output chains will instantly gobble their own buffer's worth of // data. we average for a while to decide where to draw the line. if (fill_count < 1000) { desired_fill += (double)fill/1000.0; fill_count++; return; } else if (fill_count == 1000) { // this information could be used to help estimate our effective latency? desired_fill = (2*config.buffer_start_fill) - desired_fill; debug(1, "established desired fill of %f frames, " "so output chain buffered about %f frames\n", desired_fill, desired_fill - config.buffer_start_fill); fill_count++; } #define CONTROL_A (1e-4) #define CONTROL_B (1e-1) double buf_delta = fill - desired_fill; bf_est_err = biquad_filt(&bf_err_lpf, buf_delta); double err_deriv = biquad_filt(&bf_err_deriv_lpf, bf_est_err - bf_last_err); double adj_error = CONTROL_A * bf_est_err; bf_est_drift = biquad_filt(&bf_drift_lpf, CONTROL_B*(adj_error + err_deriv) + bf_est_drift); debug(3, "bf %d err %f drift %f desiring %f ed %f estd %f\n", fill, bf_est_err, bf_est_drift, desired_fill, err_deriv, err_deriv + adj_error); bf_playback_rate = 1.0 + adj_error + bf_est_drift; bf_last_err = bf_est_err; }
static inline void bf_est_update(short fill) { if (fill_count < 1000) { desired_fill += (double)fill/1000.0; fill_count++; return; } #define CONTROL_A (1e-4) #define CONTROL_B (1e-1) double buf_delta = fill - desired_fill; bf_est_err = biquad_filt(&bf_err_lpf, buf_delta); double err_deriv = biquad_filt(&bf_err_deriv_lpf, bf_est_err - bf_last_err); double adj_error = CONTROL_A * bf_est_err; bf_est_drift = biquad_filt(&bf_drift_lpf, CONTROL_B*(adj_error + err_deriv) + bf_est_drift); #ifdef DEBUG fprintf(stderr, "bf %d err %f drift %f desiring %f ed %f estd %f\n", fill, bf_est_err, bf_est_drift, desired_fill, err_deriv, err_deriv + adj_error); #endif bf_playback_rate = 1.0 + adj_error + bf_est_drift; bf_last_err = bf_est_err; }
void display(void) { if (rptr==wptr) { glutSwapBuffers(); glutPostRedisplay(); return; } glDrawBuffer(GL_BACK); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); int n; double x, y; glBegin(GL_LINES); glColor4f(0,1,0,0.7); glVertex2f(last_x, last_y); n = 0; again: while (rptr != wptr) { x = biquad_filt(&lpf_x, ringbuf[rptr*4] / 32768.0); y = biquad_filt(&lpf_y, ringbuf[rptr*4+1] / 32768.0); if (!fullbright) glColor4f(0, ringbuf[rptr*4+2]/32768.0, 0,0.7); rptr++; if (rptr>=RING_SIZE) { rptr = 0; fprintf(stderr, "r"); } glVertex2f(x, y); glVertex2f(x, y); n++; } if (n < 1000) { glutSwapBuffers(); goto again; } glVertex2f(x, y); last_x = x; last_y = y; glEnd(); #define SKIP_ACCUM // accumulation buffer gives nice smooth decay effect, but is slow as tar on most machines #ifndef SKIP_ACCUM glAccum(GL_MULT, 0.7); glAccum(GL_ACCUM, 1.0); glDrawBuffer(GL_FRONT); glAccum(GL_RETURN, 1.0); glFlush(); #else //glDrawBuffer(GL_BACK); glutSwapBuffers(); #endif glutPostRedisplay(); }
void bf_est_update(short fill) { if (fill_count < 1000) { desired_fill += (double)fill/1000.0; fill_count++; return; } #define CONTROL_A (1e-4) #define CONTROL_B (1e-1) double buf_delta = fill - desired_fill; bf_est_err = biquad_filt(&bf_err_lpf, buf_delta); double err_deriv = biquad_filt(&bf_err_deriv_lpf, bf_est_err - bf_last_err); bf_est_drift = biquad_filt(&bf_drift_lpf, CONTROL_B*(bf_est_err*CONTROL_A + err_deriv) + bf_est_drift); if (debug) fprintf(stderr, "bf %d err %f drift %f desiring %f ed %f estd %f\r", fill, bf_est_err, bf_est_drift, desired_fill, err_deriv, err_deriv + CONTROL_A*bf_est_err); bf_playback_rate = 1.0 + CONTROL_A*bf_est_err + bf_est_drift; bf_last_err = bf_est_err; }