/* 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;
}
示例#2
0
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;
}
示例#4
0
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;
}
示例#5
0
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;
}
示例#6
0
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.;
  }
}