Audio plugin host https://kx.studio/carla
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.

Fl_EQGraph.cpp 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #include <FL/Fl.H>
  2. #include <FL/fl_draw.H>
  3. #include "Fl_EQGraph.H"
  4. #include "common.H"
  5. #include "../Effects/EffectMgr.h"
  6. #include "../DSP/FFTwrapper.h"
  7. #include "../globals.h"
  8. #include <rtosc/rtosc.h>
  9. #define MAX_DB 30
  10. Fl_EQGraph::Fl_EQGraph(int x,int y, int w, int h, const char *label)
  11. :Fl_Box(x,y,w,h,label), Fl_Osc_Widget(this), samplerate(48000)
  12. {
  13. memset(num, 0, sizeof(num));
  14. memset(dem, 0, sizeof(dem));
  15. num[0] = 1;
  16. dem[0] = 1;
  17. ext = "eq-coeffs";
  18. osc->createLink("/samplerate", this);
  19. osc->requestValue("/samplerate");
  20. oscRegister("eq-coeffs");
  21. }
  22. Fl_EQGraph::~Fl_EQGraph(void)
  23. {}
  24. void Fl_EQGraph::OSC_raw(const char *msg)
  25. {
  26. if(strstr(msg, "samplerate") && !strcmp("f", rtosc_argument_string(msg))) {
  27. samplerate = rtosc_argument(msg, 0).f;
  28. } else {
  29. memcpy(dem, rtosc_argument(msg, 0).b.data, sizeof(dem));
  30. memcpy(num, rtosc_argument(msg, 1).b.data, sizeof(dem));
  31. redraw();
  32. }
  33. }
  34. void Fl_EQGraph::update(void)
  35. {
  36. oscWrite("eq-coeffs");
  37. }
  38. void Fl_EQGraph::draw_freq_line(float freq, int type)
  39. {
  40. fl_color(FL_GRAY);
  41. float freqx=getfreqpos(freq);
  42. switch(type){
  43. case 0:if (active_r()) fl_color(FL_WHITE);
  44. else fl_color(205,205,205);
  45. fl_line_style(FL_SOLID);
  46. break;
  47. case 1:fl_line_style(FL_DOT);break;
  48. case 2:fl_line_style(FL_DASH);break;
  49. };
  50. if ((freqx>0.0)&&(freqx<1.0))
  51. fl_line(x()+(int) (freqx*w()),y(),
  52. x()+(int) (freqx*w()),y()+h());
  53. }
  54. void Fl_EQGraph::draw(void)
  55. {
  56. int ox=x(),oy=y(),lx=w(),ly=h(),i;
  57. double iy,oiy;
  58. float freqx;
  59. if (active_r()) fl_color(fl_darker(FL_GRAY));
  60. else fl_color(FL_GRAY);
  61. fl_rectf(ox,oy,lx,ly);
  62. //draw the lines
  63. fl_color(fl_lighter(FL_GRAY));
  64. fl_line_style(FL_SOLID);
  65. fl_line(ox+2,oy+ly/2,ox+lx-2,oy+ly/2);
  66. freqx=getfreqpos(1000.0);
  67. if ((freqx>0.0)&&(freqx<1.0))
  68. fl_line(ox+(int) (freqx*lx),oy,
  69. ox+(int) (freqx*lx),oy+ly);
  70. for (i=1;i<10;i++) {
  71. if(i==1) {
  72. draw_freq_line(i*100.0,0);
  73. draw_freq_line(i*1000.0,0);
  74. } else
  75. if (i==5) {
  76. draw_freq_line(i*10.0,2);
  77. draw_freq_line(i*100.0,2);
  78. draw_freq_line(i*1000.0,2);
  79. } else {
  80. draw_freq_line(i*10.0,1);
  81. draw_freq_line(i*100.0,1);
  82. draw_freq_line(i*1000.0,1);
  83. };
  84. };
  85. draw_freq_line(10000.0,0);
  86. draw_freq_line(20000.0,1);
  87. fl_line_style(FL_DOT);
  88. int GY=6;if (ly<GY*3) GY=-1;
  89. for (i=1;i<GY;i++){
  90. int tmp=(int)(ly/(float)GY*i);
  91. fl_line(ox+2,oy+tmp,ox+lx-2,oy+tmp);
  92. };
  93. //draw the frequency response
  94. if (active_r()) fl_color(FL_YELLOW);
  95. else fl_color(200,200,80);
  96. fl_line_style(FL_SOLID,2);
  97. //fl_color( fl_color_add_alpha( fl_color(), 127 ) );
  98. oiy=getresponse(ly,getfreqx(0.0));
  99. fl_begin_line();
  100. for (i=1;i<lx;i++){
  101. float frq=getfreqx(i/(float) lx);
  102. if (frq>samplerate/2) break;
  103. iy=getresponse(ly,frq);
  104. if ((oiy>=0) && (oiy<ly) &&
  105. (iy>=0) && (iy<ly) )
  106. fl_vertex(ox+i,oy+ly-iy);
  107. oiy=iy;
  108. };
  109. fl_end_line();
  110. fl_line_style(FL_SOLID,0);
  111. }
  112. /*
  113. * For those not too familiar with digital filters, what is happening here is an
  114. * evaluation of the filter's frequency response through the evaluation of
  115. * H(z^{-1}) via z^{-1}=e^{j\omega}.
  116. * This will yield a complex result which will indicate the phase and magnitude
  117. * transformation of the input at the set frequency denoted by \omega
  118. */
  119. double Fl_EQGraph::getresponse(int maxy,float freq) const
  120. {
  121. const float angle = 2*PI*freq/samplerate;
  122. std::complex<float> num_res = 0;
  123. std::complex<float> dem_res = 0;
  124. for(int i = 0; i < MAX_EQ_BANDS*MAX_FILTER_STAGES*2+1; ++i) {
  125. num_res += FFTpolar<float>(num[i], i*angle);
  126. dem_res += FFTpolar<float>(dem[i], i*angle);
  127. }
  128. float dbresp=20*log(abs(num_res/dem_res))/log(10);
  129. //rescale
  130. return (int) ((dbresp/MAX_DB+1.0)*maxy/2.0);
  131. }
  132. float Fl_EQGraph::getfreqx(float x) const
  133. {
  134. if(x>1.0)
  135. x=1.0;
  136. return(20.0*pow((float)1000.0,x));
  137. }
  138. float Fl_EQGraph::getfreqpos(float freq) const
  139. {
  140. if(freq<0.00001)
  141. freq=0.00001;
  142. return(log(freq/20.0)/log(1000.0));
  143. }