You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

299 lines
9.3KB

  1. // #include "RJModules.hpp"
  2. // #include "dsp/samplerate.hpp"
  3. // #include "dsp/ringbuffer.hpp"
  4. // #include <iostream>
  5. // #include <cmath>
  6. // #include <math.h>
  7. // #include <signal.h>
  8. // #include "libfft.h"
  9. // /* -- some basic parameters -- */
  10. // #define SAMPLE_RATE (41000)
  11. // #define FFT_SIZE (8192)
  12. // #define FFT_EXP_SIZE (13)
  13. // #define NUM_SECONDS (20)
  14. // #define HISTORY_SIZE (1<<21)
  15. // /* -- functions declared and used here -- */
  16. // void buildHammingWindow( float *window, int size );
  17. // void buildHanWindow( float *window, int size );
  18. // void applyWindow( float *window, float *data, int size );
  19. // //a must be of length 2, and b must be of length 3
  20. // void computeSecondOrderLowPassParameters( float srate, float f, float *a, float *b );
  21. // //mem must be of length 4.
  22. // float processSecondOrderFilter( float x, float *mem, float *a, float *b );
  23. // void signalHandler( int signum ) ;
  24. // static bool running = true;
  25. // static char * NOTES[] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
  26. // void buildHammingWindow( float *window, int size )
  27. // {
  28. // for( int i=0; i<size; ++i )
  29. // window[i] = .54 - .46 * cos( 2 * M_PI * i / (float) size );
  30. // }
  31. // void buildHanWindow( float *window, int size )
  32. // {
  33. // for( int i=0; i<size; ++i )
  34. // window[i] = .5 * ( 1 - cos( 2 * M_PI * i / (size-1.0) ) );
  35. // }
  36. // void applyWindow( float *window, float *data, int size )
  37. // {
  38. // for( int i=0; i<size; ++i )
  39. // data[i] *= window[i] ;
  40. // }
  41. // void computeSecondOrderLowPassParameters( float srate, float f, float *a, float *b )
  42. // {
  43. // float a0;
  44. // float w0 = 2 * M_PI * f/srate;
  45. // float cosw0 = cos(w0);
  46. // float sinw0 = sin(w0);
  47. // //float alpha = sinw0/2;
  48. // float alpha = sinw0/2 * sqrt(2);
  49. // a0 = 1 + alpha;
  50. // a[0] = (-2*cosw0) / a0;
  51. // a[1] = (1 - alpha) / a0;
  52. // b[0] = ((1-cosw0)/2) / a0;
  53. // b[1] = ( 1-cosw0) / a0;
  54. // b[2] = b[0];
  55. // }
  56. // float processSecondOrderFilter( float x, float *mem, float *a, float *b )
  57. // {
  58. // float ret = b[0] * x + b[1] * mem[0] + b[2] * mem[1]
  59. // - a[0] * mem[2] - a[1] * mem[3] ;
  60. // mem[1] = mem[0];
  61. // mem[0] = x;
  62. // mem[3] = mem[2];
  63. // mem[2] = ret;
  64. // return ret;
  65. // }
  66. // struct FFTuner: Module {
  67. // enum ParamIds {
  68. // CH1_PARAM,
  69. // NUM_PARAMS
  70. // };
  71. // enum InputIds {
  72. // CH1_INPUT,
  73. // NUM_INPUTS
  74. // };
  75. // enum OutputIds {
  76. // CH1_OUTPUT,
  77. // NUM_OUTPUTS
  78. // };
  79. // DoubleRingBuffer<float, HISTORY_SIZE> historyBuffer;
  80. // DoubleRingBuffer<float, 16> outBuffer;
  81. // SampleRateConverter<1> src;
  82. // FFTuner() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {}
  83. // void step() override;
  84. // };
  85. // void FFTuner::step() {
  86. // float in = inputs[CH1_INPUT].value;
  87. // if (!historyBuffer.full()) {
  88. // historyBuffer.push(in);
  89. // }
  90. // // How many samples do we need consume to catch up?
  91. // float consume = index - historyBuffer.size();
  92. // if (outBuffer.empty()) {
  93. // double ratio = 1.0;
  94. // if (consume <= -16)
  95. // ratio = 0.5;
  96. // else if (consume >= 16)
  97. // ratio = 2.0;
  98. // int inFrames = mini(historyBuffer.size(), 16);
  99. // int outFrames = outBuffer.capacity();
  100. // src.setRatioSmooth(ratio);
  101. // src.process((const Frame<1>*)historyBuffer.startData(), &inFrames, (Frame<1>*)outBuffer.endData(), &outFrames);
  102. // historyBuffer.startIncr(inFrames);
  103. // outBuffer.endIncr(outFrames);
  104. // }
  105. // float wet = 0.0;
  106. // if (!outBuffer.empty()) {
  107. // wet = outBuffer.shift();
  108. // }
  109. // float a[2], b[3], mem1[4], mem2[4];
  110. // float data[FFT_SIZE];
  111. // float datai[FFT_SIZE];
  112. // float window[FFT_SIZE];
  113. // float freqTable[FFT_SIZE];
  114. // char * noteNameTable[FFT_SIZE];
  115. // float notePitchTable[FFT_SIZE];
  116. // void * fft = NULL;
  117. // // build the window, fft, etc
  118. // /*
  119. // buildHanWindow( window, 30 );
  120. // for( int i=0; i<30; ++i ) {
  121. // for( int j=0; j<window[i]*50; ++j )
  122. // printf( "*" );
  123. // printf("\n");
  124. // }
  125. // exit(0);
  126. // */
  127. // buildHanWindow( window, FFT_SIZE );
  128. // fft = initfft( FFT_EXP_SIZE );
  129. // computeSecondOrderLowPassParameters( SAMPLE_RATE, 330, a, b );
  130. // mem1[0] = 0; mem1[1] = 0; mem1[2] = 0; mem1[3] = 0;
  131. // mem2[0] = 0; mem2[1] = 0; mem2[2] = 0; mem2[3] = 0;
  132. // //freq/note tables
  133. // for( int i=0; i<FFT_SIZE; ++i ) {
  134. // freqTable[i] = ( SAMPLE_RATE * i ) / (float) ( FFT_SIZE );
  135. // }
  136. // for( int i=0; i<FFT_SIZE; ++i ) {
  137. // noteNameTable[i] = NULL;
  138. // notePitchTable[i] = -1;
  139. // }
  140. // for( int i=0; i<127; ++i ) {
  141. // float pitch = ( 440.0 / 32.0 ) * pow( 2, (i-9.0)/12.0 ) ;
  142. // if( pitch > SAMPLE_RATE / 2.0 )
  143. // break;
  144. // //find the closest frequency using brute force.
  145. // float min = 1000000000.0;
  146. // int index = -1;
  147. // for( int j=0; j<FFT_SIZE; ++j ) {
  148. // if( fabsf( freqTable[j]-pitch ) < min ) {
  149. // min = fabsf( freqTable[j]-pitch );
  150. // index = j;
  151. // }
  152. // }
  153. // noteNameTable[index] = NOTES[i%12];
  154. // notePitchTable[index] = pitch;
  155. // //printf( "%f %d %s\n", pitch, index, noteNameTable[index] );
  156. // }
  157. // while( running )
  158. // {
  159. // // read some data
  160. // // err = Pa_ReadStream( stream, data, FFT_SIZE );
  161. // // if( err ) goto error; //FIXME: we don't want to err on xrun
  162. // data *= outBuffer;
  163. // // low-pass
  164. // //for( int i=0; i<FFT_SIZE; ++i )
  165. // // printf( "in %f\n", data[i] );
  166. // for( int j=0; j<FFT_SIZE; ++j ) {
  167. // data[j] = processSecondOrderFilter( data[j], mem1, a, b );
  168. // data[j] = processSecondOrderFilter( data[j], mem2, a, b );
  169. // }
  170. // // window
  171. // applyWindow( window, data, FFT_SIZE );
  172. // // do the fft
  173. // for( int j=0; j<FFT_SIZE; ++j )
  174. // datai[j] = 0;
  175. // applyfft( fft, data, datai, false );
  176. // //find the peak
  177. // float maxVal = -1;
  178. // int maxIndex = -1;
  179. // for( int j=0; j<FFT_SIZE/2; ++j ) {
  180. // float v = data[j] * data[j] + datai[j] * datai[j] ;
  181. // /*
  182. // printf( "%d: ", j*SAMPLE_RATE/(2*FFT_SIZE) );
  183. // for( int i=0; i<sqrt(v)*100000000; ++i )
  184. // printf( "*" );
  185. // printf( "\n" );
  186. // */
  187. // if( v > maxVal ) {
  188. // maxVal = v;
  189. // maxIndex = j;
  190. // }
  191. // }
  192. // float freq = freqTable[maxIndex];
  193. // //find the nearest note:
  194. // int nearestNoteDelta=0;
  195. // while( true ) {
  196. // if( nearestNoteDelta < maxIndex && noteNameTable[maxIndex-nearestNoteDelta] != NULL ) {
  197. // nearestNoteDelta = -nearestNoteDelta;
  198. // break;
  199. // } else if( nearestNoteDelta + maxIndex < FFT_SIZE && noteNameTable[maxIndex+nearestNoteDelta] != NULL ) {
  200. // break;
  201. // }
  202. // ++nearestNoteDelta;
  203. // }
  204. // char * nearestNoteName = noteNameTable[maxIndex+nearestNoteDelta];
  205. // float nearestNotePitch = notePitchTable[maxIndex+nearestNoteDelta];
  206. // float centsSharp = 1200 * log( freq / nearestNotePitch ) / log( 2.0 );
  207. // // now output the results:
  208. // printf("\033[2J\033[1;1H"); //clear screen, go to top left
  209. // fflush(stdout);
  210. // printf( "Tuner listening. Control-C to exit.\n" );
  211. // printf( "%f Hz, %d : %f\n", freq, maxIndex, maxVal*1000 );
  212. // printf( "Nearest Note: %s\n", nearestNoteName );
  213. // if( nearestNoteDelta != 0 ) {
  214. // if( centsSharp > 0 )
  215. // printf( "%f cents sharp.\n", centsSharp );
  216. // if( centsSharp < 0 )
  217. // printf( "%f cents flat.\n", -centsSharp );
  218. // } else {
  219. // printf( "in tune!\n" );
  220. // }
  221. // printf( "\n" );
  222. // int chars = 30;
  223. // if( nearestNoteDelta == 0 || centsSharp >= 0 ) {
  224. // for( int i=0; i<chars; ++i )
  225. // printf( " " );
  226. // } else {
  227. // for( int i=0; i<chars+centsSharp; ++i )
  228. // printf( " " );
  229. // for( int i=chars+centsSharp<0?0:chars+centsSharp; i<chars; ++i )
  230. // printf( "=" );
  231. // }
  232. // printf( " %2s ", nearestNoteName );
  233. // if( nearestNoteDelta != 0 )
  234. // for( int i=0; i<chars && i<centsSharp; ++i )
  235. // printf( "=" );
  236. // printf("\n");
  237. // }
  238. // // passthrough
  239. // outputs[CH1_OUTPUT].value = inputs[CH1_INPUT].value;
  240. // }
  241. // FFTunerWidget::FFTunerWidget(FFTuner *module) : ModuleWidget(module) {
  242. // box.size = Vec(15*10, 380);
  243. // {
  244. // SVGPanel *panel = new SVGPanel();
  245. // panel->box.size = box.size;
  246. // panel->setBackground(SVG::load(assetPlugin(plugin, "res/FFTuner.svg")));
  247. // addChild(panel);
  248. // }
  249. // addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  250. // addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 0)));
  251. // addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  252. // addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 365)));
  253. // addParam(ParamWidget::create<RoundBlackKnob>(Vec(57, 79), module, FFTuner::CH1_PARAM, 0.0, 1.0, 0.5));
  254. // addInput(Port::create<PJ301MPort>(Vec(22, 100), Port::INPUT, module, FFTuner::CH1_INPUT));
  255. // addOutput(Port::create<PJ301MPort>(Vec(110, 85), Port::OUTPUT, module, FFTuner::CH1_OUTPUT));
  256. // }