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.

211 lines
6.1KB

  1. #include <cstring>
  2. #include <cassert>
  3. #include <FL/Fl.H>
  4. #include <FL/Fl_Box.H>
  5. #include "../globals.h"
  6. #include "Fl_Osc_Widget.H"
  7. #include "Fl_Osc_Interface.h"
  8. class PADnoteOvertonePosition: public Fl_Box, Fl_Osc_Widget
  9. {
  10. public:
  11. PADnoteOvertonePosition(int x,int y, int w, int h, const char *label=0)
  12. :Fl_Box(x,y,w,h,label), nsamples(0),
  13. spc(0),
  14. nhr(0),
  15. spectrum(new float[w]),
  16. mode(0), osc(NULL)
  17. {
  18. memset(spectrum, 0, w*sizeof(float));
  19. }
  20. ~PADnoteOvertonePosition(void)
  21. {
  22. osc->removeLink("/oscilsize",
  23. (Fl_Osc_Widget*) this);
  24. osc->removeLink(base_path + "oscilgen/spectrum",
  25. (Fl_Osc_Widget*) this);
  26. osc->removeLink(base_path + "nhr",
  27. (Fl_Osc_Widget*) this);
  28. osc->removeLink(base_path + "Pmode",
  29. (Fl_Osc_Widget*) this);
  30. delete [] spc;
  31. delete [] nhr;
  32. delete [] spectrum;
  33. }
  34. void init(void)
  35. {
  36. Fl_Osc_Pane *og = fetch_osc_pane(this);
  37. assert(og);
  38. base_path = og->base;
  39. osc = og->osc;
  40. assert(osc);
  41. osc->createLink("/oscilsize", (Fl_Osc_Widget*) this);
  42. osc->requestValue("/oscilsize");
  43. osc->createLink(base_path + "nhr",
  44. (Fl_Osc_Widget*) this);
  45. osc->createLink(base_path + "oscilgen/spectrum",
  46. (Fl_Osc_Widget*) this);
  47. osc->createLink(base_path + "Pmode",
  48. (Fl_Osc_Widget*) this);
  49. update();
  50. }
  51. void update(void)
  52. {
  53. osc->requestValue(base_path + "nhr");
  54. osc->requestValue(base_path + "oscilgen/spectrum");
  55. osc->requestValue(base_path + "Pmode");
  56. }
  57. virtual void OSC_value(unsigned N, void *data, const char *name)
  58. override
  59. {
  60. if(N/4 != nsamples) {
  61. nsamples = N/4;
  62. delete [] spc;
  63. delete [] nhr;
  64. spc = new float[nsamples];
  65. nhr = new float[nsamples];
  66. memset(spc, 0, nsamples*sizeof(float));
  67. memset(nhr, 0, nsamples*sizeof(float));
  68. }
  69. assert(N==(4*nsamples));
  70. float *d = (float*)data;
  71. if(!strcmp(name, "spectrum"))
  72. updateSpectrum(d);
  73. else if(!strcmp(name, "nhr"))
  74. updateHarmonicPos(d);
  75. else
  76. assert(false);
  77. }
  78. virtual void OSC_value(int x, const char *name) override
  79. {
  80. if(!strcmp(name, "Pmode")) {
  81. mode = x;
  82. regenerateOvertones();
  83. } else if(!strcmp(name, "oscilsize")) {
  84. nsamples = x/2;
  85. delete [] spc;
  86. delete [] nhr;
  87. spc = new float[nsamples];
  88. nhr = new float[nsamples];
  89. memset(spc, 0, nsamples*sizeof(float));
  90. memset(nhr, 0, nsamples*sizeof(float));
  91. }
  92. }
  93. private:
  94. void updateSpectrum(float *data)
  95. {
  96. //normalize
  97. float max=0;
  98. for (unsigned i=0; i<nsamples; i++){
  99. const float x=fabs(data[i]);
  100. if (max<x) max=x;
  101. }
  102. if (max<0.000001) max=1.0;
  103. max=max*1.05;
  104. for(unsigned i=0; i<nsamples; ++i)
  105. spc[i] = data[i]/max;
  106. regenerateOvertones();
  107. }
  108. void updateHarmonicPos(float *data)
  109. {
  110. memcpy(nhr, data, nsamples*sizeof(float));
  111. regenerateOvertones();
  112. }
  113. void regenerateOvertones(void)
  114. {
  115. const int ox=x(),oy=y(),lx=w(),ly=h();
  116. (void)ox;(void)oy;(void)lx;(void)ly;
  117. const int maxharmonic=64;
  118. memset(spectrum, 0, lx*sizeof(float));
  119. for (unsigned i=1;i<nsamples;i++){
  120. int kx=(int)(lx/(float)maxharmonic*nhr[i]);
  121. if ((kx<0)||(kx>=lx)) continue;
  122. spectrum[kx]=spc[i-1]+1e-9;
  123. }
  124. if(mode==2) {
  125. int old=0;
  126. for (int i=1;i<lx;i++){
  127. if ((spectrum[i]>1e-10)||(i==(lx-1))){
  128. const int delta=i-old;
  129. const float val1=spectrum[old];
  130. const float val2=spectrum[i];
  131. const float idelta=1.0/delta;
  132. for (int j=0;j<delta;j++) {
  133. const float x=idelta*j;
  134. spectrum[old+j]=val1*(1.0-x)+val2*x;
  135. }
  136. old=i;
  137. }
  138. }
  139. }
  140. redraw();
  141. }
  142. void draw(void)
  143. {
  144. const int ox=x(),oy=y(),lx=w(),ly=h();
  145. const int maxharmonic=64;
  146. const int maxdb=60;
  147. if (!visible())
  148. return;
  149. if (damage()!=1){
  150. fl_color(fl_color_average(FL_BLACK,
  151. FL_BACKGROUND_COLOR, 0.5 ));
  152. fl_rectf(ox,oy,lx,ly);
  153. }
  154. for (int i=1;i<maxharmonic;i++){
  155. fl_color(100,100,100);
  156. fl_line_style(FL_DOT);
  157. if (i%5==0) fl_line_style(0);
  158. if (i%10==0) fl_color(120,120,120);
  159. int kx=(int)(lx/(float)maxharmonic*i);
  160. fl_line(ox+kx,oy,ox+kx,oy+ly);
  161. };
  162. fl_color(180,0,0);
  163. fl_line_style(0);
  164. for (int i=0;i<lx;i++){
  165. float x=spectrum[i];
  166. if (x>dB2rap(-maxdb)) x=rap2dB(x)/maxdb+1;
  167. else continue;
  168. int yy=(int)(x*ly);
  169. fl_line(ox+i,oy+ly-1-yy,ox+i,oy+ly-1);
  170. }
  171. }
  172. private:
  173. size_t nsamples;
  174. float *spc;
  175. float *nhr;
  176. float *spectrum;
  177. char mode;
  178. std::string base_path;
  179. Fl_Osc_Interface *osc;
  180. };