Fl_Oscilloscope.h (4668B)
1 /* 2 ZynAddSubFX - a software synthesizer 3 4 Fl_Oscilloscope.h - OSC Waveform 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 #pragma once 13 14 #include "Fl_Osc_Pane.H" 15 #include <FL/Fl_Box.H> 16 #include <FL/fl_draw.H> 17 #include "Fl_Osc_Widget.H" 18 #include "Fl_Osc_Pane.H" 19 #include "Fl_Osc_Interface.h" 20 #include "common.H" 21 #include <cassert> 22 #include <cstdio> 23 #include "../globals.h" 24 25 class Fl_Osc_Group; 26 //Consider merging in Fl_OscilSpectrum 27 class Fl_Oscilloscope : public Fl_Box, public Fl_Osc_Widget 28 { 29 public: 30 Fl_Oscilloscope(int x,int y, int w, int h, const char *label=0) 31 :Fl_Box(x,y,w,h,label), Fl_Osc_Widget(this), smps(0), oscilsize(0), 32 Overlay(NULL) 33 { 34 phase=64; 35 box(FL_FLAT_BOX); 36 bkgnd = fl_color_average( FL_BLACK, FL_BACKGROUND_COLOR, 0.5 ); 37 } 38 39 ~Fl_Oscilloscope(void) 40 { 41 delete[] smps; 42 } 43 44 void init(bool base_waveform_p) 45 { 46 ext = (base_waveform_p ? "base-waveform": "waveform"); 47 osc->createLink("/oscilsize", this); 48 osc->requestValue("/oscilsize"); 49 assert(osc); 50 oscRegister(ext.c_str()); 51 } 52 53 void update(void) 54 { 55 oscWrite(ext); 56 } 57 58 virtual void OSC_value(int smp) 59 { 60 if(smp == oscilsize) 61 return; 62 oscilsize = smp; 63 delete []smps; 64 smps = new float[oscilsize]; 65 memset(smps, 0, oscilsize*sizeof(float)); 66 } 67 68 virtual void OSC_value(unsigned N, void *data) override 69 { 70 if(oscilsize == 0) 71 OSC_value((int)N/4); 72 73 assert(N==(unsigned)(oscilsize*4)); 74 75 memcpy(smps, data, N); 76 77 //normalize 78 float max=0; 79 for (int i=0;i<oscilsize;i++) 80 if(max<fabsf(smps[i])) 81 max=fabsf(smps[i]); 82 if (max<0.00001) max=1.0; 83 max *= -1.05; 84 85 for(int i=0; i < oscilsize; ++i) 86 smps[i] /= max; 87 88 //Get widget to redraw new data 89 redraw(); 90 } 91 92 void draw(void) 93 { 94 int ox=x(),oy=y(),lx=w(),ly=h()-1; 95 96 if (damage()!=1) { 97 fl_color(bkgnd); 98 fl_rectf(ox,oy,lx,ly); 99 } 100 101 //draw 102 fl_line_style(FL_DASH); 103 if (this->active_r()) fl_color(this->parent()->labelcolor()); 104 else fl_color(this->parent()->color()); 105 106 int GX=16;if (lx<GX*3) GX=-1; 107 for (int i=1;i<GX;i++){ 108 int tmp=(int)(lx/(float)GX*i); 109 fl_line(ox+tmp,oy+2,ox+tmp,oy+ly-2); 110 } 111 112 int GY=8; if (ly<GY*3) GY=-1; 113 for (int i=1;i<GY;i++){ 114 int tmp=(int)(ly/(float)GY*i); 115 fl_line(ox+2,oy+tmp,ox+lx-2,oy+tmp); 116 } 117 118 //draw the function 119 fl_line_style(0,1); 120 fl_line(ox+2,oy+ly/2,ox+lx-2,oy+ly/2); 121 if (this->active_r()) fl_color(this->parent()->selection_color()); 122 else fl_color(this->parent()->labelcolor()); 123 124 fl_color( fl_color_add_alpha( fl_color(), 127 ) ); 125 126 if(smps) { 127 int lw=2; 128 fl_line_style(FL_SOLID,lw); 129 fl_begin_line(); 130 double ph=((phase-64.0)/128.0*oscilsize+oscilsize); 131 for (int i=1;i<lx;i++){ 132 int k2=(oscilsize*i/lx)+ph; 133 fl_vertex(i+ox,(smps[k2%oscilsize]+1)*(ly-1)/2+oy+0.5); 134 } 135 fl_end_line(); 136 } 137 138 // Erase stray pixels on margin 139 fl_color(bkgnd); 140 fl_line_style(FL_SOLID,1); 141 fl_rect(ox-1,oy-1,lx+2,ly+2); 142 143 fl_line_style(FL_SOLID,0); 144 if (Overlay) 145 Overlay->redraw(); 146 } 147 148 //allows UI to manipuate phase of displayed waveform 149 int phase; 150 151 private: 152 Fl_Osc_Pane *fetch_osc_pane(Fl_Widget *w) 153 { 154 if(!w) 155 return NULL; 156 157 Fl_Osc_Pane *pane = dynamic_cast<Fl_Osc_Pane*>(w->parent()); 158 if(pane) 159 return pane; 160 return fetch_osc_pane(w->parent()); 161 } 162 163 float *smps; 164 int oscilsize; 165 Fl_Color bkgnd; 166 public: 167 Fl_Box *Overlay; 168 };