From e40fc849149dd97c248866a4a1d026dda5e57b62 Mon Sep 17 00:00:00 2001 From: Robert Jonsson Date: Mon, 7 Mar 2011 19:01:11 +0000 Subject: clean3 --- .../synti/zynaddsubfx/Misc/Master.C | 680 +++++++++++++++++++++ 1 file changed, 680 insertions(+) create mode 100644 attic/muse_qt4_evolution/synti/zynaddsubfx/Misc/Master.C (limited to 'attic/muse_qt4_evolution/synti/zynaddsubfx/Misc/Master.C') diff --git a/attic/muse_qt4_evolution/synti/zynaddsubfx/Misc/Master.C b/attic/muse_qt4_evolution/synti/zynaddsubfx/Misc/Master.C new file mode 100644 index 00000000..99a1ac28 --- /dev/null +++ b/attic/muse_qt4_evolution/synti/zynaddsubfx/Misc/Master.C @@ -0,0 +1,680 @@ +/* + ZynAddSubFX - a software synthesizer + + Master.C - It sends Midi Messages to Parts, receives samples from parts, + process them with system/insertion effects and mix them + Copyright (C) 2002-2005 Nasca Octavian Paul + Author: Nasca Octavian Paul + + This program is free software; you can redistribute it and/or modify + it under the terms of version 2 of the GNU General Public License + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License (version 2) for more details. + + You should have received a copy of the GNU General Public License (version 2) + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "Master.h" + +#include +#include +#include + +#include + +Master::Master(){ + swaplr=0; + + busy = false; + fft=new FFTwrapper(OSCIL_SIZE); + + tmpmixl=new REALTYPE[SOUND_BUFFER_SIZE]; + tmpmixr=new REALTYPE[SOUND_BUFFER_SIZE]; + audiooutl=new REALTYPE[SOUND_BUFFER_SIZE]; + audiooutr=new REALTYPE[SOUND_BUFFER_SIZE]; + + ksoundbuffersamples=0; + ksoundbuffersamplelow=0.0; + oldsamplel=0.0;oldsampler=0.0; + shutup=0; + for (int npart=0;npartdefaults(); + part[npart]->Prcvchn=npart%NUM_MIDI_CHANNELS; + }; + + partonoff(0,1);//enable the first part + + for (int nefx=0;nefxdefaults(); + Pinsparts[nefx]=-1; + }; + + //System Effects init + for (int nefx=0;nefxdefaults(); + for (int npart=0;npartchangeeffect(1); + microtonal.defaults(); + ShutUp(); +}; + +/* + * Note On Messages (velocity=0 for NoteOff) + */ +void Master::NoteOn(unsigned char chan,unsigned char note,unsigned char velocity){ + dump.dumpnote(chan,note,velocity); + + noteon(chan,note,velocity); +}; + +/* + * Internal Note On (velocity=0 for NoteOff) + */ +void Master::noteon(unsigned char chan,unsigned char note,unsigned char velocity){ + int npart; + if (velocity!=0){ + for (npart=0;npartPrcvchn){ + fakepeakpart[npart]=velocity*2; + if (part[npart]->Penabled!=0) part[npart]->NoteOn(note,velocity,keyshift); + }; + }; + }else{ + this->NoteOff(chan,note); + }; + HDDRecorder.triggernow(); +}; + +/* + * Note Off Messages + */ +void Master::NoteOff(unsigned char chan,unsigned char note){ + dump.dumpnote(chan,note,0); + + noteoff(chan,note); +}; + +/* + * Internal Note Off + */ +void Master::noteoff(unsigned char chan,unsigned char note){ + int npart; + for (npart=0;npartPrcvchn) && (part[npart]->Penabled!=0)) + part[npart]->NoteOff(note); + }; +}; + +/* + * Controllers + */ +void Master::SetController(unsigned char chan,unsigned int type,int par){ + dump.dumpcontroller(chan,type,par); + + setcontroller(chan,type,par); +}; + +/* + * Internal Controllers + */ +void Master::setcontroller(unsigned char chan,unsigned int type,int par){ + if ((type==C_dataentryhi)||(type==C_dataentrylo)|| + (type==C_nrpnhi)||(type==C_nrpnlo)){//Process RPN and NRPN by the Master (ignore the chan) + ctl.setparameternumber(type,par); + + int parhi=-1,parlo=-1,valhi=-1,vallo=-1; + if (ctl.getnrpn(&parhi,&parlo,&valhi,&vallo)==0){//this is NRPN + //fprintf(stderr,"rcv. NRPN: %d %d %d %d\n",parhi,parlo,valhi,vallo); + switch (parhi){ + case 0x04://System Effects + if (parloseteffectpar_nolock(valhi,vallo); + }; + break; + case 0x08://Insertion Effects + if (parloseteffectpar_nolock(valhi,vallo); + }; + break; + + }; + }; + } else {//other controllers + for (int npart=0;npartPrcvchn) && (part[npart]->Penabled!=0)) + part[npart]->SetController(type,par); + }; + }; +}; + + +/* + * Enable/Disable a part + */ +void Master::partonoff(int npart,int what){ + if (npart>=NUM_MIDI_PARTS) return; + if (what==0){//disable part + fakepeakpart[npart]=0; + part[npart]->Penabled=0; + part[npart]->cleanup(); + for (int nefx=0;nefxcleanup(); + }; + }; + } else {//enabled + part[npart]->Penabled=1; + fakepeakpart[npart]=0; + }; +}; + +/* + * Master audio out (the final sound) + */ + +void Master::AudioOut(REALTYPE* outl, REALTYPE* outr) + { + int i,npart,nefx; + + //Swaps the Left channel with Right Channel (if it is asked for) + if (swaplr != 0) { + REALTYPE *tmp=outl; + outl = outr; + outr = tmp; + } + + //clean up the output samples + memset(outl, 0, sizeof(REALTYPE) * SOUND_BUFFER_SIZE); + memset(outr, 0, sizeof(REALTYPE) * SOUND_BUFFER_SIZE); + + //Compute part samples and store them part[npart]->partoutl,partoutr + for (npart=0; npartPenabled != 0) + part[npart]->ComputePartSmps(); + + //Insertion effects + for (nefx=0;nefx=0) { + int efxpart=Pinsparts[nefx]; + if (part[efxpart]->Penabled!=0) + insefx[nefx]->out(part[efxpart]->partoutl,part[efxpart]->partoutr); + } + } + + + //Apply the part volumes and pannings (after insertion effects) + for (npart = 0; npart < NUM_MIDI_PARTS; npart++) { + if (part[npart]->Penabled==0) + continue; + + REALTYPE newvol_l=part[npart]->volume; + REALTYPE newvol_r=part[npart]->volume; + REALTYPE oldvol_l=part[npart]->oldvolumel; + REALTYPE oldvol_r=part[npart]->oldvolumer; + REALTYPE pan=part[npart]->panning; + if (pan < 0.5) + newvol_l *= pan*2.0; + else + newvol_r *= (1.0-pan)*2.0; + + if (ABOVE_AMPLITUDE_THRESHOLD(oldvol_l,newvol_l)|| + ABOVE_AMPLITUDE_THRESHOLD(oldvol_r,newvol_r)){//the volume or the panning has changed and needs interpolation + + for (i=0;ipartoutl[i]*=vol_l; + part[npart]->partoutr[i]*=vol_r; + } + part[npart]->oldvolumel=newvol_l; + part[npart]->oldvolumer=newvol_r; + + } + else { + for (i=0;ipartoutl[i] *= newvol_l; + part[npart]->partoutr[i] *= newvol_r; + } + } + } + + + //System effects + for (nefx=0;nefxgeteffect()==0) continue;//the effect is disabled + + //Clean up the samples used by the system effects + memset(tmpmixl, 0, sizeof(REALTYPE) * SOUND_BUFFER_SIZE); + memset(tmpmixr, 0, sizeof(REALTYPE) * SOUND_BUFFER_SIZE); + + //Mix the channels according to the part settings about System Effect + for (npart=0;npartPenabled==0) continue; + + //the output volume of each part to system effect + REALTYPE vol=sysefxvol[nefx][npart]; + for (i=0;ipartoutl[i]*vol; + tmpmixr[i]+=part[npart]->partoutr[i]*vol; + }; + }; + + // system effect send to next ones + for (int nefxfrom=0;nefxfromefxoutl[i]*v; + tmpmixr[i]+=sysefx[nefxfrom]->efxoutr[i]*v; + }; + }; + }; + + sysefx[nefx]->out(tmpmixl,tmpmixr); + + //Add the System Effect to sound output + REALTYPE outvol=sysefx[nefx]->sysefxgetvolume(); + for (i=0;ipartoutl[i]; + outr[i] += part[npart]->partoutr[i]; + } + } + + //Insertion effects for Master Out + for (nefx=0;nefxout(outl, outr); + } + + //Master Volume + for (i = 0; i < SOUND_BUFFER_SIZE; i++) { + outl[i] *= volume; + outr[i] *= volume; + } + + //Peak computation (for vumeters) + vuoutpeakl=1e-12;vuoutpeakr=1e-12; + for (i=0;ivuoutpeakl) vuoutpeakl=fabs(outl[i]); + if (fabs(outr[i])>vuoutpeakr) vuoutpeakr=fabs(outr[i]); + }; + if ((vuoutpeakl>1.0)||(vuoutpeakr>1.0)) vuclipped=1; + if (vumaxoutpeaklPenabled!=0) { + REALTYPE *outl=part[npart]->partoutl, + *outr=part[npart]->partoutr; + for (i=0;ivuoutpeakpart[npart]) vuoutpeakpart[npart]=tmp; + }; + vuoutpeakpart[npart]*=volume; + } else { + if (fakepeakpart[npart]>1) fakepeakpart[npart]--; + }; + }; + + + //Shutup if it is asked (with fade-out) + if (shutup != 0) { + for (i = 0; i < SOUND_BUFFER_SIZE; i++) { + REALTYPE tmp=(SOUND_BUFFER_SIZE-i)/(REALTYPE) SOUND_BUFFER_SIZE; + outl[i] *= tmp; + outr[i] *= tmp; + } + ShutUp(); + } + + //update the LFO's time + LFOParams::time++; + + if (HDDRecorder.recording()) + HDDRecorder.recordbuffer(outl,outr); + dump.inctick(); + }; + +//--------------------------------------------------------- +// GetAudioOutSamples +//--------------------------------------------------------- + +void Master::GetAudioOutSamples(int nsamples, REALTYPE* outl, REALTYPE* outr) + { + int dstOffset = 0; + while (nsamples) { + if (ksoundbuffersamples <= 0) { + AudioOut(audiooutl, audiooutr); + ksoundbuffersamples = SOUND_BUFFER_SIZE; + } + int n = nsamples > ksoundbuffersamples ? ksoundbuffersamples : nsamples; + int srcOffset = SOUND_BUFFER_SIZE - ksoundbuffersamples; + memcpy(outl + dstOffset, audiooutl + srcOffset, n * sizeof(REALTYPE)); + memcpy(outr + dstOffset, audiooutr + srcOffset, n * sizeof(REALTYPE)); + nsamples -= n; + dstOffset += n; + ksoundbuffersamples -= n; + } + } + +Master::~Master(){ + for (int npart=0;npartcleanup(); + fakepeakpart[npart]=0; + }; + for (int nefx=0;nefxcleanup(); + for (int nefx=0;nefxcleanup(); + vuresetpeaks(); + shutup=0; +}; + + +/* + * Reset peaks and clear the "cliped" flag (for VU-meter) + */ +void Master::vuresetpeaks(){ + vuoutpeakl=1e-9;vuoutpeakr=1e-9;vumaxoutpeakl=1e-9;vumaxoutpeakr=1e-9; + vuclipped=0; +}; + + + +void Master::applyparameters(){ + for (int npart=0;npartapplyparameters(); + }; +}; + +void Master::add2XML(XMLwrapper *xml){ + xml->addpar("volume",Pvolume); + xml->addpar("key_shift",Pkeyshift); + xml->addparbool("nrpn_receive",ctl.NRPN.receive); + + xml->beginbranch("MICROTONAL"); + microtonal.add2XML(xml); + xml->endbranch(); + + for (int npart=0;npartbeginbranch("PART",npart); + part[npart]->add2XML(xml); + xml->endbranch(); + }; + + xml->beginbranch("SYSTEM_EFFECTS"); + for (int nefx=0;nefxbeginbranch("SYSTEM_EFFECT",nefx); + xml->beginbranch("EFFECT"); + sysefx[nefx]->add2XML(xml); + xml->endbranch(); + + for (int pefx=0;pefxbeginbranch("VOLUME",pefx); + xml->addpar("vol",Psysefxvol[nefx][pefx]); + xml->endbranch(); + }; + + for (int tonefx=nefx+1;tonefxbeginbranch("SENDTO",tonefx); + xml->addpar("send_vol",Psysefxsend[nefx][tonefx]); + xml->endbranch(); + }; + + + xml->endbranch(); + }; + xml->endbranch(); + + xml->beginbranch("INSERTION_EFFECTS"); + for (int nefx=0;nefxbeginbranch("INSERTION_EFFECT",nefx); + xml->addpar("part",Pinsparts[nefx]); + + xml->beginbranch("EFFECT"); + insefx[nefx]->add2XML(xml); + xml->endbranch(); + xml->endbranch(); + }; + + xml->endbranch(); + +}; + + +int Master::getalldata(char **data){ + XMLwrapper *xml=new XMLwrapper(); + + xml->beginbranch("MASTER"); + + busy = true; + add2XML(xml); + busy = false; + + xml->endbranch(); + + *data=xml->getXMLdata(); + delete (xml); + return(strlen(*data)+1); +}; + +void Master::putalldata(char *data,int size){ + XMLwrapper *xml=new XMLwrapper(); + if (!xml->putXMLdata(data)) { + delete(xml); + return; + }; + + if (xml->enterbranch("MASTER")==0) return; + + busy = true; + getfromXML(xml); + busy = false; + + xml->exitbranch(); + + delete(xml); +}; + +int Master::saveXML(char *filename){ + XMLwrapper *xml=new XMLwrapper(); + + xml->beginbranch("MASTER"); + add2XML(xml); + xml->endbranch(); + + int result=xml->saveXMLfile(filename); + delete (xml); + return(result); +}; + + + +int Master::loadXML(char *filename){ + XMLwrapper *xml=new XMLwrapper(); + if (xml->loadXMLfile(filename)<0) { + delete(xml); + return(-1); + }; + + if (xml->enterbranch("MASTER")==0) return(-10); + getfromXML(xml); + xml->exitbranch(); + + delete(xml); + return(0); +}; + +void Master::getfromXML(XMLwrapper *xml){ + setPvolume(xml->getpar127("volume",Pvolume)); + setPkeyshift(xml->getpar127("key_shift",Pkeyshift)); + ctl.NRPN.receive=xml->getparbool("nrpn_receive",ctl.NRPN.receive); + + + part[0]->Penabled=0; + for (int npart=0;npartenterbranch("PART",npart)==0) continue; + part[npart]->getfromXML(xml); + xml->exitbranch(); + }; + + if (xml->enterbranch("MICROTONAL")){ + microtonal.getfromXML(xml); + xml->exitbranch(); + }; + + sysefx[0]->changeeffect(0); + if (xml->enterbranch("SYSTEM_EFFECTS")){ + for (int nefx=0;nefxenterbranch("SYSTEM_EFFECT",nefx)==0) continue; + if (xml->enterbranch("EFFECT")){ + sysefx[nefx]->getfromXML(xml); + xml->exitbranch(); + }; + + for (int partefx=0;partefxenterbranch("VOLUME",partefx)==0) continue; + setPsysefxvol(partefx,nefx,xml->getpar127("vol",Psysefxvol[partefx][nefx])); + xml->exitbranch(); + }; + + for (int tonefx=nefx+1;tonefxenterbranch("SENDTO",tonefx)==0) continue; + setPsysefxsend(nefx,tonefx,xml->getpar127("send_vol",Psysefxsend[nefx][tonefx])); + xml->exitbranch(); + }; + xml->exitbranch(); + }; + xml->exitbranch(); + }; + + + if (xml->enterbranch("INSERTION_EFFECTS")){ + for (int nefx=0;nefxenterbranch("INSERTION_EFFECT",nefx)==0) continue; + Pinsparts[nefx]=xml->getpar("part",Pinsparts[nefx],-2,NUM_MIDI_PARTS); + if (xml->enterbranch("EFFECT")){ + insefx[nefx]->getfromXML(xml); + xml->exitbranch(); + }; + xml->exitbranch(); + + }; + + xml->exitbranch(); + }; + +}; + + + + -- cgit v1.2.3