Example #1
0
void NoveltyCurve::compute() {
  const vector<vector<Real> >& frequencyBands = _frequencyBands.get();
  vector<Real>& novelty = _novelty.get();
  if (frequencyBands.empty())
    throw EssentiaException("NoveltyCurve::compute, cannot compute from an empty input matrix");

  int nFrames = frequencyBands.size();
  int nBands = (int)frequencyBands[0].size();
  //vector<Real> weights = weightCurve(nBands);
  novelty.resize(nFrames-1);
  fill(novelty.begin(), novelty.end(), Real(0.0));

  vector<vector<Real> > t_frequencyBands = essentia::transpose(frequencyBands); // [bands x frames]
  vector<vector<Real> > noveltyBands(nBands);

  int meanSize = int(0.1 * _frameRate); // integral number of frames in 2*0.05 second

  // compute novelty for each sub-band
  meanSize += (meanSize % 2); // force even size // TODO: why?
  for (int bandIdx=0; bandIdx<nBands; bandIdx++) {
    noveltyBands[bandIdx] = noveltyFunction(t_frequencyBands[bandIdx], 1000, meanSize);
  }
  /////////////////////////////////////////////////////////////////////////////
  // TODO: By trial-&-error I found that combining weightings (flat, quadratic,
  // linear and inverse quadratic) was giving better results. Should this be
  // left as is or should we allow the algorithm to work with the given
  // weightings from the configuration. This overrides the parameters, so if
  // left as is, they should be removed as well.
  /////////////////////////////////////////////////////////////////////////////
  _type = FLAT;
  vector<Real> aweights = weightCurve(nBands);
  _type = QUADRATIC;
  vector<Real> bweights = weightCurve(nBands);
  _type = LINEAR;
  vector<Real> cweights = weightCurve(nBands);
  _type = INVERSE_QUADRATIC;
  vector<Real> dweights = weightCurve(nBands);
  //sum novelty on all bands (weighted) to get a single novelty value per frame
  noveltyBands = essentia::transpose(noveltyBands); // back to [frames x bands]
  vector<Real> bnovelty(nFrames-1, 0.0);
  vector<Real> cnovelty(nFrames-1, 0.0);
  vector<Real> dnovelty(nFrames-1, 0.0);
  for (int frameIdx=0; frameIdx<nFrames-1; frameIdx++) { // nFrames -1 as noveltyBands is a derivative whose size is nframes-1
    const vector<Real>& frame = noveltyBands[frameIdx];
    for (int bandIdx=0; bandIdx<nBands; bandIdx++) {
      novelty[frameIdx] += aweights[bandIdx] * frame[bandIdx];
      bnovelty[frameIdx] += bweights[bandIdx] * frame[bandIdx];
      cnovelty[frameIdx] += cweights[bandIdx] * frame[bandIdx];
      dnovelty[frameIdx] += dweights[bandIdx] * frame[bandIdx];
    }
  }
  for (int frameIdx=0; frameIdx<nFrames-1; frameIdx++) {
      novelty[frameIdx] *= bnovelty[frameIdx];
      novelty[frameIdx] *= cnovelty[frameIdx];
      novelty[frameIdx] *= dnovelty[frameIdx];
  }


  Algorithm * mavg = AlgorithmFactory::create("MovingAverage", "size", meanSize);
  vector<Real> novelty_ma;
  mavg->input("signal").set(novelty);
  mavg->output("signal").set(novelty_ma);
  mavg->compute();
  delete mavg;
  novelty.assign(novelty_ma.begin(), novelty_ma.end());
}
Example #2
0
void NoveltyCurve::compute() {
  const vector<vector<Real> >& frequencyBands = _frequencyBands.get();
  vector<Real>& novelty = _novelty.get();
  if (frequencyBands.empty())
    throw EssentiaException("NoveltyCurve::compute, cannot compute from an empty input matrix");

  int nFrames = frequencyBands.size();
  int nBands = (int)frequencyBands[0].size();
  //vector<Real> weights = weightCurve(nBands);
  novelty.resize(nFrames-1);
  fill(novelty.begin(), novelty.end(), Real(0.0));

  vector<vector<Real> > t_frequencyBands = essentia::transpose(frequencyBands); // [bands x frames]
  vector<vector<Real> > noveltyBands(nBands);

  int meanSize = int(0.1 * _frameRate); // integral number of frames in 2*0.05 second

  // compute novelty for each sub-band
  meanSize += (meanSize % 2); // force even size // TODO: why?
  for (int bandIdx=0; bandIdx<nBands; bandIdx++) {
    noveltyBands[bandIdx] = noveltyFunction(t_frequencyBands[bandIdx], 1000, meanSize);
  }


  //sum novelty on all bands (weighted) to get a single novelty value per frame
  noveltyBands = essentia::transpose(noveltyBands); // back to [frames x bands]

  // TODO: weight curves should be pre-computed in configure() method
  if (_type == HYBRID) {
    // EAylon: By trial-&-error I found that combining weightings (flat, quadratic,
    // linear and inverse quadratic) was giving better results.   
    vector<Real> aweights = weightCurve(nBands, FLAT);
    vector<Real> bweights = weightCurve(nBands, QUADRATIC);
    vector<Real> cweights = weightCurve(nBands, LINEAR);
    vector<Real> dweights = weightCurve(nBands, INVERSE_QUADRATIC);

    vector<Real> bnovelty(nFrames-1, 0.0);
    vector<Real> cnovelty(nFrames-1, 0.0);
    vector<Real> dnovelty(nFrames-1, 0.0);

    for (int frameIdx=0; frameIdx<nFrames-1; frameIdx++) { // noveltyBands is a derivative whose size is nframes-1
      for (int bandIdx=0; bandIdx<nBands; bandIdx++) {
        novelty[frameIdx] += aweights[bandIdx] * noveltyBands[frameIdx][bandIdx];
        bnovelty[frameIdx] += bweights[bandIdx] * noveltyBands[frameIdx][bandIdx];
        cnovelty[frameIdx] += cweights[bandIdx] * noveltyBands[frameIdx][bandIdx];
        dnovelty[frameIdx] += dweights[bandIdx] * noveltyBands[frameIdx][bandIdx];
      }
    }
    for (int frameIdx=0; frameIdx<nFrames-1; frameIdx++) {
      // TODO why multiplication instead of sum (or mean)? 
      novelty[frameIdx] *= bnovelty[frameIdx];
      novelty[frameIdx] *= cnovelty[frameIdx];
      novelty[frameIdx] *= dnovelty[frameIdx];
    }
  }
  else {
    // TODO weight curve should be pre-computed in configure() method
    vector<Real> weights = weightCurve(nBands, _type);

    for (int frameIdx=0; frameIdx<nFrames-1; frameIdx++) {
      for (int bandIdx=0; bandIdx<nBands; bandIdx++) {
        novelty[frameIdx] += weights[bandIdx] * noveltyBands[frameIdx][bandIdx];
      }
    }
  }

  // smoothing
  Algorithm * mavg = AlgorithmFactory::create("MovingAverage", "size", meanSize);
  vector<Real> novelty_ma;
  mavg->input("signal").set(novelty);
  mavg->output("signal").set(novelty_ma);
  mavg->compute();
  delete mavg;
  novelty.assign(novelty_ma.begin(), novelty_ma.end());
}