예제 #1
0
//void MyTransforms::calculateAnalysisData(float *input, AnalysisData &analysisData, Channel *ch, float threshold)
void MyTransforms::calculateAnalysisData(/*float *input, */int chunk, Channel *ch/*, float threshold*/)
{
  myassert(ch);
  myassert(ch->dataAtChunk(chunk));
  AnalysisData &analysisData = *ch->dataAtChunk(chunk);
  AnalysisData *prevAnalysisData = ch->dataAtChunk(chunk-1);
  //Array1d<float> output(k);
  float *output = ch->nsdfData.begin();
  float *curInput = (equalLoudness) ? ch->filteredInput.begin() : ch->directInput.begin();

  std::vector<int> nsdfMaxPositions;
  //int pos = 0;
  //int curMaxPos = 0;
  //float corrError = 0.0f;
  //freqPerBin = rate / 2.0 / double(size);

  //analysisData.maxIntensity = fabs(*std::max_element(input, input+n, absoluteLess()));
  analysisData.maxIntensityDB() = linear2dB(fabs(*std::max_element(curInput, curInput+n, absoluteLess<float>())));
  
  //if(gdata->doingActiveFFT()) {
    //std::copy(curInput, curInput+n, dataTime);
  doChannelDataFFT(ch, curInput, chunk);
    //std::copy(dataTemp, dataTemp+n, dataTime);
  //}
  std::copy(curInput, curInput+n, dataTime);
  
  //if(!gdata->doingActiveAnalysis()) return;
  //if(gdata->doingFreqAnalysis()) {
  if(gdata->doingFreqAnalysis() && (ch->firstTimeThrough() || gdata->doingActiveAnalysis())) {
    //calculate the Normalised Square Difference Function
    //analysisData.rms = nsdf(dataTime, output.begin()) / double(n/*size*/);
    //analysisData.rms = nsdf(dataTime, output) / double(n/*size*/);
    double logrms = linear2dB(nsdf(dataTime, ch->nsdfData.begin()) / double(n)); /**< Do the NSDF calculation */
    analysisData.logrms() = logrms;
    if(gdata->doingAutoNoiseFloor() && !analysisData.done) {
      //do it for gdata. this is only here for old code. remove some stage
      if(chunk == 0) { gdata->rmsFloor() = 0.0; gdata->rmsCeiling() = gdata->dBFloor(); }
      if(logrms+15 < gdata->rmsFloor()) gdata->rmsFloor() = logrms+15;
      if(logrms > gdata->rmsCeiling()) gdata->rmsCeiling() = logrms;

      //do it for the channel
      if(chunk == 0) { ch->rmsFloor = 0.0; ch->rmsCeiling = gdata->dBFloor(); }
      if(logrms+15 < ch->rmsFloor) ch->rmsFloor = logrms+15;
      if(logrms > ch->rmsCeiling) ch->rmsCeiling = logrms;
    }
    //if(!analysisData.done) {
      //analysisData.notePlaying = ch->isNotePlaying();
      //if(ch->isNotePlaying()) 
      //  addTo(ch->nsdfData.begin(), ch->nsdfData.end(), ch->nsdfAggregateData.begin());
    //}

    //analysisData.freqCentroid() = calcFreqCentroid(storeFFT, size);
    analysisData.freqCentroid() = calcFreqCentroidFromLogMagnitudes(ch->fftData1.begin(), ch->fftData1.size());
    if(prevAnalysisData)
      analysisData.deltaFreqCentroid() = bound(fabs(analysisData.freqCentroid() - prevAnalysisData->freqCentroid())*20.0, 0.0, 1.0);
    else 
      analysisData.deltaFreqCentroid() = 0.0;
    
    findNSDFMaxima(ch->nsdfData.begin(), k, nsdfMaxPositions);
    if(!analysisData.done) {
      //if(ch->isNotePlaying()) {
        //analysisData.periodOctaveEstimate = ch->calcOctaveEstimate(chunk, threshold);
/*
        findNSDFMaxima(ch->nsdfAggregateData.begin(), k, nsdfAggregateMaxPositions);
        myassert(!nsdfAggregateMaxPositions.empty());
  
        //get the highest nsdfAggregateMaxPosition
        uint j;
        int nsdfAggregateMaxIndex = 0;
        int nsdfAggregateChoosenIndex = 0;
        for(j=1; j<nsdfAggregateMaxPositions.size(); j++) {
          if(ch->nsdfAggregateData[nsdfAggregateMaxPositions[j]] > ch->nsdfAggregateData[nsdfAggregateMaxPositions[nsdfAggregateMaxIndex]]) nsdfAggregateMaxIndex = j;
        }
        //get the choosen nsdfAggregateMaxPosition
        float nsdfAggregateCutoff = ch->nsdfAggregateData[nsdfAggregateMaxPositions[nsdfAggregateMaxIndex]] * threshold;
        for(j=0; j<nsdfAggregateMaxPositions.size(); j++) {
          if(ch->nsdfAggregateData[nsdfAggregateMaxPositions[j]] >= nsdfAggregateCutoff) { nsdfAggregateChoosenIndex = j; break; }
        }
        analysisData.periodOctaveEstimate = float(nsdfAggregateMaxPositions[nsdfAggregateChoosenIndex]+1); //add 1 for index offset, ie position 0 = 1 period
*/
    }

    //store some of the best period estimates
    analysisData.periodEstimates.clear();
    analysisData.periodEstimatesAmp.clear();
    //float smallThreshold = 0.7f;
    //float smallCutoff = output[overallMaxIndex] * smallThreshold;
    float smallCutoff = 0.4f;
    for(std::vector<int>::iterator iter = nsdfMaxPositions.begin(); iter < nsdfMaxPositions.end(); iter++) {
      if(output[*iter] >= smallCutoff) {
        //analysisData.periodEstimates.push_back(double(*iter + 1) + parabolaTurningPoint(output[*iter-1], output[*iter], output[*iter+1]));
        //analysisData.periodEstimatesAmp.push_back(output[*iter]); //TODO: These should be calculated more accurately
        float x, y;
        //do a parabola fit to find the maximum
        parabolaTurningPoint2(output[*iter-1], output[*iter], output[*iter+1], float(*iter + 1), &x, &y);
        y = bound(y, -1.0f, 1.0f);
        analysisData.periodEstimates.push_back(x);
        analysisData.periodEstimatesAmp.push_back(y);
      }
    }
    
    float periodDiff = 0.0f;
    //if(maxPositions.empty()) { //no period found
    if(analysisData.periodEstimates.empty()) { //no period found
      //analysisData.correlation() = 0.0f;
      analysisData.calcScores();
      analysisData.done = true;
      //goto finished; //return;
    } else {
      //calc the periodDiff
      if(chunk > 0 && prevAnalysisData->highestCorrelationIndex!=-1) {
        float prevPeriod = prevAnalysisData->periodEstimates[prevAnalysisData->highestCorrelationIndex];
        std::vector<float>::iterator closestIter = binary_search_closest(analysisData.periodEstimates.begin(), analysisData.periodEstimates.end(), prevPeriod);
        //print_elements(analysisData.periodEstimates.begin(), analysisData.periodEstimates.end());
        //printf("closestIter = %f, %f\n", *closestIter, prevPeriod);
        periodDiff = *closestIter - prevPeriod;
        if(absolute(periodDiff) > 8.0f) periodDiff = 0.0f;
      }

      int nsdfMaxIndex = int(std::max_element(analysisData.periodEstimatesAmp.begin(), analysisData.periodEstimatesAmp.end()) - analysisData.periodEstimatesAmp.begin());
      analysisData.highestCorrelationIndex = nsdfMaxIndex;

      if(!analysisData.done) {
        //if(gdata->doingActiveCepstrum()) {
        if(gdata->analysisType() == MPM_MODIFIED_CEPSTRUM) {
            ch->chooseCorrelationIndex(chunk, float(analysisData.cepstrumIndex)); //calculate pitch
        } else {
          if(ch->isNotePlaying() && chunk > 0) {
            //ch->chooseCorrelationIndex(chunk, ch->getLastNote()->periodOctaveEstimate()); //calculate pitch
            //ch->chooseCorrelationIndex(chunk, ch->periodOctaveEstimate(std::max(0, chunk-1))); //calculate pitch
            ch->chooseCorrelationIndex(chunk, ch->periodOctaveEstimate(chunk-1)); //calculate pitch
          } else {
            ch->chooseCorrelationIndex1(chunk); //calculate pitch
          }
          //ch->chooseCorrelationIndex(chunk, (float)ch->rate() / 440.0f); //calculate pitch
        }
        ch->calcDeviation(chunk);

        ch->doPronyFit(chunk); //calculate vibratoPitch, vibratoWidth, vibratoSpeed
      }

      analysisData.changeness() = 0.0f;
      //analysisData.changeness() = get_max_note_change(dataTime, analysisData.period);

      if(gdata->doingHarmonicAnalysis()) {
        std::copy(dataTime, dataTime+n, dataTemp);
        if(analysisData.chosenCorrelationIndex >= 0)
          doHarmonicAnalysis(dataTemp, analysisData, analysisData.periodEstimates[analysisData.chosenCorrelationIndex]/*period*/);
        //doHarmonicAnalysis(input, analysisData, period);
      }

      //analysisData.volumeValue = (dB2Normalised(analysisData.logrms) + (analysisData.correlation-1.0f)) * 0.2;
    }

    //float periodDiff = 0.0f;
    if(gdata->doingFreqAnalysis() && ch->doingDetailedPitch() && ch->firstTimeThrough()) {
      //periodDiff = ch->calcDetailedPitch(curInput, analysisData.period, chunk);
      float periodDiff2 = ch->calcDetailedPitch(curInput, analysisData.period, chunk);
      //printf("chunk=%d, %f, %f\n", chunk, periodDiff, periodDiff2);
      periodDiff = periodDiff2;

      ch->pitchLookup.push_back(ch->detailedPitchData.begin(), ch->detailedPitchData.size());
      ch->pitchLookupSmoothed.push_back(ch->detailedPitchDataSmoothed.begin(), ch->detailedPitchDataSmoothed.size());
/*      float periodDiff1 = (rate / pitch2freq(ch->detailedPitchData.back()));
      float periodDiff2 = (rate / pitch2freq(ch->detailedPitchData.front()));
      periodDiff = periodDiff1 - periodDiff2;
      printf("%f, %f, %f\n", periodDiff1, periodDiff2, periodDiff);
*/
    }

    if(!analysisData.done) {
      analysisData.calcScores();
      ch->processNoteDecisions(chunk, periodDiff);
      analysisData.done = true;
    }

    if(gdata->doingFreqAnalysis() && ch->doingDetailedPitch() && ch->firstTimeThrough()) {
      ch->calcVibratoData(chunk);
    }
  }

  if(gdata->doingFreqAnalysis() && ch->doingDetailedPitch() && (!ch->firstTimeThrough())) {
    ch->pitchLookup.copyTo(ch->detailedPitchData.begin(), chunk*ch->detailedPitchData.size(), ch->detailedPitchData.size());
    ch->pitchLookupSmoothed.copyTo(ch->detailedPitchDataSmoothed.begin(), chunk*ch->detailedPitchDataSmoothed.size(), ch->detailedPitchDataSmoothed.size());
  }

  if(!analysisData.done) {
    int j;
    //calc rms by hand
    double rms = 0.0;
    for(j=0; j<n; j++) {
      rms += sq(dataTime[j]);
    }
    //analysisData.rms = sqrt(analysisData.rms);
    analysisData.logrms() = linear2dB(rms / float(n));
    analysisData.calcScores();
    analysisData.done = true;
  }

}
예제 #2
0
//------------------------------------------------------------------------------
float AnalysisData::searchClosestPeriodEstimates(const float & p_value)const
{
  std::vector<float>::const_iterator l_closest_iter = binary_search_closest(periodEstimates.begin(), periodEstimates.end(), p_value);
  return *l_closest_iter;
}