commit d9cbd96e444537d4ba4d77ff5873d80c9a0b9575
parent 51a52afa20abb351d5fc6afd34932a5e4c9d64c2
Author: fundamental <[email protected]>
Date: Sun, 11 Mar 2018 11:01:44 -0400
Merge remote-tracking branch 'github/master'
Diffstat:
13 files changed, 121 insertions(+), 70 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -1,6 +1,12 @@
*.o
*~
*.bc
+*.swp
+*.config
+*.creator
+*.creator.user
+*.files
+*.includes
src/zynaddsubfx
src/Tests/runner
src/Tests/runner.cpp
diff --git a/.gitmodules b/.gitmodules
@@ -1,6 +1,6 @@
[submodule "instruments"]
path = instruments
- url = git://git.code.sf.net/p/zynaddsubfx/instruments
+ url = https://github.com/zynaddsubfx/instruments
[submodule "rtosc"]
path = rtosc
url = https://github.com/fundamental/rtosc
diff --git a/AUTHORS.txt b/AUTHORS.txt
@@ -6,6 +6,7 @@ Active Developers:
Hans Petter Selasky (BSD Compat)
Christopher Oliver (Unison + presets fix, mousewheel support,
SUBnote overtones, unison enhancements, ...)
+ Daniel Sheeler
Contributors:
Gerald Folcher (legato, mono notes memory)
diff --git a/src/Misc/Part.cpp b/src/Misc/Part.cpp
@@ -133,7 +133,7 @@ static const Ports partPorts = {
p->Ppolymode = 0;
p->Plegatomode = 1;
}}},
- {"clear:", rProp(internal) rDoc("Reset Part To Defaults"), 0,
+ {"clear:", rProp(internal) rDoc("Reset Part To Defaults"), 0,
[](const char *, RtData &d)
{
//XXX todo forward this event for middleware to handle
@@ -534,7 +534,7 @@ bool Part::NoteOn(unsigned char note,
wm, (pre+"kit"+i+"/adpars/").c_str), 0, i});
if(item.Psubenabled)
notePool.insertNote(note, sendto,
- {memory.alloc<SUBnote>(kit[i].subpars, pars), 1, i});
+ {memory.alloc<SUBnote>(kit[i].subpars, pars, wm, (pre+"kit"+i+"/subpars/").c_str), 1, i});
if(item.Ppadenabled)
notePool.insertNote(note, sendto,
{memory.alloc<PADnote>(kit[i].padpars, pars, interpolation, wm,
@@ -571,7 +571,7 @@ void Part::NoteOff(unsigned char note) //release the key
if(!ctl.sustain.sustain) { //the sustain pedal is not pushed
if((isMonoMode() || isLegatoMode()) && !monomemEmpty())
MonoMemRenote();//Play most recent still active note
- else
+ else
notePool.release(desc);
}
else { //the sustain pedal is pushed
diff --git a/src/Params/ADnoteParameters.cpp b/src/Params/ADnoteParameters.cpp
@@ -157,8 +157,8 @@ static const Ports voicePorts = {
frequency, pulse), rDefault(none), "Modulator mode"),
rParamI(PFMVoice, rShort("voice"), rDefault(-1),
"Modulator Oscillator Selection"),
- rParamZyn(PFMVolume, rShort("vol."), rDefault(90),
- "Modulator Magnitude"),
+ rParamF(FMvolume, rShort("vol."), rLinear(0.0, 100.0),
+ rDefault(70.0), "Modulator Magnitude"),
rParamZyn(PFMVolumeDamp, rShort("damp."), rDefault(64),
"Modulator HF dampening"),
rParamZyn(PFMVelocityScaleFunction, rShort("sense"), rDefault(64),
@@ -222,7 +222,17 @@ static const Ports voicePorts = {
obj->PCoarseDetune = k + (obj->PCoarseDetune/1024)*1024;
}
}},
-
+ {"PFMVolume::i", rShort("vol.") rLinear(0,127)
+ rDoc("Modulator Magnitude"), NULL,
+ [](const char *msg, RtData &d)
+ {
+ rObject *obj = (rObject *)d.obj;
+ if (!rtosc_narguments(msg))
+ d.reply(d.loc, "i", (int)roundf(127.0f * obj->FMvolume
+ / 100.0f));
+ else
+ obj->FMvolume = 100.0f * rtosc_argument(msg, 0).i / 127.0f;
+ }},
//weird stuff for PCoarseDetune
{"FMdetunevalue:", rMap(unit,cents) rDoc("Get modulator detune"), NULL, [](const char *, RtData &d)
{
@@ -525,7 +535,7 @@ void ADnoteVoiceParam::defaults()
//I use the internal oscillator (-1)
PFMVoice = -1;
- PFMVolume = 90;
+ FMvolume = 70.0;
PFMVolumeDamp = 64;
PFMDetune = 8192;
PFMCoarseDetune = 0;
@@ -789,7 +799,7 @@ void ADnoteVoiceParam::add2XML(XMLwrapper& xml, bool fmoscilused)
xml.beginbranch("FM_PARAMETERS");
xml.addpar("input_voice", PFMVoice);
- xml.addpar("volume", PFMVolume);
+ xml.addparreal("volume", FMvolume);
xml.addpar("volume_damp", PFMVolumeDamp);
xml.addpar("velocity_sensing",
PFMVelocityScaleFunction);
@@ -1090,7 +1100,7 @@ void ADnoteVoiceParam::paste(ADnoteVoiceParam &a)
RCopy(FilterLfo);
copy(PFMVoice);
- copy(PFMVolume);
+ copy(FMvolume);
copy(PFMVolumeDamp);
copy(PFMVelocityScaleFunction);
@@ -1264,8 +1274,16 @@ void ADnoteVoiceParam::getfromXML(XMLwrapper& xml, unsigned nvoice)
}
if(xml.enterbranch("FM_PARAMETERS")) {
+ const bool upgrade_3_0_3 = (xml.fileversion() < version_type(3,0,3)) ||
+ (xml.getparreal("volume", -1) < 0);
+
PFMVoice = xml.getpar("input_voice", PFMVoice, -1, nvoice - 1);
- PFMVolume = xml.getpar127("volume", PFMVolume);
+ if (upgrade_3_0_3) {
+ int Pvolume = xml.getpar127("volume", 0);
+ FMvolume = 100.0f * Pvolume / 127.0f;
+ } else {
+ FMvolume = xml.getparreal("volume", FMvolume);
+ }
PFMVolumeDamp = xml.getpar127("volume_damp", PFMVolumeDamp);
PFMVelocityScaleFunction = xml.getpar127("velocity_sensing",
PFMVelocityScaleFunction);
diff --git a/src/Params/ADnoteParameters.h b/src/Params/ADnoteParameters.h
@@ -270,7 +270,7 @@ struct ADnoteVoiceParam {
OscilGen *FMSmp;
/* Modullator Volume */
- unsigned char PFMVolume;
+ float FMvolume;
/* Modullator damping at higher frequencies */
unsigned char PFMVolumeDamp;
diff --git a/src/Synth/ADnote.cpp b/src/Synth/ADnote.cpp
@@ -216,7 +216,7 @@ void ADnote::setupVoice(int nvoice)
voice.filterbypass = param.Pfilterbypass;
setupVoiceMod(nvoice);
-
+
voice.FMVoice = param.PFMVoice;
voice.FMFreqEnvelope = NULL;
voice.FMAmpEnvelope = NULL;
@@ -482,7 +482,7 @@ void ADnote::setupVoiceMod(int nvoice, bool first_run)
//Compute the Voice's modulator volume (incl. damping)
float fmvoldamp = powf(440.0f / getvoicebasefreq(nvoice),
param.PFMVolumeDamp / 64.0f - 1.0f);
- const float fmvolume_ = param.PFMVolume / 127.0f;
+ const float fmvolume_ = param.FMvolume / 100.0f;
switch(voice.FMEnabled) {
case PHASE_MOD:
case PW_MOD:
@@ -508,7 +508,7 @@ void ADnote::setupVoiceMod(int nvoice, bool first_run)
SynthNote *ADnote::cloneLegato(void)
{
- SynthParams sp{memory, ctl, synth, time, legato.param.freq, velocity,
+ SynthParams sp{memory, ctl, synth, time, legato.param.freq, velocity,
(bool)portamento, legato.param.midinote, true};
return memory.alloc<ADnote>(&pars, sp);
}
@@ -520,7 +520,6 @@ SynthNote *ADnote::cloneLegato(void)
void ADnote::legatonote(LegatoParams lpars)
{
//ADnoteParameters &pars = *partparams;
-
// Manage legato stuff
if(legato.update(lpars))
return;
@@ -543,7 +542,7 @@ void ADnote::legatonote(LegatoParams lpars)
else
NoteGlobalPar.Panning = pars.GlobalPar.PPanning / 128.0f;
- NoteGlobalPar.Filter->updateSense(velocity,
+ NoteGlobalPar.Filter->updateSense(velocity,
pars.GlobalPar.PFilterVelocityScale,
pars.GlobalPar.PFilterVelocityScaleFunction);
@@ -587,7 +586,6 @@ void ADnote::legatonote(LegatoParams lpars)
pars.VoicePar[nvoice].PFMCoarseDetune,
pars.VoicePar[nvoice].PFMDetune);
-
//Get the voice's oscil or external's voice oscil
int vc = nvoice;
if(pars.VoicePar[nvoice].Pextoscil != -1)
@@ -631,20 +629,20 @@ void ADnote::legatonote(LegatoParams lpars)
nvoice), pars.VoicePar[nvoice].PFMVolumeDamp
/ 64.0f);
NoteVoicePar[nvoice].FMVolume =
- (expf(pars.VoicePar[nvoice].PFMVolume / 127.0f
+ (expf(pars.VoicePar[nvoice].FMvolume / 100.0f
* FM_AMP_MULTIPLIER) - 1.0f) * fmvoldamp * 4.0f;
break;
case FREQ_MOD:
NoteVoicePar[nvoice].FMVolume =
- (expf(pars.VoicePar[nvoice].PFMVolume / 127.0f
+ (expf(pars.VoicePar[nvoice].FMvolume / 100.0f
* FM_AMP_MULTIPLIER) - 1.0f) * fmvoldamp * 4.0f;
break;
default:
if(fmvoldamp > 1.0f)
fmvoldamp = 1.0f;
NoteVoicePar[nvoice].FMVolume =
- pars.VoicePar[nvoice].PFMVolume
- / 127.0f * fmvoldamp;
+ pars.VoicePar[nvoice].FMvolume
+ / 100.0f * fmvoldamp;
}
//Voice's modulator velocity sensing
@@ -657,7 +655,6 @@ void ADnote::legatonote(LegatoParams lpars)
* logf(50.0f))
- 1.0f) / synth.buffersize_f / 10.0f * synth.samplerate_f);
}
-
/// initparameters();
///////////////
@@ -672,7 +669,6 @@ void ADnote::legatonote(LegatoParams lpars)
* VelF(
velocity,
pars.GlobalPar.PAmpVelocityScaleFunction); //velocity sensing
-
globalnewamplitude = NoteGlobalPar.Volume
* NoteGlobalPar.AmpEnvelope->envout_dB()
* NoteGlobalPar.AmpLfo->amplfoout();
@@ -1564,15 +1560,15 @@ inline void ADnote::ComputeVoicePinkNoise(int nvoice)
float *tw = tmpwave_unison[k];
float *f = &pinking[nvoice][k > 0 ? 7 : 0];
for(int i = 0; i < synth.buffersize; ++i) {
- float white = (RND-0.5)/4.0;
- f[0] = 0.99886*f[0]+white*0.0555179;
- f[1] = 0.99332*f[1]+white*0.0750759;
- f[2] = 0.96900*f[2]+white*0.1538520;
- f[3] = 0.86650*f[3]+white*0.3104856;
- f[4] = 0.55000*f[4]+white*0.5329522;
- f[5] = -0.7616*f[5]-white*0.0168980;
- tw[i] = f[0]+f[1]+f[2]+f[3]+f[4]+f[5]+f[6]+white*0.5362;
- f[6] = white*0.115926;
+ float white = (RND-0.5)/4.0;
+ f[0] = 0.99886*f[0]+white*0.0555179;
+ f[1] = 0.99332*f[1]+white*0.0750759;
+ f[2] = 0.96900*f[2]+white*0.1538520;
+ f[3] = 0.86650*f[3]+white*0.3104856;
+ f[4] = 0.55000*f[4]+white*0.5329522;
+ f[5] = -0.7616*f[5]-white*0.0168980;
+ tw[i] = f[0]+f[1]+f[2]+f[3]+f[4]+f[5]+f[6]+white*0.5362;
+ f[6] = white*0.115926;
}
}
}
@@ -1983,7 +1979,7 @@ void ADnote::Global::initparameters(const ADnoteGlobalParam ¶m,
Volume = 4.0f * powf(0.1f, 3.0f * (1.0f - param.PVolume / 96.0f)) //-60 dB .. 0 dB
* VelF(velocity, param.PAmpVelocityScaleFunction); //sensing
- Filter = memory.alloc<ModFilter>(*param.GlobalFilter, synth, time, memory,
+ Filter = memory.alloc<ModFilter>(*param.GlobalFilter, synth, time, memory,
stereo, basefreq);
FilterEnvelope = memory.alloc<Envelope>(*param.FilterEnvelope, basefreq,
@@ -1993,7 +1989,7 @@ void ADnote::Global::initparameters(const ADnoteGlobalParam ¶m,
Filter->addMod(*FilterEnvelope);
Filter->addMod(*FilterLfo);
-
+
{
Filter->updateSense(velocity, param.PFilterVelocityScale,
param.PFilterVelocityScaleFunction);
diff --git a/src/Synth/Envelope.cpp b/src/Synth/Envelope.cpp
@@ -32,7 +32,7 @@ Envelope::Envelope(EnvelopeParams &pars, float basefreq, float bufferdt,
if(!pars.Pfreemode)
pars.converttofree();
- int mode = pars.Envmode;
+ mode = pars.Envmode;
//for amplitude envelopes
if((mode == 1) && !linearenvelope)
@@ -101,26 +101,54 @@ void Envelope::forceFinish(void)
envfinish = true;
}
+void Envelope::watch(float time, float value)
+{
+ float pos[2];
+ float factor1;
+ float factor2;
+ pos[0] = time;
+ switch(mode) {
+ case 2:
+ pos[1] = 1 - value / -40.f;
+ watchOut(pos, 2);
+ break;
+ case 3:
+ factor1 = log(value/100. + 1.) / (6. * log(2));
+ factor2 = log(1. - value/100.) / (6. * log(2));
+ pos[1] = ((0.5 * factor1) >= 0) ? (0.5 * factor1 + 0.5) : (0.5 - factor2 * 0.5);
+ watchOut(pos, 2);
+ break;
+ case 4:
+ pos[1] = (value + 6.) / 12.f;
+ watchOut(pos, 2);
+ break;
+ case 5:
+ pos[1] = (value + 10.) / 20.f;
+ watchOut(pos, 2);
+ break;
+ default:
+ pos[1] = value;
+ watchOut(pos, 2);
+ }
+}
+
/*
* Envelope Output
*/
float Envelope::envout(bool doWatch)
{
float out;
-
if(envfinish) { //if the envelope is finished
envoutval = envval[envpoints - 1];
if(doWatch) {
- float pos[2] = {(float)envpoints - 1, envoutval};
- watchOut(pos, 2);
+ watch(envpoints - 1, envoutval);
}
return envoutval;
}
if((currentpoint == envsustain + 1) && !keyreleased) { //if it is sustaining now
envoutval = envval[envsustain];
if(doWatch) {
- float pos[2] = {(float)envsustain, envoutval};
- watchOut(pos, 2);
+ watch(envsustain, envoutval);
}
return envoutval;
}
@@ -144,8 +172,7 @@ float Envelope::envout(bool doWatch)
}
if(doWatch) {
- float pos[2] = {(float)tmp + t, envoutval};
- watchOut(pos, 2);
+ watch(tmp + t, envoutval);
}
return out;
@@ -169,8 +196,7 @@ float Envelope::envout(bool doWatch)
envoutval = out;
if(doWatch) {
- float pos[2] = {(float)currentpoint + t, envoutval};
- watchOut(pos, 2);
+ watch(currentpoint + t, envoutval);
}
return out;
}
@@ -201,13 +227,13 @@ float Envelope::envout_dB()
envoutval = EnvelopeParams::env_rap2dB(out);
else
envoutval = MIN_ENVELOPE_DB;
+ out = envoutval;
} else
- out = EnvelopeParams::env_dB2rap(envout(false));
+ out = envout(false);
- float pos[2] = {(float)currentpoint + t, out};
- watchOut(pos, 2);
+ watch(currentpoint + t, out);
+ return EnvelopeParams::env_dB2rap(out);
- return out;
}
bool Envelope::finished() const
diff --git a/src/Synth/Envelope.h b/src/Synth/Envelope.h
@@ -23,7 +23,6 @@ namespace zyn {
class Envelope
{
public:
-
/**Constructor*/
Envelope(class EnvelopeParams &pars, float basefreq, float dt, WatchManager *m=0,
const char *watch_prefix=0);
@@ -37,6 +36,8 @@ class Envelope
/**Determines the status of the Envelope
* @return returns 1 if the envelope is finished*/
bool finished(void) const;
+ void watch(float time, float value);
+
private:
int envpoints;
int envsustain; //"-1" means disabled
@@ -44,6 +45,7 @@ class Envelope
float envval[MAX_ENVELOPE_POINTS]; // [0.0f .. 1.0f]
float envstretch;
int linearenvelope;
+ int mode;
int currentpoint; //current envelope point (starts from 1)
bool forcedrelease;
diff --git a/src/Synth/SUBnote.cpp b/src/Synth/SUBnote.cpp
@@ -34,7 +34,8 @@
namespace zyn {
-SUBnote::SUBnote(const SUBnoteParameters *parameters, SynthParams &spars)
+SUBnote::SUBnote(const SUBnoteParameters *parameters, SynthParams &spars, WatchManager *wm, const char *prefix
+ )
:SynthNote(spars), pars(*parameters),
AmpEnvelope(nullptr),
FreqEnvelope(nullptr),
@@ -42,10 +43,9 @@ SUBnote::SUBnote(const SUBnoteParameters *parameters, SynthParams &spars)
GlobalFilter(nullptr),
GlobalFilterEnvelope(nullptr),
NoteEnabled(true),
- lfilter(nullptr), rfilter(nullptr),
- wm(nullptr)
+ lfilter(nullptr), rfilter(nullptr)
{
- setup(spars.frequency, spars.velocity, spars.portamento, spars.note);
+ setup(spars.frequency, spars.velocity, spars.portamento, spars.note, false, wm, prefix);
}
float SUBnote::setupFilters(int *pos, bool automation)
@@ -91,7 +91,9 @@ void SUBnote::setup(float freq,
float velocity,
int portamento_,
int midinote,
- bool legato)
+ bool legato,
+ WatchManager *wm,
+ const char *prefix)
{
this->velocity = velocity;
portamento = portamento_;
@@ -175,9 +177,9 @@ void SUBnote::setup(float freq,
oldbandwidth = 64;
if(!legato) { //normal note
if(pars.Pfixedfreq == 0)
- initparameters(basefreq, wm);
+ initparameters(basefreq, wm, prefix);
else
- initparameters(basefreq / 440.0f * freq, wm);
+ initparameters(basefreq / 440.0f * freq, wm, prefix);
}
else {
if(pars.Pfixedfreq == 0)
@@ -207,7 +209,7 @@ void SUBnote::legatonote(LegatoParams pars)
try {
setup(pars.frequency, pars.velocity, pars.portamento, pars.midinote,
- true);
+ true, wm);
} catch (std::bad_alloc &ba) {
std::cerr << "failed to set legato note parameter in SUBnote: " << ba.what() << std::endl;
}
@@ -353,10 +355,9 @@ void SUBnote::filter(bpfilter &filter, float *smps)
/*
* Init Parameters
*/
-void SUBnote::initparameters(float freq, WatchManager *wm)
+void SUBnote::initparameters(float freq, WatchManager *wm, const char *prefix)
{
- //TODO populate this base string
- ScratchString pre;
+ ScratchString pre = prefix;
AmpEnvelope = memory.alloc<Envelope>(*pars.AmpEnvelope, freq,
synth.dt(), wm, (pre+"AmpEnvelope/").c_str);
diff --git a/src/Synth/SUBnote.h b/src/Synth/SUBnote.h
@@ -22,7 +22,8 @@ namespace zyn {
class SUBnote:public SynthNote
{
public:
- SUBnote(const SUBnoteParameters *parameters, SynthParams &pars);
+ SUBnote(const SUBnoteParameters *parameters, SynthParams &pars,
+ WatchManager *wm = 0, const char *prefix = 0);
~SUBnote();
SynthNote *cloneLegato(void);
@@ -38,14 +39,14 @@ class SUBnote:public SynthNote
float velocity,
int portamento_,
int midinote,
- bool legato = false);
+ bool legato = false, WatchManager *wm = 0, const char *prefix = 0);
float setupFilters(int *pos, bool automation);
void computecurrentparameters();
/*
* Initialize envelopes and global filter
* calls computercurrentparameters()
*/
- void initparameters(float freq, WatchManager *wm);
+ void initparameters(float freq, WatchManager *wm, const char *prefix);
void KillNote();
const SUBnoteParameters &pars;
diff --git a/src/Synth/WatchPoint.cpp b/src/Synth/WatchPoint.cpp
@@ -50,7 +50,7 @@ bool WatchPoint::is_active(void)
return false;
}
-
+
FloatWatchPoint::FloatWatchPoint(WatchManager *ref, const char *prefix, const char *id)
:WatchPoint(ref, prefix, id)
{}
@@ -58,7 +58,7 @@ FloatWatchPoint::FloatWatchPoint(WatchManager *ref, const char *prefix, const ch
VecWatchPoint::VecWatchPoint(WatchManager *ref, const char *prefix, const char *id)
:WatchPoint(ref, prefix, id)
{}
-
+
WatchManager::WatchManager(thrlnk *link)
:write_back(link), new_active(false)
{
@@ -67,7 +67,7 @@ WatchManager::WatchManager(thrlnk *link)
memset(data_list, 0, sizeof(data_list));
memset(deactivate, 0, sizeof(deactivate));
}
-
+
void WatchManager::add_watch(const char *id)
{
//Don't add duplicate watchs
@@ -136,7 +136,7 @@ bool WatchManager::active(const char *id) const
return false;
}
-
+
int WatchManager::samples(const char *id) const
{
for(int i=0; i<MAX_WATCH; ++i)
@@ -144,7 +144,7 @@ int WatchManager::samples(const char *id) const
return sample_list[i];
return 0;
}
-
+
void WatchManager::satisfy(const char *id, float f)
{
//printf("trying to satisfy '%s'\n", id);
diff --git a/src/Tests/guitar-adnote.xmz b/src/Tests/guitar-adnote.xmz
@@ -349,7 +349,7 @@ version-revision="3" ZynAddSubFX-author="Nasca Octavian Paul">
</FILTER_PARAMETERS>
<FM_PARAMETERS>
<par name="input_voice" value="-1" />
-<par name="volume" value="46" />
+<par_real name="volume" value="36.2205" exact_value="0x4210E1C3" />
<par name="volume_damp" value="36" />
<par name="velocity_sensing" value="92" />
<par_bool name="amp_envelope_enabled" value="yes" />