/*************************************************************************** simple.cpp - simple plugin demonstration ------------------- begin : Fri Jan 20 2004 copyright : (C) 2003 by Gene Ruebsamen email : gene@erachampion.com ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "simple.h" // The plugin.h defines on_activate as a abstract virtual function that you have // to define in your plugin. Your code goes in this function. void simple::on_activate(const vector *buf, unsigned int rate) { const int threshold = 1.5; // threshold power unsigned int frame_size; // n^2 based frame size for fft // determine the fft frame size based upon the audio sampling rate. // FFT requires a frame size that is a power of 2. (redo this and make it cleaner - gene) if ((rate/2) > 16384) frame_size = 32768; else if ((rate/2) > 8192) frame_size = 16384; else frame_size = 8192; // Declare an fft object FFTReal fft (frame_size); double data[frame_size]; double result[frame_size]; double pow_spectrum[frame_size]; // take the incoming data and create a new array of size = frame_size, pad the // time domain data (spectral interpolation) with zeros to increase the frequency // resolution and reach a power of 2 for (unsigned int i=0;isize();++i) data[i] = (*buf)[i]; for (unsigned int i=buf->size();i freq domain) fft.do_fft(result,data); // convert the result to a power spectrum for (int i=0;i(frame_size); } // get the bin indexes that contains the 8-14 hz midpoint frequency (this is a 'microtremor'). // a sudden drop in amplitude of which is suppose to indicate stress double bind = static_cast(rate) / static_cast(frame_size); int start = static_cast(8.0/bind); // 8.0 hz midpoint int end = static_cast(14.0/bind); // 14.0 hz midpoint // calculate avg power of the microtremors double avg_tremor_pwr = 0.0; for (int i=start;i<=end;++i) { avg_tremor_pwr += pow_spectrum[i]; // avg tremor pwr } avg_tremor_pwr /= ((end-start)+1); double avg_total_pwr = 0.0, total_pwr = 0.0; for (int i=0;i<(frame_size/2);++i) { total_pwr += pow_spectrum[i]; } avg_total_pwr = total_pwr / (frame_size/2); double tremor_ratio; if (total_pwr < threshold) // not enough amplitude to do anything. tremor_ratio = 0.0; else tremor_ratio = avg_tremor_pwr / avg_total_pwr; double stress; if (total_pwr >= 1.0) stress = 10.0/pow(tremor_ratio,4); else stress = 0.0; // #ifndef NDEBUG // cout << "AMTP/ATP Ratio: " << tremor_ratio << "\tStress: " << stress << endl; // #endif /* // Recently, studies have found that Fundamental Frequency is a // much better indicater of stress than Microtremors. In fact, // in several studies, microtremors turned out to perform not any // better than chance... More research needs to be done on // F0 analysis. - (gene) // --------------------------------------------------------- // f0 estimation using cepstrum techniques int cutoff = static_cast(5000.0/bind); // 5000 hz midpoint if (cutoff > frame_size) cout << "ERROR" << endl; // first log|fft(s(n))| for (int i=0;i max) { max = fabs(cep_n[i]); index = i; } } double frequencyHz = rate / ((rate/5000.0)+index); // -------------------------------------------------------- */ // Output Results of Analysis if (stress > 5.0 && stress < 30.0) { set_stress(stress); set_analysis_text("POSSIBLE LIE"); } else if (stress >= 30.0) { if (stress*2.0 > 100.0) set_stress(100); else set_stress(stress*2.0); set_analysis_text("PROBABLE LIE"); } else if (stress <= 1.0 && stress > 0.0001) { set_stress(stress*2.0); set_analysis_text("PROBABLE TRUTH"); } else { set_stress(stress*2.0); set_analysis_text("UNDETERMINED"); } } // This is the proxy for the plugin. Your plugin will require this section of code to be // properly registered. It needs to be defined extern 'C' due to the C++ name mangling - Gene extern "C" { plugin *maker() { return new simple; } class proxy { public: proxy() { // register the maker with the factory factory["simple"] = maker; } }; // our one instance of the proxy proxy p; }