/* all the above in one */ void aubio_pitchyin_do (aubio_pitchyin_t * o, fvec_t * input, fvec_t * out) { smpl_t tol = o->tol; fvec_t *yin = o->yin; uint_t j, tau = 0; sint_t period; smpl_t tmp = 0., tmp2 = 0.; yin->data[0] = 1.; for (tau = 1; tau < yin->length; tau++) { yin->data[tau] = 0.; for (j = 0; j < yin->length; j++) { tmp = input->data[j] - input->data[j + tau]; yin->data[tau] += SQR (tmp); } tmp2 += yin->data[tau]; yin->data[tau] *= tau / tmp2; period = tau - 3; if (tau > 4 && (yin->data[period] < tol) && (yin->data[period] < yin->data[period + 1])) { out->data[0] = fvec_quadratic_peak_pos (yin, period); goto beach; } } out->data[0] = fvec_quadratic_peak_pos (yin, fvec_min_elem (yin)); beach: return; }
void aubio_pitchspecacf_do (aubio_pitchspecacf_t * p, const fvec_t * input, fvec_t * output) { uint_t l, tau; fvec_t *fftout = p->fftout; // window the input for (l = 0; l < input->length; l++) { p->winput->data[l] = p->win->data[l] * input->data[l]; } // get the real / imag parts of its fft aubio_fft_do_complex (p->fft, p->winput, fftout); for (l = 0; l < input->length / 2 + 1; l++) { p->sqrmag->data[l] = SQR(fftout->data[l]); } // get the real / imag parts of the fft of the squared magnitude aubio_fft_do_complex (p->fft, p->sqrmag, fftout); // copy real part to acf for (l = 0; l < fftout->length / 2 + 1; l++) { p->acf->data[l] = fftout->data[l]; } // get the minimum tau = fvec_min_elem (p->acf); // get the interpolated minimum output->data[0] = fvec_quadratic_peak_pos (p->acf, tau) * 2.; }
/** T=quadpick(X): return indices of elements of X which are peaks and positive * exact peak positions are retrieved by quadratic interpolation * * \bug peak-picking too picky, sometimes counts too many peaks ? */ uint_t aubio_pitchmcomb_quadpick (aubio_spectralpeak_t * spectral_peaks, fvec_t * X) { uint_t j, ispeak, count = 0; for (j = 1; j < X->length - 1; j++) { ispeak = fvec_peakpick (X, j); if (ispeak) { count += ispeak; spectral_peaks[count - 1].bin = j; spectral_peaks[count - 1].ebin = fvec_quadratic_peak_pos (X, j); } } return count; }
void aubio_beattracking_checkstate (aubio_beattracking_t * bt) { uint_t i, j, a, b; uint_t flagconst = 0; sint_t counter = bt->counter; uint_t flagstep = bt->flagstep; smpl_t gp = bt->gp; smpl_t bp = bt->bp; smpl_t rp = bt->rp; smpl_t rp1 = bt->rp1; smpl_t rp2 = bt->rp2; uint_t laglen = bt->rwv->length; uint_t acflen = bt->acf->length; uint_t step = bt->step; fvec_t *acf = bt->acf; fvec_t *acfout = bt->acfout; if (gp) { // compute shift invariant comb filterbank fvec_zeros (acfout); for (i = 1; i < laglen - 1; i++) { for (a = 1; a <= bt->timesig; a++) { for (b = 1; b < 2 * a; b++) { acfout->data[i] += acf->data[i * a + b - 1]; } } } // since gp is set, gwv has been computed in previous checkstate fvec_weight (acfout, bt->gwv); gp = fvec_quadratic_peak_pos (acfout, fvec_max_elem (acfout)); } else { //still only using general model gp = 0; } //now look for step change - i.e. a difference between gp and rp that // is greater than 2*constthresh - always true in first case, since gp = 0 if (counter == 0) { if (ABS (gp - rp) > 2. * bt->g_var) { flagstep = 1; // have observed step change. counter = 3; // setup 3 frame counter } else { flagstep = 0; } } //i.e. 3rd frame after flagstep initially set if (counter == 1 && flagstep == 1) { //check for consistency between previous beatperiod values if (ABS (2 * rp - rp1 - rp2) < bt->g_var) { //if true, can activate context dependent model flagconst = 1; counter = 0; // reset counter and flagstep } else { //if not consistent, then don't flag consistency! flagconst = 0; counter = 2; // let it look next time } } else if (counter > 0) { //if counter doesn't = 1, counter = counter - 1; } rp2 = rp1; rp1 = rp; if (flagconst) { /* first run of new hypothesis */ gp = rp; bt->timesig = fvec_gettimesig (acf, acflen, gp); for (j = 0; j < laglen; j++) bt->gwv->data[j] = EXP (-.5 * SQR ((smpl_t) (j + 1. - gp)) / SQR (bt->g_var)); flagconst = 0; bp = gp; /* flat phase weighting */ fvec_ones (bt->phwv); } else if (bt->timesig) { /* context dependant model */ bp = gp; /* gaussian phase weighting */ if (step > bt->lastbeat) { for (j = 0; j < 2 * laglen; j++) { bt->phwv->data[j] = EXP (-.5 * SQR ((smpl_t) (1. + j - step + bt->lastbeat)) / (bp / 8.)); } } else { //AUBIO_DBG("NOT using phase weighting as step is %d and lastbeat %d \n", // step,bt->lastbeat); fvec_ones (bt->phwv); } } else { /* initial state */ bp = rp; /* flat phase weighting */ fvec_ones (bt->phwv); } /* do some further checks on the final bp value */ /* if tempo is > 206 bpm, half it */ while (0 < bp && bp < 25) { #if AUBIO_BEAT_WARNINGS AUBIO_WRN ("doubling from %f (%f bpm) to %f (%f bpm)\n", bp, 60.*44100./512./bp, bp/2., 60.*44100./512./bp/2. ); //AUBIO_DBG("warning, halving the tempo from %f\n", 60.*samplerate/hopsize/bp); #endif /* AUBIO_BEAT_WARNINGS */ bp = bp * 2; } //AUBIO_DBG("tempo:\t%3.5f bpm | ", 5168./bp); /* smoothing */ //bp = (uint_t) (0.8 * (smpl_t)bp + 0.2 * (smpl_t)bp2); //AUBIO_DBG("tempo:\t%3.5f bpm smoothed | bp2 %d | bp %d | ", 5168./bp, bp2, bp); //bp2 = bp; //AUBIO_DBG("time signature: %d \n", bt->timesig); bt->counter = counter; bt->flagstep = flagstep; bt->gp = gp; bt->bp = bp; bt->rp1 = rp1; bt->rp2 = rp2; }
void aubio_beattracking_do (aubio_beattracking_t * bt, const fvec_t * dfframe, fvec_t * output) { uint_t i, k; uint_t step = bt->step; uint_t laglen = bt->rwv->length; uint_t winlen = bt->dfwv->length; uint_t maxindex = 0; //number of harmonics in shift invariant comb filterbank uint_t numelem = 4; smpl_t phase; // beat alignment (step - lastbeat) smpl_t beat; // beat position smpl_t bp; // beat period uint_t a, b; // used to build shift invariant comb filterbank uint_t kmax; // number of elements used to find beat phase /* copy dfframe, apply detection function weighting, and revert */ fvec_copy (dfframe, bt->dfrev); fvec_weight (bt->dfrev, bt->dfwv); fvec_rev (bt->dfrev); /* compute autocorrelation function */ aubio_autocorr (dfframe, bt->acf); /* if timesig is unknown, use metrically unbiased version of filterbank */ if (!bt->timesig) { numelem = 4; } else { numelem = bt->timesig; } /* first and last output values are left intentionally as zero */ fvec_zeros (bt->acfout); /* compute shift invariant comb filterbank */ for (i = 1; i < laglen - 1; i++) { for (a = 1; a <= numelem; a++) { for (b = 1; b < 2 * a; b++) { bt->acfout->data[i] += bt->acf->data[i * a + b - 1] * 1. / (2. * a - 1.); } } } /* apply Rayleigh weight */ fvec_weight (bt->acfout, bt->rwv); /* find non-zero Rayleigh period */ maxindex = fvec_max_elem (bt->acfout); if (maxindex > 0 && maxindex < bt->acfout->length - 1) { bt->rp = fvec_quadratic_peak_pos (bt->acfout, maxindex); } else { bt->rp = bt->rayparam; } /* activate biased filterbank */ aubio_beattracking_checkstate (bt); #if 0 // debug metronome mode bt->bp = 36.9142; #endif bp = bt->bp; /* end of biased filterbank */ if (bp == 0) { fvec_zeros(output); return; } /* deliberate integer operation, could be set to 3 max eventually */ kmax = FLOOR (winlen / bp); /* initialize output */ fvec_zeros (bt->phout); for (i = 0; i < bp; i++) { for (k = 0; k < kmax; k++) { bt->phout->data[i] += bt->dfrev->data[i + (uint_t) ROUND (bp * k)]; } } fvec_weight (bt->phout, bt->phwv); /* find Rayleigh period */ maxindex = fvec_max_elem (bt->phout); if (maxindex >= winlen - 1) { #if AUBIO_BEAT_WARNINGS AUBIO_WRN ("no idea what this groove's phase is\n"); #endif /* AUBIO_BEAT_WARNINGS */ phase = step - bt->lastbeat; } else { phase = fvec_quadratic_peak_pos (bt->phout, maxindex); } /* take back one frame delay */ phase += 1.; #if 0 // debug metronome mode phase = step - bt->lastbeat; #endif /* reset output */ fvec_zeros (output); i = 1; beat = bp - phase; // AUBIO_DBG ("bp: %f, phase: %f, lastbeat: %f, step: %d, winlen: %d\n", // bp, phase, bt->lastbeat, step, winlen); /* the next beat will be earlier than 60% of the tempo period skip this one */ if ( ( step - bt->lastbeat - phase ) < -0.40 * bp ) { #if AUBIO_BEAT_WARNINGS AUBIO_WRN ("back off-beat error, skipping this beat\n"); #endif /* AUBIO_BEAT_WARNINGS */ beat += bp; } /* start counting the beats */ while (beat + bp < 0) { beat += bp; } if (beat >= 0) { //AUBIO_DBG ("beat: %d, %f, %f\n", i, bp, beat); output->data[i] = beat; i++; } while (beat + bp <= step) { beat += bp; //AUBIO_DBG ("beat: %d, %f, %f\n", i, bp, beat); output->data[i] = beat; i++; } bt->lastbeat = beat; /* store the number of beats in this frame as the first element */ output->data[0] = i; }
void aubio_pitchyinfft_do (aubio_pitchyinfft_t * p, fvec_t * input, fvec_t * output) { uint_t tau, l; uint_t length = p->fftout->length; uint_t halfperiod; fvec_t *fftout = p->fftout; fvec_t *yin = p->yinfft; smpl_t tmp = 0., sum = 0.; // window the input for (l = 0; l < input->length; l++) { p->winput->data[l] = p->win->data[l] * input->data[l]; } // get the real / imag parts of its fft aubio_fft_do_complex (p->fft, p->winput, fftout); // get the squared magnitude spectrum, applying some weight p->sqrmag->data[0] = SQR(fftout->data[0]); p->sqrmag->data[0] *= p->weight->data[0]; for (l = 1; l < length / 2; l++) { p->sqrmag->data[l] = SQR(fftout->data[l]) + SQR(fftout->data[length - l]); p->sqrmag->data[l] *= p->weight->data[l]; p->sqrmag->data[length - l] = p->sqrmag->data[l]; } p->sqrmag->data[length / 2] = SQR(fftout->data[length / 2]); p->sqrmag->data[length / 2] *= p->weight->data[length / 2]; // get sum of weighted squared mags for (l = 0; l < length / 2 + 1; l++) { sum += p->sqrmag->data[l]; } sum *= 2.; // get the real / imag parts of the fft of the squared magnitude aubio_fft_do_complex (p->fft, p->sqrmag, fftout); yin->data[0] = 1.; for (tau = 1; tau < yin->length; tau++) { // compute the square differences yin->data[tau] = sum - fftout->data[tau]; // and the cumulative mean normalized difference function tmp += yin->data[tau]; if (tmp != 0) { yin->data[tau] *= tau / tmp; } else { yin->data[tau] = 1.; } } // find best candidates tau = fvec_min_elem (yin); if (yin->data[tau] < p->tol) { // no interpolation, directly return the period as an integer //output->data[0] = tau; //return; // 3 point quadratic interpolation //return fvec_quadratic_peak_pos (yin,tau,1); /* additional check for (unlikely) octave doubling in higher frequencies */ if (tau > p->short_period) { output->data[0] = fvec_quadratic_peak_pos (yin, tau); } else { /* should compare the minimum value of each interpolated peaks */ halfperiod = FLOOR (tau / 2 + .5); if (yin->data[halfperiod] < p->tol) output->data[0] = fvec_quadratic_peak_pos (yin, halfperiod); else output->data[0] = fvec_quadratic_peak_pos (yin, tau); } } else { output->data[0] = 0.; } }