Exemple #1
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;
}
Exemple #2
0
aubio_source_avcodec_t * new_aubio_source_avcodec(char_t * path, uint_t samplerate, uint_t hop_size) {
  aubio_source_avcodec_t * s = AUBIO_NEW(aubio_source_avcodec_t);
  int err;
  if (path == NULL) {
    AUBIO_ERR("Aborted opening null path\n");
    goto beach;
  }
  if ((sint_t)samplerate < 0) {
    AUBIO_ERR("Can not open %s with samplerate %d\n", path, samplerate);
    goto beach;
  }
  if ((sint_t)hop_size <= 0) {
    AUBIO_ERR("Can not open %s with hop_size %d\n", path, hop_size);
    goto beach;
  }

  s->hop_size = hop_size;
  s->channels = 1;
  s->path = path;

  // register all formats and codecs
  av_register_all();

  // if path[0] != '/'
  //avformat_network_init();

  // try opening the file and get some info about it
  AVFormatContext *avFormatCtx = s->avFormatCtx;
  avFormatCtx = NULL;
  if ( (err = avformat_open_input(&avFormatCtx, s->path, NULL, NULL) ) < 0 ) {
    char errorstr[256];
    av_strerror (err, errorstr, sizeof(errorstr));
    AUBIO_ERR("Failed opening %s (%s)\n", s->path, errorstr);
    goto beach;
  }

  // try to make sure max_analyze_duration is big enough for most songs
  avFormatCtx->max_analyze_duration *= 100;

  // retrieve stream information
  if ( (err = avformat_find_stream_info(avFormatCtx, NULL)) < 0 ) {
    char errorstr[256];
    av_strerror (err, errorstr, sizeof(errorstr));
    AUBIO_ERR("Could not find stream information " "for %s (%s)\n", s->path,
        errorstr);
    goto beach;
  }

  // dump information about file onto standard error
  //av_dump_format(avFormatCtx, 0, s->path, 0);

  // look for the first audio stream
  uint_t i;
  sint_t selected_stream = -1;
  for (i = 0; i < avFormatCtx->nb_streams; i++) {
    if (avFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
      if (selected_stream == -1) {
        selected_stream = i;
      } else {
        AUBIO_WRN("More than one audio stream in %s, "
            "taking the first one\n", s->path);
      }
    }
  }
  if (selected_stream == -1) {
    AUBIO_ERR("No audio stream in %s\n", s->path);
    goto beach;
  }
  //AUBIO_DBG("Taking stream %d in file %s\n", selected_stream, s->path);
  s->selected_stream = selected_stream;

  AVCodecContext *avCodecCtx = s->avCodecCtx;
  avCodecCtx = avFormatCtx->streams[selected_stream]->codec;
  AVCodec *codec = avcodec_find_decoder(avCodecCtx->codec_id);
  if (codec == NULL) {
    AUBIO_ERR("Could not find decoder for %s", s->path);
    goto beach;
  }

  if ( ( err = avcodec_open2(avCodecCtx, codec, NULL) ) < 0) {
    char errorstr[256];
    av_strerror (err, errorstr, sizeof(errorstr));
    AUBIO_ERR("Could not load codec for %s (%s)\n", s->path, errorstr);
    goto beach;
  }

  /* get input specs */
  s->input_samplerate = avCodecCtx->sample_rate;
  s->input_channels   = avCodecCtx->channels;
  //AUBIO_DBG("input_samplerate: %d\n", s->input_samplerate);
  //AUBIO_DBG("input_channels: %d\n", s->input_channels);

  if (samplerate == 0) {
    samplerate = s->input_samplerate;
    //AUBIO_DBG("sampling rate set to 0, automagically adjusting to %d\n", samplerate);
  }
  s->samplerate = samplerate;

  if (s->samplerate >  s->input_samplerate) {
    AUBIO_WRN("upsampling %s from %d to %d\n", s->path,
        s->input_samplerate, s->samplerate);
  }

  AVFrame *avFrame = s->avFrame;
  avFrame = avcodec_alloc_frame();
  if (!avFrame) {
    AUBIO_ERR("Could not allocate frame for (%s)\n", s->path);
  }

  /* allocate output for avr */
  s->output = (float *)av_malloc(AUBIO_AVCODEC_MAX_BUFFER_SIZE * sizeof(float));

  s->read_samples = 0;
  s->read_index = 0;

  s->avFormatCtx = avFormatCtx;
  s->avCodecCtx = avCodecCtx;
  s->avFrame = avFrame;

  // default to mono output
  aubio_source_avcodec_reset_resampler(s, 0);

  s->eof = 0;
  s->multi = 0;

  //av_log_set_level(AV_LOG_QUIET);

  return s;

beach:
  //AUBIO_ERR("can not read %s at samplerate %dHz with a hop_size of %d\n",
  //    s->path, s->samplerate, s->hop_size);
  del_aubio_source_avcodec(s);
  return NULL;
}
Exemple #3
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;
}
int aubio_audio_unit_blocking(aubio_audio_unit_t *o)
{
  uint_t sw_output_channels, sw_input_channels,
         hw_output_channels, hw_input_channels,
         i, j, blocksize;
  if (! o->callback) return -1;

  smpl_t ** tbuf;

  sw_output_channels = o->sw_output_channels;
  sw_input_channels = o->sw_input_channels;
  hw_output_channels = o->hw_output_channels;
  hw_input_channels = o->hw_input_channels;
  blocksize = o->blocksize;

  if (!sw_input_channels && !sw_output_channels) goto fail;

  if (o->dio_error) {
    AUBIO_WRN("audio_unit: dio error %d\n", o->total_frames);
    o->dio_error = 0;
  }

  if (o->au_ios_inbuf) {
    /* copy samples from input buffer */
    tbuf = o->input_frames->data;
    if (o->input_enabled) {
      for (j = 0; j < blocksize;j++) {
        for (i = 0; i < sw_input_channels && i < hw_input_channels; i++) {
          //tbuf[i][j] =
          //   (smpl_t)(o->au_ios_inbuf[i + (j + o->au_ios_end) * sw_input_channels] / 32768.);
          // on iphone, input is mono, copy right to left channel
          tbuf[i][j] =
            (smpl_t) o->au_ios_inbuf[0 + (j + o->au_ios_end) * hw_input_channels]
            * INT_TO_FLOAT;
        }
      }
    } else {
      // input is disabled, fill with zeroes
      for (j = 0; j < blocksize; j++) {
        for (i = 0; i < sw_input_channels && i < hw_input_channels; i++) {
          tbuf[i][j] = 0;
        }
      }
    }
  }

  o->callback(o->callback_closure, o->input_frames, o->output_frames);

  /* copy samples to output buffer */
  tbuf = o->output_frames->data;
  for (i = 0; i < o->output_frames->height; i++)	{
    for (j = 0; j < o->output_frames->length; j++) {
      smpl_t val = tbuf[i][j];
      if (val < -1.0) val = -1.0;
      if (val > 1.0) val = 1.0;
      o->au_ios_outbuf[i + (j + o->au_ios_end) * hw_output_channels ] = (SInt16)(val * 32767);
    }
  }

  o->au_ios_end += blocksize;
  o->au_ios_end %= AU_IOS_MAX_FRAMES;
  o->total_frames += blocksize;

  return 0;

fail:
  AUBIO_ERR("audio_unit: callback() failed\n");
  o->total_frames += AU_IOS_MAX_FRAMES;
  return 1;
}
aubio_source_apple_audio_t * new_aubio_source_apple_audio(char_t * path, uint_t samplerate, uint_t block_size)
{
  aubio_source_apple_audio_t * s = AUBIO_NEW(aubio_source_apple_audio_t);

  s->path = path;
  s->block_size = block_size;

  OSStatus err = noErr;
  UInt32 propSize;

  // open the resource url
  CFURLRef fileURL = getURLFromPath(path);
  err = ExtAudioFileOpenURL(fileURL, &s->audioFile);
  if (err) { AUBIO_ERR("error when trying to access %s, in ExtAudioFileOpenURL, %d\n", s->path, (int)err); goto beach;}

  // create an empty AudioStreamBasicDescription
  AudioStreamBasicDescription fileFormat;
  propSize = sizeof(fileFormat);
  memset(&fileFormat, 0, sizeof(AudioStreamBasicDescription));

  // fill it with the file description
  err = ExtAudioFileGetProperty(s->audioFile,
      kExtAudioFileProperty_FileDataFormat, &propSize, &fileFormat);
  if (err) { AUBIO_ERROR("error in ExtAudioFileGetProperty, %d\n", (int)err); goto beach;}

  if (samplerate == 0) {
    samplerate = fileFormat.mSampleRate;
    //AUBIO_DBG("sampling rate set to 0, automagically adjusting to %d\n", samplerate);
  }
  s->samplerate = samplerate;
  s->source_samplerate = fileFormat.mSampleRate;
  s->channels = fileFormat.mChannelsPerFrame;

  AudioStreamBasicDescription clientFormat;
  propSize = sizeof(clientFormat);
  memset(&clientFormat, 0, sizeof(AudioStreamBasicDescription));
  clientFormat.mFormatID         = kAudioFormatLinearPCM;
  clientFormat.mSampleRate       = (Float64)(s->samplerate);
  clientFormat.mFormatFlags      = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
  clientFormat.mChannelsPerFrame = s->channels;
  clientFormat.mBitsPerChannel   = sizeof(short) * 8;
  clientFormat.mFramesPerPacket  = 1;
  clientFormat.mBytesPerFrame    = clientFormat.mBitsPerChannel * clientFormat.mChannelsPerFrame / 8;
  clientFormat.mBytesPerPacket   = clientFormat.mFramesPerPacket * clientFormat.mBytesPerFrame;
  clientFormat.mReserved         = 0;

  // set the client format description
  err = ExtAudioFileSetProperty(s->audioFile, kExtAudioFileProperty_ClientDataFormat,
      propSize, &clientFormat);
  if (err) {
      AUBIO_ERROR("error in ExtAudioFileSetProperty, %d\n", (int)err);
#if 1
  // print client and format descriptions
  AUBIO_DBG("Opened %s\n", s->path);
  AUBIO_DBG("file/client Format.mFormatID:        : %3c%c%c%c / %c%c%c%c\n",
      (int)RT_BYTE4(fileFormat.mFormatID),   (int)RT_BYTE3(fileFormat.mFormatID),   (int)RT_BYTE2(fileFormat.mFormatID),   (int)RT_BYTE1(fileFormat.mFormatID),
      (int)RT_BYTE4(clientFormat.mFormatID), (int)RT_BYTE3(clientFormat.mFormatID), (int)RT_BYTE2(clientFormat.mFormatID), (int)RT_BYTE1(clientFormat.mFormatID)
      );

  AUBIO_DBG("file/client Format.mSampleRate       : %6.0f / %.0f\n",     fileFormat.mSampleRate      ,      clientFormat.mSampleRate);
  AUBIO_DBG("file/client Format.mFormatFlags      : %6d / %d\n",    (int)fileFormat.mFormatFlags     , (int)clientFormat.mFormatFlags);
  AUBIO_DBG("file/client Format.mChannelsPerFrame : %6d / %d\n",    (int)fileFormat.mChannelsPerFrame, (int)clientFormat.mChannelsPerFrame);
  AUBIO_DBG("file/client Format.mBitsPerChannel   : %6d / %d\n",    (int)fileFormat.mBitsPerChannel  , (int)clientFormat.mBitsPerChannel);
  AUBIO_DBG("file/client Format.mFramesPerPacket  : %6d / %d\n",    (int)fileFormat.mFramesPerPacket , (int)clientFormat.mFramesPerPacket);
  AUBIO_DBG("file/client Format.mBytesPerFrame    : %6d / %d\n",    (int)fileFormat.mBytesPerFrame   , (int)clientFormat.mBytesPerFrame);
  AUBIO_DBG("file/client Format.mBytesPerPacket   : %6d / %d\n",    (int)fileFormat.mBytesPerPacket  , (int)clientFormat.mBytesPerPacket);
  AUBIO_DBG("file/client Format.mReserved         : %6d / %d\n",    (int)fileFormat.mReserved        , (int)clientFormat.mReserved);
#endif
      goto beach;
  }

  // compute the size of the segments needed to read the input file
  UInt32 samples = s->block_size * clientFormat.mChannelsPerFrame;
  Float64 rateRatio = clientFormat.mSampleRate / fileFormat.mSampleRate;
  uint_t segmentSize= (uint_t)(samples * rateRatio + .5);
  if (rateRatio < 1.) {
    segmentSize = (uint_t)(samples / rateRatio + .5);
  } else if (rateRatio > 1.) {
    AUBIO_WRN("up-sampling %s from %0.2fHz to %0.2fHz\n", s->path, fileFormat.mSampleRate, clientFormat.mSampleRate);
  } else {
    assert ( segmentSize == samples );
    //AUBIO_DBG("not resampling, segmentSize %d, block_size %d\n", segmentSize, s->block_size);
  }

  // allocate the AudioBufferList
  if (createAubioBufferList(&s->bufferList, s->channels, segmentSize)) err = -1;

  return s;
 
beach:
  AUBIO_FREE(s);
  return NULL;
}