zynaddsubfx

ZynAddSubFX open source synthesizer
Log | Files | Refs | Submodules | LICENSE

commit 2c952c5aa81b1ead5454ce95222028db434dd853
parent 8f070f1e15b6e24a97a75cb5c7e85b729dcbed54
Author: fundamental <mark.d.mccurry@gmail.com>
Date:   Fri,  8 May 2015 13:16:39 -0400

Demote 'synth' From Global Scope

Diffstat:
Msrc/DSP/Filter.cpp | 11+++++------
Msrc/DSP/Filter.h | 3++-
Msrc/Effects/EffectMgr.cpp | 33+++++++++++++++++----------------
Msrc/Effects/EffectMgr.h | 3++-
Msrc/Misc/Master.cpp | 76++++++++++++++++++++++++++++++++++++++--------------------------------------
Msrc/Misc/Master.h | 3++-
Msrc/Misc/MiddleWare.cpp | 28++++++++++++++++++----------
Msrc/Misc/MiddleWare.h | 5++++-
Msrc/Misc/Part.cpp | 50+++++++++++++++++++++++++-------------------------
Msrc/Misc/Part.h | 3++-
Msrc/Misc/PresetExtractor.cpp | 10+++++-----
Msrc/Misc/Recorder.cpp | 7++++---
Msrc/Misc/Recorder.h | 5+++--
Msrc/Nio/AlsaEngine.cpp | 12++++++------
Msrc/Nio/AlsaEngine.h | 2+-
Msrc/Nio/AudioOut.cpp | 4++--
Msrc/Nio/AudioOut.h | 3++-
Msrc/Nio/EngineMgr.cpp | 22++++++++++++----------
Msrc/Nio/EngineMgr.h | 5+++--
Msrc/Nio/InMgr.cpp | 2+-
Msrc/Nio/JackEngine.cpp | 4++--
Msrc/Nio/JackEngine.h | 2+-
Msrc/Nio/JackMultiEngine.cpp | 18+++++++++---------
Msrc/Nio/JackMultiEngine.h | 2+-
Msrc/Nio/Nio.cpp | 6+++---
Msrc/Nio/Nio.h | 3++-
Msrc/Nio/NulEngine.cpp | 8++++----
Msrc/Nio/NulEngine.h | 2+-
Msrc/Nio/OssEngine.cpp | 18+++++++++---------
Msrc/Nio/OssEngine.h | 2+-
Msrc/Nio/OssMultiEngine.cpp | 17+++++++++--------
Msrc/Nio/OssMultiEngine.h | 2+-
Msrc/Nio/OutMgr.cpp | 38+++++++++++++++++++-------------------
Msrc/Nio/OutMgr.h | 6++++--
Msrc/Nio/PaEngine.cpp | 8++++----
Msrc/Nio/PaEngine.h | 2+-
Msrc/Nio/WavEngine.cpp | 10+++++-----
Msrc/Nio/WavEngine.h | 2+-
Msrc/Output/DSSIaudiooutput.cpp | 13++++++-------
Msrc/Params/ADnoteParameters.cpp | 14+++++++-------
Msrc/Params/ADnoteParameters.h | 6+++---
Msrc/Params/Controller.cpp | 12++++++++++--
Msrc/Params/Controller.h | 4+++-
Msrc/Params/FilterParams.cpp | 79-------------------------------------------------------------------------------
Msrc/Params/FilterParams.h | 2--
Msrc/Params/PADnoteParameters.cpp | 37+++++++++++++++++++------------------
Msrc/Params/PADnoteParameters.h | 4+++-
Msrc/Synth/ADnote.cpp | 258++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Synth/ADnote.h | 3++-
Msrc/Synth/Envelope.cpp | 4+---
Msrc/Synth/Envelope.h | 2+-
Msrc/Synth/LFO.cpp | 7++++---
Msrc/Synth/LFO.h | 3++-
Msrc/Synth/OscilGen.cpp | 166++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/Synth/OscilGen.h | 4+++-
Msrc/Synth/PADnote.cpp | 46++++++++++++++++++++++++----------------------
Msrc/Synth/SUBnote.cpp | 66++++++++++++++++++++++++++++++++++--------------------------------
Msrc/Synth/SynthNote.cpp | 21+++++++++++----------
Msrc/Synth/SynthNote.h | 7+++++--
Msrc/Tests/AdNoteTest.h | 11+++--------
Msrc/Tests/ControllerTest.h | 2+-
Msrc/Tests/InstrumentStats.cpp | 2+-
Msrc/Tests/OscilGenTest.h | 2+-
Msrc/Tests/PadNoteTest.h | 6+++---
Msrc/Tests/PluginTest.h | 2+-
Msrc/Tests/SubNoteTest.h | 9++-------
Msrc/Tests/UnisonTest.h | 6+++---
Msrc/globals.h | 6++++--
Msrc/main.cpp | 60+++++++++++++++++++++++++++++-------------------------------
69 files changed, 633 insertions(+), 668 deletions(-)

