adamstark@46: //=======================================================================
adamstark@46: /** @file OnsetDetectionFunction.cpp
adamstark@46: * @brief A class for calculating onset detection functions
adamstark@46: * @author Adam Stark
adamstark@46: * @copyright Copyright (C) 2008-2014 Queen Mary University of London
adamstark@46: *
adamstark@46: * This program is free software: you can redistribute it and/or modify
adamstark@46: * it under the terms of the GNU General Public License as published by
adamstark@46: * the Free Software Foundation, either version 3 of the License, or
adamstark@46: * (at your option) any later version.
adamstark@46: *
adamstark@46: * This program is distributed in the hope that it will be useful,
adamstark@46: * but WITHOUT ANY WARRANTY; without even the implied warranty of
adamstark@46: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
adamstark@46: * GNU General Public License for more details.
adamstark@46: *
adamstark@46: * You should have received a copy of the GNU General Public License
adamstark@46: * along with this program. If not, see .
adamstark@46: */
adamstark@46: //=======================================================================
adamstark@46:
adamstark@46: #include
adamstark@46: #include
adamstark@46: #include "OnsetDetectionFunction.h"
adamstark@46: using namespace std;
adamstark@46:
adamstark@46: //-------------------------------------------------------------------------------
adamstark@46: // Constructor
adamstark@46: OnsetDetectionFunction :: OnsetDetectionFunction()
adamstark@46: {
adamstark@46: // indicate that we have not initialised yet
adamstark@46: initialised = 0;
adamstark@46:
adamstark@46: // set pi
adamstark@46: pi = 3.14159265358979;
adamstark@46:
adamstark@46: // initialise with hopsize = 512, framesize = 1024, complex spectral difference DF and hanning window
adamstark@46: initialise(512,1024,6,1);
adamstark@46: }
adamstark@46:
adamstark@46:
adamstark@46: //-------------------------------------------------------------------------------
adamstark@46: // Constructor (with arguments)
adamstark@46: OnsetDetectionFunction :: OnsetDetectionFunction(int arg_hsize,int arg_fsize,int arg_df_type,int arg_win_type)
adamstark@46: {
adamstark@46: // indicate that we have not initialised yet
adamstark@46: initialised = 0;
adamstark@46:
adamstark@46: // set pi
adamstark@46: pi = 3.14159265358979;
adamstark@46:
adamstark@46: // initialise with arguments to constructor
adamstark@46: initialise(arg_hsize,arg_fsize,arg_df_type,arg_win_type);
adamstark@46: }
adamstark@46:
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // Destructor
adamstark@46: OnsetDetectionFunction :: ~OnsetDetectionFunction()
adamstark@46: {
adamstark@46: // destroy fft plan
adamstark@46: fftw_destroy_plan(p);
adamstark@46: fftw_free(in);
adamstark@46: fftw_free(out);
adamstark@46:
adamstark@46: // deallocate memory
adamstark@46: delete [] frame;
adamstark@46: frame = NULL;
adamstark@46: delete [] window;
adamstark@46: window = NULL;
adamstark@46: delete [] wframe;
adamstark@46: wframe = NULL;
adamstark@46: delete [] mag;
adamstark@46: mag = NULL;
adamstark@46: delete [] mag_old;
adamstark@46: mag_old = NULL;
adamstark@46: delete [] phase;
adamstark@46: phase = NULL;
adamstark@46: delete [] phase_old;
adamstark@46: phase_old = NULL;
adamstark@46: delete [] phase_old_2;
adamstark@46: phase_old_2 = NULL;
adamstark@46: }
adamstark@46:
adamstark@46: //-------------------------------------------------------------------------------
adamstark@46: // Initialisation
adamstark@46: void OnsetDetectionFunction :: initialise(int arg_hsize,int arg_fsize,int arg_df_type,int arg_win_type)
adamstark@46: {
adamstark@46: if (initialised == 1) // if we have already initialised some buffers and an FFT plan
adamstark@46: {
adamstark@46: //////////////////////////////////
adamstark@46: // TIDY UP FIRST - If initialise is called after the class has been initialised
adamstark@46: // then we want to free up memory and cancel existing FFT plans
adamstark@46:
adamstark@46: // destroy fft plan
adamstark@46: fftw_destroy_plan(p);
adamstark@46: fftw_free(in);
adamstark@46: fftw_free(out);
adamstark@46:
adamstark@46:
adamstark@46: // deallocate memory
adamstark@46: delete [] frame;
adamstark@46: frame = NULL;
adamstark@46: delete [] window;
adamstark@46: window = NULL;
adamstark@46: delete [] wframe;
adamstark@46: wframe = NULL;
adamstark@46: delete [] mag;
adamstark@46: mag = NULL;
adamstark@46: delete [] mag_old;
adamstark@46: mag_old = NULL;
adamstark@46: delete [] phase;
adamstark@46: phase = NULL;
adamstark@46: delete [] phase_old;
adamstark@46: phase_old = NULL;
adamstark@46: delete [] phase_old_2;
adamstark@46: phase_old_2 = NULL;
adamstark@46:
adamstark@46: ////// END TIDY UP ///////////////
adamstark@46: //////////////////////////////////
adamstark@46: }
adamstark@46:
adamstark@46: hopsize = arg_hsize; // set hopsize
adamstark@46: framesize = arg_fsize; // set framesize
adamstark@46:
adamstark@46: df_type = arg_df_type; // set detection function type
adamstark@46:
adamstark@46: // initialise buffers
adamstark@46: frame = new double[framesize];
adamstark@46: window = new double[framesize];
adamstark@46: wframe = new double[framesize];
adamstark@46:
adamstark@46: mag = new double[framesize];
adamstark@46: mag_old = new double[framesize];
adamstark@46:
adamstark@46: phase = new double[framesize];
adamstark@46: phase_old = new double[framesize];
adamstark@46: phase_old_2 = new double[framesize];
adamstark@46:
adamstark@46:
adamstark@46: // set the window to the specified type
adamstark@46: switch (arg_win_type){
adamstark@46: case 0:
adamstark@46: set_win_rectangular(); // Rectangular window
adamstark@46: break;
adamstark@46: case 1:
adamstark@46: set_win_hanning(); // Hanning Window
adamstark@46: break;
adamstark@46: case 2:
adamstark@46: set_win_hamming(); // Hamming Window
adamstark@46: break;
adamstark@46: case 3:
adamstark@46: set_win_blackman(); // Blackman Window
adamstark@46: break;
adamstark@46: case 4:
adamstark@46: set_win_tukey(); // Tukey Window
adamstark@46: break;
adamstark@46: default:
adamstark@46: set_win_hanning(); // DEFAULT: Hanning Window
adamstark@46: }
adamstark@46:
adamstark@46:
adamstark@46:
adamstark@46:
adamstark@46: // initialise previous magnitude spectrum to zero
adamstark@46: for (int i = 0;i < framesize;i++)
adamstark@46: {
adamstark@46: mag_old[i] = 0.0;
adamstark@46: phase_old[i] = 0.0;
adamstark@46: phase_old_2[i] = 0.0;
adamstark@46: frame[i] = 0.0;
adamstark@46: }
adamstark@46:
adamstark@46: energy_sum_old = 0.0; // initialise previous energy sum value to zero
adamstark@46:
adamstark@46: /* Init fft */
adamstark@46: in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * framesize); // complex array to hold fft data
adamstark@46: out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * framesize); // complex array to hold fft data
adamstark@46: p = fftw_plan_dft_1d(framesize, in, out, FFTW_FORWARD, FFTW_ESTIMATE); // FFT plan initialisation
adamstark@46:
adamstark@46: initialised = 1;
adamstark@46: }
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // set the detection function type to that specified by the argument
adamstark@46: void OnsetDetectionFunction :: set_df_type(int arg_df_type)
adamstark@46: {
adamstark@46: df_type = arg_df_type; // set detection function type
adamstark@46: }
adamstark@46:
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // calculates a single detection function sample from a single audio frame.
adamstark@46: double OnsetDetectionFunction :: getDFsample(double inputbuffer[])
adamstark@46: {
adamstark@46: double df_sample;
adamstark@46:
adamstark@46: // shift audio samples back in frame by hop size
adamstark@46: for (int i = 0; i < (framesize-hopsize);i++)
adamstark@46: {
adamstark@46: frame[i] = frame[i+hopsize];
adamstark@46: }
adamstark@46:
adamstark@46: // add new samples to frame from input buffer
adamstark@46: int j = 0;
adamstark@46: for (int i = (framesize-hopsize);i < framesize;i++)
adamstark@46: {
adamstark@46: frame[i] = inputbuffer[j];
adamstark@46: j++;
adamstark@46: }
adamstark@46:
adamstark@46: switch (df_type){
adamstark@46: case 0:
adamstark@46: df_sample = energy_envelope(); // calculate energy envelope detection function sample
adamstark@46: break;
adamstark@46: case 1:
adamstark@46: df_sample = energy_difference(); // calculate half-wave rectified energy difference detection function sample
adamstark@46: break;
adamstark@46: case 2:
adamstark@46: df_sample = spectral_difference(); // calculate spectral difference detection function sample
adamstark@46: break;
adamstark@46: case 3:
adamstark@46: df_sample = spectral_difference_hwr(); // calculate spectral difference detection function sample (half wave rectified)
adamstark@46: break;
adamstark@46: case 4:
adamstark@46: df_sample = phase_deviation(); // calculate phase deviation detection function sample (half wave rectified)
adamstark@46: break;
adamstark@46: case 5:
adamstark@46: df_sample = complex_spectral_difference(); // calcualte complex spectral difference detection function sample
adamstark@46: break;
adamstark@46: case 6:
adamstark@46: df_sample = complex_spectral_difference_hwr(); // calcualte complex spectral difference detection function sample (half-wave rectified)
adamstark@46: break;
adamstark@46: case 7:
adamstark@46: df_sample = high_frequency_content(); // calculate high frequency content detection function sample
adamstark@46: break;
adamstark@46: case 8:
adamstark@46: df_sample = high_frequency_spectral_difference(); // calculate high frequency spectral difference detection function sample
adamstark@46: break;
adamstark@46: case 9:
adamstark@46: df_sample = high_frequency_spectral_difference_hwr(); // calculate high frequency spectral difference detection function (half-wave rectified)
adamstark@46: break;
adamstark@46: default:
adamstark@46: df_sample = 1.0;
adamstark@46: }
adamstark@46:
adamstark@46: return df_sample;
adamstark@46: }
adamstark@46:
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // performs the fft, storing the complex result in 'out'
adamstark@46: void OnsetDetectionFunction :: perform_FFT()
adamstark@46: {
adamstark@46: int fsize2 = (framesize/2);
adamstark@46:
adamstark@46: // window frame and copy to complex array, swapping the first and second half of the signal
adamstark@46: for (int i = 0;i < fsize2;i++)
adamstark@46: {
adamstark@46: in[i][0] = frame[i+fsize2] * window[i+fsize2];
adamstark@46: in[i][1] = 0.0;
adamstark@46: in[i+fsize2][0] = frame[i] * window[i];
adamstark@46: in[i+fsize2][1] = 0.0;
adamstark@46: }
adamstark@46:
adamstark@46: // perform the fft
adamstark@46: fftw_execute(p);
adamstark@46: }
adamstark@46:
adamstark@46: ////////////////////////////////////////////////////////////////////////////////////////////////
adamstark@46: ////////////////////////////////////////////////////////////////////////////////////////////////
adamstark@46: ////////////////////////////// Methods for Detection Functions /////////////////////////////////
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // calculates an energy envelope detection function sample
adamstark@46: double OnsetDetectionFunction :: energy_envelope()
adamstark@46: {
adamstark@46: double sum;
adamstark@46:
adamstark@46: sum = 0; // initialise sum
adamstark@46:
adamstark@46: // sum the squares of the samples
adamstark@46: for (int i = 0;i < framesize;i++)
adamstark@46: {
adamstark@46: sum = sum + (frame[i]*frame[i]);
adamstark@46: }
adamstark@46:
adamstark@46: return sum; // return sum
adamstark@46: }
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // calculates a half-wave rectified energy difference detection function sample
adamstark@46: double OnsetDetectionFunction :: energy_difference()
adamstark@46: {
adamstark@46: double sum;
adamstark@46: double sample;
adamstark@46:
adamstark@46: sum = 0; // initialise sum
adamstark@46:
adamstark@46: // sum the squares of the samples
adamstark@46: for (int i = 0;i < framesize;i++)
adamstark@46: {
adamstark@46: sum = sum + (frame[i]*frame[i]);
adamstark@46: }
adamstark@46:
adamstark@46: sample = sum - energy_sum_old; // sample is first order difference in energy
adamstark@46:
adamstark@46: energy_sum_old = sum; // store energy value for next calculation
adamstark@46:
adamstark@46: if (sample > 0)
adamstark@46: {
adamstark@46: return sample; // return difference
adamstark@46: }
adamstark@46: else
adamstark@46: {
adamstark@46: return 0;
adamstark@46: }
adamstark@46: }
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // calculates a spectral difference detection function sample
adamstark@46: double OnsetDetectionFunction :: spectral_difference()
adamstark@46: {
adamstark@46: double diff;
adamstark@46: double sum;
adamstark@46:
adamstark@46: // perform the FFT
adamstark@46: perform_FFT();
adamstark@46:
adamstark@46: // compute first (N/2)+1 mag values
adamstark@46: for (int i = 0;i < (framesize/2)+1;i++)
adamstark@46: {
adamstark@46: mag[i] = sqrt(pow(out[i][0],2) + pow(out[i][1],2));
adamstark@46: }
adamstark@46: // mag spec symmetric above (N/2)+1 so copy previous values
adamstark@46: for (int i = (framesize/2)+1;i < framesize;i++)
adamstark@46: {
adamstark@46: mag[i] = mag[framesize-i];
adamstark@46: }
adamstark@46:
adamstark@46: sum = 0; // initialise sum to zero
adamstark@46:
adamstark@46: for (int i = 0;i < framesize;i++)
adamstark@46: {
adamstark@46: // calculate difference
adamstark@46: diff = mag[i] - mag_old[i];
adamstark@46:
adamstark@46: // ensure all difference values are positive
adamstark@46: if (diff < 0)
adamstark@46: {
adamstark@46: diff = diff*-1;
adamstark@46: }
adamstark@46:
adamstark@46: // add difference to sum
adamstark@46: sum = sum+diff;
adamstark@46:
adamstark@46: // store magnitude spectrum bin for next detection function sample calculation
adamstark@46: mag_old[i] = mag[i];
adamstark@46: }
adamstark@46:
adamstark@46: return sum;
adamstark@46: }
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // calculates a spectral difference detection function sample
adamstark@46: double OnsetDetectionFunction :: spectral_difference_hwr()
adamstark@46: {
adamstark@46: double diff;
adamstark@46: double sum;
adamstark@46:
adamstark@46: // perform the FFT
adamstark@46: perform_FFT();
adamstark@46:
adamstark@46: // compute first (N/2)+1 mag values
adamstark@46: for (int i = 0;i < (framesize/2)+1;i++)
adamstark@46: {
adamstark@46: mag[i] = sqrt(pow(out[i][0],2) + pow(out[i][1],2));
adamstark@46: }
adamstark@46: // mag spec symmetric above (N/2)+1 so copy previous values
adamstark@46: for (int i = (framesize/2)+1;i < framesize;i++)
adamstark@46: {
adamstark@46: mag[i] = mag[framesize-i];
adamstark@46: }
adamstark@46:
adamstark@46: sum = 0; // initialise sum to zero
adamstark@46:
adamstark@46: for (int i = 0;i < framesize;i++)
adamstark@46: {
adamstark@46: // calculate difference
adamstark@46: diff = mag[i] - mag_old[i];
adamstark@46:
adamstark@46: // only add up positive differences
adamstark@46: if (diff > 0)
adamstark@46: {
adamstark@46: // add difference to sum
adamstark@46: sum = sum+diff;
adamstark@46: }
adamstark@46:
adamstark@46:
adamstark@46:
adamstark@46: // store magnitude spectrum bin for next detection function sample calculation
adamstark@46: mag_old[i] = mag[i];
adamstark@46: }
adamstark@46:
adamstark@46: return sum;
adamstark@46: }
adamstark@46:
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // calculates a phase deviation detection function sample
adamstark@46: double OnsetDetectionFunction :: phase_deviation()
adamstark@46: {
adamstark@46: double dev,pdev;
adamstark@46: double sum;
adamstark@46:
adamstark@46: // perform the FFT
adamstark@46: perform_FFT();
adamstark@46:
adamstark@46: sum = 0; // initialise sum to zero
adamstark@46:
adamstark@46: // compute phase values from fft output and sum deviations
adamstark@46: for (int i = 0;i < framesize;i++)
adamstark@46: {
adamstark@46: // calculate phase value
adamstark@46: phase[i] = atan2(out[i][1],out[i][0]);
adamstark@46:
adamstark@46: // calculate magnitude value
adamstark@46: mag[i] = sqrt(pow(out[i][0],2) + pow(out[i][1],2));
adamstark@46:
adamstark@46:
adamstark@46: // if bin is not just a low energy bin then examine phase deviation
adamstark@46: if (mag[i] > 0.1)
adamstark@46: {
adamstark@46: dev = phase[i] - (2*phase_old[i]) + phase_old_2[i]; // phase deviation
adamstark@46: pdev = princarg(dev); // wrap into [-pi,pi] range
adamstark@46:
adamstark@46: // make all values positive
adamstark@46: if (pdev < 0)
adamstark@46: {
adamstark@46: pdev = pdev*-1;
adamstark@46: }
adamstark@46:
adamstark@46: // add to sum
adamstark@46: sum = sum + pdev;
adamstark@46: }
adamstark@46:
adamstark@46: // store values for next calculation
adamstark@46: phase_old_2[i] = phase_old[i];
adamstark@46: phase_old[i] = phase[i];
adamstark@46: }
adamstark@46:
adamstark@46: return sum;
adamstark@46: }
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // calculates a complex spectral difference detection function sample
adamstark@46: double OnsetDetectionFunction :: complex_spectral_difference()
adamstark@46: {
adamstark@46: double dev,pdev;
adamstark@46: double sum;
adamstark@46: double mag_diff,phase_diff;
adamstark@46: double value;
adamstark@46:
adamstark@46: // perform the FFT
adamstark@46: perform_FFT();
adamstark@46:
adamstark@46: sum = 0; // initialise sum to zero
adamstark@46:
adamstark@46: // compute phase values from fft output and sum deviations
adamstark@46: for (int i = 0;i < framesize;i++)
adamstark@46: {
adamstark@46: // calculate phase value
adamstark@46: phase[i] = atan2(out[i][1],out[i][0]);
adamstark@46:
adamstark@46: // calculate magnitude value
adamstark@46: mag[i] = sqrt(pow(out[i][0],2) + pow(out[i][1],2));
adamstark@46:
adamstark@46:
adamstark@46: // phase deviation
adamstark@46: dev = phase[i] - (2*phase_old[i]) + phase_old_2[i];
adamstark@46:
adamstark@46: // wrap into [-pi,pi] range
adamstark@46: pdev = princarg(dev);
adamstark@46:
adamstark@46:
adamstark@46: // calculate magnitude difference (real part of Euclidean distance between complex frames)
adamstark@46: mag_diff = mag[i] - mag_old[i];
adamstark@46:
adamstark@46: // calculate phase difference (imaginary part of Euclidean distance between complex frames)
adamstark@46: phase_diff = -mag[i]*sin(pdev);
adamstark@46:
adamstark@46:
adamstark@46:
adamstark@46: // square real and imaginary parts, sum and take square root
adamstark@46: value = sqrt(pow(mag_diff,2) + pow(phase_diff,2));
adamstark@46:
adamstark@46:
adamstark@46: // add to sum
adamstark@46: sum = sum + value;
adamstark@46:
adamstark@46:
adamstark@46: // store values for next calculation
adamstark@46: phase_old_2[i] = phase_old[i];
adamstark@46: phase_old[i] = phase[i];
adamstark@46: mag_old[i] = mag[i];
adamstark@46: }
adamstark@46:
adamstark@46: return sum;
adamstark@46: }
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // calculates a complex spectral difference detection function sample (half-wave rectified)
adamstark@46: double OnsetDetectionFunction :: complex_spectral_difference_hwr()
adamstark@46: {
adamstark@46: double dev,pdev;
adamstark@46: double sum;
adamstark@46: double mag_diff,phase_diff;
adamstark@46: double value;
adamstark@46:
adamstark@46: // perform the FFT
adamstark@46: perform_FFT();
adamstark@46:
adamstark@46: sum = 0; // initialise sum to zero
adamstark@46:
adamstark@46: // compute phase values from fft output and sum deviations
adamstark@46: for (int i = 0;i < framesize;i++)
adamstark@46: {
adamstark@46: // calculate phase value
adamstark@46: phase[i] = atan2(out[i][1],out[i][0]);
adamstark@46:
adamstark@46: // calculate magnitude value
adamstark@46: mag[i] = sqrt(pow(out[i][0],2) + pow(out[i][1],2));
adamstark@46:
adamstark@46:
adamstark@46: // phase deviation
adamstark@46: dev = phase[i] - (2*phase_old[i]) + phase_old_2[i];
adamstark@46:
adamstark@46: // wrap into [-pi,pi] range
adamstark@46: pdev = princarg(dev);
adamstark@46:
adamstark@46:
adamstark@46: // calculate magnitude difference (real part of Euclidean distance between complex frames)
adamstark@46: mag_diff = mag[i] - mag_old[i];
adamstark@46:
adamstark@46: // if we have a positive change in magnitude, then include in sum, otherwise ignore (half-wave rectification)
adamstark@46: if (mag_diff > 0)
adamstark@46: {
adamstark@46: // calculate phase difference (imaginary part of Euclidean distance between complex frames)
adamstark@46: phase_diff = -mag[i]*sin(pdev);
adamstark@46:
adamstark@46: // square real and imaginary parts, sum and take square root
adamstark@46: value = sqrt(pow(mag_diff,2) + pow(phase_diff,2));
adamstark@46:
adamstark@46: // add to sum
adamstark@46: sum = sum + value;
adamstark@46: }
adamstark@46:
adamstark@46: // store values for next calculation
adamstark@46: phase_old_2[i] = phase_old[i];
adamstark@46: phase_old[i] = phase[i];
adamstark@46: mag_old[i] = mag[i];
adamstark@46: }
adamstark@46:
adamstark@46: return sum;
adamstark@46: }
adamstark@46:
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // calculates a high frequency content detection function sample
adamstark@46: double OnsetDetectionFunction :: high_frequency_content()
adamstark@46: {
adamstark@46: double sum;
adamstark@46: double mag_diff;
adamstark@46:
adamstark@46: // perform the FFT
adamstark@46: perform_FFT();
adamstark@46:
adamstark@46: sum = 0; // initialise sum to zero
adamstark@46:
adamstark@46: // compute phase values from fft output and sum deviations
adamstark@46: for (int i = 0;i < framesize;i++)
adamstark@46: {
adamstark@46: // calculate magnitude value
adamstark@46: mag[i] = sqrt(pow(out[i][0],2) + pow(out[i][1],2));
adamstark@46:
adamstark@46:
adamstark@46: sum = sum + (mag[i]*((double) (i+1)));
adamstark@46:
adamstark@46: // store values for next calculation
adamstark@46: mag_old[i] = mag[i];
adamstark@46: }
adamstark@46:
adamstark@46: return sum;
adamstark@46: }
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // calculates a high frequency spectral difference detection function sample
adamstark@46: double OnsetDetectionFunction :: high_frequency_spectral_difference()
adamstark@46: {
adamstark@46: double sum;
adamstark@46: double mag_diff;
adamstark@46:
adamstark@46: // perform the FFT
adamstark@46: perform_FFT();
adamstark@46:
adamstark@46: sum = 0; // initialise sum to zero
adamstark@46:
adamstark@46: // compute phase values from fft output and sum deviations
adamstark@46: for (int i = 0;i < framesize;i++)
adamstark@46: {
adamstark@46: // calculate magnitude value
adamstark@46: mag[i] = sqrt(pow(out[i][0],2) + pow(out[i][1],2));
adamstark@46:
adamstark@46: // calculate difference
adamstark@46: mag_diff = mag[i] - mag_old[i];
adamstark@46:
adamstark@46: if (mag_diff < 0)
adamstark@46: {
adamstark@46: mag_diff = -mag_diff;
adamstark@46: }
adamstark@46:
adamstark@46: sum = sum + (mag_diff*((double) (i+1)));
adamstark@46:
adamstark@46: // store values for next calculation
adamstark@46: mag_old[i] = mag[i];
adamstark@46: }
adamstark@46:
adamstark@46: return sum;
adamstark@46: }
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // calculates a high frequency spectral difference detection function sample (half-wave rectified)
adamstark@46: double OnsetDetectionFunction :: high_frequency_spectral_difference_hwr()
adamstark@46: {
adamstark@46: double sum;
adamstark@46: double mag_diff;
adamstark@46:
adamstark@46: // perform the FFT
adamstark@46: perform_FFT();
adamstark@46:
adamstark@46: sum = 0; // initialise sum to zero
adamstark@46:
adamstark@46: // compute phase values from fft output and sum deviations
adamstark@46: for (int i = 0;i < framesize;i++)
adamstark@46: {
adamstark@46: // calculate magnitude value
adamstark@46: mag[i] = sqrt(pow(out[i][0],2) + pow(out[i][1],2));
adamstark@46:
adamstark@46: // calculate difference
adamstark@46: mag_diff = mag[i] - mag_old[i];
adamstark@46:
adamstark@46: if (mag_diff > 0)
adamstark@46: {
adamstark@46: sum = sum + (mag_diff*((double) (i+1)));
adamstark@46: }
adamstark@46:
adamstark@46: // store values for next calculation
adamstark@46: mag_old[i] = mag[i];
adamstark@46: }
adamstark@46:
adamstark@46: return sum;
adamstark@46: }
adamstark@46:
adamstark@46:
adamstark@46: ////////////////////////////////////////////////////////////////////////////////////////////////
adamstark@46: ////////////////////////////////////////////////////////////////////////////////////////////////
adamstark@46: ////////////////////////////// Methods to Calculate Windows ////////////////////////////////////
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // HANNING: set the window in the buffer 'window' to a Hanning window
adamstark@46: void OnsetDetectionFunction :: set_win_hanning()
adamstark@46: {
adamstark@46: double N; // variable to store framesize minus 1
adamstark@46:
adamstark@46: N = (double) (framesize-1); // framesize minus 1
adamstark@46:
adamstark@46: // Hanning window calculation
adamstark@46: for (int n = 0;n < framesize;n++)
adamstark@46: {
adamstark@46: window[n] = 0.5*(1-cos(2*pi*(n/N)));
adamstark@46: }
adamstark@46: }
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // HAMMING: set the window in the buffer 'window' to a Hanning window
adamstark@46: void OnsetDetectionFunction :: set_win_hamming()
adamstark@46: {
adamstark@46: double N; // variable to store framesize minus 1
adamstark@46: double n_val; // double version of index 'n'
adamstark@46:
adamstark@46: N = (double) (framesize-1); // framesize minus 1
adamstark@46: n_val = 0;
adamstark@46:
adamstark@46: // Hamming window calculation
adamstark@46: for (int n = 0;n < framesize;n++)
adamstark@46: {
adamstark@46: window[n] = 0.54 - (0.46*cos(2*pi*(n_val/N)));
adamstark@46: n_val = n_val+1;
adamstark@46: }
adamstark@46: }
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // BLACKMAN: set the window in the buffer 'window' to a Blackman window
adamstark@46: void OnsetDetectionFunction :: set_win_blackman()
adamstark@46: {
adamstark@46: double N; // variable to store framesize minus 1
adamstark@46: double n_val; // double version of index 'n'
adamstark@46:
adamstark@46: N = (double) (framesize-1); // framesize minus 1
adamstark@46: n_val = 0;
adamstark@46:
adamstark@46: // Blackman window calculation
adamstark@46: for (int n = 0;n < framesize;n++)
adamstark@46: {
adamstark@46: window[n] = 0.42 - (0.5*cos(2*pi*(n_val/N))) + (0.08*cos(4*pi*(n_val/N)));
adamstark@46: n_val = n_val+1;
adamstark@46: }
adamstark@46: }
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // TUKEY: set the window in the buffer 'window' to a Tukey window
adamstark@46: void OnsetDetectionFunction :: set_win_tukey()
adamstark@46: {
adamstark@46: double N; // variable to store framesize minus 1
adamstark@46: double n_val; // double version of index 'n'
adamstark@46: double alpha; // alpha [default value = 0.5];
adamstark@46:
adamstark@46: int lim1,lim2;
adamstark@46:
adamstark@46: alpha = 0.5;
adamstark@46:
adamstark@46: N = (double) (framesize-1); // framesize minus 1
adamstark@46:
adamstark@46: // Tukey window calculation
adamstark@46:
adamstark@46: n_val = (double) (-1*((framesize/2)))+1;
adamstark@46:
adamstark@46: for (int n = 0;n < framesize;n++) // left taper
adamstark@46: {
adamstark@46: if ((n_val >= 0) && (n_val <= (alpha*(N/2))))
adamstark@46: {
adamstark@46: window[n] = 1.0;
adamstark@46: }
adamstark@46: else if ((n_val <= 0) && (n_val >= (-1*alpha*(N/2))))
adamstark@46: {
adamstark@46: window[n] = 1.0;
adamstark@46: }
adamstark@46: else
adamstark@46: {
adamstark@46: window[n] = 0.5*(1+cos(pi*(((2*n_val)/(alpha*N))-1)));
adamstark@46: }
adamstark@46:
adamstark@46: n_val = n_val+1;
adamstark@46: }
adamstark@46:
adamstark@46: }
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // RECTANGULAR: set the window in the buffer 'window' to a Rectangular window
adamstark@46: void OnsetDetectionFunction :: set_win_rectangular()
adamstark@46: {
adamstark@46: // Rectangular window calculation
adamstark@46: for (int n = 0;n < framesize;n++)
adamstark@46: {
adamstark@46: window[n] = 1.0;
adamstark@46: }
adamstark@46: }
adamstark@46:
adamstark@46:
adamstark@46:
adamstark@46: ////////////////////////////////////////////////////////////////////////////////////////////////
adamstark@46: ////////////////////////////////////////////////////////////////////////////////////////////////
adamstark@46: ///////////////////////////////// Other Handy Methods //////////////////////////////////////////
adamstark@46:
adamstark@46: //--------------------------------------------------------------------------------------
adamstark@46: // set phase values to the range [-pi,pi]
adamstark@46: double OnsetDetectionFunction :: princarg(double phaseval)
adamstark@46: {
adamstark@46: // if phase value is less than or equal to -pi then add 2*pi
adamstark@46: while (phaseval <= (-pi))
adamstark@46: {
adamstark@46: phaseval = phaseval + (2*pi);
adamstark@46: }
adamstark@46:
adamstark@46: // if phase value is larger than pi, then subtract 2*pi
adamstark@46: while (phaseval > pi)
adamstark@46: {
adamstark@46: phaseval = phaseval - (2*pi);
adamstark@46: }
adamstark@46:
adamstark@46: return phaseval;
adamstark@46: }
adamstark@46:
adamstark@46:
adamstark@46:
adamstark@46:
adamstark@46:
adamstark@46:
adamstark@46:
adamstark@46:
adamstark@46:
adamstark@46:
adamstark@46:
adamstark@46:
adamstark@46: