VuMasterMeter.h (4675B)
1 /* 2 ZynAddSubFX - a software synthesizer 3 4 VuMasterMeter.h - OSC Controlled VU Meter 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 "VuMeter.h" 13 #include "Fl_Osc_Interface.h" 14 #define MIN_DB (-48) 15 using namespace zyn; 16 17 class VuMasterMeter: public VuMeter 18 { 19 public: 20 VuMasterMeter(int x,int y, int w, int h, const char *label=0) 21 :VuMeter(x,y,w,h,label), 22 olddbl(0.0f),olddbr(0.0f), 23 oldrmsdbl(0.0f),oldrmsdbr(0.0f), 24 dbl(0.0f),dbr(0.0f),rmsdbl(0.0f),rmsdbr(0.0f),maxdbl(0.0f),maxdbr(0.0f), 25 clipped(0),osc(NULL) 26 {} 27 28 void init(Fl_Osc_Interface *_osc) 29 { 30 osc = _osc; 31 } 32 33 int handle(int event) 34 { 35 switch(event){ 36 case FL_SHOW: 37 Fl::add_timeout(1.0/18.0,tick,osc); 38 break; 39 case FL_HIDE: 40 Fl::remove_timeout(tick,osc); 41 break; 42 case FL_PUSH: 43 osc->requestValue("/reset-vu"); 44 return 1; 45 } 46 47 return 0; 48 } 49 50 static void tick(void *v) 51 { 52 Fl::repeat_timeout(1.0/18.0,tick,v);//18 fps 53 Fl_Osc_Interface *osc = (Fl_Osc_Interface*)v; 54 osc->requestValue("/get-vu"); 55 } 56 57 void draw(void) 58 { 59 const int X = x(), Y = y(), W = w(), H = h(); 60 61 #define VULENX (W-35) 62 #define VULENY (H/2-3) 63 64 const int idbl = dbl*VULENX; 65 const int idbr = dbr*VULENX; 66 const int irmsdbl = rmsdbl*VULENX; 67 const int irmsdbr = rmsdbr*VULENX; 68 69 //draw the vu-meter lines 70 //dB 71 fl_rectf(X,Y,idbr,VULENY,0,200,255); 72 fl_rectf(X,Y+H/2,idbl,VULENY,0,200,255); 73 //black 74 fl_rectf(X+idbr,Y,VULENX-idbr,VULENY,0,0,0); 75 fl_rectf(X+idbl,Y+H/2,VULENX-idbl,VULENY,0,0,0); 76 77 //draw the scales 78 const float tmp=VULENX*1.0/MIN_DB; 79 for (int i=1;i<1-MIN_DB;i++){ 80 const int tx=VULENX+(int) (tmp*i); 81 fl_rectf(X+tx,Y,1,VULENY+H/2,0,160,200); 82 if (i%5==0) fl_rectf(X+tx,Y,1,VULENY+H/2,0,230,240); 83 if (i%10==0) fl_rectf(X+tx-1,Y,2,VULENY+H/2,0,225,255); 84 } 85 86 //rms 87 if (irmsdbr>2) fl_rectf(X+irmsdbr-1,Y,3,VULENY,255,255,0); 88 if (irmsdbl>2) fl_rectf(X+irmsdbl-1,Y+H/2,3,VULENY,255,255,0); 89 90 91 //draw the red box if clipping has occurred 92 if (clipped==0) fl_rectf(X+VULENX+2,Y+1,W-VULENX-3,H-4,0,0,10); 93 else fl_rectf(X+VULENX+2,Y+1,W-VULENX-3,H-4,250,10,10); 94 95 //draw the maxdB 96 fl_font(FL_HELVETICA|FL_BOLD,10); 97 fl_color(255,255,255); 98 99 char tmpstr[10]; 100 if(maxdbl>MIN_DB-20){ 101 snprintf((char *)&tmpstr,10,"%ddB",(int)maxdbr); 102 fl_draw(tmpstr,X+VULENX+1,Y+1,W-VULENX-1,VULENY,FL_ALIGN_RIGHT,NULL,0); 103 } 104 if(maxdbr>MIN_DB-20){ 105 snprintf((char *)&tmpstr,10,"%ddB",(int)maxdbl); 106 fl_draw(tmpstr,X+VULENX+1,Y+H/2+1,W-VULENX-1,VULENY,FL_ALIGN_RIGHT,NULL,0); 107 } 108 } 109 110 void update(vuData *d) 111 { 112 //Update properties 113 dbl = limit((MIN_DB-rap2dB(d->outpeakl))/MIN_DB); 114 dbr = limit((MIN_DB-rap2dB(d->outpeakr))/MIN_DB); 115 rmsdbl = limit((MIN_DB-rap2dB(d->rmspeakl))/MIN_DB); 116 rmsdbr = limit((MIN_DB-rap2dB(d->rmspeakr))/MIN_DB); 117 maxdbl = rap2dB(d->maxoutpeakl); 118 maxdbr = rap2dB(d->maxoutpeakr); 119 clipped = d->clipped; 120 121 //interpolate 122 dbl = 0.4 * dbl + 0.6 * olddbl; 123 dbr = 0.4 * dbr + 0.6 * olddbr; 124 125 rmsdbl = 0.4 * rmsdbl + 0.6 * oldrmsdbl; 126 rmsdbr = 0.4 * rmsdbr + 0.6 * oldrmsdbr; 127 128 //only update when values appear to be different 129 if(olddbl == dbl && olddbr == dbr) 130 return; 131 132 olddbl = dbl; 133 olddbr = dbr; 134 oldrmsdbl = rmsdbl; 135 oldrmsdbr = rmsdbr; 136 137 damage(FL_DAMAGE_USER1); 138 } 139 private: 140 float olddbl,olddbr; 141 float oldrmsdbl,oldrmsdbr; 142 float dbl,dbr,rmsdbl,rmsdbr,maxdbl,maxdbr; 143 int clipped; 144 145 Fl_Osc_Interface *osc; 146 };