commit 24e48c507dde62e95d4aadf7e5477f48faa70bc4
parent bda5c928ca35a54cd4917bcf308b5e8a4d656b8e
Author: fundamental <mark.d.mccurry@gmail.com>
Date: Sun, 19 Mar 2017 15:02:37 -0400
Refactor ADnote To Permit Live Mod. Automation
Adds experimental automation for modulator frequency and volume
Diffstat:
2 files changed, 360 insertions(+), 332 deletions(-)
diff --git a/src/Synth/ADnote.cpp b/src/Synth/ADnote.cpp
@@ -76,384 +76,397 @@ ADnote::ADnote(ADnoteParameters *pars_, SynthParams &spars,
NoteGlobalPar.Punch.Enabled = 0;
for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice) {
- for (int i = 0; i < 14; i++)
- pinking[nvoice][i] = 0.0;
+ setupVoice(nvoice);
+ }
- pars.VoicePar[nvoice].OscilSmp->newrandseed(prng());
- NoteVoicePar[nvoice].OscilSmp = NULL;
- NoteVoicePar[nvoice].FMSmp = NULL;
- NoteVoicePar[nvoice].VoiceOut = NULL;
+ max_unison = 1;
+ for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice)
+ if(unison_size[nvoice] > max_unison)
+ max_unison = unison_size[nvoice];
- NoteVoicePar[nvoice].FMVoice = -1;
- unison_size[nvoice] = 1;
- if(!pars.VoicePar[nvoice].Enabled) {
- NoteVoicePar[nvoice].Enabled = OFF;
- continue; //the voice is disabled
- }
+ 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);
+ }
- int BendAdj = pars.VoicePar[nvoice].PBendAdjust - 64;
- if (BendAdj % 24 == 0)
- NoteVoicePar[nvoice].BendAdjust = BendAdj / 24;
- else
- NoteVoicePar[nvoice].BendAdjust = BendAdj / 24.0f;
-
- float offset_val = (pars.VoicePar[nvoice].POffsetHz - 64)/64.0f;
- NoteVoicePar[nvoice].OffsetHz =
- 15.0f*(offset_val * sqrtf(fabsf(offset_val)));
-
- unison_stereo_spread[nvoice] =
- pars.VoicePar[nvoice].Unison_stereo_spread / 127.0f;
-
- int unison = pars.VoicePar[nvoice].Unison_size;
- if(unison < 1)
- unison = 1;
-
- bool is_pwm = pars.VoicePar[nvoice].PFMEnabled == PW_MOD;
-
- if (pars.VoicePar[nvoice].Type != 0) {
- // Since noise unison of greater than two is touch goofy...
- if (unison > 2)
- unison = 2;
- } else if (is_pwm) {
- /* Pulse width mod uses pairs of subvoices. */
- unison *= 2;
- // This many is likely to sound like noise anyhow.
- if (unison > 64)
- unison = 64;
- }
+ initparameters(wm, prefix);
+ memory.endTransaction();
+}
- //compute unison
- unison_size[nvoice] = unison;
+void ADnote::setupVoice(int nvoice)
+{
+ auto ¶m = pars.VoicePar[nvoice];
+ auto &voice = NoteVoicePar[nvoice];
- unison_base_freq_rap[nvoice] = memory.valloc<float>(unison);
- unison_freq_rap[nvoice] = memory.valloc<float>(unison);
- unison_invert_phase[nvoice] = memory.valloc<bool>(unison);
- float unison_spread =
- pars.getUnisonFrequencySpreadCents(nvoice);
- float unison_real_spread = powf(2.0f, (unison_spread * 0.5f) / 1200.0f);
- float unison_vibratto_a =
- pars.VoicePar[nvoice].Unison_vibratto / 127.0f; //0.0f .. 1.0f
- int true_unison = unison / (is_pwm ? 2 : 1);
- switch(true_unison) {
- case 1:
- unison_base_freq_rap[nvoice][0] = 1.0f; //if the unison is not used, always make the only subvoice to have the default note
- break;
- case 2: { //unison for 2 subvoices
- unison_base_freq_rap[nvoice][0] = 1.0f / unison_real_spread;
- unison_base_freq_rap[nvoice][1] = unison_real_spread;
- };
+ for (int i = 0; i < 14; i++)
+ pinking[nvoice][i] = 0.0;
+
+ param.OscilSmp->newrandseed(prng());
+ voice.OscilSmp = NULL;
+ voice.FMSmp = NULL;
+ voice.VoiceOut = NULL;
+
+ voice.FMVoice = -1;
+ unison_size[nvoice] = 1;
+
+ if(!pars.VoicePar[nvoice].Enabled) {
+ voice.Enabled = OFF;
+ return; //the voice is disabled
+ }
+
+ const int BendAdj = pars.VoicePar[nvoice].PBendAdjust - 64;
+ if (BendAdj % 24 == 0)
+ voice.BendAdjust = BendAdj / 24;
+ else
+ voice.BendAdjust = BendAdj / 24.0f;
+
+ const float offset_val = (param.POffsetHz - 64)/64.0f;
+ voice.OffsetHz = 15.0f*(offset_val * sqrtf(fabsf(offset_val)));
+
+ unison_stereo_spread[nvoice] =
+ pars.VoicePar[nvoice].Unison_stereo_spread / 127.0f;
+
+ int unison = setupVoiceUnison(nvoice);
+
+
+ oscfreqhi[nvoice] = memory.valloc<int>(unison);
+ oscfreqlo[nvoice] = memory.valloc<float>(unison);
+ oscfreqhiFM[nvoice] = memory.valloc<unsigned int>(unison);
+ oscfreqloFM[nvoice] = memory.valloc<float>(unison);
+ oscposhi[nvoice] = memory.valloc<int>(unison);
+ oscposlo[nvoice] = memory.valloc<float>(unison);
+ oscposhiFM[nvoice] = memory.valloc<unsigned int>(unison);
+ oscposloFM[nvoice] = memory.valloc<float>(unison);
+
+ voice.Enabled = ON;
+ voice.fixedfreq = pars.VoicePar[nvoice].Pfixedfreq;
+ voice.fixedfreqET = pars.VoicePar[nvoice].PfixedfreqET;
+
+ setupVoiceDetune(nvoice);
+
+ for(int k = 0; k < unison; ++k) {
+ oscposhi[nvoice][k] = 0;
+ oscposlo[nvoice][k] = 0.0f;
+ oscposhiFM[nvoice][k] = 0;
+ oscposloFM[nvoice][k] = 0.0f;
+ }
+
+ //the extra points contains the first point
+ voice.OscilSmp =
+ memory.valloc<float>(synth.oscilsize + OSCIL_SMP_EXTRA_SAMPLES);
+
+ //Get the voice's oscil or external's voice oscil
+ int vc = nvoice;
+ if(pars.VoicePar[nvoice].Pextoscil != -1)
+ vc = pars.VoicePar[nvoice].Pextoscil;
+ if(!pars.GlobalPar.Hrandgrouping)
+ pars.VoicePar[vc].OscilSmp->newrandseed(prng());
+ int oscposhi_start =
+ pars.VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,
+ getvoicebasefreq(nvoice),
+ pars.VoicePar[nvoice].Presonance);
+
+ // This code was planned for biasing the carrier in MOD_RING
+ // but that's on hold for the moment. Disabled 'cos small
+ // machines run this stuff too.
+ //
+ // //Find range of generated wave
+ // float min = NoteVoicePar[nvoice].OscilSmp[0];
+ // float max = min;
+ // float *smpls = &(NoteVoicePar[nvoice].OscilSmp[1]);
+ // for (int i = synth.oscilsize-1; i--; smpls++)
+ // if (*smpls > max)
+ // max = *smpls;
+ // else if (*smpls < min)
+ // min = *smpls;
+ // NoteVoicePar[nvoice].OscilSmpMin = min;
+ // NoteVoicePar[nvoice].OscilSmpMax = max;
+
+ //I store the first elments to the last position for speedups
+ for(int i = 0; i < OSCIL_SMP_EXTRA_SAMPLES; ++i)
+ voice.OscilSmp[synth.oscilsize + i] = voice.OscilSmp[i];
+
+ voice.phase_offset = (int)((pars.VoicePar[nvoice].Poscilphase
+ - 64.0f) / 128.0f * synth.oscilsize + synth.oscilsize * 4);
+ oscposhi_start += NoteVoicePar[nvoice].phase_offset;
+
+ int kth_start = oscposhi_start;
+ for(int k = 0; k < unison; ++k) {
+ oscposhi[nvoice][k] = kth_start % synth.oscilsize;
+ //put random starting point for other subvoices
+ kth_start = oscposhi_start +
+ (int)(RND * pars.VoicePar[nvoice].Unison_phase_randomness /
+ 127.0f * (synth.oscilsize - 1));
+ }
+
+ voice.FreqLfo = NULL;
+ voice.FreqEnvelope = NULL;
+
+ voice.AmpLfo = NULL;
+ voice.AmpEnvelope = NULL;
+
+ voice.Filter = NULL;
+ voice.FilterEnvelope = NULL;
+ voice.FilterLfo = NULL;
+
+ voice.filterbypass = param.Pfilterbypass;
+
+ setupVoiceMod(nvoice);
+
+ voice.FMVoice = param.PFMVoice;
+ voice.FMFreqEnvelope = NULL;
+ voice.FMAmpEnvelope = NULL;
+
+ FMoldsmp[nvoice] = memory.valloc<float>(unison);
+ for(int k = 0; k < unison; ++k)
+ FMoldsmp[nvoice][k] = 0.0f; //this is for FM (integration)
+
+ firsttick[nvoice] = 1;
+ voice.DelayTicks =
+ (int)((expf(param.PDelay / 127.0f * logf(50.0f))
+ - 1.0f) / synth.buffersize_f / 10.0f * synth.samplerate_f);
+}
+
+int ADnote::setupVoiceUnison(int nvoice)
+{
+ int unison = pars.VoicePar[nvoice].Unison_size;
+ if(unison < 1)
+ unison = 1;
+
+ bool is_pwm = pars.VoicePar[nvoice].PFMEnabled == PW_MOD;
+
+ if (pars.VoicePar[nvoice].Type != 0) {
+ // Since noise unison of greater than two is touch goofy...
+ if (unison > 2)
+ unison = 2;
+ } else if (is_pwm) {
+ /* Pulse width mod uses pairs of subvoices. */
+ unison *= 2;
+ // This many is likely to sound like noise anyhow.
+ if (unison > 64)
+ unison = 64;
+ }
+
+ //compute unison
+ unison_size[nvoice] = unison;
+
+ unison_base_freq_rap[nvoice] = memory.valloc<float>(unison);
+ unison_freq_rap[nvoice] = memory.valloc<float>(unison);
+ unison_invert_phase[nvoice] = memory.valloc<bool>(unison);
+ const float unison_spread =
+ pars.getUnisonFrequencySpreadCents(nvoice);
+ const float unison_real_spread = powf(2.0f, (unison_spread * 0.5f) / 1200.0f);
+ const float unison_vibratto_a =
+ pars.VoicePar[nvoice].Unison_vibratto / 127.0f; //0.0f .. 1.0f
+
+ const int true_unison = unison / (is_pwm ? 2 : 1);
+ switch(true_unison) {
+ case 1:
+ unison_base_freq_rap[nvoice][0] = 1.0f; //if the unison is not used, always make the only subvoice to have the default note
+ break;
+ case 2: { //unison for 2 subvoices
+ unison_base_freq_rap[nvoice][0] = 1.0f / unison_real_spread;
+ unison_base_freq_rap[nvoice][1] = unison_real_spread;
+ };
break;
- default: { //unison for more than 2 subvoices
- float unison_values[true_unison];
- float min = -1e-6, max = 1e-6;
- for(int k = 0; k < true_unison; ++k) {
- float step = (k / (float) (true_unison - 1)) * 2.0f - 1.0f; //this makes the unison spread more uniform
- float val = step + (RND * 2.0f - 1.0f) / (true_unison - 1);
- unison_values[k] = val;
- if (min > val) {
- min = val;
- }
- if (max < val) {
- max = val;
- }
- }
- float diff = max - min;
- for(int k = 0; k < true_unison; ++k) {
- unison_values[k] =
- (unison_values[k] - (max + min) * 0.5f) / diff; //the lowest value will be -1 and the highest will be 1
- unison_base_freq_rap[nvoice][k] =
- powf(2.0f, (unison_spread * unison_values[k]) / 1200);
- }
- };
+ default: { //unison for more than 2 subvoices
+ float unison_values[true_unison];
+ float min = -1e-6, max = 1e-6;
+ for(int k = 0; k < true_unison; ++k) {
+ float step = (k / (float) (true_unison - 1)) * 2.0f - 1.0f; //this makes the unison spread more uniform
+ float val = step + (RND * 2.0f - 1.0f) / (true_unison - 1);
+ unison_values[k] = val;
+ if (min > val) {
+ min = val;
+ }
+ if (max < val) {
+ max = val;
+ }
+ }
+ const float diff = max - min;
+ for(int k = 0; k < true_unison; ++k) {
+ unison_values[k] =
+ (unison_values[k] - (max + min) * 0.5f) / diff; //the lowest value will be -1 and the highest will be 1
+ unison_base_freq_rap[nvoice][k] =
+ powf(2.0f, (unison_spread * unison_values[k]) / 1200);
+ }
+ };
+ }
+ if (is_pwm)
+ for (int i = true_unison - 1; i >= 0; i--) {
+ unison_base_freq_rap[nvoice][2*i + 1] =
+ unison_base_freq_rap[nvoice][i];
+ unison_base_freq_rap[nvoice][2*i] =
+ unison_base_freq_rap[nvoice][i];
}
+
+ //unison vibrattos
+ if(unison > 2 || (!is_pwm && unison > 1))
+ for(int k = 0; k < unison; ++k) //reduce the frequency difference for larger vibrattos
+ unison_base_freq_rap[nvoice][k] = 1.0f
+ + (unison_base_freq_rap[
+ nvoice][k] - 1.0f)
+ * (1.0f - unison_vibratto_a);
+ unison_vibratto[nvoice].step = memory.valloc<float>(unison);
+ unison_vibratto[nvoice].position = memory.valloc<float>(unison);
+ unison_vibratto[nvoice].amplitude =
+ (unison_real_spread - 1.0f) * unison_vibratto_a;
+
+ const float increments_per_second = synth.samplerate_f / synth.buffersize_f;
+ const float vib_speed = pars.VoicePar[nvoice].Unison_vibratto_speed / 127.0f;
+ const float vibratto_base_period = 0.25f * powf(2.0f, (1.0f - vib_speed) * 4.0f);
+ for(int k = 0; k < unison; ++k) {
+ unison_vibratto[nvoice].position[k] = RND * 1.8f - 0.9f;
+ //make period to vary randomly from 50% to 200% vibratto base period
+ const float vibratto_period = vibratto_base_period
+ * powf(2.0f, RND * 2.0f - 1.0f);
+
+ const float m = (RND < 0.5f ? -1.0f : 1.0f) *
+ 4.0f / (vibratto_period * increments_per_second);
+ unison_vibratto[nvoice].step[k] = m;
+
+ // Ugly, but the alternative is likely uglier.
if (is_pwm)
- for (int i = true_unison - 1; i >= 0; i--) {
- unison_base_freq_rap[nvoice][2*i + 1] =
- unison_base_freq_rap[nvoice][i];
- unison_base_freq_rap[nvoice][2*i] =
- unison_base_freq_rap[nvoice][i];
+ for (int i = 0; i < unison; i += 2) {
+ unison_vibratto[nvoice].step[i+1] =
+ unison_vibratto[nvoice].step[i];
+ unison_vibratto[nvoice].position[i+1] =
+ unison_vibratto[nvoice].position[i];
}
+ }
- //unison vibrattos
- if(unison > 2 || (!is_pwm && unison > 1))
- for(int k = 0; k < unison; ++k) //reduce the frequency difference for larger vibrattos
- unison_base_freq_rap[nvoice][k] = 1.0f
- + (unison_base_freq_rap[
- nvoice][k] - 1.0f)
- * (1.0f - unison_vibratto_a);
- unison_vibratto[nvoice].step = memory.valloc<float>(unison);
- unison_vibratto[nvoice].position = memory.valloc<float>(unison);
- unison_vibratto[nvoice].amplitude =
- (unison_real_spread - 1.0f) * unison_vibratto_a;
-
- 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) {
- unison_vibratto[nvoice].position[k] = RND * 1.8f - 0.9f;
- //make period to vary randomly from 50% to 200% vibratto base period
- float vibratto_period = vibratto_base_period
- * powf(2.0f, RND * 2.0f - 1.0f);
-
- float m = 4.0f / (vibratto_period * increments_per_second);
- if(RND < 0.5f)
- m = -m;
- unison_vibratto[nvoice].step[k] = m;
-
- // Ugly, but the alternative is likely uglier.
- if (is_pwm)
- for (int i = 0; i < unison; i += 2) {
- unison_vibratto[nvoice].step[i+1] =
- unison_vibratto[nvoice].step[i];
- unison_vibratto[nvoice].position[i+1] =
- unison_vibratto[nvoice].position[i];
- }
+ if(unison <= 2) { //no vibratto for a single voice
+ if (is_pwm) {
+ unison_vibratto[nvoice].step[1] = 0.0f;
+ unison_vibratto[nvoice].position[1] = 0.0f;
}
-
- if(unison <= 2) { //no vibratto for a single voice
- if (is_pwm) {
- unison_vibratto[nvoice].step[1] = 0.0f;
- unison_vibratto[nvoice].position[1] = 0.0f;
- }
- if (is_pwm || unison == 1) {
- unison_vibratto[nvoice].step[0] = 0.0f;
- unison_vibratto[nvoice].position[0] = 0.0f;
- unison_vibratto[nvoice].amplitude = 0.0f;
- }
+ if (is_pwm || unison == 1) {
+ unison_vibratto[nvoice].step[0] = 0.0f;
+ unison_vibratto[nvoice].position[0] = 0.0f;
+ unison_vibratto[nvoice].amplitude = 0.0f;
}
+ }
- //phase invert for unison
- unison_invert_phase[nvoice][0] = false;
- if(unison != 1) {
- int inv = pars.VoicePar[nvoice].Unison_invert_phase;
- switch(inv) {
- case 0: for(int k = 0; k < unison; ++k)
- unison_invert_phase[nvoice][k] = false;
- break;
- case 1: for(int k = 0; k < unison; ++k)
- unison_invert_phase[nvoice][k] = (RND > 0.5f);
- break;
- default: for(int k = 0; k < unison; ++k)
- unison_invert_phase[nvoice][k] =
- (k % inv == 0) ? true : false;
- break;
- }
+ //phase invert for unison
+ unison_invert_phase[nvoice][0] = false;
+ if(unison != 1) {
+ int inv = pars.VoicePar[nvoice].Unison_invert_phase;
+ switch(inv) {
+ case 0:
+ for(int k = 0; k < unison; ++k)
+ unison_invert_phase[nvoice][k] = false;
+ break;
+ case 1:
+ for(int k = 0; k < unison; ++k)
+ unison_invert_phase[nvoice][k] = (RND > 0.5f);
+ break;
+ default:
+ for(int k = 0; k < unison; ++k)
+ unison_invert_phase[nvoice][k] =
+ (k % inv == 0) ? true : false;
+ break;
}
+ }
+ return unison;
+}
-
- oscfreqhi[nvoice] = memory.valloc<int>(unison);
- oscfreqlo[nvoice] = memory.valloc<float>(unison);
- oscfreqhiFM[nvoice] = memory.valloc<unsigned int>(unison);
- oscfreqloFM[nvoice] = memory.valloc<float>(unison);
- oscposhi[nvoice] = memory.valloc<int>(unison);
- oscposlo[nvoice] = memory.valloc<float>(unison);
- oscposhiFM[nvoice] = memory.valloc<unsigned int>(unison);
- oscposloFM[nvoice] = memory.valloc<float>(unison);
-
- NoteVoicePar[nvoice].Enabled = ON;
- NoteVoicePar[nvoice].fixedfreq = pars.VoicePar[nvoice].Pfixedfreq;
- NoteVoicePar[nvoice].fixedfreqET = pars.VoicePar[nvoice].PfixedfreqET;
-
- //use the Globalpars.detunetype if the detunetype is 0
- if(pars.VoicePar[nvoice].PDetuneType != 0) {
- NoteVoicePar[nvoice].Detune = getdetune(
+void ADnote::setupVoiceDetune(int nvoice)
+{
+ //use the Globalpars.detunetype if the detunetype is 0
+ if(pars.VoicePar[nvoice].PDetuneType != 0) {
+ NoteVoicePar[nvoice].Detune = getdetune(
pars.VoicePar[nvoice].PDetuneType,
pars.VoicePar[nvoice].
PCoarseDetune,
8192); //coarse detune
- NoteVoicePar[nvoice].FineDetune = getdetune(
+ NoteVoicePar[nvoice].FineDetune = getdetune(
pars.VoicePar[nvoice].PDetuneType,
0,
pars.VoicePar[nvoice].PDetune); //fine detune
- }
- else {
- NoteVoicePar[nvoice].Detune = getdetune(
+ }
+ else {
+ NoteVoicePar[nvoice].Detune = getdetune(
pars.GlobalPar.PDetuneType,
pars.VoicePar[nvoice].
PCoarseDetune,
8192); //coarse detune
- NoteVoicePar[nvoice].FineDetune = getdetune(
+ NoteVoicePar[nvoice].FineDetune = getdetune(
pars.GlobalPar.PDetuneType,
0,
pars.VoicePar[nvoice].PDetune); //fine detune
- }
- if(pars.VoicePar[nvoice].PFMDetuneType != 0)
- NoteVoicePar[nvoice].FMDetune = getdetune(
+ }
+ if(pars.VoicePar[nvoice].PFMDetuneType != 0)
+ NoteVoicePar[nvoice].FMDetune = getdetune(
pars.VoicePar[nvoice].PFMDetuneType,
pars.VoicePar[nvoice].
PFMCoarseDetune,
pars.VoicePar[nvoice].PFMDetune);
- else
- NoteVoicePar[nvoice].FMDetune = getdetune(
+ else
+ NoteVoicePar[nvoice].FMDetune = getdetune(
pars.GlobalPar.PDetuneType,
pars.VoicePar[nvoice].
PFMCoarseDetune,
pars.VoicePar[nvoice].PFMDetune);
+}
-
-
- for(int k = 0; k < unison; ++k) {
- oscposhi[nvoice][k] = 0;
- oscposlo[nvoice][k] = 0.0f;
- oscposhiFM[nvoice][k] = 0;
- oscposloFM[nvoice][k] = 0.0f;
- }
-
- //the extra points contains the first point
- NoteVoicePar[nvoice].OscilSmp =
- memory.valloc<float>(synth.oscilsize + OSCIL_SMP_EXTRA_SAMPLES);
-
- //Get the voice's oscil or external's voice oscil
- int vc = nvoice;
- if(pars.VoicePar[nvoice].Pextoscil != -1)
- vc = pars.VoicePar[nvoice].Pextoscil;
- if(!pars.GlobalPar.Hrandgrouping)
- pars.VoicePar[vc].OscilSmp->newrandseed(prng());
- int oscposhi_start =
- pars.VoicePar[vc].OscilSmp->get(NoteVoicePar[nvoice].OscilSmp,
- getvoicebasefreq(nvoice),
- pars.VoicePar[nvoice].Presonance);
-
- // This code was planned for biasing the carrier in MOD_RING
- // but that's on hold for the moment. Disabled 'cos small
- // machines run this stuff too.
- //
- // //Find range of generated wave
- // float min = NoteVoicePar[nvoice].OscilSmp[0];
- // float max = min;
- // float *smpls = &(NoteVoicePar[nvoice].OscilSmp[1]);
- // for (int i = synth.oscilsize-1; i--; smpls++)
- // if (*smpls > max)
- // max = *smpls;
- // else if (*smpls < min)
- // min = *smpls;
- // NoteVoicePar[nvoice].OscilSmpMin = min;
- // NoteVoicePar[nvoice].OscilSmpMax = max;
-
- //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
- + i] =
- NoteVoicePar[nvoice].OscilSmp[i];
-
- NoteVoicePar[nvoice].phase_offset =
- (int)((pars.VoicePar[nvoice].Poscilphase
- - 64.0f) / 128.0f * synth.oscilsize
- + synth.oscilsize * 4);
- oscposhi_start += NoteVoicePar[nvoice].phase_offset;
-
- int kth_start = oscposhi_start;
- for(int k = 0; k < unison; ++k) {
- oscposhi[nvoice][k] = kth_start % synth.oscilsize;
- //put random starting point for other subvoices
- kth_start = oscposhi_start +
- (int)(RND * pars.VoicePar[nvoice].Unison_phase_randomness /
- 127.0f * (synth.oscilsize - 1));
- }
-
- NoteVoicePar[nvoice].FreqLfo = NULL;
- NoteVoicePar[nvoice].FreqEnvelope = NULL;
-
- NoteVoicePar[nvoice].AmpLfo = NULL;
- NoteVoicePar[nvoice].AmpEnvelope = NULL;
-
- NoteVoicePar[nvoice].Filter = NULL;
- NoteVoicePar[nvoice].FilterEnvelope = NULL;
- NoteVoicePar[nvoice].FilterLfo = NULL;
-
- NoteVoicePar[nvoice].filterbypass =
- pars.VoicePar[nvoice].Pfilterbypass;
-
- if (pars.VoicePar[nvoice].Type != 0)
- NoteVoicePar[nvoice].FMEnabled = NONE;
- else
- switch(pars.VoicePar[nvoice].PFMEnabled) {
- case 1:
- NoteVoicePar[nvoice].FMEnabled = MORPH;
- break;
- case 2:
- NoteVoicePar[nvoice].FMEnabled = RING_MOD;
- break;
- case 3:
- NoteVoicePar[nvoice].FMEnabled = PHASE_MOD;
- break;
- case 4:
- NoteVoicePar[nvoice].FMEnabled = FREQ_MOD;
- break;
- case 5:
- NoteVoicePar[nvoice].FMEnabled = PW_MOD;
- break;
- default:
- NoteVoicePar[nvoice].FMEnabled = NONE;
- }
-
- NoteVoicePar[nvoice].FMVoice = pars.VoicePar[nvoice].PFMVoice;
- NoteVoicePar[nvoice].FMFreqEnvelope = NULL;
- NoteVoicePar[nvoice].FMAmpEnvelope = NULL;
- NoteVoicePar[nvoice].FMFreqFixed = pars.VoicePar[nvoice].PFMFixedFreq;
-
-
- //Compute the Voice's modulator volume (incl. damping)
- float fmvoldamp = powf(440.0f / getvoicebasefreq(
- nvoice),
- pars.VoicePar[nvoice].PFMVolumeDamp / 64.0f
- - 1.0f);
- switch(NoteVoicePar[nvoice].FMEnabled) {
- case PHASE_MOD:
- case PW_MOD:
- fmvoldamp =
- powf(440.0f / getvoicebasefreq(
- nvoice), pars.VoicePar[nvoice].PFMVolumeDamp
- / 64.0f);
- NoteVoicePar[nvoice].FMVolume =
- (expf(pars.VoicePar[nvoice].PFMVolume / 127.0f
- * FM_AMP_MULTIPLIER) - 1.0f) * fmvoldamp * 4.0f;
+void ADnote::setupVoiceMod(int nvoice)
+{
+ auto ¶m = pars.VoicePar[nvoice];
+ auto &voice = NoteVoicePar[nvoice];
+ if (param.Type != 0)
+ voice.FMEnabled = NONE;
+ else
+ switch(param.PFMEnabled) {
+ case 1:
+ voice.FMEnabled = MORPH;
break;
- case FREQ_MOD:
- NoteVoicePar[nvoice].FMVolume =
- (expf(pars.VoicePar[nvoice].PFMVolume / 127.0f
- * FM_AMP_MULTIPLIER) - 1.0f) * fmvoldamp * 4.0f;
+ case 2:
+ voice.FMEnabled = RING_MOD;
+ break;
+ case 3:
+ voice.FMEnabled = PHASE_MOD;
+ break;
+ case 4:
+ voice.FMEnabled = FREQ_MOD;
+ break;
+ case 5:
+ voice.FMEnabled = PW_MOD;
break;
default:
- if(fmvoldamp > 1.0f)
- fmvoldamp = 1.0f;
- NoteVoicePar[nvoice].FMVolume =
- pars.VoicePar[nvoice].PFMVolume
- / 127.0f * fmvoldamp;
+ voice.FMEnabled = NONE;
}
- //Voice's modulator velocity sensing
- NoteVoicePar[nvoice].FMVolume *=
- VelF(velocity,
- pars.VoicePar[nvoice].PFMVelocityScaleFunction);
-
- FMoldsmp[nvoice] = memory.valloc<float>(unison);
- for(int k = 0; k < unison; ++k)
- FMoldsmp[nvoice][k] = 0.0f; //this is for FM (integration)
-
- firsttick[nvoice] = 1;
- NoteVoicePar[nvoice].DelayTicks =
- (int)((expf(pars.VoicePar[nvoice].PDelay / 127.0f
- * logf(50.0f))
- - 1.0f) / synth.buffersize_f / 10.0f * synth.samplerate_f);
- }
-
- max_unison = 1;
- for(int nvoice = 0; nvoice < NUM_VOICES; ++nvoice)
- if(unison_size[nvoice] > max_unison)
- max_unison = unison_size[nvoice];
-
-
- 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);
+ voice.FMFreqFixed = param.PFMFixedFreq;
+
+
+ //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;
+ switch(voice.FMEnabled) {
+ case PHASE_MOD:
+ case PW_MOD:
+ fmvoldamp = powf(440.0f / getvoicebasefreq(nvoice),
+ param.PFMVolumeDamp / 64.0f);
+ voice.FMVolume = (expf(fmvolume_ * FM_AMP_MULTIPLIER) - 1.0f)
+ * fmvoldamp * 4.0f;
+ break;
+ case FREQ_MOD:
+ voice.FMVolume = (expf(fmvolume_ * FM_AMP_MULTIPLIER) - 1.0f)
+ * fmvoldamp * 4.0f;
+ break;
+ default:
+ if(fmvoldamp > 1.0f)
+ fmvoldamp = 1.0f;
+ voice.FMVolume = fmvolume_ * fmvoldamp;
}
- initparameters(wm, prefix);
- memory.endTransaction();
+ //Voice's modulator velocity sensing
+ NoteVoicePar[nvoice].FMVolume *=
+ VelF(velocity, pars.VoicePar[nvoice].PFMVelocityScaleFunction);
}
SynthNote *ADnote::cloneLegato(void)
@@ -914,7 +927,7 @@ void ADnote::initparameters(WatchManager *wm, const char *prefix)
FMnewamplitude[nvoice] = vce.FMVolume * ctl.fmamp.relamp;
- if(param.PFMAmpEnvelopeEnabled ) {
+ if(param.PFMAmpEnvelopeEnabled) {
vce.FMAmpEnvelope =
memory.alloc<Envelope>(*param.FMAmpEnvelope,
basefreq, synth.dt(), wm,
@@ -1552,6 +1565,16 @@ int ADnote::noteout(float *outl, float *outr)
memset(bypassl, 0, synth.bufferbytes);
memset(bypassr, 0, synth.bufferbytes);
+
+ //Update Changed Parameters From UI
+ for(unsigned nvoice = 0; nvoice < NUM_VOICES; ++nvoice) {
+ if((NoteVoicePar[nvoice].Enabled != ON)
+ || (NoteVoicePar[nvoice].DelayTicks > 0))
+ continue;
+ setupVoiceDetune(nvoice);
+ setupVoiceMod(nvoice);
+ }
+
computecurrentparameters();
for(unsigned nvoice = 0; nvoice < NUM_VOICES; ++nvoice) {
diff --git a/src/Synth/ADnote.h b/src/Synth/ADnote.h
@@ -51,6 +51,11 @@ class ADnote:public SynthNote
virtual SynthNote *cloneLegato(void) override;
private:
+ void setupVoice(int nvoice);
+ int setupVoiceUnison(int nvoice);
+ void setupVoiceDetune(int nvoice);
+ void setupVoiceMod(int nvoice);
+
/**Changes the frequency of an oscillator.
* @param nvoice voice to run computations on
* @param in_freq new frequency*/