adamstark@38: //=======================================================================
adamstark@38: /** @file OnsetDetectionFunction.cpp
adamstark@38: * @brief A class for calculating onset detection functions
adamstark@38: * @author Adam Stark
adamstark@38: * @copyright Copyright (C) 2008-2014 Queen Mary University of London
adamstark@38: *
adamstark@38: * This program is free software: you can redistribute it and/or modify
adamstark@38: * it under the terms of the GNU General Public License as published by
adamstark@38: * the Free Software Foundation, either version 3 of the License, or
adamstark@38: * (at your option) any later version.
adamstark@38: *
adamstark@38: * This program is distributed in the hope that it will be useful,
adamstark@38: * but WITHOUT ANY WARRANTY; without even the implied warranty of
adamstark@38: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
adamstark@38: * GNU General Public License for more details.
adamstark@38: *
adamstark@38: * You should have received a copy of the GNU General Public License
adamstark@38: * along with this program. If not, see .
adamstark@38: */
adamstark@38: //=======================================================================
adamstark@38:
adamstark@38: #include
adamstark@38: #include "OnsetDetectionFunction.h"
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: OnsetDetectionFunction::OnsetDetectionFunction (int hopSize_,int frameSize_)
adamstark@92: : onsetDetectionFunctionType (ComplexSpectralDifferenceHWR), windowType (HanningWindow)
adamstark@66: {
adamstark@66: // indicate that we have not initialised yet
adamstark@66: initialised = false;
adamstark@66:
adamstark@66: // set pi
adamstark@66: pi = 3.14159265358979;
adamstark@66:
adamstark@66: // initialise with arguments to constructor
adamstark@92: initialise (hopSize_, frameSize_, ComplexSpectralDifferenceHWR, HanningWindow);
adamstark@66: }
adamstark@66:
adamstark@66: //=======================================================================
adamstark@92: OnsetDetectionFunction::OnsetDetectionFunction(int hopSize_,int frameSize_,int onsetDetectionFunctionType_,int windowType_)
adamstark@92: : onsetDetectionFunctionType (ComplexSpectralDifferenceHWR), windowType (HanningWindow)
adamstark@38: {
adamstark@38: // indicate that we have not initialised yet
adamstark@64: initialised = false;
adamstark@38:
adamstark@38: // set pi
adamstark@38: pi = 3.14159265358979;
adamstark@38:
adamstark@38: // initialise with arguments to constructor
adamstark@92: initialise (hopSize_, frameSize_, onsetDetectionFunctionType_, windowType_);
adamstark@38: }
adamstark@38:
adamstark@38:
adamstark@52: //=======================================================================
adamstark@59: OnsetDetectionFunction::~OnsetDetectionFunction()
adamstark@38: {
adamstark@64: if (initialised)
adamstark@64: {
adamstark@93: freeFFT();
adamstark@64: }
adamstark@38: }
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: void OnsetDetectionFunction::initialise (int hopSize_, int frameSize_)
adamstark@66: {
adamstark@66: // use the already initialised onset detection function and window type and
adamstark@66: // pass the new frame and hop size to the main initialisation function
adamstark@92: initialise (hopSize_, frameSize_, onsetDetectionFunctionType, windowType);
adamstark@66: }
adamstark@66:
adamstark@66: //=======================================================================
adamstark@66: void OnsetDetectionFunction::initialise(int hopSize_,int frameSize_,int onsetDetectionFunctionType_,int windowType_)
adamstark@38: {
adamstark@59: hopSize = hopSize_; // set hopsize
adamstark@59: frameSize = frameSize_; // set framesize
adamstark@38:
adamstark@59: onsetDetectionFunctionType = onsetDetectionFunctionType_; // set detection function type
adamstark@66: windowType = windowType_; // set window type
adamstark@38:
adamstark@38: // initialise buffers
adamstark@92: frame.resize (frameSize);
adamstark@92: window.resize (frameSize);
adamstark@92: magSpec.resize (frameSize);
adamstark@92: prevMagSpec.resize (frameSize);
adamstark@92: phase.resize (frameSize);
adamstark@92: prevPhase.resize (frameSize);
adamstark@92: prevPhase2.resize (frameSize);
adamstark@38:
adamstark@38:
adamstark@38: // set the window to the specified type
adamstark@92: switch (windowType)
adamstark@92: {
adamstark@57: case RectangularWindow:
adamstark@59: calculateRectangularWindow(); // Rectangular window
adamstark@38: break;
adamstark@57: case HanningWindow:
adamstark@59: calculateHanningWindow(); // Hanning Window
adamstark@38: break;
adamstark@57: case HammingWindow:
adamstark@59: calclulateHammingWindow(); // Hamming Window
adamstark@38: break;
adamstark@57: case BlackmanWindow:
adamstark@59: calculateBlackmanWindow(); // Blackman Window
adamstark@38: break;
adamstark@57: case TukeyWindow:
adamstark@59: calculateTukeyWindow(); // Tukey Window
adamstark@38: break;
adamstark@38: default:
adamstark@59: calculateHanningWindow(); // DEFAULT: Hanning Window
adamstark@38: }
adamstark@38:
adamstark@38: // initialise previous magnitude spectrum to zero
adamstark@92: for (int i = 0; i < frameSize; i++)
adamstark@38: {
adamstark@59: prevMagSpec[i] = 0.0;
adamstark@59: prevPhase[i] = 0.0;
adamstark@59: prevPhase2[i] = 0.0;
adamstark@38: frame[i] = 0.0;
adamstark@38: }
adamstark@38:
adamstark@59: prevEnergySum = 0.0; // initialise previous energy sum value to zero
adamstark@38:
adamstark@93: initialiseFFT();
adamstark@93: }
adamstark@93:
adamstark@93: //=======================================================================
adamstark@93: void OnsetDetectionFunction::initialiseFFT()
adamstark@93: {
adamstark@93: if (initialised) // if we have already initialised FFT plan
adamstark@93: {
adamstark@93: freeFFT();
adamstark@93: }
adamstark@93:
adamstark@93: #ifdef USE_FFTW
adamstark@93: complexIn = (fftw_complex*) fftw_malloc (sizeof(fftw_complex) * frameSize); // complex array to hold fft data
adamstark@93: complexOut = (fftw_complex*) fftw_malloc (sizeof(fftw_complex) * frameSize); // complex array to hold fft data
adamstark@93: p = fftw_plan_dft_1d (frameSize, complexIn, complexOut, FFTW_FORWARD, FFTW_ESTIMATE); // FFT plan initialisation
adamstark@93: #endif
adamstark@93:
adamstark@93: #ifdef USE_KISS_FFT
adamstark@93: complexOut.resize (frameSize);
adamstark@93:
adamstark@93: for (int i = 0; i < frameSize;i++)
adamstark@93: {
adamstark@93: complexOut[i].resize(2);
adamstark@93: }
adamstark@93:
adamstark@93: fftIn = new kiss_fft_cpx[frameSize];
adamstark@93: fftOut = new kiss_fft_cpx[frameSize];
adamstark@93: cfg = kiss_fft_alloc (frameSize, 0, 0, 0);
adamstark@93: #endif
adamstark@93:
adamstark@93: initialised = true;
adamstark@93: }
adamstark@93:
adamstark@93: //=======================================================================
adamstark@93: void OnsetDetectionFunction::freeFFT()
adamstark@93: {
adamstark@93: #ifdef USE_FFTW
adamstark@93: fftw_destroy_plan (p);
adamstark@93: fftw_free (complexIn);
adamstark@93: fftw_free (complexOut);
adamstark@93: #endif
adamstark@93:
adamstark@93: #ifdef USE_KISS_FFT
adamstark@93: free (cfg);
adamstark@93: delete [] fftIn;
adamstark@93: delete [] fftOut;
adamstark@93: #endif
adamstark@38: }
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: void OnsetDetectionFunction::setOnsetDetectionFunctionType (int onsetDetectionFunctionType_)
adamstark@38: {
adamstark@59: onsetDetectionFunctionType = onsetDetectionFunctionType_; // set detection function type
adamstark@38: }
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: double OnsetDetectionFunction::calculateOnsetDetectionFunctionSample (double* buffer)
adamstark@38: {
adamstark@59: double odfSample;
adamstark@38:
adamstark@38: // shift audio samples back in frame by hop size
adamstark@59: for (int i = 0; i < (frameSize-hopSize);i++)
adamstark@38: {
adamstark@59: frame[i] = frame[i+hopSize];
adamstark@38: }
adamstark@38:
adamstark@38: // add new samples to frame from input buffer
adamstark@38: int j = 0;
adamstark@59: for (int i = (frameSize-hopSize);i < frameSize;i++)
adamstark@38: {
adamstark@59: frame[i] = buffer[j];
adamstark@38: j++;
adamstark@38: }
adamstark@38:
adamstark@92: switch (onsetDetectionFunctionType)
adamstark@92: {
adamstark@57: case EnergyEnvelope:
adamstark@57: {
adamstark@57: // calculate energy envelope detection function sample
adamstark@59: odfSample = energyEnvelope();
adamstark@38: break;
adamstark@57: }
adamstark@57: case EnergyDifference:
adamstark@57: {
adamstark@57: // calculate half-wave rectified energy difference detection function sample
adamstark@59: odfSample = energyDifference();
adamstark@38: break;
adamstark@57: }
adamstark@57: case SpectralDifference:
adamstark@57: {
adamstark@57: // calculate spectral difference detection function sample
adamstark@59: odfSample = spectralDifference();
adamstark@38: break;
adamstark@57: }
adamstark@57: case SpectralDifferenceHWR:
adamstark@57: {
adamstark@57: // calculate spectral difference detection function sample (half wave rectified)
adamstark@59: odfSample = spectralDifferenceHWR();
adamstark@38: break;
adamstark@57: }
adamstark@57: case PhaseDeviation:
adamstark@57: {
adamstark@57: // calculate phase deviation detection function sample (half wave rectified)
adamstark@59: odfSample = phaseDeviation();
adamstark@38: break;
adamstark@57: }
adamstark@57: case ComplexSpectralDifference:
adamstark@57: {
adamstark@57: // calcualte complex spectral difference detection function sample
adamstark@59: odfSample = complexSpectralDifference();
adamstark@38: break;
adamstark@57: }
adamstark@57: case ComplexSpectralDifferenceHWR:
adamstark@57: {
adamstark@57: // calcualte complex spectral difference detection function sample (half-wave rectified)
adamstark@59: odfSample = complexSpectralDifferenceHWR();
adamstark@38: break;
adamstark@57: }
adamstark@57: case HighFrequencyContent:
adamstark@57: {
adamstark@57: // calculate high frequency content detection function sample
adamstark@59: odfSample = highFrequencyContent();
adamstark@38: break;
adamstark@57: }
adamstark@57: case HighFrequencySpectralDifference:
adamstark@57: {
adamstark@57: // calculate high frequency spectral difference detection function sample
adamstark@59: odfSample = highFrequencySpectralDifference();
adamstark@38: break;
adamstark@57: }
adamstark@57: case HighFrequencySpectralDifferenceHWR:
adamstark@57: {
adamstark@57: // calculate high frequency spectral difference detection function (half-wave rectified)
adamstark@59: odfSample = highFrequencySpectralDifferenceHWR();
adamstark@57: break;
adamstark@57: }
adamstark@38: default:
adamstark@57: {
adamstark@59: odfSample = 1.0;
adamstark@57: }
adamstark@38: }
adamstark@38:
adamstark@59: return odfSample;
adamstark@38: }
adamstark@38:
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: void OnsetDetectionFunction::performFFT()
adamstark@38: {
adamstark@93: int fsize2 = (frameSize/2);
adamstark@93:
adamstark@93: #ifdef USE_FFTW
adamstark@38: // window frame and copy to complex array, swapping the first and second half of the signal
adamstark@38: for (int i = 0;i < fsize2;i++)
adamstark@38: {
adamstark@93: complexIn[i][0] = frame[i + fsize2] * window[i + fsize2];
adamstark@59: complexIn[i][1] = 0.0;
adamstark@59: complexIn[i+fsize2][0] = frame[i] * window[i];
adamstark@59: complexIn[i+fsize2][1] = 0.0;
adamstark@38: }
adamstark@38:
adamstark@38: // perform the fft
adamstark@92: fftw_execute (p);
adamstark@93: #endif
adamstark@93:
adamstark@93: #ifdef USE_KISS_FFT
adamstark@93: for (int i = 0; i < fsize2; i++)
adamstark@93: {
adamstark@93: fftIn[i].r = frame[i + fsize2] * window[i + fsize2];
adamstark@93: fftIn[i].i = 0.0;
adamstark@93: fftIn[i + fsize2].r = frame[i] * window[i];
adamstark@93: fftIn[i + fsize2].i = 0.0;
adamstark@93: }
adamstark@93:
adamstark@93: // execute kiss fft
adamstark@93: kiss_fft (cfg, fftIn, fftOut);
adamstark@93:
adamstark@93: // store real and imaginary parts of FFT
adamstark@93: for (int i = 0; i < frameSize; i++)
adamstark@93: {
adamstark@93: complexOut[i][0] = fftOut[i].r;
adamstark@93: complexOut[i][1] = fftOut[i].i;
adamstark@93: }
adamstark@93: #endif
adamstark@38: }
adamstark@38:
adamstark@38: ////////////////////////////////////////////////////////////////////////////////////////////////
adamstark@38: ////////////////////////////////////////////////////////////////////////////////////////////////
adamstark@38: ////////////////////////////// Methods for Detection Functions /////////////////////////////////
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: double OnsetDetectionFunction::energyEnvelope()
adamstark@38: {
adamstark@38: double sum;
adamstark@38:
adamstark@38: sum = 0; // initialise sum
adamstark@38:
adamstark@38: // sum the squares of the samples
adamstark@59: for (int i = 0;i < frameSize;i++)
adamstark@38: {
adamstark@92: sum = sum + (frame[i] * frame[i]);
adamstark@38: }
adamstark@38:
adamstark@38: return sum; // return sum
adamstark@38: }
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: double OnsetDetectionFunction::energyDifference()
adamstark@38: {
adamstark@38: double sum;
adamstark@38: double sample;
adamstark@38:
adamstark@38: sum = 0; // initialise sum
adamstark@38:
adamstark@38: // sum the squares of the samples
adamstark@92: for (int i = 0; i < frameSize; i++)
adamstark@38: {
adamstark@92: sum = sum + (frame[i] * frame[i]);
adamstark@38: }
adamstark@38:
adamstark@59: sample = sum - prevEnergySum; // sample is first order difference in energy
adamstark@38:
adamstark@59: prevEnergySum = sum; // store energy value for next calculation
adamstark@38:
adamstark@38: if (sample > 0)
adamstark@38: {
adamstark@38: return sample; // return difference
adamstark@38: }
adamstark@38: else
adamstark@38: {
adamstark@38: return 0;
adamstark@38: }
adamstark@38: }
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: double OnsetDetectionFunction::spectralDifference()
adamstark@38: {
adamstark@38: double diff;
adamstark@38: double sum;
adamstark@38:
adamstark@38: // perform the FFT
adamstark@59: performFFT();
adamstark@38:
adamstark@38: // compute first (N/2)+1 mag values
adamstark@59: for (int i = 0;i < (frameSize/2)+1;i++)
adamstark@38: {
adamstark@93: magSpec[i] = sqrt (pow (complexOut[i][0], 2) + pow (complexOut[i][1], 2));
adamstark@38: }
adamstark@38: // mag spec symmetric above (N/2)+1 so copy previous values
adamstark@92: for (int i = (frameSize/2)+1; i < frameSize; i++)
adamstark@38: {
adamstark@59: magSpec[i] = magSpec[frameSize-i];
adamstark@38: }
adamstark@38:
adamstark@38: sum = 0; // initialise sum to zero
adamstark@38:
adamstark@92: for (int i = 0; i < frameSize; i++)
adamstark@38: {
adamstark@38: // calculate difference
adamstark@59: diff = magSpec[i] - prevMagSpec[i];
adamstark@38:
adamstark@38: // ensure all difference values are positive
adamstark@38: if (diff < 0)
adamstark@38: {
adamstark@38: diff = diff*-1;
adamstark@38: }
adamstark@38:
adamstark@38: // add difference to sum
adamstark@92: sum = sum + diff;
adamstark@38:
adamstark@38: // store magnitude spectrum bin for next detection function sample calculation
adamstark@59: prevMagSpec[i] = magSpec[i];
adamstark@38: }
adamstark@38:
adamstark@38: return sum;
adamstark@38: }
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: double OnsetDetectionFunction::spectralDifferenceHWR()
adamstark@38: {
adamstark@38: double diff;
adamstark@38: double sum;
adamstark@38:
adamstark@38: // perform the FFT
adamstark@59: performFFT();
adamstark@38:
adamstark@38: // compute first (N/2)+1 mag values
adamstark@92: for (int i = 0;i < (frameSize/2) + 1; i++)
adamstark@38: {
adamstark@92: magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow (complexOut[i][1],2));
adamstark@38: }
adamstark@38: // mag spec symmetric above (N/2)+1 so copy previous values
adamstark@59: for (int i = (frameSize/2)+1;i < frameSize;i++)
adamstark@38: {
adamstark@59: magSpec[i] = magSpec[frameSize-i];
adamstark@38: }
adamstark@38:
adamstark@38: sum = 0; // initialise sum to zero
adamstark@38:
adamstark@59: for (int i = 0;i < frameSize;i++)
adamstark@38: {
adamstark@38: // calculate difference
adamstark@59: diff = magSpec[i] - prevMagSpec[i];
adamstark@38:
adamstark@38: // only add up positive differences
adamstark@38: if (diff > 0)
adamstark@38: {
adamstark@38: // add difference to sum
adamstark@38: sum = sum+diff;
adamstark@38: }
adamstark@38:
adamstark@38: // store magnitude spectrum bin for next detection function sample calculation
adamstark@59: prevMagSpec[i] = magSpec[i];
adamstark@38: }
adamstark@38:
adamstark@38: return sum;
adamstark@38: }
adamstark@38:
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: double OnsetDetectionFunction::phaseDeviation()
adamstark@38: {
adamstark@38: double dev,pdev;
adamstark@38: double sum;
adamstark@38:
adamstark@38: // perform the FFT
adamstark@59: performFFT();
adamstark@38:
adamstark@38: sum = 0; // initialise sum to zero
adamstark@38:
adamstark@38: // compute phase values from fft output and sum deviations
adamstark@59: for (int i = 0;i < frameSize;i++)
adamstark@38: {
adamstark@38: // calculate phase value
adamstark@93: phase[i] = atan2 (complexOut[i][1], complexOut[i][0]);
adamstark@38:
adamstark@38: // calculate magnitude value
adamstark@92: magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow (complexOut[i][1],2));
adamstark@38:
adamstark@38:
adamstark@38: // if bin is not just a low energy bin then examine phase deviation
adamstark@59: if (magSpec[i] > 0.1)
adamstark@38: {
adamstark@59: dev = phase[i] - (2*prevPhase[i]) + prevPhase2[i]; // phase deviation
adamstark@92: pdev = princarg (dev); // wrap into [-pi,pi] range
adamstark@38:
adamstark@38: // make all values positive
adamstark@38: if (pdev < 0)
adamstark@38: {
adamstark@38: pdev = pdev*-1;
adamstark@38: }
adamstark@38:
adamstark@38: // add to sum
adamstark@38: sum = sum + pdev;
adamstark@38: }
adamstark@38:
adamstark@38: // store values for next calculation
adamstark@59: prevPhase2[i] = prevPhase[i];
adamstark@59: prevPhase[i] = phase[i];
adamstark@38: }
adamstark@38:
adamstark@38: return sum;
adamstark@38: }
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: double OnsetDetectionFunction::complexSpectralDifference()
adamstark@38: {
adamstark@86: double phaseDeviation;
adamstark@38: double sum;
adamstark@86: double csd;
adamstark@38:
adamstark@38: // perform the FFT
adamstark@59: performFFT();
adamstark@38:
adamstark@38: sum = 0; // initialise sum to zero
adamstark@38:
adamstark@38: // compute phase values from fft output and sum deviations
adamstark@59: for (int i = 0;i < frameSize;i++)
adamstark@38: {
adamstark@38: // calculate phase value
adamstark@93: phase[i] = atan2 (complexOut[i][1], complexOut[i][0]);
adamstark@38:
adamstark@38: // calculate magnitude value
adamstark@92: magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow(complexOut[i][1],2));
adamstark@38:
adamstark@86: // phase deviation
adamstark@92: phaseDeviation = phase[i] - (2 * prevPhase[i]) + prevPhase2[i];
adamstark@38:
adamstark@86: // calculate complex spectral difference for the current spectral bin
adamstark@92: csd = sqrt (pow (magSpec[i], 2) + pow (prevMagSpec[i], 2) - 2 * magSpec[i] * prevMagSpec[i] * cos (phaseDeviation));
adamstark@38:
adamstark@38: // add to sum
adamstark@86: sum = sum + csd;
adamstark@38:
adamstark@38: // store values for next calculation
adamstark@59: prevPhase2[i] = prevPhase[i];
adamstark@59: prevPhase[i] = phase[i];
adamstark@59: prevMagSpec[i] = magSpec[i];
adamstark@38: }
adamstark@38:
adamstark@38: return sum;
adamstark@38: }
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: double OnsetDetectionFunction::complexSpectralDifferenceHWR()
adamstark@38: {
adamstark@86: double phaseDeviation;
adamstark@38: double sum;
adamstark@86: double magnitudeDifference;
adamstark@86: double csd;
adamstark@38:
adamstark@38: // perform the FFT
adamstark@59: performFFT();
adamstark@38:
adamstark@38: sum = 0; // initialise sum to zero
adamstark@38:
adamstark@38: // compute phase values from fft output and sum deviations
adamstark@59: for (int i = 0;i < frameSize;i++)
adamstark@38: {
adamstark@38: // calculate phase value
adamstark@93: phase[i] = atan2 (complexOut[i][1], complexOut[i][0]);
adamstark@38:
adamstark@38: // calculate magnitude value
adamstark@92: magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow(complexOut[i][1],2));
adamstark@38:
adamstark@86: // phase deviation
adamstark@92: phaseDeviation = phase[i] - (2 * prevPhase[i]) + prevPhase2[i];
adamstark@86:
adamstark@86: // calculate magnitude difference (real part of Euclidean distance between complex frames)
adamstark@86: magnitudeDifference = magSpec[i] - prevMagSpec[i];
adamstark@86:
adamstark@86: // if we have a positive change in magnitude, then include in sum, otherwise ignore (half-wave rectification)
adamstark@86: if (magnitudeDifference > 0)
adamstark@86: {
adamstark@86: // calculate complex spectral difference for the current spectral bin
adamstark@92: csd = sqrt (pow (magSpec[i], 2) + pow (prevMagSpec[i], 2) - 2 * magSpec[i] * prevMagSpec[i] * cos (phaseDeviation));
adamstark@86:
adamstark@86: // add to sum
adamstark@86: sum = sum + csd;
adamstark@86: }
adamstark@86:
adamstark@38: // store values for next calculation
adamstark@59: prevPhase2[i] = prevPhase[i];
adamstark@59: prevPhase[i] = phase[i];
adamstark@59: prevMagSpec[i] = magSpec[i];
adamstark@38: }
adamstark@38:
adamstark@38: return sum;
adamstark@38: }
adamstark@38:
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: double OnsetDetectionFunction::highFrequencyContent()
adamstark@38: {
adamstark@38: double sum;
adamstark@38:
adamstark@38: // perform the FFT
adamstark@59: performFFT();
adamstark@38:
adamstark@38: sum = 0; // initialise sum to zero
adamstark@38:
adamstark@38: // compute phase values from fft output and sum deviations
adamstark@92: for (int i = 0; i < frameSize; i++)
adamstark@38: {
adamstark@38: // calculate magnitude value
adamstark@92: magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow (complexOut[i][1],2));
adamstark@38:
adamstark@38:
adamstark@92: sum = sum + (magSpec[i] * ((double) (i+1)));
adamstark@38:
adamstark@38: // store values for next calculation
adamstark@59: prevMagSpec[i] = magSpec[i];
adamstark@38: }
adamstark@38:
adamstark@38: return sum;
adamstark@38: }
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: double OnsetDetectionFunction::highFrequencySpectralDifference()
adamstark@38: {
adamstark@38: double sum;
adamstark@38: double mag_diff;
adamstark@38:
adamstark@38: // perform the FFT
adamstark@59: performFFT();
adamstark@38:
adamstark@38: sum = 0; // initialise sum to zero
adamstark@38:
adamstark@38: // compute phase values from fft output and sum deviations
adamstark@59: for (int i = 0;i < frameSize;i++)
adamstark@38: {
adamstark@38: // calculate magnitude value
adamstark@92: magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow (complexOut[i][1],2));
adamstark@38:
adamstark@38: // calculate difference
adamstark@59: mag_diff = magSpec[i] - prevMagSpec[i];
adamstark@38:
adamstark@38: if (mag_diff < 0)
adamstark@38: {
adamstark@38: mag_diff = -mag_diff;
adamstark@38: }
adamstark@38:
adamstark@92: sum = sum + (mag_diff * ((double) (i+1)));
adamstark@38:
adamstark@38: // store values for next calculation
adamstark@59: prevMagSpec[i] = magSpec[i];
adamstark@38: }
adamstark@38:
adamstark@38: return sum;
adamstark@38: }
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: double OnsetDetectionFunction::highFrequencySpectralDifferenceHWR()
adamstark@38: {
adamstark@38: double sum;
adamstark@38: double mag_diff;
adamstark@38:
adamstark@38: // perform the FFT
adamstark@59: performFFT();
adamstark@38:
adamstark@38: sum = 0; // initialise sum to zero
adamstark@38:
adamstark@38: // compute phase values from fft output and sum deviations
adamstark@59: for (int i = 0;i < frameSize;i++)
adamstark@38: {
adamstark@38: // calculate magnitude value
adamstark@92: magSpec[i] = sqrt (pow (complexOut[i][0],2) + pow (complexOut[i][1],2));
adamstark@38:
adamstark@38: // calculate difference
adamstark@59: mag_diff = magSpec[i] - prevMagSpec[i];
adamstark@38:
adamstark@38: if (mag_diff > 0)
adamstark@38: {
adamstark@92: sum = sum + (mag_diff * ((double) (i+1)));
adamstark@38: }
adamstark@38:
adamstark@38: // store values for next calculation
adamstark@59: prevMagSpec[i] = magSpec[i];
adamstark@38: }
adamstark@38:
adamstark@38: return sum;
adamstark@38: }
adamstark@38:
adamstark@38:
adamstark@38: ////////////////////////////////////////////////////////////////////////////////////////////////
adamstark@38: ////////////////////////////////////////////////////////////////////////////////////////////////
adamstark@38: ////////////////////////////// Methods to Calculate Windows ////////////////////////////////////
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: void OnsetDetectionFunction::calculateHanningWindow()
adamstark@38: {
adamstark@38: double N; // variable to store framesize minus 1
adamstark@38:
adamstark@59: N = (double) (frameSize-1); // framesize minus 1
adamstark@38:
adamstark@38: // Hanning window calculation
adamstark@92: for (int n = 0; n < frameSize; n++)
adamstark@38: {
adamstark@92: window[n] = 0.5 * (1 - cos (2 * pi * (n / N)));
adamstark@38: }
adamstark@38: }
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: void OnsetDetectionFunction::calclulateHammingWindow()
adamstark@38: {
adamstark@38: double N; // variable to store framesize minus 1
adamstark@38: double n_val; // double version of index 'n'
adamstark@38:
adamstark@59: N = (double) (frameSize-1); // framesize minus 1
adamstark@38: n_val = 0;
adamstark@38:
adamstark@38: // Hamming window calculation
adamstark@59: for (int n = 0;n < frameSize;n++)
adamstark@38: {
adamstark@92: window[n] = 0.54 - (0.46 * cos (2 * pi * (n_val/N)));
adamstark@38: n_val = n_val+1;
adamstark@38: }
adamstark@38: }
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: void OnsetDetectionFunction::calculateBlackmanWindow()
adamstark@38: {
adamstark@38: double N; // variable to store framesize minus 1
adamstark@38: double n_val; // double version of index 'n'
adamstark@38:
adamstark@59: N = (double) (frameSize-1); // framesize minus 1
adamstark@38: n_val = 0;
adamstark@38:
adamstark@38: // Blackman window calculation
adamstark@59: for (int n = 0;n < frameSize;n++)
adamstark@38: {
adamstark@38: window[n] = 0.42 - (0.5*cos(2*pi*(n_val/N))) + (0.08*cos(4*pi*(n_val/N)));
adamstark@38: n_val = n_val+1;
adamstark@38: }
adamstark@38: }
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: void OnsetDetectionFunction::calculateTukeyWindow()
adamstark@38: {
adamstark@38: double N; // variable to store framesize minus 1
adamstark@38: double n_val; // double version of index 'n'
adamstark@38: double alpha; // alpha [default value = 0.5];
adamstark@38:
adamstark@38: alpha = 0.5;
adamstark@38:
adamstark@59: N = (double) (frameSize-1); // framesize minus 1
adamstark@38:
adamstark@38: // Tukey window calculation
adamstark@38:
adamstark@59: n_val = (double) (-1*((frameSize/2)))+1;
adamstark@38:
adamstark@59: for (int n = 0;n < frameSize;n++) // left taper
adamstark@38: {
adamstark@38: if ((n_val >= 0) && (n_val <= (alpha*(N/2))))
adamstark@38: {
adamstark@38: window[n] = 1.0;
adamstark@38: }
adamstark@38: else if ((n_val <= 0) && (n_val >= (-1*alpha*(N/2))))
adamstark@38: {
adamstark@38: window[n] = 1.0;
adamstark@38: }
adamstark@38: else
adamstark@38: {
adamstark@38: window[n] = 0.5*(1+cos(pi*(((2*n_val)/(alpha*N))-1)));
adamstark@38: }
adamstark@38:
adamstark@38: n_val = n_val+1;
adamstark@38: }
adamstark@38:
adamstark@38: }
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: void OnsetDetectionFunction::calculateRectangularWindow()
adamstark@38: {
adamstark@38: // Rectangular window calculation
adamstark@59: for (int n = 0;n < frameSize;n++)
adamstark@38: {
adamstark@38: window[n] = 1.0;
adamstark@38: }
adamstark@38: }
adamstark@38:
adamstark@38: ////////////////////////////////////////////////////////////////////////////////////////////////
adamstark@38: ////////////////////////////////////////////////////////////////////////////////////////////////
adamstark@38: ///////////////////////////////// Other Handy Methods //////////////////////////////////////////
adamstark@38:
adamstark@52: //=======================================================================
adamstark@92: double OnsetDetectionFunction::princarg(double phaseVal)
adamstark@38: {
adamstark@38: // if phase value is less than or equal to -pi then add 2*pi
adamstark@59: while (phaseVal <= (-pi))
adamstark@38: {
adamstark@92: phaseVal = phaseVal + (2 * pi);
adamstark@38: }
adamstark@38:
adamstark@38: // if phase value is larger than pi, then subtract 2*pi
adamstark@59: while (phaseVal > pi)
adamstark@38: {
adamstark@92: phaseVal = phaseVal - (2 * pi);
adamstark@38: }
adamstark@38:
adamstark@59: return phaseVal;
adamstark@38: }