c@225: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ c@225: c@225: /* c@225: QM DSP Library c@225: c@225: Centre for Digital Music, Queen Mary, University of London. c@225: This file copyright 2005-2006 Christian Landone. c@225: All rights reserved. c@225: */ c@225: c@225: c@225: #include "ChromaProcess.h" c@241: #include "maths/Histogram.h" c@225: #include c@225: ////////////////////////////////////////////////////////////////////// c@225: // Construction/Destruction c@225: ////////////////////////////////////////////////////////////////////// c@225: c@225: ChromaProcess::ChromaProcess() c@225: { c@225: c@225: } c@225: c@225: ChromaProcess::~ChromaProcess() c@225: { c@225: c@225: } c@225: c@225: int ChromaProcess::findChromaBias( vector chromaVector, unsigned int BPO, unsigned int frames ) c@225: { c@225: vector newChroma; c@225: vector peakIndex; c@225: vector modPeakIndex; c@225: c@225: unsigned int chromaLength = chromaVector.size(); c@225: c@225: unsigned int newLength = chromaLength + (2*BPO); c@225: c@225: newChroma.resize( newLength ); c@225: newChroma.clear(); c@225: c@225: modPeakIndex.resize( newLength ); c@225: modPeakIndex.clear(); c@225: c@225: //adds last row at the top and first row at the bottom to create c@225: //circularity - effectively adds 2 to the bpo-length of the vectors: c@225: c@225: for( unsigned int i = 0; i < BPO; i++ ) c@225: { c@225: newChroma.push_back( chromaVector[ chromaLength - BPO + i ] ); c@225: } c@225: c@225: for( unsigned i = 0; i < chromaLength; i++ ) c@225: { c@225: newChroma.push_back( chromaVector[ i ] ); c@225: } c@225: c@225: for( unsigned i = 0; i < BPO; i++ ) c@225: { c@225: newChroma.push_back( chromaVector[ i ] ); c@225: } c@225: c@225: // pick peaks in the chroma c@225: peakIndex = getPeaks( newChroma, BPO ); c@225: c@225: // modularises to res = bpo/12 bins: c@225: // corrects the mod value for bin 3 c@225: modPeakIndex = mod( peakIndex, 3 ); c@225: c@225: // finds the highest concentration of peaks on the bpo/12 bin resolution c@225: THistogram m_hist(3); c@225: c@225: double ave, adev, sdev, var, skew, ccurt; c@225: c@225: m_hist.compute(modPeakIndex); c@225: c@225: m_hist.getMoments( modPeakIndex, ave, adev, sdev, var, skew, ccurt ); c@225: c@225: vector histogram = m_hist.geTHistogramD(); c@225: ////////////////////////////////////////////////////////////////////////////// c@225: c@225: /////////////////////////////////////////////////////////////////////////// c@225: // Find actual bias from histogram c@225: int minIdx, maxIdx; c@225: double min, max; c@225: c@225: findHistMaxMin( histogram, &max, &maxIdx, &min, &minIdx ); c@225: c@225: /* c@225: FILE* foutchroma = fopen("../testdata/newchroma.bin","wb"); c@225: FILE* foutpeaks = fopen("../testdata/peaks.bin","wb"); c@225: c@225: c@225: fwrite( &chromaVector[0], sizeof(double), chromaVector.size(), foutchroma ); c@225: fwrite( &histogram[0], sizeof(double), histogram.size(), foutpeaks ); c@225: c@225: fclose( foutchroma ); c@225: fclose( foutpeaks ); c@225: */ c@225: return maxIdx - 1; c@225: } c@225: c@225: c@225: vector ChromaProcess::getPeaks(vector chroma, unsigned int BPO) c@225: { c@225: vector peaks; c@225: c@225: double pre = 0; c@225: double post = 0; c@225: double current = 0; c@225: c@225: unsigned int BPOCounter = 0; c@225: unsigned int mult = 0; c@225: unsigned int idx = 0; c@225: c@225: for( unsigned int i = 0; i < chroma.size() - 0; i++ ) c@225: { c@225: BPOCounter++; c@225: c@225: pre = chroma[ i ]; c@225: current = chroma[ i + 1 ]; c@225: post = chroma[ i + 2 ]; c@225: c@225: if( (current > 0) && (current > pre) && (current > post) ) c@225: { c@225: peaks.push_back( BPOCounter + 1); c@225: } c@225: c@225: c@225: if( BPOCounter == (BPO - 2 ) ) c@225: { c@225: BPOCounter = 0; c@225: i+=2; c@225: } c@225: c@225: } c@225: c@225: /* c@225: for( unsigned int i = 1; i < chroma.size() - 1; i++ ) c@225: { c@225: BPOCounter++ ; c@225: c@225: pre = chroma[ i - 1 ]; c@225: current = chroma[ i ]; c@225: post = chroma[ i + 1 ]; c@225: c@225: if( (current > 0) && (current > pre) && (current > post) ) c@225: { c@225: peaks.push_back( BPOCounter + 1 ); c@225: } c@225: c@225: if( BPOCounter == (PO - 1) ) c@225: { c@225: BPOCounter = 1; c@225: i+=2; c@225: } c@225: } c@225: */ c@225: return peaks; c@225: } c@225: c@225: vector ChromaProcess::mod(vector input, int res) c@225: { c@225: vector result; c@225: c@225: for( unsigned int i = 0; i < input.size(); i++ ) c@225: { c@225: int val = input[ i ]; c@225: int res = val - res * floor( (double)val / (double)res ); c@225: c@225: if( val != 0 ) c@225: { c@225: if( res == 0 ) c@225: res = 3; c@225: c@225: result.push_back( res ); c@225: } c@225: else c@225: { c@225: result.push_back( val ); c@225: } c@225: } c@225: return result; c@225: } c@225: c@225: void ChromaProcess::findHistMaxMin( vector hist, double* max, int* maxIdx, double* min, int* minIdx ) c@225: { c@225: double temp = 0.0; c@225: unsigned int vecLength = hist.size(); c@225: c@225: *minIdx = 0; c@225: *maxIdx = 0; c@225: c@225: *min = hist[0]; c@225: *max = *min; c@225: c@225: for( unsigned int u = 0; u < vecLength; u++ ) c@225: { c@225: temp = hist[ u ]; c@225: c@225: if( temp < *min ) c@225: { c@225: *min = temp ; c@225: *minIdx = u; c@225: } c@225: if( temp > *max ) c@225: { c@225: *max = temp ; c@225: *maxIdx = u; c@225: } c@225: c@225: } c@225: }