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