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