commit 08bf033917388745b3a706ca58b572fcd1fc0452
parent 20ed6166c0ebeb61323ffad0b0b2fc06cf2320f5
Author: friedolino78 <34608315+friedolino78@users.noreply.github.com>
Date: Wed, 28 Sep 2022 23:48:21 +0200
implement guitar string frequencies (#207)
Also:
* Add stringchoir sizes
* Add preset menu to FL GUI
Diffstat:
4 files changed, 146 insertions(+), 19 deletions(-)
diff --git a/src/Effects/CombFilterBank.cpp b/src/Effects/CombFilterBank.cpp
@@ -107,6 +107,7 @@ namespace zyn {
for (unsigned int j = 0; j < nrOfStrings; ++j)
{
+ if (delays[j] == 0.0f) continue;
assert(float(mem_size)>delays[j]);
// calculate the feedback sample positions in the buffer
const float pos_reader = fmodf(float(pos_writer+mem_size) - delays[j], float(mem_size));
@@ -117,13 +118,17 @@ namespace zyn {
}
// mix output buffer samples to output sample
smp[i]=0.0f;
+ unsigned int nrOfActualStrings = 0;
for (unsigned int j = 0; j < nrOfStrings; ++j)
- smp[i] += string_smps[j][pos_writer];
+ if (delays[j] != 0.0f) {
+ smp[i] += string_smps[j][pos_writer];
+ nrOfActualStrings++;
+ }
// apply output gain to sum of strings and
// divide by nrOfStrings to get mean value
// division by zero is catched at the beginning filterOut()
- smp[i] *= outgain / (float)nrOfStrings;
+ smp[i] *= outgain / (float)nrOfActualStrings;
// increment writing position
++pos_writer %= mem_size;
diff --git a/src/Effects/Sympathetic.cpp b/src/Effects/Sympathetic.cpp
@@ -32,7 +32,7 @@ namespace zyn {
rtosc::Ports Sympathetic::ports = {
{"preset::i", rProp(parameter)
- rOptions(Piano, Grand, Guitar, 12-String)
+ rOptions(Generic, Piano, Grand, Guitar, 12-String)
rDoc("Instrument Presets"), 0,
rBegin;
rObject *o = (rObject*)d.obj;
@@ -41,25 +41,25 @@ rtosc::Ports Sympathetic::ports = {
else
d.reply(d.loc, "i", o->Ppreset);
rEnd},
- rEffParVol(rDefault(127)),
+ rEffParVol(rDefault(127), rPresets(100, 80, 100, 90)),
rEffParPan(rDefault(64)),
rEffPar(Pq, 2, rShort("q"), rDefault(65),
- "Resonance"),
+ rPresets(125, 125, 110, 110), "Resonance"),
rEffPar(Pdrive, 3, rShort("dr"), rDefault(65),
- "Input Amplification"),
+ rPresets(5, 5, 20, 20), "Input Amplification"),
rEffPar(Plevel, 4, rShort("lev"), rDefault(65),
- "Output Amplification"),
+ rPresets(80, 90, 65, 77), "Output Amplification"),
rEffPar(Punison_frequency_spread, 5, rShort("detune"), rDefault(30),
- "Unison String Detune"),
+ rPresets(10, 5, 0, 10), "Unison String Detune"),
rEffParTF(Pnegate, 6, rShort("neg"), rDefault(false), "Negate Signal"),
rEffPar(Plpf, 7, rShort("lpf"), rDefault(127), "Low Pass Cutoff"),
rEffPar(Phpf, 8, rShort("hpf"), rDefault(0), "High Pass Cutoff"),
rEffParRange(Punison_size, 9, rShort("uni"), rLinear(1,3), rDefault(1),
- "Number of Unison Strings"),
+ rPresets(3, 1, 1, 2), "Number of Unison Strings"),
rEffParRange(Pstrings, 10, rShort("str"), rLinear(0,76), rDefault(0),
- "Number of Strings"),
+ rPresets(12, 60, 6, 6), "Number of Strings"),
rEffPar(Pbasenote, 11, rShort("base"), rDefault(57), // basefreq = powf(2.0f, (basenote-69)/12)*440; 57->220Hz
- "Midi Note of Lowest String"),
+ rPresets(57, 33, 52, 52), "Midi Note of Lowest String"),
rArrayF(freqs, 88, rLinear(27.50f,4186.01f),
"String Frequencies"),
};
@@ -198,13 +198,30 @@ void Sympathetic::sethpf(unsigned char _Phpf)
void Sympathetic::calcFreqs()
{
+ switch(Ppreset) {
+ case 0:
+ calcFreqsGeneric();
+ break;
+ case 1:
+ case 2:
+ calcFreqsPiano();
+ break;
+ case 3:
+ case 4:
+ calcFreqsGuitar();
+ break;
+ }
+}
+
+void Sympathetic::calcFreqsGeneric()
+{
const float unison_spread_semicent = powf(Punison_frequency_spread / 63.5f, 2.0f) * 25.0f;
const float unison_real_spread_up = powf(2.0f, (unison_spread_semicent * 0.5f) / 1200.0f);
const float unison_real_spread_down = 1.0f/unison_real_spread_up;
for(unsigned int i = 0; i < Punison_size*Pstrings; i+=Punison_size)
{
- const float centerFreq = powf(2.0f, (float)i / 12.0f) * baseFreq;
+ const float centerFreq = powf(2.0f, (float)i / 36.0f) * baseFreq;
filterBank->delays[i] = ((float)samplerate)/centerFreq;
if (Punison_size > 1) filterBank->delays[i+1] = ((float)samplerate)/(centerFreq * unison_real_spread_up);
if (Punison_size > 2) filterBank->delays[i+2] = ((float)samplerate)/(centerFreq * unison_real_spread_down);
@@ -213,20 +230,56 @@ void Sympathetic::calcFreqs()
}
+void Sympathetic::calcFreqsPiano()
+{
+ const float unison_spread_semicent = powf(Punison_frequency_spread / 63.5f, 2.0f) * 25.0f;
+ const float unison_real_spread_up = powf(2.0f, (unison_spread_semicent * 0.5f) / 1200.0f);
+ const float unison_real_spread_down = 1.0f/unison_real_spread_up;
+
+ for(unsigned int i = 0; i < Punison_size*Pstrings; i+=Punison_size)
+ {
+ const float centerFreq = powf(2.0f, (float)i / 36.0f) * baseFreq;
+ const unsigned int stringchoir_size =
+ i>num_single_strings ? (i>Pstrings-num_triple_strings ? 3 : 2) :1;
+ filterBank->delays[i] = ((float)samplerate)/centerFreq;
+ if (stringchoir_size > 1) filterBank->delays[i+1] = ((float)samplerate)/(centerFreq * unison_real_spread_up);
+ else filterBank->delays[i+1] = 0;
+ if (stringchoir_size > 2) filterBank->delays[i+2] = ((float)samplerate)/(centerFreq * unison_real_spread_down);
+ else filterBank->delays[i+2] = 0;
+ }
+ filterBank->setStrings(Pstrings*Punison_size,baseFreq);
+
+}
+
+void Sympathetic::calcFreqsGuitar()
+{
+ const float unison_spread_semicent = powf(Punison_frequency_spread / 63.5f, 2.0f) * 25.0f;
+ const float unison_real_spread_up = powf(2.0f, (unison_spread_semicent * 0.5f) / 1200.0f);
+
+ for(auto i = 0; i < 6*Punison_size; i+=Punison_size)
+ {
+ assert(guitar_freqs[i/Punison_size]>0.0f);
+ filterBank->delays[i] = ((float)samplerate)/guitar_freqs[i/Punison_size];
+ if (Punison_size > 1) filterBank->delays[i+1] = ((float)samplerate)/(guitar_freqs[i/Punison_size] * unison_real_spread_up);
+ }
+ filterBank->setStrings(Pstrings*Punison_size,guitar_freqs[0]);
+
+}
+
unsigned char Sympathetic::getpresetpar(unsigned char npreset, unsigned int npar)
{
#define PRESET_SIZE 13
#define NUM_PRESETS 4
static const unsigned char presets[NUM_PRESETS][PRESET_SIZE] = {
- //Vol Pan Q Drive Lev Spr neg lp hp sz strings note cross
+ //Vol Pan Q Drive Lev Spr neg lp hp sz strings note
//Piano 12-String
{100, 64, 125, 5, 80, 10, 0, 127, 0, 3, 12, 57},
//Piano 60-String
{80, 64, 125, 5, 90, 5, 0, 127, 0, 1, 60, 33},
//Guitar 6-String
- {100, 64, 110, 5, 65, 0, 0, 127, 0, 1, 6, 52},
+ {100, 64, 110, 20, 65, 0, 0, 127, 0, 1, 6, 52},
//Guitar 12-String
- {90, 64, 110, 5, 77, 10, 0, 127, 0, 2, 6, 52},
+ {90, 64, 110, 20, 77, 10, 0, 127, 0, 2, 6, 52},
};
if(npreset < NUM_PRESETS && npar < PRESET_SIZE) {
if(npar == 0 && insertion == 0) {
@@ -245,6 +298,8 @@ void Sympathetic::setpreset(unsigned char npreset)
for(int n = 0; n != 128; n++)
changepar(n, getpresetpar(npreset, n));
Ppreset = npreset;
+
+ calcFreqs();
cleanup();
}
@@ -288,10 +343,12 @@ void Sympathetic::changepar(int npar, unsigned char value)
break;
case 9:
Punison_size = limit(value, (unsigned char) 1, (unsigned char) 3);
+ if (Punison_size>2) Ppreset=0;
calcFreqs();
break;
case 10:
Pstrings = limit(value, (unsigned char) 0, (unsigned char) 76);
+ if (Pstrings>6) Ppreset=0;
calcFreqs();
break;
case 11:
diff --git a/src/Effects/Sympathetic.h b/src/Effects/Sympathetic.h
@@ -24,6 +24,14 @@ namespace zyn {
const float gainbwd_offset = 0.873f;
const float gainbwd_factor = 0.001f;
+// number of piano keys with single string
+const unsigned int num_single_strings = 12;
+// number of piano keys with triple strings
+const unsigned int num_triple_strings = 48;
+
+// frequencies of a guitar in standard e tuning
+const float guitar_freqs[6] = {82.4f, 110.0f, 146.8f, 196.0f, 246.9f, 329.6f};
+
class Sympathetic:public Effect
{
@@ -64,6 +72,9 @@ class Sympathetic:public Effect
void setlpf(unsigned char _Plpf);
void sethpf(unsigned char _Phpf);
void calcFreqs();
+ void calcFreqsGeneric();
+ void calcFreqsPiano();
+ void calcFreqsGuitar();
//Real Parameters
class AnalogFilter * lpfl, *lpfr, *hpfl, *hpfr;
diff --git a/src/UI/EffUI.fl b/src/UI/EffUI.fl
@@ -1164,6 +1164,33 @@ eqgraph->update();}
code3 {set_module_parameters(o);}
class Fl_Group visible
} {
+ Fl_Choice sympp {
+ label Preset
+ xywh {11 15 95 15} box UP_BOX down_box BORDER_BOX color 47 selection_color 7 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10
+ code0 {o->init("preset");}
+ class Fl_Osc_Choice
+ } {
+ MenuItem {} {
+ label {Generic}
+ xywh {20 20 100 20} labelfont 1 labelsize 10
+ }
+ MenuItem {} {
+ label {Piano}
+ xywh {30 30 100 20} labelfont 1 labelsize 10
+ }
+ MenuItem {} {
+ label {Grand}
+ xywh {40 40 100 20} labelfont 1 labelsize 10
+ }
+ MenuItem {} {
+ label {Guitar}
+ xywh {50 50 100 20} labelfont 1 labelsize 10
+ }
+ MenuItem {} {
+ label {12-String}
+ xywh {50 50 100 20} labelfont 1 labelsize 10
+ }
+ }
Fl_Dial symp0 {
label Vol
tooltip {Effect Volume} xywh {10 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
@@ -1202,7 +1229,7 @@ eqgraph->update();}
}
Fl_Dial symp10 {
label Str
- tooltip {number of strings} xywh {220 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 48
+ tooltip {number of strings} xywh {220 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 76
code0 {o->init("parameter10");}
class Fl_Osc_Dial
}
@@ -1319,7 +1346,7 @@ switch(efftype){
effalienwahwindow->show();
break;
case 6:
- effdistortionwindow->show();
+ effdistortionwindow->show();
break;
case 7:eqband=0;
bandcounter->value(eqband);
@@ -2091,6 +2118,33 @@ eqgraph->redraw();}
code3 {set_module_parameters(o);}
class Fl_Group visible
} {
+ Fl_Choice sympp {
+ label Preset
+ xywh {11 15 95 15} box UP_BOX down_box BORDER_BOX color 47 selection_color 7 labelfont 1 labelsize 10 align 5 textfont 1 textsize 10
+ code0 {o->init("preset");}
+ class Fl_Osc_Choice
+ } {
+ MenuItem {} {
+ label {Generic}
+ xywh {20 20 100 20} labelfont 1 labelsize 10
+ }
+ MenuItem {} {
+ label {Piano}
+ xywh {30 30 100 20} labelfont 1 labelsize 10
+ }
+ MenuItem {} {
+ label {Grand}
+ xywh {40 40 100 20} labelfont 1 labelsize 10
+ }
+ MenuItem {} {
+ label {Guitar}
+ xywh {50 50 100 20} labelfont 1 labelsize 10
+ }
+ MenuItem {} {
+ label {12-String}
+ xywh {50 50 100 20} labelfont 1 labelsize 10
+ }
+ }
Fl_Dial symp0 {
label Vol
tooltip {Effect Volume} xywh {10 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
@@ -2129,7 +2183,7 @@ eqgraph->redraw();}
}
Fl_Dial symp10 {
label Strings
- tooltip {number of strings} xywh {220 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 127
+ tooltip {number of strings} xywh {220 40 30 30} box ROUND_UP_BOX labelfont 1 labelsize 11 maximum 76
code0 {o->init("parameter10");}
class Fl_Osc_Dial
}
@@ -2218,7 +2272,7 @@ switch(efftype){
effalienwahwindow->show();
break;
case 6:
- effdistortionwindow->show();
+ effdistortionwindow->show();
break;
case 7:
bandcounter->value(eqband);