// #include "RJModules.hpp" // #include "dsp/samplerate.hpp" // #include "dsp/ringbuffer.hpp" // #include // #include // #include // #include // #include "libfft.h" // /* -- some basic parameters -- */ // #define SAMPLE_RATE (41000) // #define FFT_SIZE (8192) // #define FFT_EXP_SIZE (13) // #define NUM_SECONDS (20) // #define HISTORY_SIZE (1<<21) // /* -- functions declared and used here -- */ // void buildHammingWindow( float *window, int size ); // void buildHanWindow( float *window, int size ); // void applyWindow( float *window, float *data, int size ); // //a must be of length 2, and b must be of length 3 // void computeSecondOrderLowPassParameters( float srate, float f, float *a, float *b ); // //mem must be of length 4. // float processSecondOrderFilter( float x, float *mem, float *a, float *b ); // void signalHandler( int signum ) ; // static bool running = true; // static char * NOTES[] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" }; // void buildHammingWindow( float *window, int size ) // { // for( int i=0; i historyBuffer; // DoubleRingBuffer outBuffer; // SampleRateConverter<1> src; // FFTuner() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {} // void step() override; // }; // void FFTuner::step() { // float in = inputs[CH1_INPUT].value; // if (!historyBuffer.full()) { // historyBuffer.push(in); // } // // How many samples do we need consume to catch up? // float consume = index - historyBuffer.size(); // if (outBuffer.empty()) { // double ratio = 1.0; // if (consume <= -16) // ratio = 0.5; // else if (consume >= 16) // ratio = 2.0; // int inFrames = mini(historyBuffer.size(), 16); // int outFrames = outBuffer.capacity(); // src.setRatioSmooth(ratio); // src.process((const Frame<1>*)historyBuffer.startData(), &inFrames, (Frame<1>*)outBuffer.endData(), &outFrames); // historyBuffer.startIncr(inFrames); // outBuffer.endIncr(outFrames); // } // float wet = 0.0; // if (!outBuffer.empty()) { // wet = outBuffer.shift(); // } // float a[2], b[3], mem1[4], mem2[4]; // float data[FFT_SIZE]; // float datai[FFT_SIZE]; // float window[FFT_SIZE]; // float freqTable[FFT_SIZE]; // char * noteNameTable[FFT_SIZE]; // float notePitchTable[FFT_SIZE]; // void * fft = NULL; // // build the window, fft, etc // /* // buildHanWindow( window, 30 ); // for( int i=0; i<30; ++i ) { // for( int j=0; j SAMPLE_RATE / 2.0 ) // break; // //find the closest frequency using brute force. // float min = 1000000000.0; // int index = -1; // for( int j=0; j maxVal ) { // maxVal = v; // maxIndex = j; // } // } // float freq = freqTable[maxIndex]; // //find the nearest note: // int nearestNoteDelta=0; // while( true ) { // if( nearestNoteDelta < maxIndex && noteNameTable[maxIndex-nearestNoteDelta] != NULL ) { // nearestNoteDelta = -nearestNoteDelta; // break; // } else if( nearestNoteDelta + maxIndex < FFT_SIZE && noteNameTable[maxIndex+nearestNoteDelta] != NULL ) { // break; // } // ++nearestNoteDelta; // } // char * nearestNoteName = noteNameTable[maxIndex+nearestNoteDelta]; // float nearestNotePitch = notePitchTable[maxIndex+nearestNoteDelta]; // float centsSharp = 1200 * log( freq / nearestNotePitch ) / log( 2.0 ); // // now output the results: // printf("\033[2J\033[1;1H"); //clear screen, go to top left // fflush(stdout); // printf( "Tuner listening. Control-C to exit.\n" ); // printf( "%f Hz, %d : %f\n", freq, maxIndex, maxVal*1000 ); // printf( "Nearest Note: %s\n", nearestNoteName ); // if( nearestNoteDelta != 0 ) { // if( centsSharp > 0 ) // printf( "%f cents sharp.\n", centsSharp ); // if( centsSharp < 0 ) // printf( "%f cents flat.\n", -centsSharp ); // } else { // printf( "in tune!\n" ); // } // printf( "\n" ); // int chars = 30; // if( nearestNoteDelta == 0 || centsSharp >= 0 ) { // for( int i=0; ibox.size = box.size; // panel->setBackground(SVG::load(assetPlugin(plugin, "res/FFTuner.svg"))); // addChild(panel); // } // addChild(Widget::create(Vec(15, 0))); // addChild(Widget::create(Vec(box.size.x-30, 0))); // addChild(Widget::create(Vec(15, 365))); // addChild(Widget::create(Vec(box.size.x-30, 365))); // addParam(ParamWidget::create(Vec(57, 79), module, FFTuner::CH1_PARAM, 0.0, 1.0, 0.5)); // addInput(Port::create(Vec(22, 100), Port::INPUT, module, FFTuner::CH1_INPUT)); // addOutput(Port::create(Vec(110, 85), Port::OUTPUT, module, FFTuner::CH1_OUTPUT)); // }