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.

259 lines
6.8KB

  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. Fl_Resonance_Graph.cpp - OSC Resonance Graph View
  4. Copyright (C) 2016 Mark McCurry
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation; either version 2
  8. of the License, or (at your option) any later version.
  9. */
  10. #include "Fl_Resonance_Graph.H"
  11. #include <FL/Fl.H>
  12. #include <FL/fl_draw.H>
  13. #include <FL/Fl_Value_Output.H>
  14. #include <rtosc/rtosc.h>
  15. using namespace zyncarla;
  16. Fl_Resonance_Graph::Fl_Resonance_Graph(int x,int y, int w, int h, const char *label)
  17. :Fl_Box(x,y,w,h,label), Fl_Osc_Widget(this), khzvalue(NULL), dbvalue(NULL),
  18. oldx(-1), oldy(-1), cbwidget(NULL), applybutton(NULL), Pcenterfreq(0), Poctavesfreq(0),
  19. PmaxdB(0)
  20. {
  21. memset(Prespoints, 64, N_RES_POINTS);
  22. //Get values
  23. oscRegister("Prespoints");
  24. oscRegister("Pcenterfreq");
  25. oscRegister("Poctavesfreq");
  26. oscRegister("PmaxdB");
  27. cbwidget=NULL;
  28. applybutton=NULL;
  29. }
  30. Fl_Resonance_Graph::~Fl_Resonance_Graph(void)
  31. {
  32. }
  33. void Fl_Resonance_Graph::init(Fl_Value_Output *khzvalue_,Fl_Value_Output *dbvalue_)
  34. {
  35. khzvalue=khzvalue_;
  36. dbvalue=dbvalue_;
  37. oldx=-1;
  38. khzval=-1;
  39. }
  40. void Fl_Resonance_Graph::draw_freq_line(float freq,int type)
  41. {
  42. const float freqx=getfreqpos(freq);//XXX
  43. switch(type){
  44. case 0:fl_line_style(FL_SOLID);break;
  45. case 1:fl_line_style(FL_DOT);break;
  46. case 2:fl_line_style(FL_DASH);break;
  47. }
  48. if ((freqx>0.0)&&(freqx<1.0))
  49. fl_line(x()+(int) (freqx*w()),y(),
  50. x()+(int) (freqx*w()),y()+h());
  51. }
  52. void Fl_Resonance_Graph::draw()
  53. {
  54. const int ox=x(),oy=y(),lx=w(),ly=h();
  55. fl_color(FL_DARK1);
  56. fl_rectf(ox,oy,lx,ly);
  57. //draw the lines
  58. fl_color(FL_GRAY);
  59. fl_line_style(FL_SOLID);
  60. fl_line(ox+2,oy+ly/2,ox+lx-2,oy+ly/2);
  61. //Draw 1kHz line
  62. const float freqx=getfreqpos(1000.0);//XXX
  63. if ((freqx>0.0)&&(freqx<1.0))
  64. fl_line(ox+(int) (freqx*lx),oy,
  65. ox+(int) (freqx*lx),oy+ly);
  66. //Draw other frequency lines
  67. for (int i=1; i<10; ++i){
  68. if(i==1) {
  69. draw_freq_line(i*100.0,0);
  70. draw_freq_line(i*1000.0,0);
  71. } else
  72. if (i==5) {
  73. draw_freq_line(i*100.0,2);
  74. draw_freq_line(i*1000.0,2);
  75. } else {
  76. draw_freq_line(i*100.0,1);
  77. draw_freq_line(i*1000.0,1);
  78. }
  79. }
  80. draw_freq_line(10000.0,0);
  81. draw_freq_line(20000.0,1);
  82. //Draw dotted grid
  83. fl_line_style(FL_DOT);
  84. int GY=10;if (ly<GY*3) GY=-1;
  85. for (int i=1; i<GY; ++i){
  86. int tmp=(int)(ly/(float)GY*i);
  87. fl_line(ox+2,oy+tmp,ox+lx-2,oy+tmp);
  88. }
  89. //draw the data
  90. fl_color(FL_RED);
  91. fl_line_style(FL_SOLID,2);
  92. fl_begin_line();
  93. int oiy = ly*Prespoints[0]/128.0;//XXX easy
  94. for (int i=1; i<N_RES_POINTS; ++i){
  95. const int ix=(i*1.0/N_RES_POINTS*lx);
  96. const int iy= ly*Prespoints[i]/128.0;//XXX easy
  97. fl_vertex(ox+ix,oy+ly-oiy);
  98. oiy=iy;
  99. }
  100. fl_end_line();
  101. fl_line_style(FL_SOLID,0);
  102. }
  103. int Fl_Resonance_Graph::handle(int event)
  104. {
  105. int x_=Fl::event_x()-x();
  106. int y_=Fl::event_y()-y();
  107. if((x_>=0)&&(x_<w()) && (y_>=0)&&(y_<h())){
  108. khzvalue->value(getfreqx(x_*1.0/w())/1000.0);//XXX
  109. dbvalue->value((1.0-y_*2.0/h())*PmaxdB);//XXX
  110. }
  111. if((event==FL_PUSH)||(event==FL_DRAG)){
  112. const bool leftbutton = Fl::event_button() == FL_LEFT_MOUSE;
  113. if (x_<0) x_=0;if (y_<0) y_=0;
  114. if (x_>=w()) x_=w();if (y_>=h()-1) y_=h()-1;
  115. if ((oldx<0)||(oldx==x_)){
  116. int sn=(int)(x_*1.0/w()*N_RES_POINTS);
  117. int sp=127-(int)(y_*1.0/h()*127);
  118. if(leftbutton)
  119. setPoint(sn,sp);
  120. //oscWrite("setpoint", "ii", sn, sp);//respar->setpoint(sn,sp);//XXX easy
  121. else
  122. setPoint(sn,sp);
  123. //oscWrite("setpoint", "ii", sn, 64);//respar->setpoint(sn,64);//XXX easy
  124. } else {
  125. int x1=oldx;
  126. int x2=x_;
  127. int y1=oldy;
  128. int y2=y_;
  129. if (oldx>x_){
  130. x1=x_;y1=y_;
  131. x2=oldx;y2=oldy;
  132. }
  133. for (int i=0;i<x2-x1;i++){
  134. int sn=(int)((i+x1)*1.0/w()*N_RES_POINTS);
  135. float yy=(y2-y1)*1.0/(x2-x1)*i;
  136. int sp=127-(int)((y1+yy)/h()*127);
  137. if(leftbutton) //respar->setpoint(sn,sp);//XXX easy
  138. setPoint(sn, sp);
  139. //oscWrite("setpoint", "ii", sn, sp);
  140. else //respar->setpoint(sn,64);//XXX easy
  141. setPoint(sn, sp);
  142. //oscWrite("setpoint", "ii", sn, sp);
  143. }
  144. }
  145. oldx=x_;oldy=y_;
  146. redraw();
  147. }
  148. if(event==FL_RELEASE) {
  149. oldx=-1;
  150. if(cbwidget) {
  151. cbwidget->do_callback();
  152. if(applybutton) {
  153. applybutton->color(FL_RED);
  154. applybutton->redraw();
  155. }
  156. }
  157. }
  158. return 1;
  159. }
  160. void Fl_Resonance_Graph::setcbwidget(Fl_Widget *cbwidget,Fl_Widget *applybutton)
  161. {
  162. this->cbwidget=cbwidget;
  163. this->applybutton=applybutton;
  164. }
  165. void Fl_Resonance_Graph::update(void)
  166. {
  167. oscWrite("Prespoints");
  168. oscWrite("Pcenterfreq");
  169. oscWrite("Poctavesfreq");
  170. oscWrite("PmaxdB");
  171. }
  172. void Fl_Resonance_Graph::OSC_raw(const char *msg)
  173. {
  174. //TODO check the types (OSC regex)
  175. if(strstr(msg, "Prespoints")) {
  176. rtosc_blob_t arg = rtosc_argument(msg, 0).b;
  177. assert(arg.len == N_RES_POINTS);
  178. memcpy(Prespoints, arg.data, N_RES_POINTS);
  179. } else if(strstr(msg, "Pcenterfreq"))
  180. Pcenterfreq = rtosc_argument(msg, 0).i;
  181. else if(strstr(msg, "Poctavesfreq"))
  182. Poctavesfreq = rtosc_argument(msg, 0).i;
  183. else if(strstr(msg, "PmaxdB"))
  184. PmaxdB = rtosc_argument(msg, 0).i;
  185. else
  186. puts("I got an unknown message...");
  187. redraw();
  188. }
  189. float Fl_Resonance_Graph::getfreqx(float x) const
  190. {
  191. const float octf = powf(2.0f, getoctavesfreq());
  192. return getcenterfreq() / sqrt(octf) * powf(octf, limit(x, 0.0f, 1.0f));
  193. }
  194. /*
  195. * Get the x coordinate from frequency (used by the UI)
  196. */
  197. float Fl_Resonance_Graph::getfreqpos(float freq) const
  198. {
  199. return (logf(freq) - logf(getfreqx(0.0f))) / logf(2.0f) / getoctavesfreq();
  200. }
  201. /*
  202. * Get the center frequency of the resonance graph
  203. */
  204. float Fl_Resonance_Graph::getcenterfreq() const
  205. {
  206. return 10000.0f * powf(10, -(1.0f - Pcenterfreq / 127.0f) * 2.0f);
  207. }
  208. /*
  209. * Get the number of octave that the resonance functions applies to
  210. */
  211. float Fl_Resonance_Graph::getoctavesfreq() const
  212. {
  213. return 0.25f + 10.0f * Poctavesfreq / 127.0f;
  214. }
  215. void Fl_Resonance_Graph::setPoint(int idx, int val)
  216. {
  217. Prespoints[idx] = val;
  218. oscWrite(std::string("Prespoints")+to_s(idx), "c", val);
  219. redraw();
  220. }