diff --git a/src/DSP/Filter.cpp b/src/DSP/Filter.cpp @@ -20,8 +20,9 @@ */ -#include <math.h> -#include <stdio.h> +#include <cmath> +#include <cstdio> +#include <cassert> #include "Filter.h" #include "AnalogFilter.h" @@ -41,10 +42,8 @@ Filter::Filter(unsigned int srate, int bufsize) Filter *Filter::generate(Allocator &memory, FilterParams *pars, unsigned int srate, int bufsize) { - if (srate == 0) - srate = synth->samplerate; - if (bufsize == 0) - bufsize = synth->buffersize; + assert(srate != 0); + assert(bufsize != 0); unsigned char Ftype = pars->Ptype; unsigned char Fstages = pars->Pstages; diff --git a/src/DSP/Filter.h b/src/DSP/Filter.h @@ -29,7 +29,8 @@ class Filter { public: static float getrealfreq(float freqpitch); - static Filter *generate(class Allocator &memory, class FilterParams * pars, unsigned int srate = 0, int bufsize = 0); + static Filter *generate(class Allocator &memory, class FilterParams *pars, + unsigned int srate, int bufsize); Filter(unsigned int srate, int bufsize); virtual ~Filter() {} diff --git a/src/Effects/EffectMgr.cpp b/src/Effects/EffectMgr.cpp @@ -108,19 +108,20 @@ static const rtosc::Ports local_ports = { const rtosc::Ports &EffectMgr::ports = local_ports; -EffectMgr::EffectMgr(Allocator &alloc, const bool insertion_) +EffectMgr::EffectMgr(Allocator &alloc, const SYNTH_T &synth_, const bool insertion_) :insertion(insertion_), - efxoutl(new float[synth->buffersize]), - efxoutr(new float[synth->buffersize]), + efxoutl(new float[synth_.buffersize]), + efxoutr(new float[synth_.buffersize]), filterpars(NULL), nefx(0), efx(NULL), dryonly(false), - memory(alloc) + memory(alloc), + synth(synth_) { setpresettype("Peffect"); - memset(efxoutl, 0, synth->bufferbytes); - memset(efxoutr, 0, synth->bufferbytes); + memset(efxoutl, 0, synth.bufferbytes); + memset(efxoutr, 0, synth.bufferbytes); memset(settings, 0, sizeof(settings)); defaults(); } @@ -146,11 +147,11 @@ void EffectMgr::changeeffectrt(int _nefx) if(nefx == _nefx && efx != NULL) return; nefx = _nefx; - memset(efxoutl, 0, synth->bufferbytes); - memset(efxoutr, 0, synth->bufferbytes); + memset(efxoutl, 0, synth.bufferbytes); + memset(efxoutr, 0, synth.bufferbytes); memory.dealloc(efx); EffectParams pars(memory, insertion, efxoutl, efxoutr, 0, - synth->samplerate, synth->buffersize); + synth.samplerate, synth.buffersize); switch(nefx) { case 1: efx = memory.alloc<Reverb>(pars); @@ -285,7 +286,7 @@ void EffectMgr::out(float *smpsl, float *smpsr) { if(!efx) { if(!insertion) - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { smpsl[i] = 0.0f; smpsr[i] = 0.0f; efxoutl[i] = 0.0f; @@ -293,7 +294,7 @@ void EffectMgr::out(float *smpsl, float *smpsr) } return; } - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { smpsl[i] += denormalkillbuf[i]; smpsr[i] += denormalkillbuf[i]; efxoutl[i] = 0.0f; @@ -304,8 +305,8 @@ void EffectMgr::out(float *smpsl, float *smpsr) float volume = efx->volume; if(nefx == 7) { //this is need only for the EQ effect - memcpy(smpsl, efxoutl, synth->bufferbytes); - memcpy(smpsr, efxoutr, synth->bufferbytes); + memcpy(smpsl, efxoutl, synth.bufferbytes); + memcpy(smpsr, efxoutr, synth.bufferbytes); return; } @@ -324,20 +325,20 @@ void EffectMgr::out(float *smpsl, float *smpsr) v2 *= v2; //for Reverb and Echo, the wet function is not liniar if(dryonly) //this is used for instrument effect only - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { smpsl[i] *= v1; smpsr[i] *= v1; efxoutl[i] *= v2; efxoutr[i] *= v2; } else // normal instrument/insertion effect - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { smpsl[i] = smpsl[i] * v1 + efxoutl[i] * v2; smpsr[i] = smpsr[i] * v1 + efxoutr[i] * v2; } } else // System effect - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { efxoutl[i] *= 2.0f * volume; efxoutr[i] *= 2.0f * volume; smpsl[i] = efxoutl[i]; diff --git a/src/Effects/EffectMgr.h b/src/Effects/EffectMgr.h @@ -43,7 +43,7 @@ class Allocator; class EffectMgr:public Presets { public: - EffectMgr(Allocator &alloc, const bool insertion_); + EffectMgr(Allocator &alloc, const SYNTH_T &synth, const bool insertion_); ~EffectMgr(); void paste(EffectMgr &e); @@ -93,6 +93,7 @@ class EffectMgr:public Presets bool dryonly; Allocator &memory; + const SYNTH_T &synth; }; #endif diff --git a/src/Misc/Master.cpp b/src/Misc/Master.cpp @@ -210,13 +210,13 @@ static const Ports master_ports = { m.pendingMemory = false; }}, {"samplerate:", rMap(unit, Hz) rDoc("Synthesizer Global Sample Rate"), 0, [](const char *, RtData &d) { - //Master &m = *(Master*)d.obj; - d.reply("/samplerate", "f", synth->samplerate_f); + Master &m = *(Master*)d.obj; + d.reply("/samplerate", "f", m.synth.samplerate_f); }}, {"oscilsize:", rDoc("Synthesizer Global Oscillator Size"), 0, [](const char *, RtData &d) { - //Master &m = *(Master*)d.obj; - d.reply("/oscilsize", "f", synth->oscilsize_f); - d.reply("/oscilsize", "i", synth->oscilsize); + Master &m = *(Master*)d.obj; + d.reply("/oscilsize", "f", m.synth.oscilsize_f); + d.reply("/oscilsize", "i", m.synth.oscilsize); }}, {"undo_pause",0,0,[](const char *, rtosc::RtData &d) {d.reply("/undo_pause", "");}}, @@ -284,8 +284,8 @@ vuData::vuData(void) rmspeakl(0.0f), rmspeakr(0.0f), clipped(0) {} -Master::Master() -:midi(Master::ports), frozenState(false), pendingMemory(false) +Master::Master(const SYNTH_T &synth_) +:HDDRecorder(synth_), ctl(synth_), midi(Master::ports), frozenState(false), pendingMemory(false), synth(synth_) { bToU = NULL; uToB = NULL; @@ -294,10 +294,10 @@ Master::Master() swaplr = 0; off = 0; smps = 0; - bufl = new float[synth->buffersize]; - bufr = new float[synth->buffersize]; + bufl = new float[synth.buffersize]; + bufr = new float[synth.buffersize]; - fft = new FFTwrapper(synth->oscilsize); + fft = new FFTwrapper(synth.oscilsize); shutup = 0; for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart) { @@ -306,15 +306,15 @@ Master::Master() } for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart) - part[npart] = new Part(*memory, &microtonal, fft); + part[npart] = new Part(*memory, synth, &microtonal, fft); //Insertion Effects init for(int nefx = 0; nefx < NUM_INS_EFX; ++nefx) - insefx[nefx] = new EffectMgr(*memory, 1); + insefx[nefx] = new EffectMgr(*memory, synth, 1); //System Effects init for(int nefx = 0; nefx < NUM_SYS_EFX; ++nefx) - sysefx[nefx] = new EffectMgr(*memory, 0); + sysefx[nefx] = new EffectMgr(*memory, synth, 0); defaults(); @@ -471,7 +471,7 @@ void Master::vuUpdate(const float *outl, const float *outr) //Peak computation (for vumeters) vu.outpeakl = 1e-12; vu.outpeakr = 1e-12; - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { if(fabs(outl[i]) > vu.outpeakl) vu.outpeakl = fabs(outl[i]); if(fabs(outr[i]) > vu.outpeakr) @@ -487,12 +487,12 @@ void Master::vuUpdate(const float *outl, const float *outr) //RMS Peak computation (for vumeters) vu.rmspeakl = 1e-12; vu.rmspeakr = 1e-12; - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { vu.rmspeakl += outl[i] * outl[i]; vu.rmspeakr += outr[i] * outr[i]; } - vu.rmspeakl = sqrt(vu.rmspeakl / synth->buffersize_f); - vu.rmspeakr = sqrt(vu.rmspeakr / synth->buffersize_f); + vu.rmspeakl = sqrt(vu.rmspeakl / synth.buffersize_f); + vu.rmspeakr = sqrt(vu.rmspeakr / synth.buffersize_f); //Part Peak computation (for Part vumeters or fake part vumeters) for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart) { @@ -500,7 +500,7 @@ void Master::vuUpdate(const float *outl, const float *outr) if(part[npart]->Penabled != 0) { float *outl = part[npart]->partoutl, *outr = part[npart]->partoutr; - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { float tmp = fabs(outl[i] + outr[i]); if(tmp > vuoutpeakpart[npart]) vuoutpeakpart[npart] = tmp; @@ -655,8 +655,8 @@ void Master::AudioOut(float *outl, float *outr) swap(outl, outr); //clean up the output samples (should not be needed?) - memset(outl, 0, synth->bufferbytes); - memset(outr, 0, synth->bufferbytes); + memset(outl, 0, synth.bufferbytes); + memset(outr, 0, synth.bufferbytes); //Compute part samples and store them part[npart]->partoutl,partoutr for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart) @@ -693,11 +693,11 @@ void Master::AudioOut(float *outl, float *outr) //the volume or the panning has changed and needs interpolation if(ABOVE_AMPLITUDE_THRESHOLD(oldvol.l, newvol.l) || ABOVE_AMPLITUDE_THRESHOLD(oldvol.r, newvol.r)) { - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { Stereo<float> vol(INTERPOLATE_AMPLITUDE(oldvol.l, newvol.l, - i, synth->buffersize), + i, synth.buffersize), INTERPOLATE_AMPLITUDE(oldvol.r, newvol.r, - i, synth->buffersize)); + i, synth.buffersize)); part[npart]->partoutl[i] *= vol.l; part[npart]->partoutr[i] *= vol.r; } @@ -705,7 +705,7 @@ void Master::AudioOut(float *outl, float *outr) part[npart]->oldvolumer = newvol.r; } else { - for(int i = 0; i < synth->buffersize; ++i) { //the volume did not changed + for(int i = 0; i < synth.buffersize; ++i) { //the volume did not changed part[npart]->partoutl[i] *= newvol.l; part[npart]->partoutr[i] *= newvol.r; } @@ -718,11 +718,11 @@ void Master::AudioOut(float *outl, float *outr) if(sysefx[nefx]->geteffect() == 0) continue; //the effect is disabled - float tmpmixl[synth->buffersize]; - float tmpmixr[synth->buffersize]; + float tmpmixl[synth.buffersize]; + float tmpmixr[synth.buffersize]; //Clean up the samples used by the system effects - memset(tmpmixl, 0, synth->bufferbytes); - memset(tmpmixr, 0, synth->bufferbytes); + memset(tmpmixl, 0, synth.bufferbytes); + memset(tmpmixr, 0, synth.bufferbytes); //Mix the channels according to the part settings about System Effect for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart) { @@ -736,7 +736,7 @@ void Master::AudioOut(float *outl, float *outr) //the output volume of each part to system effect const float vol = sysefxvol[nefx][npart]; - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { tmpmixl[i] += part[npart]->partoutl[i] * vol; tmpmixr[i] += part[npart]->partoutr[i] * vol; } @@ -746,7 +746,7 @@ void Master::AudioOut(float *outl, float *outr) for(int nefxfrom = 0; nefxfrom < nefx; ++nefxfrom) if(Psysefxsend[nefxfrom][nefx] != 0) { const float vol = sysefxsend[nefxfrom][nefx]; - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { tmpmixl[i] += sysefx[nefxfrom]->efxoutl[i] * vol; tmpmixr[i] += sysefx[nefxfrom]->efxoutr[i] * vol; } @@ -756,7 +756,7 @@ void Master::AudioOut(float *outl, float *outr) //Add the System Effect to sound output const float outvol = sysefx[nefx]->sysefxgetvolume(); - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { outl[i] += tmpmixl[i] * outvol; outr[i] += tmpmixr[i] * outvol; } @@ -765,7 +765,7 @@ void Master::AudioOut(float *outl, float *outr) //Mix all parts for(int npart = 0; npart < NUM_MIDI_PARTS; ++npart) if(part[npart]->Penabled) //only mix active parts - for(int i = 0; i < synth->buffersize; ++i) { //the volume did not changed + for(int i = 0; i < synth.buffersize; ++i) { //the volume did not changed outl[i] += part[npart]->partoutl[i]; outr[i] += part[npart]->partoutr[i]; } @@ -777,7 +777,7 @@ void Master::AudioOut(float *outl, float *outr) //Master Volume - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { outl[i] *= volume; outr[i] *= volume; } @@ -786,8 +786,8 @@ void Master::AudioOut(float *outl, float *outr) //Shutup if it is asked (with fade-out) if(shutup) { - for(int i = 0; i < synth->buffersize; ++i) { - float tmp = (synth->buffersize_f - i) / synth->buffersize_f; + for(int i = 0; i < synth.buffersize; ++i) { + float tmp = (synth.buffersize_f - i) / synth.buffersize_f; outl[i] *= tmp; outr[i] *= tmp; } @@ -808,8 +808,8 @@ void Master::GetAudioOutSamples(size_t nsamples, off_t out_off = 0; //Fail when resampling rather than doing a poor job - if(synth->samplerate != samplerate) { - printf("darn it: %d vs %d\n", synth->samplerate, samplerate); + if(synth.samplerate != samplerate) { + printf("darn it: %d vs %d\n", synth.samplerate, samplerate); return; } @@ -824,7 +824,7 @@ void Master::GetAudioOutSamples(size_t nsamples, AudioOut(bufl, bufr); off = 0; out_off += smps; - smps = synth->buffersize; + smps = synth.buffersize; } else { //use some samples memcpy(outl + out_off, bufl + off, sizeof(float) * nsamples); diff --git a/src/Misc/Master.h b/src/Misc/Master.h @@ -49,7 +49,7 @@ class Master { public: /** Constructor TODO make private*/ - Master(); + Master(const SYNTH_T &synth); /** Destructor*/ ~Master(); @@ -167,6 +167,7 @@ class Master rtosc::ThreadLink *bToU; rtosc::ThreadLink *uToB; bool pendingMemory; + const SYNTH_T &synth; private: float sysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS]; float sysefxsend[NUM_SYS_EFX][NUM_SYS_EFX]; diff --git a/src/Misc/MiddleWare.cpp b/src/Misc/MiddleWare.cpp @@ -529,7 +529,7 @@ class MiddleWareImpl } public: - MiddleWareImpl(MiddleWare *mw, int prefered_port); + MiddleWareImpl(MiddleWare *mw, SYNTH_T synth, int prefered_port); ~MiddleWareImpl(void); void warnMemoryLeaks(void); @@ -616,7 +616,7 @@ public: auto alloc = std::async(std::launch::async, [master,filename,this,npart](){ - Part *p = new Part(*master->memory, &master->microtonal, master->fft); + Part *p = new Part(*master->memory, synth, &master->microtonal, master->fft); if(p->loadXMLinstrument(filename)) fprintf(stderr, "Warning: failed to load part!\n"); @@ -650,7 +650,7 @@ public: //structures at once... TODO error handling void loadMaster(const char *filename) { - Master *m = new Master(); + Master *m = new Master(synth); m->uToB = uToB; m->bToU = bToU; if(filename) { @@ -799,10 +799,13 @@ public: //LIBLO lo_server server; string last_url, curr_url; + + //Synthesis Rate Parameters + const SYNTH_T synth; }; -MiddleWareImpl::MiddleWareImpl(MiddleWare *mw, int prefered_port) - :parent(mw) +MiddleWareImpl::MiddleWareImpl(MiddleWare *mw, SYNTH_T synth_, int prefered_port) + :parent(mw), synth(synth_) { bToU = new rtosc::ThreadLink(4096*2,1024); uToB = new rtosc::ThreadLink(4096*2,1024); @@ -821,7 +824,7 @@ MiddleWareImpl::MiddleWareImpl(MiddleWare *mw, int prefered_port) idle = 0; the_bToU = bToU; - master = new Master(); + master = new Master(synth); master->bToU = bToU; master->uToB = uToB; osc = GUI::genOscInterface(mw); @@ -1073,11 +1076,11 @@ void MiddleWareImpl::kitEnable(int part, int kit, int type) string url = "/part"+to_s(part)+"/kit"+to_s(kit)+"/"; void *ptr = NULL; if(type == 0 && kits.add[part][kit] == NULL) { - ptr = kits.add[part][kit] = new ADnoteParameters(master->fft); + ptr = kits.add[part][kit] = new ADnoteParameters(synth, master->fft); url += "adpars-data"; obj_store.extractAD(kits.add[part][kit], part, kit); } else if(type == 1 && kits.pad[part][kit] == NULL) { - ptr = kits.pad[part][kit] = new PADnoteParameters(master->fft); + ptr = kits.pad[part][kit] = new PADnoteParameters(synth, master->fft); url += "padpars-data"; obj_store.extractPAD(kits.pad[part][kit], part, kit); } else if(type == 2 && kits.sub[part][kit] == NULL) { @@ -1212,8 +1215,8 @@ void MiddleWareImpl::warnMemoryLeaks(void) /****************************************************************************** * MidleWare Forwarding Stubs * ******************************************************************************/ -MiddleWare::MiddleWare(int prefered_port) -:impl(new MiddleWareImpl(this, prefered_port)) +MiddleWare::MiddleWare(SYNTH_T synth, int prefered_port) +:impl(new MiddleWareImpl(this, synth, prefered_port)) {} MiddleWare::~MiddleWare(void) { @@ -1289,3 +1292,8 @@ void MiddleWare::activeUrl(std::string u) { impl->last_url = u; } + +const SYNTH_T &MiddleWare::getSynth(void) const +{ + return impl->synth; +} diff --git a/src/Misc/MiddleWare.h b/src/Misc/MiddleWare.h @@ -3,11 +3,12 @@ #include <cstdarg> #include <string> +struct SYNTH_T; //Link between realtime and non-realtime layers class MiddleWare { public: - MiddleWare(int prefered_port = -1); + MiddleWare(SYNTH_T synth, int prefered_port = -1); ~MiddleWare(void); //returns internal master pointer class Master *spawnMaster(void); @@ -32,6 +33,8 @@ class MiddleWare //Get/Set the active bToU url std::string activeUrl(void); void activeUrl(std::string u); + //View Synthesis Parameters + const SYNTH_T &getSynth(void) const; private: class MiddleWareImpl *impl; }; diff --git a/src/Misc/Part.cpp b/src/Misc/Part.cpp @@ -168,13 +168,13 @@ static const Ports kitPorts = { const Ports &Part::Kit::ports = kitPorts; const Ports &Part::ports = partPorts; -Part::Part(Allocator &alloc, Microtonal *microtonal_, FFTwrapper *fft_) - :memory(alloc) +Part::Part(Allocator &alloc, const SYNTH_T &synth_, Microtonal *microtonal_, FFTwrapper *fft_) + :ctl(synth_), memory(alloc), synth(synth_) { microtonal = microtonal_; fft = fft_; - partoutl = new float [synth->buffersize]; - partoutr = new float [synth->buffersize]; + partoutl = new float [synth.buffersize]; + partoutr = new float [synth.buffersize]; monomemClear(); @@ -185,17 +185,17 @@ Part::Part(Allocator &alloc, Microtonal *microtonal_, FFTwrapper *fft_) kit[n].padpars = nullptr; } - kit[0].adpars = new ADnoteParameters(fft); + kit[0].adpars = new ADnoteParameters(synth, fft); //Part's Insertion Effects init for(int nefx = 0; nefx < NUM_PART_EFX; ++nefx) { - partefx[nefx] = new EffectMgr(memory, 1); + partefx[nefx] = new EffectMgr(memory, synth, 1); Pefxbypass[nefx] = false; } for(int n = 0; n < NUM_PART_EFX + 1; ++n) { - partfxinputl[n] = new float [synth->buffersize]; - partfxinputr[n] = new float [synth->buffersize]; + partfxinputl[n] = new float [synth.buffersize]; + partfxinputr[n] = new float [synth.buffersize]; } killallnotes = false; @@ -311,7 +311,7 @@ void Part::cleanup(bool final_) { for(int k = 0; k < POLYPHONY; ++k) KillNotePos(k); - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { partoutl[i] = final_ ? 0.0f : denormalkillbuf[i]; partoutr[i] = final_ ? 0.0f : denormalkillbuf[i]; } @@ -319,7 +319,7 @@ void Part::cleanup(bool final_) for(int nefx = 0; nefx < NUM_PART_EFX; ++nefx) partefx[nefx]->cleanup(); for(int n = 0; n < NUM_PART_EFX + 1; ++n) - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { partfxinputl[n][i] = final_ ? 0.0f : denormalkillbuf[i]; partfxinputr[n][i] = final_ ? 0.0f : denormalkillbuf[i]; } @@ -553,7 +553,7 @@ void Part::NoteOn(unsigned char note, if(Pkitmode == 0) { //init the notes for the "normal mode" partnote[pos].kititem[0].sendtoparteffect = 0; - SynthParams pars{memory, ctl, notebasefreq, vel, (bool) portamento, note, false}; + SynthParams pars{memory, ctl, synth, notebasefreq, vel, (bool) portamento, note, false}; if(kit[0].Padenabled) partnote[pos].kititem[0].adnote = @@ -599,7 +599,7 @@ void Part::NoteOn(unsigned char note, //if this parameter is 127 for "unprocessed" note1.sendtoparteffect = limit((int)kit[item].Psendtoparteffect, 0, NUM_PART_EFX); - SynthParams pars{memory, ctl, notebasefreq, vel, (bool) portamento, note, false}; + SynthParams pars{memory, ctl, synth, notebasefreq, vel, (bool) portamento, note, false}; if(kit[item].adpars && kit[item].Padenabled) note1.adnote = @@ -946,13 +946,13 @@ void Part::RunNote(unsigned int k) continue; noteplay++; - float tmpoutr[synth->buffersize]; - float tmpoutl[synth->buffersize]; + float tmpoutr[synth.buffersize]; + float tmpoutl[synth.buffersize]; (*note)->noteout(&tmpoutl[0], &tmpoutr[0]); if((*note)->finished()) memory.dealloc(*note); - for(int i = 0; i < synth->buffersize; ++i) { //add the note to part(mix) + for(int i = 0; i < synth.buffersize; ++i) { //add the note to part(mix) partfxinputl[sendcurrenttofx][i] += tmpoutl[i]; partfxinputr[sendcurrenttofx][i] += tmpoutr[i]; } @@ -970,7 +970,7 @@ void Part::RunNote(unsigned int k) void Part::ComputePartSmps() { for(unsigned nefx = 0; nefx < NUM_PART_EFX + 1; ++nefx) - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { partfxinputl[nefx][i] = 0.0f; partfxinputr[nefx][i] = 0.0f; } @@ -989,25 +989,25 @@ void Part::ComputePartSmps() if(!Pefxbypass[nefx]) { partefx[nefx]->out(partfxinputl[nefx], partfxinputr[nefx]); if(Pefxroute[nefx] == 2) - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { partfxinputl[nefx + 1][i] += partefx[nefx]->efxoutl[i]; partfxinputr[nefx + 1][i] += partefx[nefx]->efxoutr[i]; } } int routeto = ((Pefxroute[nefx] == 0) ? nefx + 1 : NUM_PART_EFX); - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { partfxinputl[routeto][i] += partfxinputl[nefx][i]; partfxinputr[routeto][i] += partfxinputr[nefx][i]; } } - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { partoutl[i] = partfxinputl[NUM_PART_EFX][i]; partoutr[i] = partfxinputr[NUM_PART_EFX][i]; } if(killallnotes) { - for(int i = 0; i < synth->buffersize; ++i) { - float tmp = (synth->buffersize_f - i) / synth->buffersize_f; + for(int i = 0; i < synth.buffersize; ++i) { + float tmp = (synth.buffersize_f - i) / synth.buffersize_f; partoutl[i] *= tmp; partoutr[i] *= tmp; } @@ -1065,9 +1065,9 @@ void Part::setkititemstatus(unsigned kititem, bool Penabled_) else { //All parameters must be NULL in this case assert(!(kkit.adpars || kkit.subpars || kkit.padpars)); - kkit.adpars = new ADnoteParameters(fft); + kkit.adpars = new ADnoteParameters(synth, fft); kkit.subpars = new SUBnoteParameters(); - kkit.padpars = new PADnoteParameters(fft); + kkit.padpars = new PADnoteParameters(synth, fft); } } @@ -1301,7 +1301,7 @@ void Part::getfromXMLinstrument(XMLwrapper *xml) kit[i].Padenabled); if(xml->enterbranch("ADD_SYNTH_PARAMETERS")) { if(!kit[i].adpars) - kit[i].adpars = new ADnoteParameters(fft); + kit[i].adpars = new ADnoteParameters(synth, fft); kit[i].adpars->getfromXML(xml); xml->exitbranch(); } @@ -1319,7 +1319,7 @@ void Part::getfromXMLinstrument(XMLwrapper *xml) kit[i].Ppadenabled); if(xml->enterbranch("PAD_SYNTH_PARAMETERS")) { if(!kit[i].padpars) - kit[i].padpars = new PADnoteParameters(fft); + kit[i].padpars = new PADnoteParameters(synth, fft); kit[i].padpars->getfromXML(xml); xml->exitbranch(); } diff --git a/src/Misc/Part.h b/src/Misc/Part.h @@ -37,7 +37,7 @@ class Part /**Constructor * @param microtonal_ Pointer to the microtonal object * @param fft_ Pointer to the FFTwrapper*/ - Part(Allocator &alloc, Microtonal *microtonal_, FFTwrapper *fft_); + Part(Allocator &alloc, const SYNTH_T &synth, Microtonal *microtonal_, FFTwrapper *fft_); /**Destructor*/ ~Part(); @@ -197,6 +197,7 @@ class Part Microtonal *microtonal; FFTwrapper *fft; Allocator &memory; + const SYNTH_T &synth; }; #endif diff --git a/src/Misc/PresetExtractor.cpp b/src/Misc/PresetExtractor.cpp @@ -291,17 +291,17 @@ void doClassPaste(std::string type, std::string type_, MiddleWare &mw, string ur else if(type == "FilterParams") doPaste<FilterParams>(mw, url, type_, data); else if(type == "ADnoteParameters") - doPaste<ADnoteParameters>(mw, url, type_, data, (FFTwrapper*)NULL); + doPaste<ADnoteParameters>(mw, url, type_, data, mw.getSynth(), (FFTwrapper*)NULL); else if(type == "PADnoteParameters") - doPaste<PADnoteParameters>(mw, url, type_, data, (FFTwrapper*)NULL); + doPaste<PADnoteParameters>(mw, url, type_, data, mw.getSynth(), (FFTwrapper*)NULL); else if(type == "SUBnoteParameters") doPaste<SUBnoteParameters>(mw, url, type_, data); else if(type == "OscilGen") - doPaste<OscilGen>(mw, url, type_, data, (FFTwrapper*)NULL, (Resonance*)NULL); + doPaste<OscilGen>(mw, url, type_, data, mw.getSynth(), (FFTwrapper*)NULL, (Resonance*)NULL); else if(type == "Resonance") doPaste<Resonance>(mw, url, type_, data); else if(type == "EffectMgr") - doPaste<EffectMgr>(mw, url, type_, data, DummyAlloc, false); + doPaste<EffectMgr>(mw, url, type_, data, DummyAlloc, mw.getSynth(), false); else { fprintf(stderr, "Warning: Unknown type<%s> from url<%s>\n", type.c_str(), url.c_str()); } @@ -336,7 +336,7 @@ void doClassArrayPaste(std::string type, std::string type_, int field, MiddleWar if(type == "FilterParams") doArrayPaste<FilterParams>(mw, field, url, type_, data); else if(type == "ADnoteParameters") - doArrayPaste<ADnoteParameters>(mw, field, url, type_, data, (FFTwrapper*)NULL); + doArrayPaste<ADnoteParameters>(mw, field, url, type_, data, mw.getSynth(), (FFTwrapper*)NULL); } std::string doClassArrayCopy(std::string type, int field, MiddleWare &mw, string url, string name) diff --git a/src/Misc/Recorder.cpp b/src/Misc/Recorder.cpp @@ -23,10 +23,11 @@ #include <sys/stat.h> #include "Recorder.h" #include "WavFile.h" +#include "../globals.h" #include "../Nio/Nio.h" -Recorder::Recorder() - :status(0), notetrigger(0) +Recorder::Recorder(const SYNTH_T &synth_) + :status(0), notetrigger(0),synth(synth_) {} Recorder::~Recorder() @@ -45,7 +46,7 @@ int Recorder::preparefile(std::string filename_, int overwrite) return 1; } - Nio::waveNew(new WavFile(filename_, synth->samplerate, 2)); + Nio::waveNew(new WavFile(filename_, synth.samplerate, 2)); status = 1; //ready diff --git a/src/Misc/Recorder.h b/src/Misc/Recorder.h @@ -23,14 +23,14 @@ #ifndef RECORDER_H #define RECORDER_H #include <string> -#include "../globals.h" +struct SYNTH_T; /**Records sound to a file*/ class Recorder { public: - Recorder(); + Recorder(const SYNTH_T &synth); ~Recorder(); /**Prepare the given file. * @returns 1 if the file exists */ @@ -49,6 +49,7 @@ class Recorder private: int notetrigger; + const SYNTH_T &synth; }; #endif diff --git a/src/Nio/AlsaEngine.cpp b/src/Nio/AlsaEngine.cpp @@ -29,10 +29,10 @@ using namespace std; #include "InMgr.h" #include "AlsaEngine.h" -AlsaEngine::AlsaEngine() - :AudioOut() +AlsaEngine::AlsaEngine(const SYNTH_T &synth) + :AudioOut(synth) { - audio.buffer = new short[synth->buffersize * 2]; + audio.buffer = new short[synth.buffersize * 2]; name = "ALSA"; audio.handle = NULL; @@ -296,7 +296,7 @@ bool AlsaEngine::openAudio() /* Two channels (stereo) */ snd_pcm_hw_params_set_channels(audio.handle, audio.params, 2); - audio.sampleRate = synth->samplerate; + audio.sampleRate = synth.samplerate; snd_pcm_hw_params_set_rate_near(audio.handle, audio.params, &audio.sampleRate, NULL); @@ -321,7 +321,7 @@ bool AlsaEngine::openAudio() /* latency = periodsize * periods / (rate * bytes_per_frame) */ snd_pcm_hw_params_set_buffer_size(audio.handle, audio.params, - synth->buffersize); + synth.buffersize); //snd_pcm_hw_params_get_period_size(audio.params, &audio.frames, NULL); //snd_pcm_hw_params_get_period_time(audio.params, &val, NULL); @@ -353,7 +353,7 @@ void *AlsaEngine::processAudio() while(audio.handle) { audio.buffer = interleave(getNext()); snd_pcm_t *handle = audio.handle; - int rc = snd_pcm_writei(handle, audio.buffer, synth->buffersize); + int rc = snd_pcm_writei(handle, audio.buffer, synth.buffersize); if(rc == -EPIPE) { /* EPIPE means underrun */ cerr << "underrun occurred" << endl; diff --git a/src/Nio/AlsaEngine.h b/src/Nio/AlsaEngine.h @@ -35,7 +35,7 @@ class AlsaEngine:public AudioOut, MidiIn { public: - AlsaEngine(); + AlsaEngine(const SYNTH_T &synth); ~AlsaEngine(); bool Start(); diff --git a/src/Nio/AudioOut.cpp b/src/Nio/AudioOut.cpp @@ -30,8 +30,8 @@ using namespace std; #include "../Misc/Master.h" #include "AudioOut.h" -AudioOut::AudioOut() - :samplerate(synth->samplerate), bufferSize(synth->buffersize) +AudioOut::AudioOut(const SYNTH_T &synth_) + :synth(synth_), samplerate(synth.samplerate), bufferSize(synth.buffersize) {} AudioOut::~AudioOut() diff --git a/src/Nio/AudioOut.h b/src/Nio/AudioOut.h @@ -30,7 +30,7 @@ class AudioOut:public virtual Engine { public: - AudioOut(); + AudioOut(const SYNTH_T &synth); virtual ~AudioOut(); /**Sets the Sample Rate of this Output @@ -54,6 +54,7 @@ class AudioOut:public virtual Engine * (has nsamples sampled at a rate of samplerate)*/ const Stereo<float *> getNext(); + const SYNTH_T &synth; int samplerate; int bufferSize; }; diff --git a/src/Nio/EngineMgr.cpp b/src/Nio/EngineMgr.cpp @@ -1,6 +1,7 @@ #include "EngineMgr.h" #include <algorithm> #include <iostream> +#include <cassert> #include "Nio.h" #include "InMgr.h" #include "OutMgr.h" @@ -24,31 +25,32 @@ using namespace std; -EngineMgr &EngineMgr::getInstance() +EngineMgr &EngineMgr::getInstance(const SYNTH_T *synth) { - static EngineMgr instance; + static EngineMgr instance(synth); return instance; } -EngineMgr::EngineMgr() +EngineMgr::EngineMgr(const SYNTH_T *synth) { - Engine *defaultEng = new NulEngine(); + assert(synth); + Engine *defaultEng = new NulEngine(*synth); //conditional compiling mess (but contained) engines.push_back(defaultEng); #if OSS - engines.push_back(new OssEngine()); - engines.push_back(new OssMultiEngine()); + engines.push_back(new OssEngine(*synth)); + engines.push_back(new OssMultiEngine(*synth)); #endif #if ALSA - engines.push_back(new AlsaEngine()); + engines.push_back(new AlsaEngine(*synth)); #endif #if JACK - engines.push_back(new JackEngine()); - engines.push_back(new JackMultiEngine()); + engines.push_back(new JackEngine(*synth)); + engines.push_back(new JackMultiEngine(*synth)); #endif #if PORTAUDIO - engines.push_back(new PaEngine()); + engines.push_back(new PaEngine(*synth)); #endif defaultOut = dynamic_cast<AudioOut *>(defaultEng); diff --git a/src/Nio/EngineMgr.h b/src/Nio/EngineMgr.h @@ -9,11 +9,12 @@ class MidiIn; class AudioOut; class OutMgr; +struct SYNTH_T; /**Container/Owner of the long lived Engines*/ class EngineMgr { public: - static EngineMgr &getInstance(); + static EngineMgr &getInstance(const SYNTH_T *synth=NULL); ~EngineMgr(); /**Gets requested engine @@ -38,6 +39,6 @@ class EngineMgr AudioOut *defaultOut; MidiIn *defaultIn; private: - EngineMgr(); + EngineMgr(const SYNTH_T *synth); }; #endif diff --git a/src/Nio/InMgr.cpp b/src/Nio/InMgr.cpp @@ -144,7 +144,7 @@ string InMgr::getSource() const MidiIn *InMgr::getIn(string name) { - EngineMgr &eng = EngineMgr::getInstance(); + EngineMgr &eng = EngineMgr::getInstance(NULL); return dynamic_cast<MidiIn *>(eng.getEng(name)); } diff --git a/src/Nio/JackEngine.cpp b/src/Nio/JackEngine.cpp @@ -44,8 +44,8 @@ using namespace std; extern char *instance_name; -JackEngine::JackEngine() - :AudioOut(), jackClient(NULL) +JackEngine::JackEngine(const SYNTH_T &synth) + :AudioOut(synth), jackClient(NULL) { name = "JACK"; audio.jackSamplerate = 0; diff --git a/src/Nio/JackEngine.h b/src/Nio/JackEngine.h @@ -36,7 +36,7 @@ typedef jack_default_audio_sample_t jsample_t; class JackEngine:public AudioOut, MidiIn { public: - JackEngine(); + JackEngine(const SYNTH_T &synth); ~JackEngine() { } bool Start(); diff --git a/src/Nio/JackMultiEngine.cpp b/src/Nio/JackMultiEngine.cpp @@ -28,7 +28,7 @@ #include <cassert> #include "Nio.h" -#include "Misc/Util.h" +#include "../Misc/Util.h" #include "../Misc/Master.h" #include "../Misc/Part.h" #include "../Misc/MiddleWare.h" @@ -45,8 +45,8 @@ struct jack_multi bool running; }; -JackMultiEngine::JackMultiEngine(void) - :impl(new jack_multi()) +JackMultiEngine::JackMultiEngine(const SYNTH_T &synth) + :AudioOut(synth), impl(new jack_multi()) { impl->running = false; impl->client = NULL; @@ -115,9 +115,9 @@ bool JackMultiEngine::Start(void) //verify that all sample rate and buffer_size are the same in jack. //This insures that the connection can be made with no resampling or //buffering - if(synth->samplerate != jack_get_sample_rate(impl->client)) + if(synth.samplerate != jack_get_sample_rate(impl->client)) errx(1, "jack must have the same sample rate!"); - if(synth->buffersize != (int) jack_get_buffer_size(impl->client)) + if(synth.buffersize != (int) jack_get_buffer_size(impl->client)) errx(1, "jack must have the same buffer size"); jack_set_process_callback(impl->client, _processCallback, this); @@ -147,14 +147,14 @@ int JackMultiEngine::processAudio(jack_nframes_t nframes) //Get the wet samples from OutMgr Stereo<float *> smp = getNext(); - memcpy(buffers[0], smp.l, synth->bufferbytes); - memcpy(buffers[1], smp.r, synth->bufferbytes); + memcpy(buffers[0], smp.l, synth.bufferbytes); + memcpy(buffers[1], smp.r, synth.bufferbytes); //Gather other samples from individual parts Master &master = *middleware->spawnMaster(); for(int i = 0; i < NUM_MIDI_PARTS; ++i) { - memcpy(buffers[2*i + 2], master.part[i]->partoutl, synth->bufferbytes); - memcpy(buffers[2*i + 3], master.part[i]->partoutr, synth->bufferbytes); + memcpy(buffers[2*i + 2], master.part[i]->partoutl, synth.bufferbytes); + memcpy(buffers[2*i + 3], master.part[i]->partoutr, synth.bufferbytes); } return false; diff --git a/src/Nio/JackMultiEngine.h b/src/Nio/JackMultiEngine.h @@ -27,7 +27,7 @@ class JackMultiEngine:public AudioOut { public: - JackMultiEngine(void); + JackMultiEngine(const SYNTH_T &synth); ~JackMultiEngine(void); void setAudioEn(bool nval); diff --git a/src/Nio/Nio.cpp b/src/Nio/Nio.cpp @@ -29,11 +29,11 @@ bool Nio::pidInClientName = false; string Nio::defaultSource = IN_DEFAULT; string Nio::defaultSink = OUT_DEFAULT; -void Nio::init(class Master *master) +void Nio::init(const SYNTH_T &synth, class Master *master) { in = &InMgr::getInstance(); //Enable input wrapper - out = &OutMgr::getInstance(); //Initialize the Output Systems - eng = &EngineMgr::getInstance(); //Initialize The Engines + out = &OutMgr::getInstance(&synth); //Initialize the Output Systems + eng = &EngineMgr::getInstance(&synth); //Initialize The Engines in->setMaster(master); out->setMaster(master); diff --git a/src/Nio/Nio.h b/src/Nio/Nio.h @@ -5,13 +5,14 @@ class WavFile; class Master; +struct SYNTH_T; /**Interface to Nio Subsystem * * Should be only externally included header */ namespace Nio { - void init(Master *master); + void init(const SYNTH_T &synth, Master *master); bool start(void); void stop(void); diff --git a/src/Nio/NulEngine.cpp b/src/Nio/NulEngine.cpp @@ -28,8 +28,8 @@ using namespace std; -NulEngine::NulEngine() - :AudioOut(), pThread(NULL) +NulEngine::NulEngine(const SYNTH_T &synth_) + :AudioOut(synth_), pThread(NULL) { name = "NULL"; playing_until.tv_sec = 0; @@ -62,8 +62,8 @@ void *NulEngine::AudioThread() if(remaining < 0) cerr << "WARNING - too late" << endl; } - playing_until.tv_usec += synth->buffersize * 1000000 - / synth->samplerate; + playing_until.tv_usec += synth.buffersize * 1000000 + / synth.samplerate; if(remaining < 0) playing_until.tv_usec -= remaining; playing_until.tv_sec += playing_until.tv_usec / 1000000; diff --git a/src/Nio/NulEngine.h b/src/Nio/NulEngine.h @@ -32,7 +32,7 @@ class NulEngine:public AudioOut, MidiIn { public: - NulEngine(); + NulEngine(const SYNTH_T &synth_); ~NulEngine(); bool Start(); diff --git a/src/Nio/OssEngine.cpp b/src/Nio/OssEngine.cpp @@ -179,8 +179,8 @@ OssMidiParse(struct OssMidiParse &midi_parse, return (0); } -OssEngine::OssEngine() - :AudioOut(), audioThread(NULL), midiThread(NULL) +OssEngine::OssEngine(const SYNTH_T &synth) + :AudioOut(synth), audioThread(NULL), midiThread(NULL) { name = "OSS"; @@ -188,8 +188,8 @@ OssEngine::OssEngine() audio.handle = -1; /* allocate worst case audio buffer */ - audio.smps.ps32 = new int[synth->buffersize * 2]; - memset(audio.smps.ps32, 0, sizeof(int) * synth->buffersize * 2); + audio.smps.ps32 = new int[synth.buffersize * 2]; + memset(audio.smps.ps32, 0, sizeof(int) * synth.buffersize * 2); memset(&midi.state, 0, sizeof(midi.state)); } @@ -208,7 +208,7 @@ bool OssEngine::openAudio() int snd_fragment; int snd_stereo = 1; //stereo; - int snd_samplerate = synth->samplerate; + int snd_samplerate = synth.samplerate; const char *device = getenv("DSP_DEVICE"); if(device == NULL) @@ -243,15 +243,15 @@ bool OssEngine::openAudio() ioctl(audio.handle, SNDCTL_DSP_STEREO, &snd_stereo); ioctl(audio.handle, SNDCTL_DSP_SPEED, &snd_samplerate); - if (snd_samplerate != (int)synth->samplerate) { + if (snd_samplerate != (int)synth.samplerate) { cerr << "ERROR - Cannot set samplerate for " << device << ". " << snd_samplerate - << " != " << synth->samplerate << endl; + << " != " << synth.samplerate << endl; goto error; } /* compute buffer size for 16-bit stereo samples */ - audio.buffersize = 4 * synth->buffersize; + audio.buffersize = 4 * synth.buffersize; if (audio.is32bit) audio.buffersize *= 2; @@ -407,7 +407,7 @@ void *OssEngine::audioThreadCb() const Stereo<float *> smps = getNext(); float l, r; - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { l = smps.l[i]; r = smps.r[i]; diff --git a/src/Nio/OssEngine.h b/src/Nio/OssEngine.h @@ -45,7 +45,7 @@ struct OssMidiParse { class OssEngine:public AudioOut, MidiIn { public: - OssEngine(); + OssEngine(const SYNTH_T &synth); ~OssEngine(); bool Start(); diff --git a/src/Nio/OssMultiEngine.cpp b/src/Nio/OssMultiEngine.cpp @@ -43,7 +43,8 @@ extern MiddleWare *middleware; using namespace std; -OssMultiEngine :: OssMultiEngine() +OssMultiEngine :: OssMultiEngine(const SYNTH_T &synth) + :AudioOut(synth) { /* setup variables */ name = "OSS-MULTI"; @@ -55,7 +56,7 @@ OssMultiEngine :: OssMultiEngine() buffersize = 0; /* compute worst case buffer size */ - maxbuffersize = NUM_MIDI_PARTS * sizeof(int) * synth->buffersize * 2; + maxbuffersize = NUM_MIDI_PARTS * sizeof(int) * synth.buffersize * 2; /* allocate buffer */ smps.ps32 = new int[maxbuffersize / sizeof(int)]; memset(smps.ps32, 0, maxbuffersize); @@ -118,19 +119,19 @@ OssMultiEngine :: openAudio() } channels = x; - snd_samplerate = synth->samplerate; + snd_samplerate = synth.samplerate; ioctl(handle, SNDCTL_DSP_SPEED, &snd_samplerate); - if (snd_samplerate != (int)synth->samplerate) { + if (snd_samplerate != (int)synth.samplerate) { cerr << "ERROR - Cannot set samplerate for " << device << ". " << snd_samplerate - << " != " << synth->samplerate << endl; + << " != " << synth.samplerate << endl; goto error; } /* compute buffer size for 16-bit samples */ - buffersize = 2 * synth->buffersize * channels; + buffersize = 2 * synth.buffersize * channels; if (is32bit) buffersize *= 2; @@ -232,7 +233,7 @@ OssMultiEngine :: audioThreadCb() Part *part = middleware->spawnMaster()->part[x / 2]; if (is32bit) { - for (y = 0; y != synth->buffersize; y++) { + for (y = 0; y != synth.buffersize; y++) { l = part->partoutl[y]; if (l < -1.0f) l = -1.0f; @@ -247,7 +248,7 @@ OssMultiEngine :: audioThreadCb() smps.ps32[y * channels + x + 1] = (int)(r * 2147483647.0f); } } else { - for (y = 0; y != synth->buffersize; y++) { + for (y = 0; y != synth.buffersize; y++) { l = part->partoutl[y]; if (l < -1.0f) l = -1.0f; diff --git a/src/Nio/OssMultiEngine.h b/src/Nio/OssMultiEngine.h @@ -29,7 +29,7 @@ class OssMultiEngine : public AudioOut { public: - OssMultiEngine(); + OssMultiEngine(const SYNTH_T &synth); ~OssMultiEngine(); bool Start(); diff --git a/src/Nio/OutMgr.cpp b/src/Nio/OutMgr.cpp @@ -12,26 +12,26 @@ using namespace std; -OutMgr &OutMgr::getInstance() +OutMgr &OutMgr::getInstance(const SYNTH_T *synth) { - static OutMgr instance; + static OutMgr instance(synth); return instance; } -OutMgr::OutMgr() - :wave(new WavEngine()), +OutMgr::OutMgr(const SYNTH_T *synth_) + :wave(new WavEngine(*synth_)), priBuf(new float[4096], new float[4096]), priBuffCurrent(priBuf), - master(NULL) + master(NULL), stales(0), synth(*synth_) { + assert(synth_); currentOut = NULL; - stales = 0; //init samples - outr = new float[synth->buffersize]; - outl = new float[synth->buffersize]; - memset(outl, 0, synth->bufferbytes); - memset(outr, 0, synth->bufferbytes); + outr = new float[synth.buffersize]; + outl = new float[synth.buffersize]; + memset(outl, 0, synth.bufferbytes); + memset(outr, 0, synth.bufferbytes); } OutMgr::~OutMgr() @@ -60,7 +60,7 @@ const Stereo<float *> OutMgr::tick(unsigned int frameSize) int i=0; while(frameSize > storedSmps()) { if(!midi.empty()) { - midi.flush(i*synth->buffersize, (i+1)*synth->buffersize); + midi.flush(i*synth.buffersize, (i+1)*synth.buffersize); } master->AudioOut(outl, outr); addSmps(outl, outr); @@ -143,27 +143,27 @@ static size_t resample(float *dest, void OutMgr::addSmps(float *l, float *r) { //allow wave file to syphon off stream - wave->push(Stereo<float *>(l, r), synth->buffersize); + wave->push(Stereo<float *>(l, r), synth.buffersize); const int s_out = currentOut->getSampleRate(), - s_sys = synth->samplerate; + s_sys = synth.samplerate; if(s_out != s_sys) { //we need to resample const size_t steps = resample(priBuffCurrent.l, l, s_sys, s_out, - synth->buffersize); - resample(priBuffCurrent.r, r, s_sys, s_out, synth->buffersize); + synth.buffersize); + resample(priBuffCurrent.r, r, s_sys, s_out, synth.buffersize); priBuffCurrent.l += steps; priBuffCurrent.r += steps; } else { //just copy the samples - memcpy(priBuffCurrent.l, l, synth->bufferbytes); - memcpy(priBuffCurrent.r, r, synth->bufferbytes); - priBuffCurrent.l += synth->buffersize; - priBuffCurrent.r += synth->buffersize; + memcpy(priBuffCurrent.l, l, synth.bufferbytes); + memcpy(priBuffCurrent.r, r, synth.bufferbytes); + priBuffCurrent.l += synth.buffersize; + priBuffCurrent.r += synth.buffersize; } } diff --git a/src/Nio/OutMgr.h b/src/Nio/OutMgr.h @@ -8,10 +8,11 @@ class AudioOut; +struct SYNTH_T; class OutMgr { public: - static OutMgr &getInstance(); + static OutMgr &getInstance(const SYNTH_T *synth=NULL); ~OutMgr(); /**Execute a tick*/ @@ -44,7 +45,7 @@ class OutMgr void setMaster(class Master *master_); void applyOscEventRt(const char *msg); private: - OutMgr(); + OutMgr(const SYNTH_T *synth); void addSmps(float *l, float *r); unsigned int storedSmps() const {return priBuffCurrent.l - priBuf.l; } void removeStaleSmps(); @@ -62,6 +63,7 @@ class OutMgr class Master *master; int stales; + const SYNTH_T &synth; }; #endif diff --git a/src/Nio/PaEngine.cpp b/src/Nio/PaEngine.cpp @@ -25,8 +25,8 @@ using namespace std; -PaEngine::PaEngine() - :stream(NULL) +PaEngine::PaEngine(const SYNTH_T &synth) + :AudioOut(synth), stream(NULL) { name = "PA"; } @@ -60,8 +60,8 @@ bool PaEngine::Start() Pa_OpenStream(&stream, NULL, &outputParameters, - synth->samplerate, - synth->buffersize, + synth.samplerate, + synth.buffersize, 0, PAprocess, (void *) this); diff --git a/src/Nio/PaEngine.h b/src/Nio/PaEngine.h @@ -30,7 +30,7 @@ class PaEngine:public AudioOut { public: - PaEngine(); + PaEngine(const SYNTH_T &synth); ~PaEngine(); bool Start(); diff --git a/src/Nio/WavEngine.cpp b/src/Nio/WavEngine.cpp @@ -25,8 +25,8 @@ using namespace std; -WavEngine::WavEngine() - :AudioOut(), file(NULL), buffer(synth->samplerate * 4), pThread(NULL) +WavEngine::WavEngine(const SYNTH_T &synth_) + :AudioOut(synth_), file(NULL), buffer(synth.samplerate * 4), pThread(NULL) { work.init(PTHREAD_PROCESS_PRIVATE, 0); } @@ -110,10 +110,10 @@ void *WavEngine::_AudioThread(void *arg) void *WavEngine::AudioThread() { - short *recordbuf_16bit = new short[2 * synth->buffersize]; + short *recordbuf_16bit = new short[2 * synth.buffersize]; while(!work.wait() && pThread) { - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { float left = 0.0f, right = 0.0f; buffer.pop(left); buffer.pop(right); @@ -124,7 +124,7 @@ void *WavEngine::AudioThread() -32768, 32767); } - file->writeStereoSamples(synth->buffersize, recordbuf_16bit); + file->writeStereoSamples(synth.buffersize, recordbuf_16bit); } delete[] recordbuf_16bit; diff --git a/src/Nio/WavEngine.h b/src/Nio/WavEngine.h @@ -32,7 +32,7 @@ class WavFile; class WavEngine:public AudioOut { public: - WavEngine(); + WavEngine(const SYNTH_T &synth); ~WavEngine(); bool openAudio(); diff --git a/src/Output/DSSIaudiooutput.cpp b/src/Output/DSSIaudiooutput.cpp @@ -585,7 +585,6 @@ DSSIaudiooutput *DSSIaudiooutput::getInstance(LADSPA_Handle instance) return (DSSIaudiooutput *)(instance); } -SYNTH_T *synth; /** * The private sole constructor for the DSSIaudiooutput class. @@ -596,8 +595,8 @@ SYNTH_T *synth; */ DSSIaudiooutput::DSSIaudiooutput(unsigned long sampleRate) { - synth = new SYNTH_T; - synth->samplerate = sampleRate; + SYNTH_T synth; + synth.samplerate = sampleRate; this->sampleRate = sampleRate; this->banksInited = false; @@ -605,12 +604,12 @@ DSSIaudiooutput::DSSIaudiooutput(unsigned long sampleRate) config.init(); sprng(time(NULL)); - denormalkillbuf = new float [synth->buffersize]; - for(int i = 0; i < synth->buffersize; i++) + denormalkillbuf = new float [synth.buffersize]; + for(int i = 0; i < synth.buffersize; i++) denormalkillbuf[i] = (RND - 0.5f) * 1e-16; - synth->alias(); - middleware = new MiddleWare(); + synth.alias(); + middleware = new MiddleWare(synth); initBanks(); loadThread = new std::thread([this]() { while(middleware) { diff --git a/src/Params/ADnoteParameters.cpp b/src/Params/ADnoteParameters.cpp @@ -276,7 +276,7 @@ const Ports &ADnoteGlobalParam::ports = globalPorts; int ADnote_unison_sizes[] = {1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 25, 30, 40, 50, 0}; -ADnoteParameters::ADnoteParameters(FFTwrapper *fft_) +ADnoteParameters::ADnoteParameters(const SYNTH_T &synth, FFTwrapper *fft_) :PresetsArray() { setpresettype("Padsynth"); @@ -284,7 +284,7 @@ ADnoteParameters::ADnoteParameters(FFTwrapper *fft_) for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice) - EnableVoice(nvoice); + EnableVoice(synth, nvoice); defaults(); } @@ -429,15 +429,15 @@ void ADnoteVoiceParam::defaults() /* * Init the voice parameters */ -void ADnoteParameters::EnableVoice(int nvoice) +void ADnoteParameters::EnableVoice(const SYNTH_T &synth, int nvoice) { - VoicePar[nvoice].enable(fft, GlobalPar.Reson); + VoicePar[nvoice].enable(synth, fft, GlobalPar.Reson); } -void ADnoteVoiceParam::enable(FFTwrapper *fft, Resonance *Reson) +void ADnoteVoiceParam::enable(const SYNTH_T &synth, FFTwrapper *fft, Resonance *Reson) { - OscilSmp = new OscilGen(fft, Reson); - FMSmp = new OscilGen(fft, NULL); + OscilSmp = new OscilGen(synth, fft, Reson); + FMSmp = new OscilGen(synth, fft, NULL); AmpEnvelope = new EnvelopeParams(64, 1); AmpEnvelope->ADSRinit_dB(0, 100, 127, 100); diff --git a/src/Params/ADnoteParameters.h b/src/Params/ADnoteParameters.h @@ -117,7 +117,7 @@ struct ADnoteVoiceParam { void add2XML(XMLwrapper *xml, bool fmoscilused); void paste(ADnoteVoiceParam &p); void defaults(void); - void enable(FFTwrapper *fft, Resonance *Reson); + void enable(const SYNTH_T &synth, FFTwrapper *fft, Resonance *Reson); void kill(void); float getUnisonFrequencySpreadCents(void) const; /** If the voice is enabled */ @@ -289,7 +289,7 @@ struct ADnoteVoiceParam { class ADnoteParameters:public PresetsArray { public: - ADnoteParameters(FFTwrapper *fft_); + ADnoteParameters(const SYNTH_T &synth, FFTwrapper *fft_); ~ADnoteParameters(); ADnoteGlobalParam GlobalPar; @@ -313,7 +313,7 @@ class ADnoteParameters:public PresetsArray void getfromXMLsection(XMLwrapper *xml, int n); private: - void EnableVoice(int nvoice); + void EnableVoice(const SYNTH_T &synth, int nvoice); void KillVoice(int nvoice); FFTwrapper *fft; }; diff --git a/src/Params/Controller.cpp b/src/Params/Controller.cpp @@ -60,12 +60,20 @@ const rtosc::Ports Controller::ports = { }; -Controller::Controller() +Controller::Controller(const SYNTH_T &synth_) + :synth(synth_) { defaults(); resetall(); } +Controller &Controller::operator=(const Controller &c) +{ + //just pretend that undefined behavior doesn't exist... + memcpy(this, &c, sizeof(Controller)); + return *this; +} + Controller::~Controller() {} @@ -284,7 +292,7 @@ int Controller::initportamento(float oldfreq, //printf("%f->%f : Time %f\n",oldfreq,newfreq,portamentotime); - portamento.dx = synth->buffersize_f / (portamentotime * synth->samplerate_f); + portamento.dx = synth.buffersize_f / (portamentotime * synth.samplerate_f); portamento.origfreqrap = oldfreq / newfreq; float tmprap = ((portamento.origfreqrap > 1.0f) ? diff --git a/src/Params/Controller.h b/src/Params/Controller.h @@ -30,7 +30,8 @@ class Controller { public: - Controller(); + Controller(const SYNTH_T &synth); + Controller&operator=(const Controller &c); ~Controller(); void resetall(); @@ -215,6 +216,7 @@ class Controller static const rtosc::Ports ports; private: + const SYNTH_T &synth; }; #endif diff --git a/src/Params/FilterParams.cpp b/src/Params/FilterParams.cpp @@ -282,85 +282,6 @@ float FilterParams::getfreqpos(float freq) return (logf(freq) - logf(getfreqx(0.0f))) / logf(2.0f) / getoctavesfreq(); } - -/* - * Get the freq. response of the formant filter - */ -void FilterParams::formantfilterH(int nvowel, int nfreqs, float *freqs) -{ - float c[3], d[3]; - - for(int i = 0; i < nfreqs; ++i) - freqs[i] = 0.0f; - - //for each formant... - for(int nformant = 0; nformant < Pnumformants; ++nformant) { - //compute formant parameters(frequency,amplitude,etc.) - const float filter_freq = getformantfreq(Pvowels[nvowel].formants[nformant].freq); - float filter_q = getformantq(Pvowels[nvowel].formants[nformant].q) * getq(); - if(Pstages > 0) - filter_q = (filter_q > 1.0f ? powf(filter_q, 1.0f / (Pstages + 1)) : filter_q); - - const float filter_amp = getformantamp(Pvowels[nvowel].formants[nformant].amp); - - - if(filter_freq <= (synth->samplerate / 2 - 100.0f)) { - const float omega = 2 * PI * filter_freq / synth->samplerate_f; - const float sn = sinf(omega); - const float cs = cosf(omega); - const float alpha = sn / (2 * filter_q); - const float tmp = 1 + alpha; - c[0] = alpha / tmp *sqrt(filter_q + 1); - c[1] = 0; - c[2] = -alpha / tmp *sqrt(filter_q + 1); - d[1] = -2 * cs / tmp * (-1); - d[2] = (1 - alpha) / tmp * (-1); - } - else - continue; - - - for(int i = 0; i < nfreqs; ++i) { - const float freq = getfreqx(i / (float) nfreqs); - - //Discard frequencies above nyquist rate - if(freq > synth->samplerate / 2) { - for(int tmp = i; tmp < nfreqs; ++tmp) - freqs[tmp] = 0.0f; - break; - } - - //Convert to normalized frequency - const float fr = freq / synth->samplerate * PI * 2.0f; - - //Evaluate Complex domain ratio - float x = c[0], y = 0.0f; - for(int n = 1; n < 3; ++n) { - x += cosf(n * fr) * c[n]; - y -= sinf(n * fr) * c[n]; - } - float h = x * x + y * y; - x = 1.0f; - y = 0.0f; - for(int n = 1; n < 3; ++n) { - x -= cosf(n * fr) * d[n]; - y += sinf(n * fr) * d[n]; - } - h = h / (x * x + y * y); - - freqs[i] += powf(h, (Pstages + 1.0f) / 2.0f) * filter_amp; - } - } - - //Convert to logarithmic data ignoring points that are too small - for(int i = 0; i < nfreqs; ++i) { - if(freqs[i] > 0.000000001f) - freqs[i] = rap2dB(freqs[i]) + getgain(); - else - freqs[i] = -90.0f; - } -} - /* * Transforms a parameter to the real value */ diff --git a/src/Params/FilterParams.h b/src/Params/FilterParams.h @@ -85,8 +85,6 @@ class FilterParams:public PresetsArray float getfreqpos(float freq); float getfreqx(float x); - void formantfilterH(int nvowel, int nfreqs, float *freqs); //used by UI - float getformantfreq(unsigned char freq); float getformantamp(unsigned char amp); float getformantq(unsigned char q); diff --git a/src/Params/PADnoteParameters.cpp b/src/Params/PADnoteParameters.cpp @@ -125,7 +125,7 @@ static const rtosc::Ports localPorts = {"nhr:", rProp(non-realtime) rDoc("Returns the harmonic shifts"), NULL, [](const char *, rtosc::RtData &d) { PADnoteParameters *p = ((PADnoteParameters*)d.obj); - const unsigned n = synth->oscilsize / 2; + const unsigned n = p->synth.oscilsize / 2; float *tmp = new float[n]; for(unsigned i=1; i<n; ++i) tmp[i] = p->getNhr(i); @@ -189,14 +189,15 @@ static const rtosc::Ports localPorts = const rtosc::Ports &PADnoteParameters::ports = localPorts; -PADnoteParameters::PADnoteParameters(FFTwrapper *fft_):Presets() +PADnoteParameters::PADnoteParameters(const SYNTH_T &synth_, FFTwrapper *fft_) + :Presets(), synth(synth_) { setpresettype("Ppadsynth"); fft = fft_; resonance = new Resonance(); - oscilgen = new OscilGen(fft_, resonance); + oscilgen = new OscilGen(synth, fft_, resonance); oscilgen->ADvsPAD = true; FreqEnvelope = new EnvelopeParams(0, 0); @@ -586,23 +587,23 @@ void PADnoteParameters::generatespectrum_bandwidthMode(float *spectrum, int profilesize, float bwadjust) { - float harmonics[synth->oscilsize]; + float harmonics[synth.oscilsize]; memset(spectrum, 0, sizeof(float) * size); - memset(harmonics, 0, sizeof(float) * synth->oscilsize); + memset(harmonics, 0, sizeof(float) * synth.oscilsize); //get the harmonic structure from the oscillator (I am using the frequency amplitudes, only) oscilgen->get(harmonics, basefreq, false); //normalize - normalize_max(harmonics, synth->oscilsize / 2); + normalize_max(harmonics, synth.oscilsize / 2); //Constants across harmonics const float power = Pbwscale_translate(Pbwscale); const float bandwidthcents = setPbandwidth(Pbandwidth); - for(int nh = 1; nh < synth->oscilsize / 2; ++nh) { //for each harmonic + for(int nh = 1; nh < synth.oscilsize / 2; ++nh) { //for each harmonic const float realfreq = getNhr(nh) * basefreq; - if(realfreq > synth->samplerate_f * 0.49999f) + if(realfreq > synth.samplerate_f * 0.49999f) break; if(realfreq < 20.0f) break; @@ -613,7 +614,7 @@ void PADnoteParameters::generatespectrum_bandwidthMode(float *spectrum, const float bw = ((powf(2.0f, bandwidthcents / 1200.0f) - 1.0f) * basefreq / bwadjust) * powf(realfreq / basefreq, power); - const int ibw = (int)((bw / (synth->samplerate_f * 0.5f) * size)) + 1; + const int ibw = (int)((bw / (synth.samplerate_f * 0.5f) * size)) + 1; float amp = harmonics[nh - 1]; if(resonance->Penabled) @@ -623,7 +624,7 @@ void PADnoteParameters::generatespectrum_bandwidthMode(float *spectrum, const float rap = sqrt((float)profilesize / (float)ibw); const int cfreq = (int) (realfreq - / (synth->samplerate_f * 0.5f) * size) - ibw / 2; + / (synth.samplerate_f * 0.5f) * size) - ibw / 2; for(int i = 0; i < ibw; ++i) { const int src = i * rap * rap; const int spfreq = i + cfreq; @@ -636,7 +637,7 @@ void PADnoteParameters::generatespectrum_bandwidthMode(float *spectrum, } else { //if the bandwidth is smaller than the profilesize const float rap = sqrt((float)ibw / (float)profilesize); - const float ibasefreq = realfreq / (synth->samplerate_f * 0.5f) * size; + const float ibasefreq = realfreq / (synth.samplerate_f * 0.5f) * size; for(int i = 0; i < profilesize; ++i) { const float idfreq = (i / (float)profilesize - 0.5f) * ibw; const int spfreq = (int) (idfreq + ibasefreq); @@ -660,21 +661,21 @@ void PADnoteParameters::generatespectrum_otherModes(float *spectrum, int size, float basefreq) { - float harmonics[synth->oscilsize]; + float harmonics[synth.oscilsize]; memset(spectrum, 0, sizeof(float) * size); - memset(harmonics, 0, sizeof(float) * synth->oscilsize); + memset(harmonics, 0, sizeof(float) * synth.oscilsize); //get the harmonic structure from the oscillator (I am using the frequency amplitudes, only) oscilgen->get(harmonics, basefreq, false); //normalize - normalize_max(harmonics, synth->oscilsize / 2); + normalize_max(harmonics, synth.oscilsize / 2); - for(int nh = 1; nh < synth->oscilsize / 2; ++nh) { //for each harmonic + for(int nh = 1; nh < synth.oscilsize / 2; ++nh) { //for each harmonic const float realfreq = getNhr(nh) * basefreq; //take care of interpolation if frequency decreases - if(realfreq > synth->samplerate_f * 0.49999f) + if(realfreq > synth.samplerate_f * 0.49999f) break; if(realfreq < 20.0f) break; @@ -683,7 +684,7 @@ void PADnoteParameters::generatespectrum_otherModes(float *spectrum, float amp = harmonics[nh - 1]; if(resonance->Penabled) amp *= resonance->getfreqresponse(realfreq); - const int cfreq = realfreq / (synth->samplerate_f * 0.5f) * size; + const int cfreq = realfreq / (synth.samplerate_f * 0.5f) * size; spectrum[cfreq] = amp + 1e-9; } @@ -844,7 +845,7 @@ void PADnoteParameters::export2wav(std::string basefilename) char tmpstr[20]; snprintf(tmpstr, 20, "_%02d", k + 1); std::string filename = basefilename + std::string(tmpstr) + ".wav"; - WavFile wav(filename, synth->samplerate, 1); + WavFile wav(filename, synth.samplerate, 1); if(wav.good()) { int nsmps = sample[k].size; short int *smps = new short int[nsmps]; diff --git a/src/Params/PADnoteParameters.h b/src/Params/PADnoteParameters.h @@ -42,7 +42,7 @@ class PADnoteParameters:public Presets { public: - PADnoteParameters(FFTwrapper *fft_); + PADnoteParameters(const SYNTH_T &synth_, FFTwrapper *fft_); ~PADnoteParameters(); void defaults(); @@ -181,6 +181,8 @@ class PADnoteParameters:public Presets void deletesample(int n); FFTwrapper *fft; + public: + const SYNTH_T &synth; }; diff --git a/src/Synth/ADnote.cpp b/src/Synth/ADnote.cpp @@ -35,14 +35,13 @@ #include "OscilGen.h" #include "ADnote.h" - ADnote::ADnote(ADnoteParameters *pars_, SynthParams &spars) :SynthNote(spars), pars(*pars_) { - tmpwavel = memory.valloc<float>(synth->buffersize); - tmpwaver = memory.valloc<float>(synth->buffersize); - bypassl = memory.valloc<float>(synth->buffersize); - bypassr = memory.valloc<float>(synth->buffersize); + tmpwavel = memory.valloc<float>(synth.buffersize); + tmpwaver = memory.valloc<float>(synth.buffersize); + bypassl = memory.valloc<float>(synth.buffersize); + bypassr = memory.valloc<float>(synth.buffersize); ADnoteParameters &pars = *pars_; portamento = spars.portamento; @@ -82,7 +81,7 @@ ADnote::ADnote(ADnoteParameters *pars_, SynthParams &spars) powf(10, 3.0f * pars.GlobalPar.PPunchTime / 127.0f) / 10000.0f; //0.1f .. 100 ms float stretch = powf(440.0f / spars.frequency, pars.GlobalPar.PPunchStretch / 64.0f); - NoteGlobalPar.Punch.dt = 1.0f / (time * synth->samplerate_f * stretch); + NoteGlobalPar.Punch.dt = 1.0f / (time * synth.samplerate_f * stretch); } else NoteGlobalPar.Punch.Enabled = 0; @@ -165,7 +164,7 @@ ADnote::ADnote(ADnoteParameters *pars_, SynthParams &spars) unison_vibratto[nvoice].amplitude = (unison_real_spread - 1.0f) * unison_vibratto_a; - float increments_per_second = synth->samplerate_f / synth->buffersize_f; + float increments_per_second = synth.samplerate_f / synth.buffersize_f; const float vib_speed = pars.VoicePar[nvoice].Unison_vibratto_speed / 127.0f; float vibratto_base_period = 0.25f * powf(2.0f, (1.0f - vib_speed) * 4.0f); for(int k = 0; k < unison; ++k) { @@ -265,7 +264,7 @@ ADnote::ADnote(ADnoteParameters *pars_, SynthParams &spars) //the extra points contains the first point NoteVoicePar[nvoice].OscilSmp = - memory.valloc<float>(synth->oscilsize + OSCIL_SMP_EXTRA_SAMPLES); + memory.valloc<float>(synth.oscilsize + OSCIL_SMP_EXTRA_SAMPLES); //Get the voice's oscil or external's voice oscil int vc = nvoice; @@ -280,21 +279,21 @@ ADnote::ADnote(ADnoteParameters *pars_, SynthParams &spars) //I store the first elments to the last position for speedups for(int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; ++i) - NoteVoicePar[nvoice].OscilSmp[synth->oscilsize + NoteVoicePar[nvoice].OscilSmp[synth.oscilsize + i] = NoteVoicePar[nvoice].OscilSmp[i]; oscposhi_start += (int)((pars.VoicePar[nvoice].Poscilphase - - 64.0f) / 128.0f * synth->oscilsize + synth->oscilsize * 4); - oscposhi_start %= synth->oscilsize; + - 64.0f) / 128.0f * synth.oscilsize + synth.oscilsize * 4); + oscposhi_start %= synth.oscilsize; for(int k = 0; k < unison; ++k) { oscposhi[nvoice][k] = oscposhi_start; //put random starting point for other subvoices oscposhi_start = (int)(RND * pars.VoicePar[nvoice].Unison_phase_randomness / - 127.0f * (synth->oscilsize - 1)); + 127.0f * (synth.oscilsize - 1)); } NoteVoicePar[nvoice].FreqLfo = NULL; @@ -380,7 +379,7 @@ ADnote::ADnote(ADnoteParameters *pars_, SynthParams &spars) NoteVoicePar[nvoice].DelayTicks = (int)((expf(pars.VoicePar[nvoice].PDelay / 127.0f * logf(50.0f)) - - 1.0f) / synth->buffersize_f / 10.0f * synth->samplerate_f); + - 1.0f) / synth.buffersize_f / 10.0f * synth.samplerate_f); } max_unison = 1; @@ -391,8 +390,8 @@ ADnote::ADnote(ADnoteParameters *pars_, SynthParams &spars) tmpwave_unison = memory.valloc<float*>(max_unison); for(int k = 0; k < max_unison; ++k) { - tmpwave_unison[k] = memory.valloc<float>(synth->buffersize); - memset(tmpwave_unison[k], 0, synth->bufferbytes); + tmpwave_unison[k] = memory.valloc<float>(synth.buffersize); + memset(tmpwave_unison[k], 0, synth.bufferbytes); } initparameters(); @@ -490,7 +489,7 @@ void ADnote::legatonote(LegatoParams lpars) //I store the first elments to the last position for speedups for(int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; ++i) - NoteVoicePar[nvoice].OscilSmp[synth->oscilsize + NoteVoicePar[nvoice].OscilSmp[synth.oscilsize + i] = NoteVoicePar[nvoice].OscilSmp[i]; @@ -541,7 +540,7 @@ void ADnote::legatonote(LegatoParams lpars) NoteVoicePar[nvoice].DelayTicks = (int)((expf(pars.VoicePar[nvoice].PDelay / 127.0f * logf(50.0f)) - - 1.0f) / synth->buffersize_f / 10.0f * synth->samplerate_f); + - 1.0f) / synth.buffersize_f / 10.0f * synth.samplerate_f); } /// initparameters(); @@ -623,7 +622,7 @@ void ADnote::legatonote(LegatoParams lpars) pars.VoicePar[vc].FMSmp->newrandseed(prng()); for(int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; ++i) - NoteVoicePar[nvoice].FMSmp[synth->oscilsize + i] = + NoteVoicePar[nvoice].FMSmp[synth.oscilsize + i] = NoteVoicePar[nvoice].FMSmp[i]; } @@ -667,7 +666,7 @@ void ADnote::KillVoice(int nvoice) memory.devalloc(unison_vibratto[nvoice].step); memory.devalloc(unison_vibratto[nvoice].position); - NoteVoicePar[nvoice].kill(memory); + NoteVoicePar[nvoice].kill(memory, synth); } /* @@ -711,7 +710,7 @@ void ADnote::initparameters() //ADnoteParameters &pars = *partparams; // Global Parameters - NoteGlobalPar.initparameters(pars.GlobalPar, + NoteGlobalPar.initparameters(pars.GlobalPar, synth, memory, basefreq, velocity, stereo); @@ -748,34 +747,36 @@ void ADnote::initparameters() newamplitude[nvoice] = 1.0f; if(param.PAmpEnvelopeEnabled) { - vce.AmpEnvelope = memory.alloc<Envelope>(*param.AmpEnvelope, basefreq); + vce.AmpEnvelope = memory.alloc<Envelope>(*param.AmpEnvelope, basefreq, synth.dt()); vce.AmpEnvelope->envout_dB(); //discard the first envelope sample newamplitude[nvoice] *= vce.AmpEnvelope->envout_dB(); } if(param.PAmpLfoEnabled) { - vce.AmpLfo = memory.alloc<LFO>(*param.AmpLfo, basefreq); + vce.AmpLfo = memory.alloc<LFO>(*param.AmpLfo, basefreq, synth.dt()); newamplitude[nvoice] *= vce.AmpLfo->amplfoout(); } /* Voice Frequency Parameters Init */ if(param.PFreqEnvelopeEnabled) - vce.FreqEnvelope = memory.alloc<Envelope>(*param.FreqEnvelope, basefreq); + vce.FreqEnvelope = memory.alloc<Envelope>(*param.FreqEnvelope, basefreq, synth.dt()); if(param.PFreqLfoEnabled) - vce.FreqLfo = memory.alloc<LFO>(*param.FreqLfo, basefreq); + vce.FreqLfo = memory.alloc<LFO>(*param.FreqLfo, basefreq, synth.dt()); /* Voice Filter Parameters Init */ if(param.PFilterEnabled != 0) { - vce.VoiceFilterL = Filter::generate(memory, param.VoiceFilter); - vce.VoiceFilterR = Filter::generate(memory, param.VoiceFilter); + vce.VoiceFilterL = Filter::generate(memory, param.VoiceFilter, + synth.samplerate, synth.buffersize); + vce.VoiceFilterR = Filter::generate(memory, param.VoiceFilter, + synth.samplerate, synth.buffersize); } if(param.PFilterEnvelopeEnabled) - vce.FilterEnvelope = memory.alloc<Envelope>(*param.FilterEnvelope, basefreq); + vce.FilterEnvelope = memory.alloc<Envelope>(*param.FilterEnvelope, basefreq, synth.dt()); if(param.PFilterLfoEnabled) - vce.FilterLfo = memory.alloc<LFO>(*param.FilterLfo, basefreq); + vce.FilterLfo = memory.alloc<LFO>(*param.FilterLfo, basefreq, synth.dt()); vce.FilterFreqTracking = param.VoiceFilter->getfreqtracking(basefreq); @@ -783,7 +784,7 @@ void ADnote::initparameters() /* Voice Modulation Parameters Init */ if((vce.FMEnabled != NONE) && (vce.FMVoice < 0)) { param.FMSmp->newrandseed(prng()); - vce.FMSmp = memory.valloc<float>(synth->oscilsize + OSCIL_SMP_EXTRA_SAMPLES); + vce.FMSmp = memory.valloc<float>(synth.oscilsize + OSCIL_SMP_EXTRA_SAMPLES); //Perform Anti-aliasing only on MORPH or RING MODULATION @@ -804,28 +805,28 @@ void ADnote::initparameters() oscposhiFM[nvoice][k] = (oscposhi[nvoice][k] + pars.VoicePar[vc].FMSmp->get( vce.FMSmp, tmp)) - % synth->oscilsize; + % synth.oscilsize; for(int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; ++i) - vce.FMSmp[synth->oscilsize + i] = vce.FMSmp[i]; + vce.FMSmp[synth.oscilsize + i] = vce.FMSmp[i]; int oscposhiFM_add = (int)((param.PFMoscilphase - - 64.0f) / 128.0f * synth->oscilsize - + synth->oscilsize * 4); + - 64.0f) / 128.0f * synth.oscilsize + + synth.oscilsize * 4); for(int k = 0; k < unison_size[nvoice]; ++k) { oscposhiFM[nvoice][k] += oscposhiFM_add; - oscposhiFM[nvoice][k] %= synth->oscilsize; + oscposhiFM[nvoice][k] %= synth.oscilsize; } } if(param.PFMFreqEnvelopeEnabled) - vce.FMFreqEnvelope = memory.alloc<Envelope>(*param.FMFreqEnvelope, basefreq); + vce.FMFreqEnvelope = memory.alloc<Envelope>(*param.FMFreqEnvelope, basefreq, synth.dt()); FMnewamplitude[nvoice] = vce.FMVolume * ctl.fmamp.relamp; if(param.PFMAmpEnvelopeEnabled ) { vce.FMAmpEnvelope = - memory.alloc<Envelope>(*param.FMAmpEnvelope, basefreq); + memory.alloc<Envelope>(*param.FMAmpEnvelope, basefreq, synth.dt()); FMnewamplitude[nvoice] *= vce.FMAmpEnvelope->envout_dB(); } } @@ -836,12 +837,12 @@ void ADnote::initparameters() for(int i = nvoice + 1; i < NUM_VOICES; ++i) if((NoteVoicePar[i].FMVoice == nvoice) && (tmp[i] == 0)) { NoteVoicePar[nvoice].VoiceOut = - memory.valloc<float>(synth->buffersize); + memory.valloc<float>(synth.buffersize); tmp[i] = 1; } if(NoteVoicePar[nvoice].VoiceOut) - memset(NoteVoicePar[nvoice].VoiceOut, 0, synth->bufferbytes); + memset(NoteVoicePar[nvoice].VoiceOut, 0, synth.bufferbytes); } } @@ -888,9 +889,9 @@ void ADnote::setfreq(int nvoice, float in_freq) { for(int k = 0; k < unison_size[nvoice]; ++k) { float freq = fabs(in_freq) * unison_freq_rap[nvoice][k]; - float speed = freq * synth->oscilsize_f / synth->samplerate_f; - if(speed > synth->oscilsize_f) - speed = synth->oscilsize_f; + float speed = freq * synth.oscilsize_f / synth.samplerate_f; + if(speed > synth.oscilsize_f) + speed = synth.oscilsize_f; F2I(speed, oscfreqhi[nvoice][k]); oscfreqlo[nvoice][k] = speed - floor(speed); @@ -904,9 +905,9 @@ void ADnote::setfreqFM(int nvoice, float in_freq) { for(int k = 0; k < unison_size[nvoice]; ++k) { float freq = fabs(in_freq) * unison_freq_rap[nvoice][k]; - float speed = freq * synth->oscilsize_f / synth->samplerate_f; - if(speed > synth->samplerate_f) - speed = synth->samplerate_f; + float speed = freq * synth.oscilsize_f / synth.samplerate_f; + if(speed > synth.samplerate_f) + speed = synth.samplerate_f; F2I(speed, oscfreqhiFM[nvoice][k]); oscfreqloFM[nvoice][k] = speed - floor(speed); @@ -1070,7 +1071,7 @@ void ADnote::computecurrentparameters() } } } - time += synth->buffersize_f / synth->samplerate_f; + time += synth.buffersize_f / synth.samplerate_f; } @@ -1080,18 +1081,18 @@ void ADnote::computecurrentparameters() inline void ADnote::fadein(float *smps) const { int zerocrossings = 0; - for(int i = 1; i < synth->buffersize; ++i) + for(int i = 1; i < synth.buffersize; ++i) if((smps[i - 1] < 0.0f) && (smps[i] > 0.0f)) zerocrossings++; //this is only the possitive crossings - float tmp = (synth->buffersize_f - 1.0f) / (zerocrossings + 1) / 3.0f; + float tmp = (synth.buffersize_f - 1.0f) / (zerocrossings + 1) / 3.0f; if(tmp < 8.0f) tmp = 8.0f; int n; F2I(tmp, n); //how many samples is the fade-in - if(n > synth->buffersize) - n = synth->buffersize; + if(n > synth.buffersize) + n = synth.buffersize; for(int i = 0; i < n; ++i) { //fade-in float tmp = 0.5f - cosf((float)i / (float) n * PI) * 0.5f; smps[i] *= tmp; @@ -1125,12 +1126,12 @@ inline void ADnote::ComputeVoiceOscillator_LinearInterpolation(int nvoice) float *smps = NoteVoicePar[nvoice].OscilSmp; float *tw = tmpwave_unison[k]; assert(oscfreqlo[nvoice][k] < 1.0f); - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { tw[i] = (smps[poshi] * ((1<<24) - poslo) + smps[poshi + 1] * poslo)/(1.0f*(1<<24)); poslo += freqlo; poshi += freqhi + (poslo>>24); poslo &= 0xffffff; - poshi &= synth->oscilsize - 1; + poshi &= synth.oscilsize - 1; } oscposhi[nvoice][k] = poshi; oscposlo[nvoice][k] = poslo/(1.0f*(1<<24)); @@ -1142,7 +1143,7 @@ inline void ADnote::ComputeVoiceOscillator_LinearInterpolation(int nvoice) /* * Computes the Oscillator (Without Modulation) - CubicInterpolation * - The differences from the Linear are to little to deserve to be used. This is because I am using a large synth->oscilsize (>512) + The differences from the Linear are to little to deserve to be used. This is because I am using a large synth.oscilsize (>512) inline void ADnote::ComputeVoiceOscillator_CubicInterpolation(int nvoice){ int i,poshi; float poslo; @@ -1151,7 +1152,7 @@ inline void ADnote::ComputeVoiceOscillator_CubicInterpolation(int nvoice){ poslo=oscposlo[nvoice]; float *smps=NoteVoicePar[nvoice].OscilSmp; float xm1,x0,x1,x2,a,b,c; - for (i=0;i<synth->buffersize;i++){ + for (i=0;i<synth.buffersize;i++){ xm1=smps[poshi]; x0=smps[poshi+1]; x1=smps[poshi+2]; @@ -1168,7 +1169,7 @@ inline void ADnote::ComputeVoiceOscillator_CubicInterpolation(int nvoice){ poshi++; }; poshi+=oscfreqhi[nvoice]; - poshi&=synth->oscilsize-1; + poshi&=synth.oscilsize-1; }; oscposhi[nvoice]=poshi; oscposlo[nvoice]=poslo; @@ -1190,11 +1191,11 @@ inline void ADnote::ComputeVoiceOscillatorMorph(int nvoice) int FMVoice = NoteVoicePar[nvoice].FMVoice; for(int k = 0; k < unison_size[nvoice]; ++k) { float *tw = tmpwave_unison[k]; - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { float amp = INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice], FMnewamplitude[nvoice], i, - synth->buffersize); + synth.buffersize); tw[i] = tw[i] * (1.0f - amp) + amp * NoteVoicePar[FMVoice].VoiceOut[i]; } @@ -1208,11 +1209,11 @@ inline void ADnote::ComputeVoiceOscillatorMorph(int nvoice) float freqloFM = oscfreqloFM[nvoice][k]; float *tw = tmpwave_unison[k]; - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { float amp = INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice], FMnewamplitude[nvoice], i, - synth->buffersize); + synth.buffersize); tw[i] = tw[i] * (1.0f - amp) + amp * (NoteVoicePar[nvoice].FMSmp[poshiFM] * (1 - posloFM) + NoteVoicePar[nvoice].FMSmp[poshiFM + 1] * posloFM); @@ -1222,7 +1223,7 @@ inline void ADnote::ComputeVoiceOscillatorMorph(int nvoice) poshiFM++; } poshiFM += freqhiFM; - poshiFM &= synth->oscilsize - 1; + poshiFM &= synth.oscilsize - 1; } oscposhiFM[nvoice][k] = poshiFM; oscposloFM[nvoice][k] = posloFM; @@ -1243,11 +1244,11 @@ inline void ADnote::ComputeVoiceOscillatorRingModulation(int nvoice) // if I use VoiceOut[] as modullator for(int k = 0; k < unison_size[nvoice]; ++k) { float *tw = tmpwave_unison[k]; - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { float amp = INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice], FMnewamplitude[nvoice], i, - synth->buffersize); + synth.buffersize); int FMVoice = NoteVoicePar[nvoice].FMVoice; tw[i] *= (1.0f - amp) + amp * NoteVoicePar[FMVoice].VoiceOut[i]; } @@ -1260,11 +1261,11 @@ inline void ADnote::ComputeVoiceOscillatorRingModulation(int nvoice) float freqloFM = oscfreqloFM[nvoice][k]; float *tw = tmpwave_unison[k]; - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { float amp = INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice], FMnewamplitude[nvoice], i, - synth->buffersize); + synth.buffersize); tw[i] *= (NoteVoicePar[nvoice].FMSmp[poshiFM] * (1.0f - posloFM) + NoteVoicePar[nvoice].FMSmp[poshiFM + 1] * posloFM) * amp @@ -1275,7 +1276,7 @@ inline void ADnote::ComputeVoiceOscillatorRingModulation(int nvoice) poshiFM++; } poshiFM += freqhiFM; - poshiFM &= synth->oscilsize - 1; + poshiFM &= synth.oscilsize - 1; } oscposhiFM[nvoice][k] = poshiFM; oscposloFM[nvoice][k] = posloFM; @@ -1293,7 +1294,7 @@ inline void ADnote::ComputeVoiceOscillatorFrequencyModulation(int nvoice, for(int k = 0; k < unison_size[nvoice]; ++k) { float *tw = tmpwave_unison[k]; const float *smps = NoteVoicePar[NoteVoicePar[nvoice].FMVoice].VoiceOut; - memcpy(tw, smps, synth->bufferbytes); + memcpy(tw, smps, synth.bufferbytes); } } else { //Compute the modulator and store it in tmpwave_unison[][] @@ -1305,7 +1306,7 @@ inline void ADnote::ComputeVoiceOscillatorFrequencyModulation(int nvoice, float *tw = tmpwave_unison[k]; const float *smps = NoteVoicePar[nvoice].FMSmp; - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { tw[i] = (smps[poshiFM] * ((1<<24) - posloFM) + smps[poshiFM + 1] * posloFM) / (1.0f*(1<<24)); posloFM += freqloFM; @@ -1314,7 +1315,7 @@ inline void ADnote::ComputeVoiceOscillatorFrequencyModulation(int nvoice, poshiFM++; } poshiFM += freqhiFM; - poshiFM &= synth->oscilsize - 1; + poshiFM &= synth.oscilsize - 1; } oscposhiFM[nvoice][k] = poshiFM; oscposloFM[nvoice][k] = posloFM/((1<<24)*1.0f); @@ -1325,16 +1326,16 @@ inline void ADnote::ComputeVoiceOscillatorFrequencyModulation(int nvoice, FMnewamplitude[nvoice])) { for(int k = 0; k < unison_size[nvoice]; ++k) { float *tw = tmpwave_unison[k]; - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < synth.buffersize; ++i) tw[i] *= INTERPOLATE_AMPLITUDE(FMoldamplitude[nvoice], FMnewamplitude[nvoice], i, - synth->buffersize); + synth.buffersize); } } else { for(int k = 0; k < unison_size[nvoice]; ++k) { float *tw = tmpwave_unison[k]; - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < synth.buffersize; ++i) tw[i] *= FMnewamplitude[nvoice]; } } @@ -1342,23 +1343,23 @@ inline void ADnote::ComputeVoiceOscillatorFrequencyModulation(int nvoice, //normalize: makes all sample-rates, oscil_sizes to produce same sound if(FMmode != 0) { //Frequency modulation - const float normalize = synth->oscilsize_f / 262144.0f * 44100.0f - / synth->samplerate_f; + const float normalize = synth.oscilsize_f / 262144.0f * 44100.0f + / synth.samplerate_f; for(int k = 0; k < unison_size[nvoice]; ++k) { float *tw = tmpwave_unison[k]; float fmold = FMoldsmp[nvoice][k]; - for(int i = 0; i < synth->buffersize; ++i) { - fmold = fmod(fmold + tw[i] * normalize, synth->oscilsize); + for(int i = 0; i < synth.buffersize; ++i) { + fmold = fmod(fmold + tw[i] * normalize, synth.oscilsize); tw[i] = fmold; } FMoldsmp[nvoice][k] = fmold; } } else { //Phase modulation - const float normalize = synth->oscilsize_f / 262144.0f; + const float normalize = synth.oscilsize_f / 262144.0f; for(int k = 0; k < unison_size[nvoice]; ++k) { float *tw = tmpwave_unison[k]; - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < synth.buffersize; ++i) tw[i] *= normalize; } } @@ -1372,7 +1373,7 @@ inline void ADnote::ComputeVoiceOscillatorFrequencyModulation(int nvoice, int freqhi = oscfreqhi[nvoice][k]; int freqlo = oscfreqlo[nvoice][k] * (1<<24); - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { int FMmodfreqhi = 0; F2I(tw[i], FMmodfreqhi); float FMmodfreqlo = tw[i]-FMmodfreqhi;//fmod(tw[i] /*+ 0.0000000001f*/, 1.0f); @@ -1387,7 +1388,7 @@ inline void ADnote::ComputeVoiceOscillatorFrequencyModulation(int nvoice, carposhi++; carposlo &= 0xffffff;//fmod(carposlo, 1.0f); } - carposhi &= (synth->oscilsize - 1); + carposhi &= (synth.oscilsize - 1); tw[i] = (smps[carposhi] * ((1<<24) - carposlo) + smps[carposhi + 1] * carposlo)/(1.0f*(1<<24)); @@ -1399,7 +1400,7 @@ inline void ADnote::ComputeVoiceOscillatorFrequencyModulation(int nvoice, } poshi += freqhi; - poshi &= synth->oscilsize - 1; + poshi &= synth.oscilsize - 1; } oscposhi[nvoice][k] = poshi; oscposlo[nvoice][k] = (poslo)/((1<<24)*1.0f); @@ -1420,7 +1421,7 @@ inline void ADnote::ComputeVoiceNoise(int nvoice) { for(int k = 0; k < unison_size[nvoice]; ++k) { float *tw = tmpwave_unison[k]; - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < synth.buffersize; ++i) tw[i] = RND * 2.0f - 1.0f; } } @@ -1433,14 +1434,14 @@ inline void ADnote::ComputeVoiceNoise(int nvoice) */ int ADnote::noteout(float *outl, float *outr) { - memcpy(outl, denormalkillbuf, synth->bufferbytes); - memcpy(outr, denormalkillbuf, synth->bufferbytes); + memcpy(outl, denormalkillbuf, synth.bufferbytes); + memcpy(outr, denormalkillbuf, synth.bufferbytes); if(NoteEnabled == OFF) return 0; - memset(bypassl, 0, synth->bufferbytes); - memset(bypassr, 0, synth->bufferbytes); + memset(bypassl, 0, synth.bufferbytes); + memset(bypassr, 0, synth.bufferbytes); computecurrentparameters(); for(unsigned nvoice = 0; nvoice < NUM_VOICES; ++nvoice) { @@ -1472,9 +1473,9 @@ int ADnote::noteout(float *outl, float *outr) //mix subvoices into voice - memset(tmpwavel, 0, synth->bufferbytes); + memset(tmpwavel, 0, synth.bufferbytes); if(stereo) - memset(tmpwaver, 0, synth->bufferbytes); + memset(tmpwaver, 0, synth.bufferbytes); for(int k = 0; k < unison_size[nvoice]; ++k) { float *tw = tmpwave_unison[k]; if(stereo) { @@ -1512,13 +1513,13 @@ int ADnote::noteout(float *outl, float *outr) rvol = -rvol; } - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < synth.buffersize; ++i) tmpwavel[i] += tw[i] * lvol; - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < synth.buffersize; ++i) tmpwaver[i] += tw[i] * rvol; } else - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < synth.buffersize; ++i) tmpwavel[i] += tw[i]; } @@ -1529,31 +1530,31 @@ int ADnote::noteout(float *outl, float *outr) float newam = newamplitude[nvoice] * unison_amplitude; if(ABOVE_AMPLITUDE_THRESHOLD(oldam, newam)) { - int rest = synth->buffersize; + int rest = synth.buffersize; //test if the amplitude if raising and the difference is high if((newam > oldam) && ((newam - oldam) > 0.25f)) { rest = 10; - if(rest > synth->buffersize) - rest = synth->buffersize; - for(int i = 0; i < synth->buffersize - rest; ++i) + if(rest > synth.buffersize) + rest = synth.buffersize; + for(int i = 0; i < synth.buffersize - rest; ++i) tmpwavel[i] *= oldam; if(stereo) - for(int i = 0; i < synth->buffersize - rest; ++i) + for(int i = 0; i < synth.buffersize - rest; ++i) tmpwaver[i] *= oldam; } // Amplitude interpolation for(int i = 0; i < rest; ++i) { float amp = INTERPOLATE_AMPLITUDE(oldam, newam, i, rest); - tmpwavel[i + (synth->buffersize - rest)] *= amp; + tmpwavel[i + (synth.buffersize - rest)] *= amp; if(stereo) - tmpwaver[i + (synth->buffersize - rest)] *= amp; + tmpwaver[i + (synth.buffersize - rest)] *= amp; } } else { - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < synth.buffersize; ++i) tmpwavel[i] *= newam; if(stereo) - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < synth.buffersize; ++i) tmpwaver[i] *= newam; } @@ -1575,11 +1576,11 @@ int ADnote::noteout(float *outl, float *outr) //check if the amplitude envelope is finished, if yes, the voice will be fadeout if(NoteVoicePar[nvoice].AmpEnvelope) if(NoteVoicePar[nvoice].AmpEnvelope->finished()) { - for(int i = 0; i < synth->buffersize; ++i) - tmpwavel[i] *= 1.0f - (float)i / synth->buffersize_f; + for(int i = 0; i < synth.buffersize; ++i) + tmpwavel[i] *= 1.0f - (float)i / synth.buffersize_f; if(stereo) - for(int i = 0; i < synth->buffersize; ++i) - tmpwaver[i] *= 1.0f - (float)i / synth->buffersize_f; + for(int i = 0; i < synth.buffersize; ++i) + tmpwaver[i] *= 1.0f - (float)i / synth.buffersize_f; } //the voice is killed later @@ -1587,11 +1588,11 @@ int ADnote::noteout(float *outl, float *outr) // Put the ADnote samples in VoiceOut (without appling Global volume, because I wish to use this voice as a modullator) if(NoteVoicePar[nvoice].VoiceOut) { if(stereo) - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < synth.buffersize; ++i) NoteVoicePar[nvoice].VoiceOut[i] = tmpwavel[i] + tmpwaver[i]; else //mono - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < synth.buffersize; ++i) NoteVoicePar[nvoice].VoiceOut[i] = tmpwavel[i]; } @@ -1599,19 +1600,19 @@ int ADnote::noteout(float *outl, float *outr) // Add the voice that do not bypass the filter to out if(NoteVoicePar[nvoice].filterbypass == 0) { //no bypass if(stereo) - for(int i = 0; i < synth->buffersize; ++i) { //stereo + for(int i = 0; i < synth.buffersize; ++i) { //stereo outl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume * NoteVoicePar[nvoice].Panning * 2.0f; outr[i] += tmpwaver[i] * NoteVoicePar[nvoice].Volume * (1.0f - NoteVoicePar[nvoice].Panning) * 2.0f; } else - for(int i = 0; i < synth->buffersize; ++i) //mono + for(int i = 0; i < synth.buffersize; ++i) //mono outl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume; } else { //bypass the filter if(stereo) - for(int i = 0; i < synth->buffersize; ++i) { //stereo + for(int i = 0; i < synth.buffersize; ++i) { //stereo bypassl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume * NoteVoicePar[nvoice].Panning * 2.0f; bypassr[i] += tmpwaver[i] * NoteVoicePar[nvoice].Volume @@ -1619,7 +1620,7 @@ int ADnote::noteout(float *outl, float *outr) - NoteVoicePar[nvoice].Panning) * 2.0f; } else - for(int i = 0; i < synth->buffersize; ++i) //mono + for(int i = 0; i < synth.buffersize; ++i) //mono bypassl[i] += tmpwavel[i] * NoteVoicePar[nvoice].Volume; } // chech if there is necesary to proces the voice longer (if the Amplitude envelope isn't finished) @@ -1633,36 +1634,36 @@ int ADnote::noteout(float *outl, float *outr) NoteGlobalPar.GlobalFilterL->filterout(&outl[0]); if(stereo == 0) { //set the right channel=left channel - memcpy(outr, outl, synth->bufferbytes); - memcpy(bypassr, bypassl, synth->bufferbytes); + memcpy(outr, outl, synth.bufferbytes); + memcpy(bypassr, bypassl, synth.bufferbytes); } else NoteGlobalPar.GlobalFilterR->filterout(&outr[0]); - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { outl[i] += bypassl[i]; outr[i] += bypassr[i]; } if(ABOVE_AMPLITUDE_THRESHOLD(globaloldamplitude, globalnewamplitude)) // Amplitude Interpolation - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { float tmpvol = INTERPOLATE_AMPLITUDE(globaloldamplitude, globalnewamplitude, i, - synth->buffersize); + synth.buffersize); outl[i] *= tmpvol * NoteGlobalPar.Panning; outr[i] *= tmpvol * (1.0f - NoteGlobalPar.Panning); } else - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { outl[i] *= globalnewamplitude * NoteGlobalPar.Panning; outr[i] *= globalnewamplitude * (1.0f - NoteGlobalPar.Panning); } //Apply the punch if(NoteGlobalPar.Punch.Enabled != 0) - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { float punchamp = NoteGlobalPar.Punch.initialvalue * NoteGlobalPar.Punch.t + 1.0f; outl[i] *= punchamp; @@ -1682,8 +1683,8 @@ int ADnote::noteout(float *outl, float *outr) // Check if the global amplitude is finished. // If it does, disable the note if(NoteGlobalPar.AmpEnvelope->finished()) { - for(int i = 0; i < synth->buffersize; ++i) { //fade-out - float tmp = 1.0f - (float)i / synth->buffersize_f; + for(int i = 0; i < synth.buffersize; ++i) { //fade-out + float tmp = 1.0f - (float)i / synth.buffersize_f; outl[i] *= tmp; outr[i] *= tmp; } @@ -1732,7 +1733,7 @@ void ADnote::Voice::releasekey() FMAmpEnvelope->releasekey(); } -void ADnote::Voice::kill(Allocator &memory) +void ADnote::Voice::kill(Allocator &memory, const SYNTH_T &synth) { memory.devalloc(OscilSmp); memory.dealloc(FreqEnvelope); @@ -1750,7 +1751,7 @@ void ADnote::Voice::kill(Allocator &memory) memory.devalloc(FMSmp); if(VoiceOut) - memset(VoiceOut, 0, synth->bufferbytes); + memset(VoiceOut, 0, synth.bufferbytes); //the buffer can't be safely deleted as it may be //an input to another voice @@ -1770,27 +1771,30 @@ void ADnote::Global::kill(Allocator &memory) } void ADnote::Global::initparameters(const ADnoteGlobalParam &param, + const SYNTH_T &synth, class Allocator &memory, float basefreq, float velocity, bool stereo) { - FreqEnvelope = memory.alloc<Envelope>(*param.FreqEnvelope, basefreq); - FreqLfo = memory.alloc<LFO>(*param.FreqLfo, basefreq); + FreqEnvelope = memory.alloc<Envelope>(*param.FreqEnvelope, basefreq, synth.dt()); + FreqLfo = memory.alloc<LFO>(*param.FreqLfo, basefreq, synth.dt()); - AmpEnvelope = memory.alloc<Envelope>(*param.AmpEnvelope, basefreq); - AmpLfo = memory.alloc<LFO>(*param.AmpLfo, basefreq); + AmpEnvelope = memory.alloc<Envelope>(*param.AmpEnvelope, basefreq, synth.dt()); + AmpLfo = memory.alloc<LFO>(*param.AmpLfo, basefreq, synth.dt()); Volume = 4.0f * powf(0.1f, 3.0f * (1.0f - param.PVolume / 96.0f)) //-60 dB .. 0 dB * VelF(velocity, param.PAmpVelocityScaleFunction); //sensing - GlobalFilterL = Filter::generate(memory, param.GlobalFilter); + GlobalFilterL = Filter::generate(memory, param.GlobalFilter, + synth.samplerate, synth.buffersize); if(stereo) - GlobalFilterR = Filter::generate(memory, param.GlobalFilter); + GlobalFilterR = Filter::generate(memory, param.GlobalFilter, + synth.samplerate, synth.buffersize); else GlobalFilterR = NULL; - FilterEnvelope = memory.alloc<Envelope>(*param.FilterEnvelope, basefreq); - FilterLfo = memory.alloc<LFO>(*param.FilterLfo, basefreq); + FilterEnvelope = memory.alloc<Envelope>(*param.FilterEnvelope, basefreq, synth.dt()); + FilterLfo = memory.alloc<LFO>(*param.FilterLfo, basefreq, synth.dt()); FilterQ = param.GlobalFilter->getq(); FilterFreqTracking = param.GlobalFilter->getfreqtracking(basefreq); } diff --git a/src/Synth/ADnote.h b/src/Synth/ADnote.h @@ -118,6 +118,7 @@ class ADnote:public SynthNote struct Global { void kill(Allocator &memory); void initparameters(const ADnoteGlobalParam &param, + const SYNTH_T &synth, class Allocator &memory, float basefreq, float velocity, bool stereo); @@ -165,7 +166,7 @@ class ADnote:public SynthNote /***********************************************************/ struct Voice { void releasekey(); - void kill(Allocator &memory); + void kill(Allocator &memory, const SYNTH_T &synth); /* If the voice is enabled */ ONOFFTYPE Enabled; diff --git a/src/Synth/Envelope.cpp b/src/Synth/Envelope.cpp @@ -24,7 +24,7 @@ #include "Envelope.h" #include "../Params/EnvelopeParams.h" -Envelope::Envelope(EnvelopeParams &pars, float basefreq) +Envelope::Envelope(EnvelopeParams &pars, float basefreq, float bufferdt) { envpoints = pars.Penvpoints; if(envpoints > MAX_ENVELOPE_POINTS) @@ -37,8 +37,6 @@ Envelope::Envelope(EnvelopeParams &pars, float basefreq) if(!pars.Pfreemode) pars.converttofree(); - const float bufferdt = synth->buffersize_f / synth->samplerate_f; - int mode = pars.Envmode; //for amplitude envelopes diff --git a/src/Synth/Envelope.h b/src/Synth/Envelope.h @@ -31,7 +31,7 @@ class Envelope public: /**Constructor*/ - Envelope(class EnvelopeParams &pars, float basefreq); + Envelope(class EnvelopeParams &pars, float basefreq, float dt); /**Destructor*/ ~Envelope(); void releasekey(); diff --git a/src/Synth/LFO.cpp b/src/Synth/LFO.cpp @@ -28,7 +28,8 @@ #include <cstdio> #include <cmath> -LFO::LFO(const LFOParams &lfopars, float basefreq) +LFO::LFO(const LFOParams &lfopars, float basefreq, float dt_) + :dt(dt_) { int stretch = lfopars.Pstretch; if(stretch == 0) @@ -39,7 +40,7 @@ LFO::LFO(const LFOParams &lfopars, float basefreq) float lfofreq = (powf(2, lfopars.Pfreq * 10.0f) - 1.0f) / 12.0f * lfostretch; - incx = fabs(lfofreq) * synth->buffersize_f / synth->samplerate_f; + incx = fabs(lfofreq) * dt; if(!lfopars.Pcontinous) { if(lfopars.Pstartphase == 0) @@ -150,7 +151,7 @@ float LFO::lfoout() } } else - lfodelay -= synth->buffersize_f / synth->samplerate_f; + lfodelay -= dt; return out; } diff --git a/src/Synth/LFO.h b/src/Synth/LFO.h @@ -34,7 +34,7 @@ class LFO * @param lfopars pointer to a LFOParams object * @param basefreq base frequency of LFO */ - LFO(const LFOParams &lfopars, float basefreq); + LFO(const LFOParams &lfopars, float basefreq, float dt); /**Deconstructor*/ ~LFO(); float lfoout(); @@ -46,6 +46,7 @@ class LFO float lfointensity; float lfornd, lfofreqrnd; float lfodelay; + const float dt; /**\todo see if an enum would be better here*/ char lfotype; int freqrndenabled; diff --git a/src/Synth/OscilGen.cpp b/src/Synth/OscilGen.cpp @@ -99,7 +99,8 @@ const rtosc::Ports OscilGen::ports = { }}, {"base-spectrum:", rProp(non-realtime) rDoc("Returns spectrum of base waveshape"), NULL, [](const char *, rtosc::RtData &d) { - const unsigned n = synth->oscilsize / 2; + OscilGen &o = *((OscilGen*)d.obj); + const unsigned n = o.synth.oscilsize / 2; float *spc = new float[n]; memset(spc, 0, 4*n); ((OscilGen*)d.obj)->getspectrum(n,spc,1); @@ -108,7 +109,8 @@ const rtosc::Ports OscilGen::ports = { }}, {"base-waveform:", rProp(non-realtime) rDoc("Returns base waveshape points"), NULL, [](const char *, rtosc::RtData &d) { - const unsigned n = synth->oscilsize; + OscilGen &o = *((OscilGen*)d.obj); + const unsigned n = o.synth.oscilsize; float *smps = new float[n]; memset(smps, 0, 4*n); ((OscilGen*)d.obj)->getcurrentbasefunction(smps); @@ -117,7 +119,8 @@ const rtosc::Ports OscilGen::ports = { }}, {"spectrum:", rProp(non-realtime) rDoc("Returns spectrum of waveform"), NULL, [](const char *, rtosc::RtData &d) { - const unsigned n = synth->oscilsize / 2; + OscilGen &o = *((OscilGen*)d.obj); + const unsigned n = o.synth.oscilsize / 2; float *spc = new float[n]; memset(spc, 0, 4*n); ((OscilGen*)d.obj)->getspectrum(n,spc,0); @@ -126,10 +129,10 @@ const rtosc::Ports OscilGen::ports = { }}, {"waveform:", rProp(non-realtime) rDoc("Returns waveform points"), NULL, [](const char *, rtosc::RtData &d) { - const unsigned n = synth->oscilsize; + OscilGen &o = *((OscilGen*)d.obj); + const unsigned n = o.synth.oscilsize; float *smps = new float[n]; memset(smps, 0, 4*n); - OscilGen &o = *((OscilGen*)d.obj); //printf("%d\n", o->needPrepare()); o.get(smps,-1.0); //printf("wave: %f %f %f %f\n", smps[0], smps[1], smps[2], smps[3]); @@ -140,7 +143,7 @@ const rtosc::Ports OscilGen::ports = { NULL, [](const char *, rtosc::RtData &d) { //fprintf(stderr, "prepare: got a message from '%s'\n", m); OscilGen &o = *(OscilGen*)d.obj; - fft_t *data = new fft_t[synth->oscilsize / 2]; + fft_t *data = new fft_t[o.synth.oscilsize / 2]; o.prepare(data); //fprintf(stderr, "sending '%p' of fft data\n", data); d.reply("/forward", "sb", d.loc, sizeof(fft_t*), &data); @@ -167,9 +170,9 @@ const rtosc::Ports OscilGen::ports = { //operations on FFTfreqs -inline void clearAll(fft_t *freqs) +inline void clearAll(fft_t *freqs, int oscilsize) { - memset(freqs, 0, synth->oscilsize / 2 * sizeof(fft_t)); + memset(freqs, 0, oscilsize / 2 * sizeof(fft_t)); } inline void clearDC(fft_t *freqs) @@ -200,10 +203,10 @@ inline float arg(const fft_t *freqs, off_t x) * Take frequency spectrum and ensure values are normalized based upon * magnitude to 0<=x<=1 */ -void normalize(fft_t *freqs) +void normalize(fft_t *freqs, int oscilsize) { float normMax = 0.0f; - for(int i = 0; i < synth->oscilsize / 2; ++i) { + for(int i = 0; i < oscilsize / 2; ++i) { //magnitude squared const float norm = normal(freqs, i); if(normMax < norm) @@ -214,15 +217,15 @@ void normalize(fft_t *freqs) if(max < 1e-8) //data is all ~zero, do not amplify noise return; - for(int i = 0; i < synth->oscilsize / 2; ++i) + for(int i = 0; i < oscilsize / 2; ++i) freqs[i] /= max; } //Full RMS normalize -void rmsNormalize(fft_t *freqs) +void rmsNormalize(fft_t *freqs, int oscilsize) { float sum = 0.0f; - for(int i = 1; i < synth->oscilsize / 2; ++i) + for(int i = 1; i < oscilsize / 2; ++i) sum += normal(freqs, i); if(sum < 0.000001f) @@ -230,13 +233,14 @@ void rmsNormalize(fft_t *freqs) const float gain = 1.0f / sqrt(sum); - for(int i = 1; i < synth->oscilsize / 2; ++i) + for(int i = 1; i < oscilsize / 2; ++i) freqs[i] *= gain; } #define DIFF(par) (old ## par != P ## par) -OscilGen::OscilGen(FFTwrapper *fft_, Resonance *res_):Presets() +OscilGen::OscilGen(const SYNTH_T &synth_, FFTwrapper *fft_, Resonance *res_) + :Presets(), synth(synth_) { //assert(fft_); @@ -245,10 +249,10 @@ OscilGen::OscilGen(FFTwrapper *fft_, Resonance *res_):Presets() res = res_; - tmpsmps = new float[synth->oscilsize]; - outoscilFFTfreqs = new fft_t[synth->oscilsize / 2]; - oscilFFTfreqs = new fft_t[synth->oscilsize / 2]; - basefuncFFTfreqs = new fft_t[synth->oscilsize / 2]; + tmpsmps = new float[synth.oscilsize]; + outoscilFFTfreqs = new fft_t[synth.oscilsize / 2]; + oscilFFTfreqs = new fft_t[synth.oscilsize / 2]; + basefuncFFTfreqs = new fft_t[synth.oscilsize / 2]; pendingfreqs = oscilFFTfreqs; randseed = 1; @@ -329,8 +333,8 @@ void OscilGen::defaults() Padaptiveharmonicsbasefreq = 128; Padaptiveharmonicspar = 50; - clearAll(oscilFFTfreqs); - clearAll(basefuncFFTfreqs); + clearAll(oscilFFTfreqs, synth.oscilsize); + clearAll(basefuncFFTfreqs, synth.oscilsize); oscilprepared = 0; oldfilterpars = 0; oldsapars = 0; @@ -340,15 +344,15 @@ void OscilGen::defaults() void OscilGen::convert2sine() { float mag[MAX_AD_HARMONICS], phase[MAX_AD_HARMONICS]; - float oscil[synth->oscilsize]; - fft_t *freqs = new fft_t[synth->oscilsize / 2]; + float oscil[synth.oscilsize]; + fft_t *freqs = new fft_t[synth.oscilsize / 2]; get(oscil, -1.0f); - FFTwrapper *fft = new FFTwrapper(synth->oscilsize); + FFTwrapper *fft = new FFTwrapper(synth.oscilsize); fft->smps2freqs(oscil, freqs); delete (fft); - normalize(freqs); + normalize(freqs, synth.oscilsize); mag[0] = 0; phase[0] = 0; @@ -417,8 +421,8 @@ void OscilGen::getbasefunction(float *smps) base_func func = getBaseFunction(Pcurrentbasefunc); - for(i = 0; i < synth->oscilsize; ++i) { - float t = i * 1.0f / synth->oscilsize; + for(i = 0; i < synth.oscilsize; ++i) { + float t = i * 1.0f / synth.oscilsize; switch(Pbasefuncmodulation) { case 1: @@ -447,7 +451,7 @@ void OscilGen::getbasefunction(float *smps) if(func) smps[i] = func(t, par); else - smps[i] = -sinf(2.0f * PI * i / synth->oscilsize); + smps[i] = -sinf(2.0f * PI * i / synth.oscilsize); } } @@ -464,10 +468,10 @@ void OscilGen::oscilfilter(fft_t *freqs) const float par2 = Pfilterpar2 / 127.0f; filter_func filter = getFilter(Pfiltertype); - for(int i = 1; i < synth->oscilsize / 2; ++i) + for(int i = 1; i < synth.oscilsize / 2; ++i) freqs[i] *= filter(i, par, par2); - normalize(freqs); + normalize(freqs, synth.oscilsize); } @@ -482,7 +486,7 @@ void OscilGen::changebasefunction(void) clearDC(basefuncFFTfreqs); } else //in this case basefuncFFTfreqs are not used - clearAll(basefuncFFTfreqs); + clearAll(basefuncFFTfreqs, synth.oscilsize); oscilprepared = 0; oldbasefunc = Pcurrentbasefunc; oldbasepar = Pbasefuncpar; @@ -519,17 +523,17 @@ void OscilGen::waveshape(fft_t *freqs) clearDC(freqs); //reduce the amplitude of the freqs near the nyquist - for(int i = 1; i < synth->oscilsize / 8; ++i) { - float gain = i / (synth->oscilsize / 8.0f); - freqs[synth->oscilsize / 2 - i] *= gain; + for(int i = 1; i < synth.oscilsize / 8; ++i) { + float gain = i / (synth.oscilsize / 8.0f); + freqs[synth.oscilsize / 2 - i] *= gain; } fft->freqs2smps(freqs, tmpsmps); //Normalize - normalize(tmpsmps, synth->oscilsize); + normalize(tmpsmps, synth.oscilsize); //Do the waveshaping - waveShapeSmps(synth->oscilsize, tmpsmps, Pwaveshapingfunction, Pwaveshaping); + waveShapeSmps(synth.oscilsize, tmpsmps, Pwaveshapingfunction, Pwaveshaping); fft->smps2freqs(tmpsmps, freqs); //perform FFT } @@ -573,25 +577,25 @@ void OscilGen::modulation(fft_t *freqs) clearDC(freqs); //remove the DC //reduce the amplitude of the freqs near the nyquist - for(int i = 1; i < synth->oscilsize / 8; ++i) { - const float tmp = i / (synth->oscilsize / 8.0f); - freqs[synth->oscilsize / 2 - i] *= tmp; + for(int i = 1; i < synth.oscilsize / 8; ++i) { + const float tmp = i / (synth.oscilsize / 8.0f); + freqs[synth.oscilsize / 2 - i] *= tmp; } fft->freqs2smps(freqs, tmpsmps); const int extra_points = 2; - float *in = new float[synth->oscilsize + extra_points]; + float *in = new float[synth.oscilsize + extra_points]; //Normalize - normalize(tmpsmps, synth->oscilsize); + normalize(tmpsmps, synth.oscilsize); - for(int i = 0; i < synth->oscilsize; ++i) + for(int i = 0; i < synth.oscilsize; ++i) in[i] = tmpsmps[i]; for(int i = 0; i < extra_points; ++i) - in[i + synth->oscilsize] = tmpsmps[i]; + in[i + synth.oscilsize] = tmpsmps[i]; //Do the modulation - for(int i = 0; i < synth->oscilsize; ++i) { - float t = i * 1.0f / synth->oscilsize; + for(int i = 0; i < synth.oscilsize; ++i) { + float t = i * 1.0f / synth.oscilsize; switch(Pmodulation) { case 1: @@ -610,7 +614,7 @@ void OscilGen::modulation(fft_t *freqs) break; } - t = (t - floor(t)) * synth->oscilsize; + t = (t - floor(t)) * synth.oscilsize; const int poshi = (int) t; const float poslo = t - floor(t); @@ -648,9 +652,9 @@ void OscilGen::spectrumadjust(fft_t *freqs) } - normalize(freqs); + normalize(freqs, synth.oscilsize); - for(int i = 0; i < synth->oscilsize / 2; ++i) { + for(int i = 0; i < synth.oscilsize / 2; ++i) { float mag = abs(oscilFFTfreqs, i); float phase = M_PI_2 - arg(oscilFFTfreqs, i); @@ -681,7 +685,7 @@ void OscilGen::shiftharmonics(fft_t *freqs) fft_t h; if(harmonicshift > 0) - for(int i = synth->oscilsize / 2 - 2; i >= 0; i--) { + for(int i = synth.oscilsize / 2 - 2; i >= 0; i--) { int oldh = i - harmonicshift; if(oldh < 0) h = 0.0f; @@ -690,9 +694,9 @@ void OscilGen::shiftharmonics(fft_t *freqs) freqs[i + 1] = h; } else - for(int i = 0; i < synth->oscilsize / 2 - 1; ++i) { + for(int i = 0; i < synth.oscilsize / 2 - 1; ++i) { int oldh = i + abs(harmonicshift); - if(oldh >= (synth->oscilsize / 2 - 1)) + if(oldh >= (synth.oscilsize / 2 - 1)) h = 0.0f; else { h = freqs[oldh + 1]; @@ -754,7 +758,7 @@ void OscilGen::prepare(fft_t *freqs) hmag[i] = 0.0f; - clearAll(freqs); + clearAll(freqs, synth.oscilsize); if(Pcurrentbasefunc == 0) //the sine case for(int i = 0; i < MAX_AD_HARMONICS - 1; ++i) { freqs[i + 1] = @@ -765,9 +769,9 @@ void OscilGen::prepare(fft_t *freqs) for(int j = 0; j < MAX_AD_HARMONICS; ++j) { if(Phmag[j] == 64) continue; - for(int i = 1; i < synth->oscilsize / 2; ++i) { + for(int i = 1; i < synth.oscilsize / 2; ++i) { int k = i * (j + 1); - if(k >= synth->oscilsize / 2) + if(k >= synth.oscilsize / 2) break; freqs[k] += basefuncFFTfreqs[i] * FFTpolar<fftw_real>( hmag[j], @@ -812,10 +816,10 @@ void OscilGen::adaptiveharmonic(fft_t *f, float freq) if(freq < 1.0f) freq = 440.0f; - fft_t *inf = new fft_t[synth->oscilsize / 2]; - for(int i = 0; i < synth->oscilsize / 2; ++i) + fft_t *inf = new fft_t[synth.oscilsize / 2]; + for(int i = 0; i < synth.oscilsize / 2; ++i) inf[i] = f[i]; - clearAll(f); + clearAll(f, synth.oscilsize); clearDC(inf); float basefreq = 30.0f * powf(10.0f, Padaptiveharmonicsbasefreq / 128.0f); @@ -831,11 +835,11 @@ void OscilGen::adaptiveharmonic(fft_t *f, float freq) down = true; } - for(int i = 0; i < synth->oscilsize / 2 - 2; ++i) { + for(int i = 0; i < synth.oscilsize / 2 - 2; ++i) { const int high = (int)(i * rap); const float low = fmod(i * rap, 1.0f); - if(high >= (synth->oscilsize / 2 - 2)) + if(high >= (synth.oscilsize / 2 - 2)) break; if(down) { @@ -946,36 +950,36 @@ short int OscilGen::get(float *smps, float freqHz, int resonance) int outpos = (int)((RND * 2.0f - - 1.0f) * synth->oscilsize_f * (Prand - 64.0f) / 64.0f); - outpos = (outpos + 2 * synth->oscilsize) % synth->oscilsize; + - 1.0f) * synth.oscilsize_f * (Prand - 64.0f) / 64.0f); + outpos = (outpos + 2 * synth.oscilsize) % synth.oscilsize; - clearAll(outoscilFFTfreqs); + clearAll(outoscilFFTfreqs, synth.oscilsize); - int nyquist = (int)(0.5f * synth->samplerate_f / fabs(freqHz)) + 2; + int nyquist = (int)(0.5f * synth.samplerate_f / fabs(freqHz)) + 2; if(ADvsPAD) - nyquist = (int)(synth->oscilsize / 2); - if(nyquist > synth->oscilsize / 2) - nyquist = synth->oscilsize / 2; + nyquist = (int)(synth.oscilsize / 2); + if(nyquist > synth.oscilsize / 2) + nyquist = synth.oscilsize / 2; //Process harmonics { int realnyquist = nyquist; if(Padaptiveharmonics != 0) - nyquist = synth->oscilsize / 2; + nyquist = synth.oscilsize / 2; for(int i = 1; i < nyquist - 1; ++i) outoscilFFTfreqs[i] = input[i]; adaptiveharmonic(outoscilFFTfreqs, freqHz); adaptiveharmonicpostprocess(&outoscilFFTfreqs[1], - synth->oscilsize / 2 - 1); + synth.oscilsize / 2 - 1); nyquist = realnyquist; } if(Padaptiveharmonics) //do the antialiasing in the case of adaptive harmonics - for(int i = nyquist; i < synth->oscilsize / 2; ++i) + for(int i = nyquist; i < synth.oscilsize / 2; ++i) outoscilFFTfreqs[i] = fft_t(0.0f, 0.0f); // Randomness (each harmonic), the block type is computed @@ -1015,14 +1019,14 @@ short int OscilGen::get(float *smps, float freqHz, int resonance) if((freqHz > 0.1f) && (resonance != 0)) res->applyres(nyquist - 1, outoscilFFTfreqs, freqHz); - rmsNormalize(outoscilFFTfreqs); + rmsNormalize(outoscilFFTfreqs, synth.oscilsize); if((ADvsPAD) && (freqHz > 0.1f)) //in this case the smps will contain the freqs - for(int i = 1; i < synth->oscilsize / 2; ++i) + for(int i = 1; i < synth.oscilsize / 2; ++i) smps[i - 1] = abs(outoscilFFTfreqs, i); else { fft->freqs2smps(outoscilFFTfreqs, smps); - for(int i = 0; i < synth->oscilsize; ++i) + for(int i = 0; i < synth.oscilsize; ++i) smps[i] *= 0.25f; //correct the amplitude } @@ -1042,7 +1046,7 @@ short int OscilGen::get(float *smps, float freqHz, int resonance) // // clearAll(outoscilFFTfreqs); // -// const int nyquist = (synth->oscilsize / 2); +// const int nyquist = (synth.oscilsize / 2); // // //Process harmonics // for(int i = 1; i < nyquist - 1; ++i) @@ -1063,8 +1067,8 @@ short int OscilGen::get(float *smps, float freqHz, int resonance) */ void OscilGen::getspectrum(int n, float *spc, int what) { - if(n > synth->oscilsize / 2) - n = synth->oscilsize / 2; + if(n > synth.oscilsize / 2) + n = synth.oscilsize / 2; for(int i = 1; i < n; ++i) { if(what == 0) @@ -1081,7 +1085,7 @@ void OscilGen::getspectrum(int n, float *spc, int what) for(int i = 0; i < n; ++i) outoscilFFTfreqs[i] = fft_t(spc[i], spc[i]); memset(outoscilFFTfreqs + n, 0, - (synth->oscilsize / 2 - n) * sizeof(fft_t)); + (synth.oscilsize / 2 - n) * sizeof(fft_t)); adaptiveharmonic(outoscilFFTfreqs, 0.0f); adaptiveharmonicpostprocess(outoscilFFTfreqs, n - 1); for(int i = 0; i < n; ++i) @@ -1095,7 +1099,7 @@ void OscilGen::getspectrum(int n, float *spc, int what) */ void OscilGen::useasbase() { - for(int i = 0; i < synth->oscilsize / 2; ++i) + for(int i = 0; i < synth.oscilsize / 2; ++i) basefuncFFTfreqs[i] = oscilFFTfreqs[i]; oldbasefunc = Pcurrentbasefunc = 127; @@ -1188,10 +1192,10 @@ void OscilGen::add2XML(XMLwrapper *xml) xml->endbranch(); if(Pcurrentbasefunc == 127) { - normalize(basefuncFFTfreqs); + normalize(basefuncFFTfreqs, synth.oscilsize); xml->beginbranch("BASE_FUNCTION"); - for(int i = 1; i < synth->oscilsize / 2; ++i) { + for(int i = 1; i < synth.oscilsize / 2; ++i) { float xc = basefuncFFTfreqs[i].real(); float xs = basefuncFFTfreqs[i].imag(); if((fabs(xs) > 1e-6f) && (fabs(xc) > 1e-6f)) { @@ -1286,7 +1290,7 @@ void OscilGen::getfromXML(XMLwrapper *xml) if(xml->enterbranch("BASE_FUNCTION")) { - for(int i = 1; i < synth->oscilsize / 2; ++i) + for(int i = 1; i < synth.oscilsize / 2; ++i) if(xml->enterbranch("BF_HARMONIC", i)) { basefuncFFTfreqs[i] = std::complex<float>(xml->getparreal("cos", 0.0f), @@ -1296,7 +1300,7 @@ void OscilGen::getfromXML(XMLwrapper *xml) xml->exitbranch(); clearDC(basefuncFFTfreqs); - normalize(basefuncFFTfreqs); + normalize(basefuncFFTfreqs, synth.oscilsize); } } diff --git a/src/Synth/OscilGen.h b/src/Synth/OscilGen.h @@ -30,7 +30,7 @@ class OscilGen:public Presets { public: - OscilGen(FFTwrapper *fft_, Resonance *res_); + OscilGen(const SYNTH_T &synth, FFTwrapper *fft_, Resonance *res_); ~OscilGen(); /**computes the full spectrum of oscil from harmonics,phases and basefunc*/ @@ -177,6 +177,8 @@ class OscilGen:public Presets Resonance *res; unsigned int randseed; + public: + const SYNTH_T &synth; }; typedef float (*filter_func)(unsigned int, float, float); diff --git a/src/Synth/PADnote.cpp b/src/Synth/PADnote.cpp @@ -125,16 +125,16 @@ void PADnote::setup(float freq, powf(10, 3.0f * pars.PPunchTime / 127.0f) / 10000.0f; //0.1f .. 100 ms float stretch = powf(440.0f / freq, pars.PPunchStretch / 64.0f); NoteGlobalPar.Punch.dt = 1.0f - / (time * synth->samplerate_f * stretch); + / (time * synth.samplerate_f * stretch); } else NoteGlobalPar.Punch.Enabled = 0; - NoteGlobalPar.FreqEnvelope = memory.alloc<Envelope>(*pars.FreqEnvelope, basefreq); - NoteGlobalPar.FreqLfo = memory.alloc<LFO>(*pars.FreqLfo, basefreq); + NoteGlobalPar.FreqEnvelope = memory.alloc<Envelope>(*pars.FreqEnvelope, basefreq, synth.dt()); + NoteGlobalPar.FreqLfo = memory.alloc<LFO>(*pars.FreqLfo, basefreq, synth.dt()); - NoteGlobalPar.AmpEnvelope = memory.alloc<Envelope>(*pars.AmpEnvelope, basefreq); - NoteGlobalPar.AmpLfo = memory.alloc<LFO>(*pars.AmpLfo, basefreq); + NoteGlobalPar.AmpEnvelope = memory.alloc<Envelope>(*pars.AmpEnvelope, basefreq, synth.dt()); + NoteGlobalPar.AmpLfo = memory.alloc<LFO>(*pars.AmpLfo, basefreq, synth.dt()); } NoteGlobalPar.Volume = 4.0f @@ -148,11 +148,13 @@ void PADnote::setup(float freq, * NoteGlobalPar.AmpLfo->amplfoout(); if(!legato) { - NoteGlobalPar.GlobalFilterL = Filter::generate(memory, pars.GlobalFilter); - NoteGlobalPar.GlobalFilterR = Filter::generate(memory, pars.GlobalFilter); + NoteGlobalPar.GlobalFilterL = Filter::generate(memory, pars.GlobalFilter, + synth.samplerate, synth.buffersize); + NoteGlobalPar.GlobalFilterR = Filter::generate(memory, pars.GlobalFilter, + synth.samplerate, synth.buffersize); - NoteGlobalPar.FilterEnvelope = memory.alloc<Envelope>(*pars.FilterEnvelope, basefreq); - NoteGlobalPar.FilterLfo = memory.alloc<LFO>(*pars.FilterLfo, basefreq); + NoteGlobalPar.FilterEnvelope = memory.alloc<Envelope>(*pars.FilterEnvelope, basefreq, synth.dt()); + NoteGlobalPar.FilterLfo = memory.alloc<LFO>(*pars.FilterLfo, basefreq, synth.dt()); } NoteGlobalPar.FilterQ = pars.GlobalFilter->getq(); NoteGlobalPar.FilterFreqTracking = pars.GlobalFilter->getfreqtracking( @@ -190,18 +192,18 @@ PADnote::~PADnote() inline void PADnote::fadein(float *smps) { int zerocrossings = 0; - for(int i = 1; i < synth->buffersize; ++i) + for(int i = 1; i < synth.buffersize; ++i) if((smps[i - 1] < 0.0f) && (smps[i] > 0.0f)) zerocrossings++; //this is only the possitive crossings - float tmp = (synth->buffersize_f - 1.0f) / (zerocrossings + 1) / 3.0f; + float tmp = (synth.buffersize_f - 1.0f) / (zerocrossings + 1) / 3.0f; if(tmp < 8.0f) tmp = 8.0f; int n; F2I(tmp, n); //how many samples is the fade-in - if(n > synth->buffersize) - n = synth->buffersize; + if(n > synth.buffersize) + n = synth.buffersize; for(int i = 0; i < n; ++i) { //fade-in float tmp = 0.5f - cosf((float)i / (float) n * PI) * 0.5f; smps[i] *= tmp; @@ -257,7 +259,7 @@ int PADnote::Compute_Linear(float *outl, return 1; } int size = pars.sample[nsample].size; - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { poshi_l += freqhi; poshi_r += freqhi; poslo += freqlo; @@ -288,7 +290,7 @@ int PADnote::Compute_Cubic(float *outl, } int size = pars.sample[nsample].size; float xm1, x0, x1, x2, a, b, c; - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { poshi_l += freqhi; poshi_r += freqhi; poslo += freqlo; @@ -331,7 +333,7 @@ int PADnote::noteout(float *outl, float *outr) computecurrentparameters(); float *smps = pars.sample[nsample].smp; if(smps == NULL) { - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { outl[i] = 0.0f; outr[i] = 0.0f; } @@ -362,7 +364,7 @@ int PADnote::noteout(float *outl, float *outr) //Apply the punch if(NoteGlobalPar.Punch.Enabled != 0) - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { float punchamp = NoteGlobalPar.Punch.initialvalue * NoteGlobalPar.Punch.t + 1.0f; outl[i] *= punchamp; @@ -376,16 +378,16 @@ int PADnote::noteout(float *outl, float *outr) if(ABOVE_AMPLITUDE_THRESHOLD(globaloldamplitude, globalnewamplitude)) // Amplitude Interpolation - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { float tmpvol = INTERPOLATE_AMPLITUDE(globaloldamplitude, globalnewamplitude, i, - synth->buffersize); + synth.buffersize); outl[i] *= tmpvol * NoteGlobalPar.Panning; outr[i] *= tmpvol * (1.0f - NoteGlobalPar.Panning); } else - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { outl[i] *= globalnewamplitude * NoteGlobalPar.Panning; outr[i] *= globalnewamplitude * (1.0f - NoteGlobalPar.Panning); } @@ -397,8 +399,8 @@ int PADnote::noteout(float *outl, float *outr) // Check if the global amplitude is finished. // If it does, disable the note if(NoteGlobalPar.AmpEnvelope->finished()) { - for(int i = 0; i < synth->buffersize; ++i) { //fade-out - float tmp = 1.0f - (float)i / synth->buffersize_f; + for(int i = 0; i < synth.buffersize; ++i) { //fade-out + float tmp = 1.0f - (float)i / synth.buffersize_f; outl[i] *= tmp; outr[i] *= tmp; } diff --git a/src/Synth/SUBnote.cpp b/src/Synth/SUBnote.cpp @@ -254,11 +254,11 @@ void SUBnote::computefiltercoefs(bpfilter &filter, float bw, float gain) { - if(freq > synth->samplerate_f / 2.0f - 200.0f) - freq = synth->samplerate_f / 2.0f - 200.0f; + if(freq > synth.samplerate_f / 2.0f - 200.0f) + freq = synth.samplerate_f / 2.0f - 200.0f; - float omega = 2.0f * PI * freq / synth->samplerate_f; + float omega = 2.0f * PI * freq / synth.samplerate_f; float sn = sinf(omega); float cs = cosf(omega); float alpha = sn * sinh(LOG_2 / 2.0f * bw * omega / sn); @@ -297,11 +297,11 @@ void SUBnote::initfilter(bpfilter &filter, if(start == 1) a *= RND; filter.yn1 = a * cosf(p); - filter.yn2 = a * cosf(p + freq * 2.0f * PI / synth->samplerate_f); + filter.yn2 = a * cosf(p + freq * 2.0f * PI / synth.samplerate_f); //correct the error of computation the start amplitude //at very high frequencies - if(freq > synth->samplerate_f * 0.96f) { + if(freq > synth.samplerate_f * 0.96f) { filter.yn1 = 0.0f; filter.yn2 = 0.0f; } @@ -335,11 +335,11 @@ inline void SubFilterB(const float coeff[4], float &src, float work[4]) //in quite a bit of wasted time void SUBnote::filter(bpfilter &filter, float *smps) { - assert(synth->buffersize % 8 == 0); + assert(synth.buffersize % 8 == 0); float coeff[4] = {filter.b0, filter.b2, -filter.a1, -filter.a2}; float work[4] = {filter.xn1, filter.xn2, filter.yn1, filter.yn2}; - for(int i = 0; i < synth->buffersize; i += 8) { + for(int i = 0; i < synth.buffersize; i += 8) { SubFilterA(coeff, smps[i + 0], work); SubFilterB(coeff, smps[i + 1], work); SubFilterA(coeff, smps[i + 2], work); @@ -360,21 +360,23 @@ void SUBnote::filter(bpfilter &filter, float *smps) */ void SUBnote::initparameters(float freq) { - AmpEnvelope = memory.alloc<Envelope>(*pars.AmpEnvelope, freq); + AmpEnvelope = memory.alloc<Envelope>(*pars.AmpEnvelope, freq, synth.dt()); if(pars.PFreqEnvelopeEnabled) - FreqEnvelope = memory.alloc<Envelope>(*pars.FreqEnvelope, freq); + FreqEnvelope = memory.alloc<Envelope>(*pars.FreqEnvelope, freq, synth.dt()); else FreqEnvelope = NULL; if(pars.PBandWidthEnvelopeEnabled) - BandWidthEnvelope = memory.alloc<Envelope>(*pars.BandWidthEnvelope, freq); + BandWidthEnvelope = memory.alloc<Envelope>(*pars.BandWidthEnvelope, freq, synth.dt()); else BandWidthEnvelope = NULL; if(pars.PGlobalFilterEnabled) { globalfiltercenterq = pars.GlobalFilter->getq(); - GlobalFilterL = Filter::generate(memory, pars.GlobalFilter); + GlobalFilterL = Filter::generate(memory, pars.GlobalFilter, + synth.samplerate, synth.buffersize); if(stereo) - GlobalFilterR = Filter::generate(memory, pars.GlobalFilter); - GlobalFilterEnvelope = memory.alloc<Envelope>(*pars.GlobalFilterEnvelope, freq); + GlobalFilterR = Filter::generate(memory, pars.GlobalFilter, + synth.samplerate, synth.buffersize); + GlobalFilterEnvelope = memory.alloc<Envelope>(*pars.GlobalFilterEnvelope, freq, synth.dt()); GlobalFilterFreqTracking = pars.GlobalFilter->getfreqtracking(basefreq); } computecurrentparameters(); @@ -388,7 +390,7 @@ float SUBnote::computerolloff(float freq) const float lower_limit = 10.0f; const float lower_width = 10.0f; const float upper_width = 200.0f; - float upper_limit = synth->samplerate / 2.0f; + float upper_limit = synth.samplerate / 2.0f; if (freq > lower_limit + lower_width && freq < upper_limit - upper_width) @@ -489,23 +491,23 @@ void SUBnote::computecurrentparameters() */ int SUBnote::noteout(float *outl, float *outr) { - memcpy(outl, denormalkillbuf, synth->bufferbytes); - memcpy(outr, denormalkillbuf, synth->bufferbytes); + memcpy(outl, denormalkillbuf, synth.bufferbytes); + memcpy(outr, denormalkillbuf, synth.bufferbytes); if(NoteEnabled == OFF) return 0; - float tmprnd[synth->buffersize]; - float tmpsmp[synth->buffersize]; + float tmprnd[synth.buffersize]; + float tmpsmp[synth.buffersize]; //left channel - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < synth.buffersize; ++i) tmprnd[i] = RND * 2.0f - 1.0f; for(int n = 0; n < numharmonics; ++n) { float rolloff = overtone_rolloff[n]; - memcpy(tmpsmp, tmprnd, synth->bufferbytes); + memcpy(tmpsmp, tmprnd, synth.bufferbytes); for(int nph = 0; nph < numstages; ++nph) filter(lfilter[nph + n * numstages], tmpsmp); - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < synth.buffersize; ++i) outl[i] += tmpsmp[i] * rolloff; } @@ -514,26 +516,26 @@ int SUBnote::noteout(float *outl, float *outr) //right channel if(stereo) { - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < synth.buffersize; ++i) tmprnd[i] = RND * 2.0f - 1.0f; for(int n = 0; n < numharmonics; ++n) { float rolloff = overtone_rolloff[n]; - memcpy(tmpsmp, tmprnd, synth->bufferbytes); + memcpy(tmpsmp, tmprnd, synth.bufferbytes); for(int nph = 0; nph < numstages; ++nph) filter(rfilter[nph + n * numstages], tmpsmp); - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < synth.buffersize; ++i) outr[i] += tmpsmp[i] * rolloff; } if(GlobalFilterR != NULL) GlobalFilterR->filterout(&outr[0]); } else - memcpy(outr, outl, synth->bufferbytes); + memcpy(outr, outl, synth.bufferbytes); if(firsttick != 0) { int n = 10; - if(n > synth->buffersize) - n = synth->buffersize; + if(n > synth.buffersize) + n = synth.buffersize; for(int i = 0; i < n; ++i) { float ampfadein = 0.5f - 0.5f * cosf( (float) i / (float) n * PI); @@ -545,16 +547,16 @@ int SUBnote::noteout(float *outl, float *outr) if(ABOVE_AMPLITUDE_THRESHOLD(oldamplitude, newamplitude)) // Amplitude interpolation - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { float tmpvol = INTERPOLATE_AMPLITUDE(oldamplitude, newamplitude, i, - synth->buffersize); + synth.buffersize); outl[i] *= tmpvol * panning; outr[i] *= tmpvol * (1.0f - panning); } else - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { outl[i] *= newamplitude * panning; outr[i] *= newamplitude * (1.0f - panning); } @@ -567,8 +569,8 @@ int SUBnote::noteout(float *outl, float *outr) // Check if the note needs to be computed more if(AmpEnvelope->finished() != 0) { - for(int i = 0; i < synth->buffersize; ++i) { //fade-out - float tmp = 1.0f - (float)i / synth->buffersize_f; + for(int i = 0; i < synth.buffersize; ++i) { //fade-out + float tmp = 1.0f - (float)i / synth.buffersize_f; outl[i] *= tmp; outr[i] *= tmp; } diff --git a/src/Synth/SynthNote.cpp b/src/Synth/SynthNote.cpp @@ -3,17 +3,18 @@ #include <cstring> SynthNote::SynthNote(SynthParams &pars) - :legato(pars.frequency, pars.velocity, pars.portamento, + :legato(pars.synth, pars.frequency, pars.velocity, pars.portamento, pars.note, pars.quiet), - memory(pars.memory), ctl(pars.ctl) + memory(pars.memory), ctl(pars.ctl), synth(pars.synth) {} -SynthNote::Legato::Legato(float freq, float vel, int port, +SynthNote::Legato::Legato(const SYNTH_T &synth_, float freq, float vel, int port, int note, bool quiet) + :synth(synth_) { // Initialise some legato-specific vars msg = LM_Norm; - fade.length = (int)(synth->samplerate_f * 0.005f); // 0.005f seems ok. + fade.length = (int)(synth.samplerate_f * 0.005f); // 0.005f seems ok. if(fade.length < 1) fade.length = 1; // (if something's fishy) fade.step = (1.0f / fade.length); @@ -57,15 +58,15 @@ void SynthNote::Legato::apply(SynthNote &note, float *outl, float *outr) { if(silent) // Silencer if(msg != LM_FadeIn) { - memset(outl, 0, synth->bufferbytes); - memset(outr, 0, synth->bufferbytes); + memset(outl, 0, synth.bufferbytes); + memset(outr, 0, synth.bufferbytes); } switch(msg) { case LM_CatchUp: // Continue the catch-up... if(decounter == -10) decounter = fade.length; //Yea, could be done without the loop... - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { decounter--; if(decounter < 1) { // Catching-up done, we can finally set @@ -83,7 +84,7 @@ void SynthNote::Legato::apply(SynthNote &note, float *outl, float *outr) if(decounter == -10) decounter = fade.length; silent = false; - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { decounter--; if(decounter < 1) { decounter = -10; @@ -98,10 +99,10 @@ void SynthNote::Legato::apply(SynthNote &note, float *outl, float *outr) case LM_FadeOut: // Fade-out, then set the catch-up if(decounter == -10) decounter = fade.length; - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < synth.buffersize; ++i) { decounter--; if(decounter < 1) { - for(int j = i; j < synth->buffersize; ++j) { + for(int j = i; j < synth.buffersize; ++j) { outl[j] = 0.0f; outr[j] = 0.0f; } diff --git a/src/Synth/SynthNote.h b/src/Synth/SynthNote.h @@ -29,6 +29,7 @@ struct SynthParams { Allocator &memory; //Memory Allocator for the Note to use Controller &ctl; + const SYNTH_T &synth; float frequency; //Note base frequency float velocity; //Velocity of the Note bool portamento;//True if portamento is used for this note @@ -71,7 +72,7 @@ class SynthNote class Legato { public: - Legato(float freq, float vel, int port, + Legato(const SYNTH_T &synth_, float freq, float vel, int port, int note, bool quiet); void apply(SynthNote &note, float *outl, float *outr); @@ -91,6 +92,7 @@ class SynthNote bool portamento; int midinote; } param; + const SYNTH_T &synth; public: /* Some get routines for legatonote calls (aftertouch feature)*/ float getFreq() {return param.freq; } @@ -102,8 +104,9 @@ class SynthNote } legato; //Realtime Safe Memory Allocator For notes - class Allocator &memory; + class Allocator &memory; const Controller &ctl; + const SYNTH_T &synth; }; #endif diff --git a/src/Tests/AdNoteTest.h b/src/Tests/AdNoteTest.h @@ -75,7 +75,7 @@ class AdNoteTest:public CxxTest::TestSuite fft = new FFTwrapper(synth->oscilsize); //prepare the default settings - ADnoteParameters *defaultPreset = new ADnoteParameters(fft); + ADnoteParameters *defaultPreset = new ADnoteParameters(*synth, fft); //Assert defaults TS_ASSERT(!defaultPreset->VoicePar[1].Enabled); @@ -99,12 +99,12 @@ class AdNoteTest:public CxxTest::TestSuite - controller = new Controller(); + controller = new Controller(*synth); //lets go with.... 50! as a nice note testnote = 50; float freq = 440.0f * powf(2.0f, (testnote - 69.0f) / 12.0f); - SynthParams pars{memory, *controller, freq, 120, 0, testnote, false}; + SynthParams pars{memory, *controller, *synth, freq, 120, 0, testnote, false}; note = new ADnote(defaultPreset, pars); @@ -112,11 +112,6 @@ class AdNoteTest:public CxxTest::TestSuite delete wrap; } - void willNoteBeRunButIsHereForLinkingReasonsHowsThisForCamelCaseEh() - { - master = new Master(); - } - void tearDown() { delete note; delete controller; diff --git a/src/Tests/ControllerTest.h b/src/Tests/ControllerTest.h @@ -30,7 +30,7 @@ class ControllerTest:public CxxTest::TestSuite public: void setUp() { synth = new SYNTH_T; - testCtl = new Controller(); + testCtl = new Controller(*synth); } void tearDown() { diff --git a/src/Tests/InstrumentStats.cpp b/src/Tests/InstrumentStats.cpp @@ -65,7 +65,7 @@ void setup() { denormalkillbuf = new float[synth->buffersize]; for(int i = 0; i < synth->buffersize; ++i) denormalkillbuf[i] = 0; - p = new Part(alloc, &microtonal, &fft); + p = new Part(alloc, *synth, &microtonal, &fft); } void xml(string s) diff --git a/src/Tests/OscilGenTest.h b/src/Tests/OscilGenTest.h @@ -57,7 +57,7 @@ class OscilGenTest:public CxxTest::TestSuite //prepare the default settings fft = new FFTwrapper(synth->oscilsize); - oscil = new OscilGen(fft, NULL); + oscil = new OscilGen(*synth, fft, NULL); //Assert defaults [TODO] diff --git a/src/Tests/PadNoteTest.h b/src/Tests/PadNoteTest.h @@ -81,7 +81,7 @@ class PadNoteTest:public CxxTest::TestSuite fft = new FFTwrapper(synth->oscilsize); //prepare the default settings - pars = new PADnoteParameters(fft); + pars = new PADnoteParameters(*synth, fft); //Assert defaults @@ -109,12 +109,12 @@ class PadNoteTest:public CxxTest::TestSuite - controller = new Controller(); + controller = new Controller(*synth); //lets go with.... 50! as a nice note testnote = 50; float freq = 440.0f * powf(2.0f, (testnote - 69.0f) / 12.0f); - SynthParams pars_{memory, *controller, freq, 120, 0, testnote, false}; + SynthParams pars_{memory, *controller, *synth, freq, 120, 0, testnote, false}; note = new PADnote(pars, pars_); } diff --git a/src/Tests/PluginTest.h b/src/Tests/PluginTest.h @@ -63,7 +63,7 @@ class PluginTest:public CxxTest::TestSuite denormalkillbuf[i] = 0; for(int i = 0; i < 16; ++i) - master[i] = new Master(); + master[i] = new Master(*synth); } void tearDown() { diff --git a/src/Tests/SubNoteTest.h b/src/Tests/SubNoteTest.h @@ -82,23 +82,18 @@ class SubNoteTest:public CxxTest::TestSuite TS_ASSERT(wrap->enterbranch("SUB_SYNTH_PARAMETERS")); defaultPreset->getfromXML(wrap); - controller = new Controller(); + controller = new Controller(*synth); //lets go with.... 50! as a nice note testnote = 50; float freq = 440.0f * powf(2.0f, (testnote - 69.0f) / 12.0f); - SynthParams pars{memory, *controller, freq, 120, 0, testnote, false}; + SynthParams pars{memory, *controller, *synth, freq, 120, 0, testnote, false}; note = new SUBnote(defaultPreset, pars); delete wrap; delete defaultPreset; } - void willNoteBeRunButIsHereForLinkingReasonsHowsThisForCamelCaseEh() - { - master = new Master(); - } - void tearDown() { delete controller; delete note; diff --git a/src/Tests/UnisonTest.h b/src/Tests/UnisonTest.h @@ -70,12 +70,12 @@ class AdNoteTest:public CxxTest::TestSuite fft = new FFTwrapper(BUF); //prepare the default settings - params = new ADnoteParameters(fft); + params = new ADnoteParameters(*synth, fft); //sawtooth to make things a bit more interesting params->VoicePar[0].OscilSmp->Pcurrentbasefunc = 3; - controller = new Controller(); + controller = new Controller(*synth); //lets go with.... 50! as a nice note testnote = 50; @@ -103,7 +103,7 @@ class AdNoteTest:public CxxTest::TestSuite params->VoicePar[0].Unison_vibratto_speed = e; params->VoicePar[0].Unison_invert_phase = f; - SynthParams pars{memory, *controller, freq, 120, 0, testnote, false}; + SynthParams pars{memory, *controller, *synth, freq, 120, 0, testnote, false}; note = new ADnote(params, pars); note->noteout(outL, outR); TS_ASSERT_DELTA(outL[80], values[0], 1e-5); diff --git a/src/globals.h b/src/globals.h @@ -287,6 +287,10 @@ struct SYNTH_T { int bufferbytes; float oscilsize_f; + float dt(void) const + { + return buffersize_f / samplerate_f; + } inline void alias(void) { halfsamplerate_f = (samplerate_f = samplerate) / 2.0f; @@ -296,6 +300,4 @@ struct SYNTH_T { } static float numRandom(void); //defined in Util.cpp for now }; - -extern SYNTH_T *synth; #endif diff --git a/src/main.cpp b/src/main.cpp @@ -59,7 +59,6 @@ MiddleWare *middleware; using namespace std; Master *master; -SYNTH_T *synth; int swaplr = 0; //1 for left-right swapping int Pexitprogram = 0; //if the UI set this to 1, the program will exit @@ -92,15 +91,15 @@ void sigterm_exit(int /*sig*/) /* * Program initialisation */ -void initprogram(int prefered_port) +void initprogram(SYNTH_T synth, int prefered_port) { - middleware = new MiddleWare(prefered_port); + middleware = new MiddleWare(synth, prefered_port); master = middleware->spawnMaster(); master->swaplr = swaplr; signal(SIGINT, sigterm_exit); signal(SIGTERM, sigterm_exit); - Nio::init(master); + Nio::init(master->synth, master); } /* @@ -129,7 +128,7 @@ void exitprogram() int main(int argc, char *argv[]) { main_thread = pthread_self(); - synth = new SYNTH_T; + SYNTH_T synth; config.init(); int noui = 0; cerr @@ -145,14 +144,14 @@ int main(int argc, char *argv[]) cerr << "Try 'zynaddsubfx --help' for command-line options." << endl; /* Get the settings from the Config*/ - synth->samplerate = config.cfg.SampleRate; - synth->buffersize = config.cfg.SoundBufferSize; - synth->oscilsize = config.cfg.OscilSize; + synth.samplerate = config.cfg.SampleRate; + synth.buffersize = config.cfg.SoundBufferSize; + synth.oscilsize = config.cfg.OscilSize; swaplr = config.cfg.SwapStereo; - Nio::preferedSampleRate(synth->samplerate); + Nio::preferedSampleRate(synth.samplerate); - synth->alias(); //build aliases + synth.alias(); //build aliases sprng(time(NULL)); @@ -266,16 +265,16 @@ int main(int argc, char *argv[]) GETOP(loadinstrument); break; case 'r': - GETOPNUM(synth->samplerate); - if(synth->samplerate < 4000) { + GETOPNUM(synth.samplerate); + if(synth.samplerate < 4000) { cerr << "ERROR:Incorrect sample rate: " << optarguments << endl; exit(1); } break; case 'b': - GETOPNUM(synth->buffersize); - if(synth->buffersize < 2) { + GETOPNUM(synth.buffersize); + if(synth.buffersize < 2) { cerr << "ERROR:Incorrect buffer size: " << optarguments << endl; exit(1); @@ -283,17 +282,17 @@ int main(int argc, char *argv[]) break; case 'o': if(optarguments) - synth->oscilsize = tmp = atoi(optarguments); - if(synth->oscilsize < MAX_AD_HARMONICS * 2) - synth->oscilsize = MAX_AD_HARMONICS * 2; - synth->oscilsize = + synth.oscilsize = tmp = atoi(optarguments); + if(synth.oscilsize < MAX_AD_HARMONICS * 2) + synth.oscilsize = MAX_AD_HARMONICS * 2; + synth.oscilsize = (int) powf(2, - ceil(logf(synth->oscilsize - 1.0f) / logf(2.0f))); - if(tmp != synth->oscilsize) + ceil(logf(synth.oscilsize - 1.0f) / logf(2.0f))); + if(tmp != synth.oscilsize) cerr << - "synth->oscilsize is wrong (must be 2^n) or too small. Adjusting to " - << synth->oscilsize << "." << endl; + "synth.oscilsize is wrong (must be 2^n) or too small. Adjusting to " + << synth.oscilsize << "." << endl; break; case 'S': swaplr = 1; @@ -343,7 +342,7 @@ int main(int argc, char *argv[]) } } - synth->alias(); + synth.alias(); if(exitwithversion) { cout << "Version: " << VERSION << endl; @@ -377,11 +376,11 @@ int main(int argc, char *argv[]) } //produce denormal buf - denormalkillbuf = new float [synth->buffersize]; - for(int i = 0; i < synth->buffersize; ++i) + denormalkillbuf = new float [synth.buffersize]; + for(int i = 0; i < synth.buffersize; ++i) denormalkillbuf[i] = (RND - 0.5f) * 1e-16; - initprogram(prefered_port); + initprogram(synth, prefered_port); if(!loadfile.empty()) { int tmp = master->loadXML(loadfile.c_str()); @@ -417,11 +416,10 @@ int main(int argc, char *argv[]) cerr.precision(1); cerr << std::fixed; - cerr << "\nSample Rate = \t\t" << synth->samplerate << endl; - cerr << "Sound Buffer Size = \t" << synth->buffersize << " samples" << endl; - cerr << "Internal latency = \t" << synth->buffersize_f * 1000.0f - / synth->samplerate_f << " ms" << endl; - cerr << "ADsynth Oscil.Size = \t" << synth->oscilsize << " samples" << endl; + cerr << "\nSample Rate = \t\t" << synth.samplerate << endl; + cerr << "Sound Buffer Size = \t" << synth.buffersize << " samples" << endl; + cerr << "Internal latency = \t" << synth.dt() * 1000.0f << " ms" << endl; + cerr << "ADsynth Oscil.Size = \t" << synth.oscilsize << " samples" << endl; if(!execAfterInit.empty()) { cout << "Executing user supplied command: " << execAfterInit << endl;