@@ -144,6 +144,8 @@ extern "C" { | |||
#include "zynaddsubfx/Synth/ADnote.cpp" | |||
#include "zynaddsubfx/Synth/Envelope.cpp" | |||
#include "zynaddsubfx/Synth/LFO.cpp" | |||
#undef rChangeCb | |||
#define rChangeCb | |||
#include "zynaddsubfx/Synth/OscilGen.cpp" | |||
#undef rObject | |||
#undef PC | |||
@@ -26,7 +26,7 @@ | |||
#include "../DSP/Filter.h" | |||
#include "../Misc/Allocator.h" | |||
DynamicFilter::DynamicFilter(EffectParams pars) | |||
DynamicFilter::DynamicFilter(EffectParams pars, const AbsTime *time) | |||
:Effect(pars), | |||
lfo(pars.srate, pars.bufsize), | |||
Pvolume(110), | |||
@@ -37,7 +37,7 @@ DynamicFilter::DynamicFilter(EffectParams pars) | |||
filterl(NULL), | |||
filterr(NULL) | |||
{ | |||
filterpars = memory.alloc<FilterParams>(0,0,0); | |||
filterpars = memory.alloc<FilterParams>(0,0,0,time); | |||
setpreset(Ppreset); | |||
cleanup(); | |||
} | |||
@@ -30,7 +30,7 @@ | |||
class DynamicFilter:public Effect | |||
{ | |||
public: | |||
DynamicFilter(EffectParams pars); | |||
DynamicFilter(EffectParams pars, const AbsTime *time = nullptr); | |||
~DynamicFilter(); | |||
void out(const Stereo<float *> &smp); | |||
@@ -135,13 +135,15 @@ static const rtosc::Ports local_ports = { | |||
const rtosc::Ports &EffectMgr::ports = local_ports; | |||
EffectMgr::EffectMgr(Allocator &alloc, const SYNTH_T &synth_, const bool insertion_) | |||
EffectMgr::EffectMgr(Allocator &alloc, const SYNTH_T &synth_, | |||
const bool insertion_, const AbsTime *time_) | |||
:insertion(insertion_), | |||
efxoutl(new float[synth_.buffersize]), | |||
efxoutr(new float[synth_.buffersize]), | |||
filterpars(NULL), | |||
nefx(0), | |||
efx(NULL), | |||
time(time_), | |||
dryonly(false), | |||
memory(alloc), | |||
synth(synth_) | |||
@@ -203,7 +205,7 @@ void EffectMgr::changeeffectrt(int _nefx, bool avoidSmash) | |||
efx = memory.alloc<EQ>(pars); | |||
break; | |||
case 8: | |||
efx = memory.alloc<DynamicFilter>(pars); | |||
efx = memory.alloc<DynamicFilter>(pars, time); | |||
break; | |||
//put more effect here | |||
default: | |||
@@ -36,7 +36,8 @@ class Allocator; | |||
class EffectMgr:public Presets | |||
{ | |||
public: | |||
EffectMgr(Allocator &alloc, const SYNTH_T &synth, const bool insertion_); | |||
EffectMgr(Allocator &alloc, const SYNTH_T &synth, const bool insertion_, | |||
const AbsTime *time_ = nullptr); | |||
~EffectMgr(); | |||
void paste(EffectMgr &e); | |||
@@ -77,6 +78,7 @@ class EffectMgr:public Presets | |||
static const rtosc::Ports &ports; | |||
int nefx; | |||
Effect *efx; | |||
const AbsTime *time; | |||
private: | |||
//Parameters Prior to initialization | |||
@@ -33,7 +33,7 @@ struct AllocatorImpl | |||
unsigned long long totalAlloced = 0; | |||
}; | |||
Allocator::Allocator(void) | |||
Allocator::Allocator(void) : transaction_active() | |||
{ | |||
impl = new AllocatorImpl; | |||
size_t default_size = 10*1024*1024; | |||
@@ -124,6 +124,19 @@ typedef struct block_header_t | |||
static const size_t block_header_free_bit = 1 << 0; | |||
#endif | |||
void Allocator::beginTransaction() { | |||
// TODO: log about unsupported nested transaction when a RT compliant | |||
// logging is available and transaction_active == true | |||
transaction_active = true; | |||
transaction_alloc_index = 0; | |||
} | |||
void Allocator::endTransaction() { | |||
// TODO: log about invalid end of transaction when a RT copmliant logging | |||
// is available and transaction_active == false | |||
transaction_active = false; | |||
} | |||
bool Allocator::memFree(void *pool) const | |||
{ | |||
size_t bh_shift = sizeof(next_t)+sizeof(size_t); | |||
@@ -174,6 +187,22 @@ unsigned long long Allocator::totalAlloced() const | |||
return impl->totalAlloced; | |||
} | |||
void Allocator::rollbackTransaction() { | |||
// if a transaction is active | |||
if (transaction_active) { | |||
// deallocate all allocated memory within this transaction | |||
for (size_t temp_idx = 0; | |||
temp_idx < transaction_alloc_index; ++temp_idx) { | |||
dealloc_mem(transaction_alloc_content[temp_idx]); | |||
} | |||
} | |||
transaction_active = false; | |||
} | |||
/* | |||
* Notes on tlsf internals | |||
* - TLSF consists of blocks linked by block headers and these form a doubly | |||
@@ -16,7 +16,8 @@ class Allocator | |||
virtual void dealloc_mem(void *memory) = 0; | |||
/** | |||
* High level allocator method, which return a pointer to a class or struct | |||
* High level allocator method, which return a pointer to a class | |||
* or struct | |||
* allocated with the specialized subclass strategy | |||
* @param ts argument(s) for the constructor of the type T | |||
* @return a non null pointer to a new object of type T | |||
@@ -26,13 +27,17 @@ class Allocator | |||
T *alloc(Ts&&... ts) | |||
{ | |||
void *data = alloc_mem(sizeof(T)); | |||
if(!data) | |||
if(!data) { | |||
rollbackTransaction(); | |||
throw std::bad_alloc(); | |||
} | |||
append_alloc_to_memory_transaction(data); | |||
return new (data) T(std::forward<Ts>(ts)...); | |||
} | |||
/** | |||
* High level allocator method, which return a pointer to an array of class or struct | |||
* High level allocator method, which return a pointer to an array of | |||
* class or struct | |||
* allocated with the specialized subclass strategy | |||
* @param len the array length | |||
* @param ts argument(s) for the constructor of the type T | |||
@@ -43,8 +48,11 @@ class Allocator | |||
T *valloc(size_t len, Ts&&... ts) | |||
{ | |||
T *data = (T*)alloc_mem(len*sizeof(T)); | |||
if(!data) | |||
if(!data) { | |||
rollbackTransaction(); | |||
throw std::bad_alloc(); | |||
} | |||
append_alloc_to_memory_transaction(data); | |||
for(unsigned i=0; i<len; ++i) | |||
new ((void*)&data[i]) T(std::forward<Ts>(ts)...); | |||
@@ -83,6 +91,9 @@ class Allocator | |||
} | |||
} | |||
void beginTransaction(); | |||
void endTransaction(); | |||
virtual void addMemory(void *, size_t mem_size) = 0; | |||
//Return true if the current pool cannot allocate n chunks of chunk_size | |||
@@ -97,6 +108,31 @@ class Allocator | |||
unsigned long long totalAlloced() const; | |||
struct AllocatorImpl *impl; | |||
private: | |||
const static size_t max_transaction_length = 256; | |||
void* transaction_alloc_content[max_transaction_length]; | |||
size_t transaction_alloc_index; | |||
bool transaction_active; | |||
void rollbackTransaction(); | |||
/** | |||
* Append memory block to the list of memory blocks allocated during this | |||
* transaction | |||
* @param new_memory pointer to the memory pointer to freshly allocated | |||
*/ | |||
void append_alloc_to_memory_transaction(void *new_memory) { | |||
if (transaction_active) { | |||
if (transaction_alloc_index < max_transaction_length) { | |||
transaction_alloc_content[transaction_alloc_index++] = new_memory; | |||
} | |||
// TODO add log about transaction too long and memory transaction | |||
// safety net being disabled | |||
} | |||
} | |||
}; | |||
//! the allocator for normal use | |||
@@ -301,10 +301,10 @@ vuData::vuData(void) | |||
{} | |||
Master::Master(const SYNTH_T &synth_, Config* config) | |||
:HDDRecorder(synth_), ctl(synth_), | |||
:HDDRecorder(synth_), time(synth_), ctl(synth_, &time), | |||
microtonal(config->cfg.GzipCompression), bank(config), | |||
frozenState(false), pendingMemory(false), | |||
synth(synth_), time(synth), gzip_compression(config->cfg.GzipCompression) | |||
synth(synth_), gzip_compression(config->cfg.GzipCompression) | |||
{ | |||
bToU = NULL; | |||
uToB = NULL; | |||
@@ -335,11 +335,11 @@ Master::Master(const SYNTH_T &synth_, Config* config) | |||
//Insertion Effects init | |||
for(int nefx = 0; nefx < NUM_INS_EFX; ++nefx) | |||
insefx[nefx] = new EffectMgr(*memory, synth, 1); | |||
insefx[nefx] = new EffectMgr(*memory, synth, 1, &time); | |||
//System Effects init | |||
for(int nefx = 0; nefx < NUM_SYS_EFX; ++nefx) | |||
sysefx[nefx] = new EffectMgr(*memory, synth, 0); | |||
sysefx[nefx] = new EffectMgr(*memory, synth, 0, &time); | |||
defaults(); | |||
@@ -149,6 +149,7 @@ class Master | |||
float vuoutpeakpart[NUM_MIDI_PARTS]; | |||
unsigned char fakepeakpart[NUM_MIDI_PARTS]; //this is used to compute the "peak" when the part is disabled | |||
AbsTime time; | |||
Controller ctl; | |||
bool swaplr; //if L and R are swapped | |||
@@ -174,7 +175,6 @@ class Master | |||
rtosc::ThreadLink *uToB; | |||
bool pendingMemory; | |||
const SYNTH_T &synth; | |||
AbsTime time; | |||
const int& gzip_compression; //!< value from config | |||
private: | |||
float sysefxvol[NUM_SYS_EFX][NUM_MIDI_PARTS]; | |||
@@ -1338,15 +1338,17 @@ 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(synth, master->fft); | |||
ptr = kits.add[part][kit] = new ADnoteParameters(synth, master->fft, | |||
&master->time); | |||
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(synth, master->fft); | |||
ptr = kits.pad[part][kit] = new PADnoteParameters(synth, master->fft, | |||
&master->time); | |||
url += "padpars-data"; | |||
obj_store.extractPAD(kits.pad[part][kit], part, kit); | |||
} else if(type == 2 && kits.sub[part][kit] == NULL) { | |||
ptr = kits.sub[part][kit] = new SUBnoteParameters(); | |||
ptr = kits.sub[part][kit] = new SUBnoteParameters(&master->time); | |||
url += "subpars-data"; | |||
} | |||
@@ -210,7 +210,7 @@ Part::Part(Allocator &alloc, const SYNTH_T &synth_, const AbsTime &time_, | |||
Plegatomode(false), | |||
partoutl(new float[synth_.buffersize]), | |||
partoutr(new float[synth_.buffersize]), | |||
ctl(synth_), | |||
ctl(synth_, &time_), | |||
microtonal(microtonal_), | |||
fft(fft_), | |||
memory(alloc), | |||
@@ -229,11 +229,11 @@ Part::Part(Allocator &alloc, const SYNTH_T &synth_, const AbsTime &time_, | |||
kit[n].padpars = nullptr; | |||
} | |||
kit[0].adpars = new ADnoteParameters(synth, fft); | |||
kit[0].adpars = new ADnoteParameters(synth, fft, &time); | |||
//Part's Insertion Effects init | |||
for(int nefx = 0; nefx < NUM_PART_EFX; ++nefx) { | |||
partefx[nefx] = new EffectMgr(memory, synth, 1); | |||
partefx[nefx] = new EffectMgr(memory, synth, 1, &time); | |||
Pefxbypass[nefx] = false; | |||
} | |||
assert(partefx[0]); | |||
@@ -847,9 +847,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(synth, fft); | |||
kkit.subpars = new SUBnoteParameters(); | |||
kkit.padpars = new PADnoteParameters(synth, fft); | |||
kkit.adpars = new ADnoteParameters(synth, fft, &time); | |||
kkit.subpars = new SUBnoteParameters(&time); | |||
kkit.padpars = new PADnoteParameters(synth, fft, &time); | |||
} | |||
} | |||
@@ -1082,7 +1082,7 @@ void Part::getfromXMLinstrument(XMLwrapper& xml) | |||
kit[i].Padenabled); | |||
if(xml.enterbranch("ADD_SYNTH_PARAMETERS")) { | |||
if(!kit[i].adpars) | |||
kit[i].adpars = new ADnoteParameters(synth, fft); | |||
kit[i].adpars = new ADnoteParameters(synth, fft, &time); | |||
kit[i].adpars->getfromXML(xml); | |||
xml.exitbranch(); | |||
} | |||
@@ -1091,7 +1091,7 @@ void Part::getfromXMLinstrument(XMLwrapper& xml) | |||
kit[i].Psubenabled); | |||
if(xml.enterbranch("SUB_SYNTH_PARAMETERS")) { | |||
if(!kit[i].subpars) | |||
kit[i].subpars = new SUBnoteParameters(); | |||
kit[i].subpars = new SUBnoteParameters(&time); | |||
kit[i].subpars->getfromXML(xml); | |||
xml.exitbranch(); | |||
} | |||
@@ -1100,7 +1100,7 @@ void Part::getfromXMLinstrument(XMLwrapper& xml) | |||
kit[i].Ppadenabled); | |||
if(xml.enterbranch("PAD_SYNTH_PARAMETERS")) { | |||
if(!kit[i].padpars) | |||
kit[i].padpars = new PADnoteParameters(synth, fft); | |||
kit[i].padpars = new PADnoteParameters(synth, fft, &time); | |||
kit[i].padpars->getfromXML(xml); | |||
xml.exitbranch(); | |||
} | |||
@@ -41,6 +41,8 @@ using rtosc::RtData; | |||
#define EXPAND(x) x | |||
#define rObject ADnoteVoiceParam | |||
#undef rChangeCb | |||
#define rChangeCb if (obj->time) { obj->last_update_timestamp = obj->time->time(); } | |||
static const Ports voicePorts = { | |||
//Send Messages To Oscillator Realtime Table | |||
{"OscilSmp/", rDoc("Primary Oscillator"), | |||
@@ -221,10 +223,12 @@ static const Ports voicePorts = { | |||
d.reply(d.loc, "f", obj->getUnisonFrequencySpreadCents()); | |||
}}, | |||
}; | |||
#undef rChangeCb | |||
#undef rObject | |||
#define rObject ADnoteGlobalParam | |||
#define rChangeCb if (obj->time) { obj->last_update_timestamp = obj->time->time(); } | |||
static const Ports globalPorts = { | |||
rRecurp(Reson, "Resonance"), | |||
rRecurp(FreqLfo, "Frequency LFO"), | |||
@@ -298,9 +302,12 @@ static const Ports globalPorts = { | |||
}}, | |||
}; | |||
#undef rChangeCb | |||
#undef rObject | |||
#define rObject ADnoteParameters | |||
#define rChangeCb obj->last_update_timestamp = obj->time.time(); | |||
static const Ports adPorts = {//XXX 16 should not be hard coded | |||
rSelf(ADnoteParameters), | |||
rPaste, | |||
@@ -308,13 +315,14 @@ static const Ports adPorts = {//XXX 16 should not be hard coded | |||
rRecurs(VoicePar, NUM_VOICES), | |||
rRecur(GlobalPar, "Adnote Parameters"), | |||
}; | |||
#undef rChangeCb | |||
const Ports &ADnoteParameters::ports = adPorts; | |||
const Ports &ADnoteVoiceParam::ports = voicePorts; | |||
const Ports &ADnoteGlobalParam::ports = globalPorts; | |||
ADnoteParameters::ADnoteParameters(const SYNTH_T &synth, FFTwrapper *fft_) | |||
:PresetsArray() | |||
ADnoteParameters::ADnoteParameters(const SYNTH_T &synth, FFTwrapper *fft_, | |||
const AbsTime *time_) | |||
:PresetsArray(), GlobalPar(time_), time(time_), last_update_timestamp(0) | |||
{ | |||
setpresettype("Padsynth"); | |||
fft = fft_; | |||
@@ -322,26 +330,28 @@ ADnoteParameters::ADnoteParameters(const SYNTH_T &synth, FFTwrapper *fft_) | |||
for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice) { | |||
VoicePar[nvoice].GlobalPDetuneType = &GlobalPar.PDetuneType; | |||
EnableVoice(synth, nvoice); | |||
VoicePar[nvoice].time = time_; | |||
EnableVoice(synth, nvoice, time_); | |||
} | |||
defaults(); | |||
} | |||
ADnoteGlobalParam::ADnoteGlobalParam() | |||
ADnoteGlobalParam::ADnoteGlobalParam(const AbsTime *time_) : | |||
time(time_), last_update_timestamp(0) | |||
{ | |||
FreqEnvelope = new EnvelopeParams(0, 0); | |||
FreqEnvelope = new EnvelopeParams(0, 0, time_); | |||
FreqEnvelope->ASRinit(64, 50, 64, 60); | |||
FreqLfo = new LFOParams(70, 0, 64, 0, 0, 0, 0, 0); | |||
FreqLfo = new LFOParams(70, 0, 64, 0, 0, 0, 0, 0, time_); | |||
AmpEnvelope = new EnvelopeParams(64, 1); | |||
AmpEnvelope = new EnvelopeParams(64, 1, time_); | |||
AmpEnvelope->ADSRinit_dB(0, 40, 127, 25); | |||
AmpLfo = new LFOParams(80, 0, 64, 0, 0, 0, 0, 1); | |||
AmpLfo = new LFOParams(80, 0, 64, 0, 0, 0, 0, 1, time_); | |||
GlobalFilter = new FilterParams(2, 94, 40); | |||
FilterEnvelope = new EnvelopeParams(0, 1); | |||
GlobalFilter = new FilterParams(2, 94, 40, time_); | |||
FilterEnvelope = new EnvelopeParams(0, 1, time_); | |||
FilterEnvelope->ADSRinit_filter(64, 40, 64, 70, 60, 64); | |||
FilterLfo = new LFOParams(80, 0, 64, 0, 0, 0, 0, 2); | |||
FilterLfo = new LFOParams(80, 0, 64, 0, 0, 0, 0, 2, time_); | |||
Reson = new Resonance(); | |||
} | |||
@@ -474,32 +484,34 @@ void ADnoteVoiceParam::defaults() | |||
/* | |||
* Init the voice parameters | |||
*/ | |||
void ADnoteParameters::EnableVoice(const SYNTH_T &synth, int nvoice) | |||
void ADnoteParameters::EnableVoice(const SYNTH_T &synth, int nvoice, | |||
const AbsTime *time) | |||
{ | |||
VoicePar[nvoice].enable(synth, fft, GlobalPar.Reson); | |||
VoicePar[nvoice].enable(synth, fft, GlobalPar.Reson, time); | |||
} | |||
void ADnoteVoiceParam::enable(const SYNTH_T &synth, FFTwrapper *fft, Resonance *Reson) | |||
void ADnoteVoiceParam::enable(const SYNTH_T &synth, FFTwrapper *fft, | |||
Resonance *Reson, const AbsTime *time) | |||
{ | |||
OscilSmp = new OscilGen(synth, fft, Reson); | |||
FMSmp = new OscilGen(synth, fft, NULL); | |||
AmpEnvelope = new EnvelopeParams(64, 1); | |||
AmpEnvelope = new EnvelopeParams(64, 1, time); | |||
AmpEnvelope->ADSRinit_dB(0, 100, 127, 100); | |||
AmpLfo = new LFOParams(90, 32, 64, 0, 0, 30, 0, 1); | |||
AmpLfo = new LFOParams(90, 32, 64, 0, 0, 30, 0, 1, time); | |||
FreqEnvelope = new EnvelopeParams(0, 0); | |||
FreqEnvelope = new EnvelopeParams(0, 0, time); | |||
FreqEnvelope->ASRinit(30, 40, 64, 60); | |||
FreqLfo = new LFOParams(50, 40, 0, 0, 0, 0, 0, 0); | |||
FreqLfo = new LFOParams(50, 40, 0, 0, 0, 0, 0, 0, time); | |||
VoiceFilter = new FilterParams(2, 50, 60); | |||
FilterEnvelope = new EnvelopeParams(0, 0); | |||
VoiceFilter = new FilterParams(2, 50, 60, time); | |||
FilterEnvelope = new EnvelopeParams(0, 0, time); | |||
FilterEnvelope->ADSRinit_filter(90, 70, 40, 70, 10, 40); | |||
FilterLfo = new LFOParams(50, 20, 64, 0, 0, 0, 0, 2); | |||
FilterLfo = new LFOParams(50, 20, 64, 0, 0, 0, 0, 2, time); | |||
FMFreqEnvelope = new EnvelopeParams(0, 0); | |||
FMFreqEnvelope = new EnvelopeParams(0, 0, time); | |||
FMFreqEnvelope->ASRinit(20, 90, 40, 80); | |||
FMAmpEnvelope = new EnvelopeParams(64, 1); | |||
FMAmpEnvelope = new EnvelopeParams(64, 1, time); | |||
FMAmpEnvelope->ADSRinit(80, 90, 127, 100); | |||
} | |||
@@ -919,6 +931,10 @@ void ADnoteParameters::paste(ADnoteParameters &a) | |||
this->GlobalPar.paste(a.GlobalPar); | |||
for(int i=0; i<NUM_VOICES; ++i) | |||
this->VoicePar[i].paste(a.VoicePar[i]); | |||
if ( time ) { | |||
last_update_timestamp = time->time(); | |||
} | |||
} | |||
void ADnoteParameters::pasteArray(ADnoteParameters &a, int nvoice) | |||
@@ -927,6 +943,10 @@ void ADnoteParameters::pasteArray(ADnoteParameters &a, int nvoice) | |||
return; | |||
VoicePar[nvoice].paste(a.VoicePar[nvoice]); | |||
if ( time ) { | |||
last_update_timestamp = time->time(); | |||
} | |||
} | |||
#define copy(x) this->x = a.x | |||
@@ -1015,6 +1035,10 @@ void ADnoteVoiceParam::paste(ADnoteVoiceParam &a) | |||
RCopy(FMFreqEnvelope); | |||
RCopy(FMSmp); | |||
if ( time ) { | |||
last_update_timestamp = time->time(); | |||
} | |||
} | |||
void ADnoteGlobalParam::paste(ADnoteGlobalParam &a) | |||
@@ -1050,6 +1074,10 @@ void ADnoteGlobalParam::paste(ADnoteGlobalParam &a) | |||
RCopy(FilterEnvelope); | |||
RCopy(FilterLfo); | |||
RCopy(Reson); | |||
if ( time ) { | |||
last_update_timestamp = time->time(); | |||
} | |||
} | |||
#undef copy | |||
#undef RCopy | |||
@@ -35,7 +35,7 @@ enum FMTYPE { | |||
/*****************************************************************/ | |||
struct ADnoteGlobalParam { | |||
ADnoteGlobalParam(); | |||
ADnoteGlobalParam(const AbsTime* time_ = nullptr); | |||
~ADnoteGlobalParam(); | |||
void defaults(); | |||
void add2XML(XMLwrapper& xml); | |||
@@ -106,6 +106,9 @@ struct ADnoteGlobalParam { | |||
//how the randomness is applied to the harmonics on more voices using the same oscillator | |||
unsigned char Hrandgrouping; | |||
const AbsTime *time; | |||
int64_t last_update_timestamp; | |||
static const rtosc::Ports &ports; | |||
}; | |||
@@ -115,11 +118,13 @@ struct ADnoteGlobalParam { | |||
/* VOICE PARAMETERS */ | |||
/***********************************************************/ | |||
struct ADnoteVoiceParam { | |||
ADnoteVoiceParam() : time(nullptr), last_update_timestamp(0) { }; | |||
void getfromXML(XMLwrapper& xml, unsigned nvoice); | |||
void add2XML(XMLwrapper& xml, bool fmoscilused); | |||
void paste(ADnoteVoiceParam &p); | |||
void defaults(void); | |||
void enable(const SYNTH_T &synth, FFTwrapper *fft, Resonance *Reson); | |||
void enable(const SYNTH_T &synth, FFTwrapper *fft, Resonance *Reson, | |||
const AbsTime *time); | |||
void kill(void); | |||
float getUnisonFrequencySpreadCents(void) const; | |||
/** If the voice is enabled */ | |||
@@ -302,13 +307,17 @@ struct ADnoteVoiceParam { | |||
unsigned char *GlobalPDetuneType; | |||
const AbsTime *time; | |||
int64_t last_update_timestamp; | |||
static const rtosc::Ports &ports; | |||
}; | |||
class ADnoteParameters:public PresetsArray | |||
{ | |||
public: | |||
ADnoteParameters(const SYNTH_T &synth, FFTwrapper *fft_); | |||
ADnoteParameters(const SYNTH_T &synth, FFTwrapper *fft_, | |||
const AbsTime *time_ = nullptr); | |||
~ADnoteParameters(); | |||
ADnoteGlobalParam GlobalPar; | |||
@@ -330,9 +339,12 @@ class ADnoteParameters:public PresetsArray | |||
void getfromXMLsection(XMLwrapper& xml, int n); | |||
private: | |||
void EnableVoice(const SYNTH_T &synth, int nvoice); | |||
void EnableVoice(const SYNTH_T &synth, int nvoice, const AbsTime* time); | |||
void KillVoice(int nvoice); | |||
FFTwrapper *fft; | |||
const AbsTime *time; | |||
int64_t last_update_timestamp; | |||
}; | |||
#endif |
@@ -22,6 +22,7 @@ | |||
#include "Controller.h" | |||
#include "../Misc/Util.h" | |||
#include "../Misc/Time.h" | |||
#include "../Misc/XMLwrapper.h" | |||
#include <cmath> | |||
#include <cstdio> | |||
@@ -31,6 +32,9 @@ | |||
using namespace rtosc; | |||
#define rObject Controller | |||
#undef rChangeCb | |||
#define rChangeCb if (obj->time) { obj->last_update_timestamp = obj->time->time(); } | |||
const rtosc::Ports Controller::ports = { | |||
rParamZyn(panning.depth, "Depth of Panning MIDI Control"), | |||
rParamZyn(filtercutoff.depth, "Depth of Filter Cutoff MIDI Control"), | |||
@@ -60,10 +64,10 @@ const rtosc::Ports Controller::ports = { | |||
rToggle(NRPN.receive, "NRPN MIDI Enable"), | |||
rAction(defaults), | |||
}; | |||
#undef rChangeCb | |||
Controller::Controller(const SYNTH_T &synth_) | |||
:synth(synth_) | |||
Controller::Controller(const SYNTH_T &synth_, const AbsTime *time_) | |||
:time(time_), last_update_timestamp(0), synth(synth_) | |||
{ | |||
defaults(); | |||
resetall(); | |||
@@ -24,13 +24,14 @@ | |||
#ifndef CONTROLLER_H | |||
#define CONTROLLER_H | |||
#include <stdint.h> | |||
#include "../globals.h" | |||
/**(Midi) Controllers implementation*/ | |||
class Controller | |||
{ | |||
public: | |||
Controller(const SYNTH_T &synth); | |||
Controller(const SYNTH_T &synth, const AbsTime *time = nullptr); | |||
Controller&operator=(const Controller &c); | |||
~Controller(); | |||
void resetall(); | |||
@@ -215,6 +216,10 @@ class Controller | |||
unsigned char receive; //this is saved to disk by Master | |||
} NRPN; | |||
const AbsTime *time; | |||
int64_t last_update_timestamp; | |||
static const rtosc::Ports ports; | |||
private: | |||
const SYNTH_T &synth; | |||
@@ -28,6 +28,7 @@ | |||
#include "EnvelopeParams.h" | |||
#include "../Misc/Util.h" | |||
#include "../Misc/Time.h" | |||
#define rObject EnvelopeParams | |||
using namespace rtosc; | |||
@@ -36,10 +37,11 @@ static const rtosc::Ports localPorts = { | |||
rSelf(EnvelopeParams), | |||
rPaste, | |||
#undef rChangeCb | |||
#define rChangeCb if(!obj->Pfreemode) obj->converttofree(); | |||
#define rChangeCb if(!obj->Pfreemode) obj->converttofree(); if (obj->time) { \ | |||
obj->last_update_timestamp = obj->time->time(); } | |||
rToggle(Pfreemode, "Complex Envelope Definitions"), | |||
#undef rChangeCb | |||
#define rChangeCb | |||
#define rChangeCb if (obj->time) { obj->last_update_timestamp = obj->time->time(); } | |||
rParamZyn(Penvpoints, rProp(internal), "Number of points in complex definition"), | |||
rParamZyn(Penvsustain, rProp(internal), "Location of the sustain point"), | |||
rParams(Penvdt, MAX_ENVELOPE_POINTS, "Envelope Delay Times"), | |||
@@ -94,11 +96,14 @@ static const rtosc::Ports localPorts = { | |||
}}, | |||
}; | |||
#undef rChangeCb | |||
const rtosc::Ports &EnvelopeParams::ports = localPorts; | |||
EnvelopeParams::EnvelopeParams(unsigned char Penvstretch_, | |||
unsigned char Pforcedrelease_) | |||
unsigned char Pforcedrelease_, | |||
const AbsTime *time_): | |||
time(time_), last_update_timestamp(0) | |||
{ | |||
PA_dt = 10; | |||
PD_dt = 10; | |||
@@ -149,6 +154,10 @@ void EnvelopeParams::paste(const EnvelopeParams &ep) | |||
COPY(PD_val); | |||
COPY(PS_val); | |||
COPY(PR_val); | |||
if ( time ) { | |||
last_update_timestamp = time->time(); | |||
} | |||
} | |||
#undef COPY | |||
@@ -31,7 +31,8 @@ class EnvelopeParams:public Presets | |||
{ | |||
public: | |||
EnvelopeParams(unsigned char Penvstretch_=64, | |||
unsigned char Pforcedrelease_=0); | |||
unsigned char Pforcedrelease_=0, | |||
const AbsTime *time_ = nullptr); | |||
~EnvelopeParams(); | |||
void paste(const EnvelopeParams &ep); | |||
void ADSRinit(char A_dt, char D_dt, char S_val, char R_dt); | |||
@@ -74,6 +75,9 @@ class EnvelopeParams:public Presets | |||
// 4 for ADSR_filter parameters (filter parameters) | |||
// 5 for ASR_bw parameters (bandwidth parameters) | |||
const AbsTime *time; | |||
int64_t last_update_timestamp; | |||
static const rtosc::Ports &ports; | |||
private: | |||
void store2defaults(); | |||
@@ -22,6 +22,7 @@ | |||
#include "FilterParams.h" | |||
#include "../Misc/Util.h" | |||
#include "../Misc/Time.h" | |||
#include <cmath> | |||
#include <cstdio> | |||
#include <cstdlib> | |||
@@ -36,11 +37,15 @@ using namespace rtosc; | |||
constexpr int sizeof_pvowels = sizeof(FilterParams::Pvowels); | |||
#define rObject FilterParams::Pvowels_t::formants_t | |||
#undef rChangeCb | |||
#define rChangeCb if (obj->time) { obj->last_update_timestamp = obj->time->time(); } | |||
static const rtosc::Ports subsubports = { | |||
rParamZyn(freq, "Formant frequency"), | |||
rParamZyn(amp, "Strength of formant"), | |||
rParamZyn(q, "Quality Factor"), | |||
}; | |||
#undef rChangeCb | |||
#undef rObject | |||
static const rtosc::Ports subports = { | |||
@@ -54,12 +59,14 @@ static const rtosc::Ports subports = { | |||
FilterParams::Pvowels_t *obj = (FilterParams::Pvowels_t *) d.obj; | |||
d.obj = (void*) &obj->formants[idx]; | |||
subsubports.dispatch(msg, d); | |||
if (obj->time) { obj->last_update_timestamp = obj->time->time(); } | |||
}}, | |||
}; | |||
#define rObject FilterParams | |||
#undef rChangeCb | |||
#define rChangeCb obj->changed = true; | |||
#define rChangeCb obj->changed = true; if ( obj->time) { \ | |||
obj->last_update_timestamp = obj->time->time(); } | |||
const rtosc::Ports FilterParams::ports = { | |||
rSelf(FilterParams), | |||
rPaste, | |||
@@ -127,13 +134,15 @@ const rtosc::Ports FilterParams::ports = { | |||
FilterParams::FilterParams() | |||
:FilterParams(0,64,64) | |||
FilterParams::FilterParams(const AbsTime *time_) | |||
:FilterParams(0,64,64, time_) | |||
{ | |||
} | |||
FilterParams::FilterParams(unsigned char Ptype_, | |||
unsigned char Pfreq_, | |||
unsigned char Pq_) | |||
unsigned char Pq_, | |||
const AbsTime *time_): | |||
time(time_), last_update_timestamp(0) | |||
{ | |||
setpresettype("Pfilter"); | |||
Dtype = Ptype_; | |||
@@ -179,10 +188,14 @@ void FilterParams::defaults() | |||
void FilterParams::defaults(int n) | |||
{ | |||
int j = n; | |||
Pvowels[j].time = time; | |||
for(int i = 0; i < FF_MAX_FORMANTS; ++i) { | |||
Pvowels[j].formants[i].freq = (int)(RND * 127.0f); //some random freqs | |||
Pvowels[j].formants[i].q = 64; | |||
Pvowels[j].formants[i].amp = 127; | |||
Pvowels[j].formants[i].time = time; | |||
} | |||
} | |||
@@ -455,6 +468,10 @@ void FilterParams::paste(FilterParams &x) | |||
this->Psequence[i] = x.Psequence[i]; | |||
COPY(changed); | |||
if ( time ) { | |||
last_update_timestamp = time->time(); | |||
} | |||
} | |||
#undef COPY | |||
@@ -468,4 +485,8 @@ void FilterParams::pasteArray(FilterParams &x, int nvowel) | |||
self.amp = update.amp; | |||
self.q = update.q; | |||
} | |||
if ( time ) { | |||
last_update_timestamp = time->time(); | |||
} | |||
} |
@@ -30,10 +30,11 @@ | |||
class FilterParams:public PresetsArray | |||
{ | |||
public: | |||
FilterParams(); | |||
FilterParams(const AbsTime *time_ = nullptr); | |||
FilterParams(unsigned char Ptype_, | |||
unsigned char Pfreq, | |||
unsigned char Pq_); | |||
unsigned char Pq_, | |||
const AbsTime *time_ = nullptr); | |||
~FilterParams(); | |||
void add2XML(XMLwrapper& xml); | |||
@@ -67,9 +68,17 @@ class FilterParams:public PresetsArray | |||
unsigned char Pcenterfreq, Poctavesfreq; //the center frequency of the res. func., and the number of octaves | |||
struct Pvowels_t { | |||
Pvowels_t() : last_update_timestamp(0) {} | |||
struct formants_t { | |||
formants_t() : last_update_timestamp(0) {} | |||
unsigned char freq, amp, q; //frequency,amplitude,Q | |||
const AbsTime *time; | |||
int64_t last_update_timestamp; | |||
} formants[FF_MAX_FORMANTS]; | |||
const AbsTime *time; | |||
int64_t last_update_timestamp; | |||
} Pvowels[FF_MAX_VOWELS]; | |||
@@ -94,6 +103,9 @@ class FilterParams:public PresetsArray | |||
bool changed; | |||
const AbsTime *time; | |||
int64_t last_update_timestamp; | |||
static const rtosc::Ports ports; | |||
private: | |||
@@ -33,6 +33,8 @@ using namespace rtosc; | |||
#define rObject LFOParams | |||
#undef rChangeCb | |||
#define rChangeCb if (obj->time) { obj->last_update_timestamp = obj->time->time(); } | |||
static const rtosc::Ports _ports = { | |||
rSelf(LFOParams), | |||
rPaste, | |||
@@ -50,10 +52,11 @@ static const rtosc::Ports _ports = { | |||
rToggle(Pcontinous, "Enable for global operation"), | |||
rParamZyn(Pstretch, rCentered, "Note frequency stretch"), | |||
}; | |||
#undef rChangeCb | |||
const rtosc::Ports &LFOParams::ports = _ports; | |||
LFOParams::LFOParams() | |||
LFOParams::LFOParams(const AbsTime *time_) : time(time_) | |||
{ | |||
Dfreq = 64; | |||
Dintensity = 0; | |||
@@ -74,8 +77,9 @@ LFOParams::LFOParams(char Pfreq_, | |||
char Prandomness_, | |||
char Pdelay_, | |||
char Pcontinous_, | |||
char fel_) | |||
{ | |||
char fel_, | |||
const AbsTime *time_) : time(time_), | |||
last_update_timestamp(0) { | |||
switch(fel_) { | |||
case 0: | |||
setpresettype("Plfofrequency"); | |||
@@ -154,5 +158,9 @@ void LFOParams::paste(LFOParams &x) | |||
COPY(Pdelay); | |||
COPY(Pcontinous); | |||
COPY(Pstretch); | |||
if ( time ) { | |||
last_update_timestamp = time->time(); | |||
} | |||
} | |||
#undef COPY |
@@ -23,6 +23,7 @@ | |||
#ifndef LFO_PARAMS_H | |||
#define LFO_PARAMS_H | |||
#include <Misc/Time.h> | |||
#include <rtosc/ports.h> | |||
#include "Presets.h" | |||
@@ -40,7 +41,7 @@ class XMLwrapper; | |||
class LFOParams:public Presets | |||
{ | |||
public: | |||
LFOParams(); | |||
LFOParams(const AbsTime* time_ = nullptr); | |||
LFOParams(char Pfreq_, | |||
char Pintensity_, | |||
char Pstartphase_, | |||
@@ -48,7 +49,8 @@ class LFOParams:public Presets | |||
char Prandomness_, | |||
char Pdelay_, | |||
char Pcontinous, | |||
char fel_); | |||
char fel_, | |||
const AbsTime* time_ = nullptr); | |||
~LFOParams(); | |||
void add2XML(XMLwrapper& xml); | |||
@@ -70,6 +72,9 @@ class LFOParams:public Presets | |||
int fel; //what kind is the LFO (0 - frequency, 1 - amplitude, 2 - filter) | |||
const AbsTime *time; | |||
int64_t last_update_timestamp; | |||
static const rtosc::Ports &ports; | |||
private: | |||
/* Default parameters */ | |||
@@ -35,6 +35,8 @@ using namespace rtosc; | |||
#define rObject PADnoteParameters | |||
#undef rChangeCb | |||
#define rChangeCb if (obj->time) { obj->last_update_timestamp = obj->time->time(); } | |||
static const rtosc::Ports realtime_ports = | |||
{ | |||
rRecurp(FreqLfo, "Frequency LFO"), | |||
@@ -237,6 +239,7 @@ static const rtosc::Ports non_realtime_ports = | |||
{"needPrepare:", rDoc("Unimplemented Stub"), | |||
NULL, [](const char *, rtosc::RtData&) {}}, | |||
}; | |||
#undef rChangeCb | |||
const rtosc::Ports &PADnoteParameters::non_realtime_ports = ::non_realtime_ports; | |||
const rtosc::Ports &PADnoteParameters::realtime_ports = ::realtime_ports; | |||
@@ -249,8 +252,9 @@ const rtosc::MergePorts PADnoteParameters::ports = | |||
}; | |||
PADnoteParameters::PADnoteParameters(const SYNTH_T &synth_, FFTwrapper *fft_) | |||
:Presets(), synth(synth_) | |||
PADnoteParameters::PADnoteParameters(const SYNTH_T &synth_, FFTwrapper *fft_, | |||
const AbsTime *time_) | |||
: Presets(), time(time_), last_update_timestamp(0), synth(synth_) | |||
{ | |||
setpresettype("Ppadsynth"); | |||
@@ -260,18 +264,18 @@ PADnoteParameters::PADnoteParameters(const SYNTH_T &synth_, FFTwrapper *fft_) | |||
oscilgen = new OscilGen(synth, fft_, resonance); | |||
oscilgen->ADvsPAD = true; | |||
FreqEnvelope = new EnvelopeParams(0, 0); | |||
FreqEnvelope = new EnvelopeParams(0, 0, time_); | |||
FreqEnvelope->ASRinit(64, 50, 64, 60); | |||
FreqLfo = new LFOParams(70, 0, 64, 0, 0, 0, 0, 0); | |||
FreqLfo = new LFOParams(70, 0, 64, 0, 0, 0, 0, 0, time_); | |||
AmpEnvelope = new EnvelopeParams(64, 1); | |||
AmpEnvelope = new EnvelopeParams(64, 1, time_); | |||
AmpEnvelope->ADSRinit_dB(0, 40, 127, 25); | |||
AmpLfo = new LFOParams(80, 0, 64, 0, 0, 0, 0, 1); | |||
AmpLfo = new LFOParams(80, 0, 64, 0, 0, 0, 0, 1, time_); | |||
GlobalFilter = new FilterParams(2, 94, 40); | |||
FilterEnvelope = new EnvelopeParams(0, 1); | |||
GlobalFilter = new FilterParams(2, 94, 40, time_); | |||
FilterEnvelope = new EnvelopeParams(0, 1, time_); | |||
FilterEnvelope->ADSRinit_filter(64, 40, 64, 70, 60, 64); | |||
FilterLfo = new LFOParams(80, 0, 64, 0, 0, 0, 0, 2); | |||
FilterLfo = new LFOParams(80, 0, 64, 0, 0, 0, 0, 2, time_); | |||
for(int i = 0; i < PAD_MAX_SAMPLES; ++i) | |||
sample[i].smp = NULL; | |||
@@ -1176,6 +1180,10 @@ void PADnoteParameters::paste(PADnoteParameters &x) | |||
oscilgen->paste(*x.oscilgen); | |||
resonance->paste(*x.resonance); | |||
if ( time ) { | |||
last_update_timestamp = time->time(); | |||
} | |||
} | |||
void PADnoteParameters::pasteRT(PADnoteParameters &x) | |||
@@ -1215,5 +1223,9 @@ void PADnoteParameters::pasteRT(PADnoteParameters &x) | |||
FilterEnvelope->paste(*x.FilterEnvelope); | |||
FilterLfo->paste(*x.FilterLfo); | |||
if ( time ) { | |||
last_update_timestamp = time->time(); | |||
} | |||
} | |||
#undef COPY |
@@ -42,7 +42,8 @@ | |||
class PADnoteParameters:public Presets | |||
{ | |||
public: | |||
PADnoteParameters(const SYNTH_T &synth_, FFTwrapper *fft_); | |||
PADnoteParameters(const SYNTH_T &synth_, FFTwrapper *fft_, | |||
const AbsTime *time_ = nullptr); | |||
~PADnoteParameters(); | |||
void defaults(); | |||
@@ -173,6 +174,9 @@ class PADnoteParameters:public Presets | |||
void sampleGenerator(PADnoteParameters::callback cb, | |||
std::function<bool()> do_abort); | |||
const AbsTime *time; | |||
int64_t last_update_timestamp; | |||
static const rtosc::MergePorts ports; | |||
static const rtosc::Ports &non_realtime_ports; | |||
static const rtosc::Ports &realtime_ports; | |||
@@ -25,6 +25,7 @@ | |||
#include "EnvelopeParams.h" | |||
#include "FilterParams.h" | |||
#include "../Misc/Util.h" | |||
#include "../Misc/Time.h" | |||
#include <cstdio> | |||
#include <cmath> | |||
@@ -33,6 +34,9 @@ | |||
#define rObject SUBnoteParameters | |||
using namespace rtosc; | |||
#undef rChangeCb | |||
#define rChangeCb if (obj->time) { obj->last_update_timestamp = obj->time->time(); } | |||
static const rtosc::Ports SUBnotePorts = { | |||
rSelf(SUBnoteParameters), | |||
rPaste, | |||
@@ -56,7 +60,8 @@ static const rtosc::Ports SUBnotePorts = { | |||
rParamZyn(PBendAdjust, "Pitch bend adjustment"), | |||
rParamZyn(POffsetHz, "Voice constant offset"), | |||
#undef rChangeCb | |||
#define rChangeCb obj->updateFrequencyMultipliers(); | |||
#define rChangeCb obj->updateFrequencyMultipliers(); if (obj->time) { \ | |||
obj->last_update_timestamp = obj->time->time(); } | |||
rParamI(POvertoneSpread.type, rMap(min, 0), rMap(max, 7), | |||
"Spread of harmonic frequencies"), | |||
rParamI(POvertoneSpread.par1, rMap(min, 0), rMap(max, 255), | |||
@@ -66,7 +71,7 @@ static const rtosc::Ports SUBnotePorts = { | |||
rParamI(POvertoneSpread.par3, rMap(min, 0), rMap(max, 255), | |||
"Overtone Parameter"), | |||
#undef rChangeCb | |||
#define rChangeCb | |||
#define rChangeCb if (obj->time) { obj->last_update_timestamp = obj->time->time(); } | |||
rParamZyn(Pnumstages, rMap(min, 1), rMap(max, 5), "Number of filter stages"), | |||
rParamZyn(Pbandwidth, "Bandwidth of filters"), | |||
rParamZyn(Phmagtype, "How the magnitudes are computed (0=linear,1=-60dB,2=-60dB)"), | |||
@@ -125,21 +130,23 @@ static const rtosc::Ports SUBnotePorts = { | |||
}}, | |||
}; | |||
#undef rChangeCb | |||
const rtosc::Ports &SUBnoteParameters::ports = SUBnotePorts; | |||
SUBnoteParameters::SUBnoteParameters():Presets() | |||
SUBnoteParameters::SUBnoteParameters(const AbsTime *time_) | |||
: Presets(), time(time_), last_update_timestamp(0) | |||
{ | |||
setpresettype("Psubsynth"); | |||
AmpEnvelope = new EnvelopeParams(64, 1); | |||
AmpEnvelope = new EnvelopeParams(64, 1, time_); | |||
AmpEnvelope->ADSRinit_dB(0, 40, 127, 25); | |||
FreqEnvelope = new EnvelopeParams(64, 0); | |||
FreqEnvelope = new EnvelopeParams(64, 0, time_); | |||
FreqEnvelope->ASRinit(30, 50, 64, 60); | |||
BandWidthEnvelope = new EnvelopeParams(64, 0); | |||
BandWidthEnvelope = new EnvelopeParams(64, 0, time_); | |||
BandWidthEnvelope->ASRinit_bw(100, 70, 64, 60); | |||
GlobalFilter = new FilterParams(2, 80, 40); | |||
GlobalFilterEnvelope = new EnvelopeParams(0, 1); | |||
GlobalFilter = new FilterParams(2, 80, 40, time_); | |||
GlobalFilterEnvelope = new EnvelopeParams(0, 1, time_); | |||
GlobalFilterEnvelope->ADSRinit_filter(64, 40, 64, 70, 60, 64); | |||
defaults(); | |||
@@ -395,6 +402,10 @@ void SUBnoteParameters::paste(SUBnoteParameters &sub) | |||
doPaste(Pbwscale); | |||
doPaste(Pstart); | |||
if ( time ) { | |||
last_update_timestamp = time->time(); | |||
} | |||
} | |||
void SUBnoteParameters::getfromXML(XMLwrapper& xml) | |||
@@ -23,13 +23,14 @@ | |||
#ifndef SUB_NOTE_PARAMETERS_H | |||
#define SUB_NOTE_PARAMETERS_H | |||
#include <stdint.h> | |||
#include "../globals.h" | |||
#include "Presets.h" | |||
class SUBnoteParameters:public Presets | |||
{ | |||
public: | |||
SUBnoteParameters(); | |||
SUBnoteParameters(const AbsTime *time_ = nullptr); | |||
~SUBnoteParameters(); | |||
void add2XML(XMLwrapper& xml); | |||
@@ -105,6 +106,9 @@ class SUBnoteParameters:public Presets | |||
//how the harmonics start("0"=0,"1"=random,"2"=1) | |||
unsigned char Pstart; | |||
const AbsTime *time; | |||
int64_t last_update_timestamp; | |||
static const rtosc::Ports &ports; | |||
}; | |||
@@ -38,6 +38,7 @@ | |||
ADnote::ADnote(ADnoteParameters *pars_, SynthParams &spars) | |||
:SynthNote(spars), pars(*pars_) | |||
{ | |||
memory.beginTransaction(); | |||
tmpwavel = memory.valloc<float>(synth.buffersize); | |||
tmpwaver = memory.valloc<float>(synth.buffersize); | |||
bypassl = memory.valloc<float>(synth.buffersize); | |||
@@ -473,6 +474,7 @@ ADnote::ADnote(ADnoteParameters *pars_, SynthParams &spars) | |||
} | |||
initparameters(); | |||
memory.endTransaction(); | |||
} | |||
SynthNote *ADnote::cloneLegato(void) | |||
@@ -124,6 +124,7 @@ float LFO::baseOut(const char waveShape, const float phase) | |||
float LFO::lfoout() | |||
{ | |||
//update internals XXX TODO cleanup | |||
if ( ! lfopars_.time || lfopars_.last_update_timestamp == lfopars_.time->time()) | |||
{ | |||
waveShape = lfopars_.PLFOtype; | |||
int stretch = lfopars_.Pstretch; | |||