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.

213 lines
6.2KB

  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, public 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. if(x/2 != (int)nsamples) {
  85. nsamples = x/2;
  86. delete [] spc;
  87. delete [] nhr;
  88. spc = new float[nsamples];
  89. nhr = new float[nsamples];
  90. memset(spc, 0, nsamples*sizeof(float));
  91. memset(nhr, 0, nsamples*sizeof(float));
  92. }
  93. }
  94. }
  95. private:
  96. void updateSpectrum(float *data)
  97. {
  98. //normalize
  99. float max=0;
  100. for (unsigned i=0; i<nsamples; i++){
  101. const float x=fabs(data[i]);
  102. if (max<x) max=x;
  103. }
  104. if (max<0.000001) max=1.0;
  105. max=max*1.05;
  106. for(unsigned i=0; i<nsamples; ++i)
  107. spc[i] = data[i]/max;
  108. regenerateOvertones();
  109. }
  110. void updateHarmonicPos(float *data)
  111. {
  112. memcpy(nhr, data, nsamples*sizeof(float));
  113. regenerateOvertones();
  114. }
  115. void regenerateOvertones(void)
  116. {
  117. const int ox=x(),oy=y(),lx=w(),ly=h();
  118. (void)ox;(void)oy;(void)lx;(void)ly;
  119. const int maxharmonic=64;
  120. memset(spectrum, 0, lx*sizeof(float));
  121. for (unsigned i=1;i<nsamples;i++){
  122. int kx=(int)(lx/(float)maxharmonic*nhr[i]);
  123. if ((kx<0)||(kx>=lx)) continue;
  124. spectrum[kx]=spc[i-1]+1e-9;
  125. }
  126. if(mode==2) {
  127. int old=0;
  128. for (int i=1;i<lx;i++){
  129. if ((spectrum[i]>1e-10)||(i==(lx-1))){
  130. const int delta=i-old;
  131. const float val1=spectrum[old];
  132. const float val2=spectrum[i];
  133. const float idelta=1.0/delta;
  134. for (int j=0;j<delta;j++) {
  135. const float x=idelta*j;
  136. spectrum[old+j]=val1*(1.0-x)+val2*x;
  137. }
  138. old=i;
  139. }
  140. }
  141. }
  142. redraw();
  143. }
  144. void draw(void)
  145. {
  146. const int ox=x(),oy=y(),lx=w(),ly=h();
  147. const int maxharmonic=64;
  148. const int maxdb=60;
  149. if (!visible())
  150. return;
  151. if (damage()!=1){
  152. fl_color(fl_color_average(FL_BLACK,
  153. FL_BACKGROUND_COLOR, 0.5 ));
  154. fl_rectf(ox,oy,lx,ly);
  155. }
  156. for (int i=1;i<maxharmonic;i++){
  157. fl_color(100,100,100);
  158. fl_line_style(FL_DOT);
  159. if (i%5==0) fl_line_style(0);
  160. if (i%10==0) fl_color(120,120,120);
  161. int kx=(int)(lx/(float)maxharmonic*i);
  162. fl_line(ox+kx,oy,ox+kx,oy+ly);
  163. };
  164. fl_color(180,0,0);
  165. fl_line_style(0);
  166. for (int i=0;i<lx;i++){
  167. float x=spectrum[i];
  168. if (x>dB2rap(-maxdb)) x=rap2dB(x)/maxdb+1;
  169. else continue;
  170. int yy=(int)(x*ly);
  171. fl_line(ox+i,oy+ly-1-yy,ox+i,oy+ly-1);
  172. }
  173. }
  174. private:
  175. size_t nsamples;
  176. float *spc;
  177. float *nhr;
  178. float *spectrum;
  179. char mode;
  180. std::string base_path;
  181. Fl_Osc_Interface *osc;
  182. };