1
/*******************************************/
3
Four Resonance Modal Synthesis Instrument
4
by Perry R. Cook, 1995-2000
6
This instrument contains an excitation
7
wavetable, an envelope, an oscillator,
8
and four resonances (Non-Sweeping BiQuad
11
/*******************************************/
17
envelope = new Envelope;
18
// We don't make the excitation wave here yet,
19
// because we don't know what it's going to be.
20
filters[0] = new BiQuad;
21
filters[1] = new BiQuad;
22
filters[2] = new BiQuad;
23
filters[3] = new BiQuad;
24
onepole = new OnePole;
26
// Concatenate the STK RAWWAVE_PATH to the rawwave file
28
strcpy(file, RAWWAVE_PATH);
29
vibr = new RawWvIn(strcat(file,"rawwaves/sinewave.raw"),"looping");
30
vibr->setFreq((MY_FLOAT) 6.0);
31
vibrGain = (MY_FLOAT) 0.0; // zero gain by default
33
directGain = (MY_FLOAT) 0.0;
34
masterGain = (MY_FLOAT) 1.0;
35
baseFreq = (MY_FLOAT) 440.0;
36
this->setRatioAndReson(0,(MY_FLOAT) 1.00,(MY_FLOAT) 0.9997); /* Set some */
37
this->setRatioAndReson(1,(MY_FLOAT) 1.30,(MY_FLOAT) 0.9997); /* silly */
38
this->setRatioAndReson(2,(MY_FLOAT) 1.77,(MY_FLOAT) 0.9997); /* default */
39
this->setRatioAndReson(3,(MY_FLOAT) 2.37,(MY_FLOAT) 0.9997); /* values here */
40
this->setFiltGain(0,(MY_FLOAT) 0.01);
41
this->setFiltGain(1,(MY_FLOAT) 0.01);
42
this->setFiltGain(2,(MY_FLOAT) 0.01);
43
this->setFiltGain(3,(MY_FLOAT) 0.01);
45
filters[0]->setEqualGainZeroes();
46
filters[1]->setEqualGainZeroes();
47
filters[2]->setEqualGainZeroes();
48
filters[3]->setEqualGainZeroes();
49
stickHardness = (MY_FLOAT) 0.5;
50
strikePosition = (MY_FLOAT) 0.561;
64
void Modal4 :: clear()
73
void Modal4 :: setFreq(MY_FLOAT frequency)
76
this->setRatioAndReson(0,ratios[0],resons[0]);
77
this->setRatioAndReson(1,ratios[1],resons[1]);
78
this->setRatioAndReson(2,ratios[2],resons[2]);
79
this->setRatioAndReson(3,ratios[3],resons[3]);
84
void Modal4 :: setRatioAndReson(int whichOne, MY_FLOAT ratio,MY_FLOAT reson)
88
if (ratio*baseFreq < SRATE_OVER_TWO) {
89
ratios[whichOne] = ratio;
93
while (temp*baseFreq > SRATE_OVER_TWO) temp *= (MY_FLOAT) 0.5;
94
ratios[whichOne] = temp;
96
printf("Modal4 : Aliasing would occur here, correcting.\n");
99
resons[whichOne] = reson;
103
temp = ratio*baseFreq;
105
filters[whichOne]->setFreqAndReson(temp,reson);
108
void Modal4 :: setMasterGain(MY_FLOAT aGain)
113
void Modal4 :: setDirectGain(MY_FLOAT aGain)
118
void Modal4 :: setFiltGain(int whichOne, MY_FLOAT gain)
120
filters[whichOne]->setGain(gain);
123
void Modal4 :: strike(MY_FLOAT amplitude)
128
envelope->setRate((MY_FLOAT) 1.0);
129
envelope->setTarget(amplitude);
130
onepole->setPole((MY_FLOAT) 1.0 - amplitude);
134
for (i=0; i<4; i++) {
138
temp = ratios[i] * baseFreq;
139
filters[i]->setFreqAndReson(temp,resons[i]);
143
void Modal4 :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
148
printf("Modal4 : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
152
/* This calls damp, but inverts the meaning of amplitude
153
* (high amplitude means fast damping).
155
void Modal4 :: noteOff(MY_FLOAT amp)
157
this->damp((MY_FLOAT) 1.0 - (amp * (MY_FLOAT) 0.03));
159
printf("Modal4 : NoteOff: Amp=%lf\n",amp);
163
void Modal4 :: damp(MY_FLOAT amplitude)
168
for (i=0; i<4; i++) {
172
temp = ratios[i] * baseFreq;
173
filters[i]->setFreqAndReson(temp,resons[i]*amplitude);
177
void Modal4 :: controlChange(int number, MY_FLOAT value)
181
MY_FLOAT Modal4 :: tick()
185
temp = masterGain * onepole->tick(wave->tick() * envelope->tick());
186
temp2 = filters[0]->tick(temp);
187
temp2 += filters[1]->tick(temp);
188
temp2 += filters[2]->tick(temp);
189
temp2 += filters[3]->tick(temp);
190
temp2 = temp2 - (temp2 * directGain);
191
temp2 += directGain * temp;
193
if (vibrGain != 0.0) {
194
// Calculate AM and apply to master out
195
temp = (MY_FLOAT) 1.0 + (vibr->tick() * vibrGain);
196
temp2 = temp * temp2;
199
lastOutput = temp2 * (MY_FLOAT) 2.0;