/* ZynAddSubFX - a software synthesizer VuMasterMeter.h - OSC Controlled VU Meter Copyright (C) 2016 Mark McCurry This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ #include "VuMeter.h" #include "Fl_Osc_Interface.h" #define MIN_DB (-48) using namespace zyncarla; class VuMasterMeter: public VuMeter { public: VuMasterMeter(int x,int y, int w, int h, const char *label=0) :VuMeter(x,y,w,h,label), olddbl(0.0f),olddbr(0.0f), oldrmsdbl(0.0f),oldrmsdbr(0.0f), dbl(0.0f),dbr(0.0f),rmsdbl(0.0f),rmsdbr(0.0f),maxdbl(0.0f),maxdbr(0.0f), clipped(0),osc(NULL) {} void init(Fl_Osc_Interface *_osc) { osc = _osc; } int handle(int event) { switch(event){ case FL_SHOW: Fl::add_timeout(1.0/18.0,tick,osc); break; case FL_HIDE: Fl::remove_timeout(tick,osc); break; case FL_PUSH: osc->requestValue("/reset-vu"); return 1; } return 0; } static void tick(void *v) { Fl::repeat_timeout(1.0/18.0,tick,v);//18 fps Fl_Osc_Interface *osc = (Fl_Osc_Interface*)v; osc->requestValue("/get-vu"); } void draw(void) { const int X = x(), Y = y(), W = w(), H = h(); #define VULENX (W-35) #define VULENY (H/2-3) const int idbl = dbl*VULENX; const int idbr = dbr*VULENX; const int irmsdbl = rmsdbl*VULENX; const int irmsdbr = rmsdbr*VULENX; //draw the vu-meter lines //dB fl_rectf(X,Y,idbr,VULENY,0,200,255); fl_rectf(X,Y+H/2,idbl,VULENY,0,200,255); //black fl_rectf(X+idbr,Y,VULENX-idbr,VULENY,0,0,0); fl_rectf(X+idbl,Y+H/2,VULENX-idbl,VULENY,0,0,0); //draw the scales const float tmp=VULENX*1.0/MIN_DB; for (int i=1;i<1-MIN_DB;i++){ const int tx=VULENX+(int) (tmp*i); fl_rectf(X+tx,Y,1,VULENY+H/2,0,160,200); if (i%5==0) fl_rectf(X+tx,Y,1,VULENY+H/2,0,230,240); if (i%10==0) fl_rectf(X+tx-1,Y,2,VULENY+H/2,0,225,255); } //rms if (irmsdbr>2) fl_rectf(X+irmsdbr-1,Y,3,VULENY,255,255,0); if (irmsdbl>2) fl_rectf(X+irmsdbl-1,Y+H/2,3,VULENY,255,255,0); //draw the red box if clipping has occured if (clipped==0) fl_rectf(X+VULENX+2,Y+1,W-VULENX-3,H-4,0,0,10); else fl_rectf(X+VULENX+2,Y+1,W-VULENX-3,H-4,250,10,10); //draw the maxdB fl_font(FL_HELVETICA|FL_BOLD,10); fl_color(255,255,255); char tmpstr[10]; if(maxdbl>MIN_DB-20){ snprintf((char *)&tmpstr,10,"%ddB",(int)maxdbr); fl_draw(tmpstr,X+VULENX+1,Y+1,W-VULENX-1,VULENY,FL_ALIGN_RIGHT,NULL,0); } if(maxdbr>MIN_DB-20){ snprintf((char *)&tmpstr,10,"%ddB",(int)maxdbl); fl_draw(tmpstr,X+VULENX+1,Y+H/2+1,W-VULENX-1,VULENY,FL_ALIGN_RIGHT,NULL,0); } } void update(vuData *d) { //Update properties dbl = limit((MIN_DB-rap2dB(d->outpeakl))/MIN_DB); dbr = limit((MIN_DB-rap2dB(d->outpeakr))/MIN_DB); rmsdbl = limit((MIN_DB-rap2dB(d->rmspeakl))/MIN_DB); rmsdbr = limit((MIN_DB-rap2dB(d->rmspeakr))/MIN_DB); maxdbl = rap2dB(d->maxoutpeakl); maxdbr = rap2dB(d->maxoutpeakr); clipped = d->clipped; //interpolate dbl = 0.4 * dbl + 0.6 * olddbl; dbr = 0.4 * dbr + 0.6 * olddbr; rmsdbl = 0.4 * rmsdbl + 0.6 * oldrmsdbl; rmsdbr = 0.4 * rmsdbr + 0.6 * oldrmsdbr; //only update when values appear to be different if(olddbl == dbl && olddbr == dbr) return; olddbl = dbl; olddbr = dbr; oldrmsdbl = rmsdbl; oldrmsdbr = rmsdbr; damage(FL_DAMAGE_USER1); } private: float olddbl,olddbr; float oldrmsdbl,oldrmsdbr; float dbl,dbr,rmsdbl,rmsdbr,maxdbl,maxdbr; int clipped; Fl_Osc_Interface *osc; };