//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; } }
//------------------------------------------------------------------------------ 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; }