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.

224 lines
6.6KB

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