mirror of
https://github.com/thestk/stk
synced 2026-01-11 20:11:52 +00:00
117 lines
4.5 KiB
C++
117 lines
4.5 KiB
C++
/********************************************/
|
|
/* Commuted Mandolin Subclass of enhanced */
|
|
/* dual plucked-string model */
|
|
/* by Perry Cook, 1995-96 */
|
|
/* Controls: CONTROL1 = bodySize */
|
|
/* CONTROL2 = pluckPosition */
|
|
/* CONTROL3 = loopGain */
|
|
/* MOD_WHEEL= deTuning */
|
|
/* */
|
|
/* Note: Commuted Synthesis, as with many */
|
|
/* other WaveGuide techniques, is covered */
|
|
/* by patents, granted, pending, and/or */
|
|
/* applied-for. Many are assigned to the */
|
|
/* Board of Trustees, Stanford University. */
|
|
/* For information, contact the Office of */
|
|
/* Technology Licensing, Stanford U. */
|
|
/********************************************/
|
|
|
|
#include "Mandolin.h"
|
|
|
|
Mandolin :: Mandolin(MY_FLOAT lowestFreq) : Plucked2(lowestFreq)
|
|
{
|
|
soundfile = new RawWave("rawwaves/mandpluk.raw");
|
|
soundfile->normalize(0.05); /* Empirical hack here */
|
|
soundfile->setLooping(0);
|
|
dampTime = 0;
|
|
waveDone = 1;
|
|
}
|
|
|
|
void Mandolin :: pluck(MY_FLOAT amplitude)
|
|
{ /* this function gets interesting here, */
|
|
soundfile->reset(); /* because pluck may be longer than */
|
|
pluckAmp = amplitude; /* string length, so we just reset the */
|
|
/* soundfile and add in the pluck in */
|
|
/* the tick method. */
|
|
combDelay->setDelay(
|
|
0.5 * pluckPos * lastLength); /* Set Pick Position */
|
|
/* which puts zeroes at pos*length */
|
|
dampTime = (long) lastLength; /* See tick method below */
|
|
waveDone = 0;
|
|
}
|
|
|
|
void Mandolin :: pluck(MY_FLOAT amplitude, MY_FLOAT position)
|
|
{
|
|
pluckPos = position; /* pluck position is zeroes at pos*length */
|
|
this->pluck(amplitude);
|
|
}
|
|
|
|
void Mandolin :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
|
|
{
|
|
this->setFreq(freq);
|
|
this->pluck(amp);
|
|
#if defined(_debug_)
|
|
printf("Mandolin : NoteOn: Freq=%lf Amp=%lf\n",freq,amp);
|
|
#endif
|
|
}
|
|
|
|
void Mandolin :: setBodySize(MY_FLOAT size)
|
|
{
|
|
soundfile->setRate(size);
|
|
}
|
|
|
|
MY_FLOAT Mandolin :: tick()
|
|
{
|
|
MY_FLOAT temp = 0;
|
|
if (!waveDone) {
|
|
waveDone = soundfile->informTick(); /* as long as it goes . . . */
|
|
temp = soundfile->lastOut() * pluckAmp; /* scaled pluck excitation */
|
|
temp = temp - combDelay->tick(temp); /* with comb filtering */
|
|
}
|
|
if (dampTime>=0) { /* Damping hack to help avoid */
|
|
dampTime -= 1; /* overflow on replucking */
|
|
lastOutput = delayLine->tick( /* Calculate 1st delay */
|
|
filter->tick( /* filterered reflection */
|
|
temp + /* plus pluck excitation */
|
|
(delayLine->lastOut() * 0.7)));
|
|
lastOutput += delayLine2->tick( /* and 2nd delay */
|
|
filter2->tick( /* just like the 1st */
|
|
temp +
|
|
(delayLine2->lastOut() * 0.7))); /* that's the whole thing!! */
|
|
}
|
|
else { /* No damping hack after 1 period */
|
|
lastOutput = delayLine->tick( /* Calculate 1st delay */
|
|
filter->tick( /* filtered reflection */
|
|
temp + /* plus pluck excitation */
|
|
(delayLine->lastOut()
|
|
* loopGain)));
|
|
lastOutput += delayLine2->tick( /* and 2nd delay */
|
|
filter2->tick( /* just like the 1st */
|
|
temp +
|
|
(delayLine2->lastOut()
|
|
* loopGain)));
|
|
}
|
|
lastOutput *= 2.0;
|
|
return lastOutput;
|
|
}
|
|
|
|
void Mandolin :: controlChange(int number, MY_FLOAT value)
|
|
{
|
|
#if defined(_debug_)
|
|
printf("Mandolin : ControlChange: Number=%i Value=%f\n",number,value);
|
|
#endif
|
|
if (number == MIDI_control1)
|
|
this->setBodySize(value * NORM_7 * 2.0);
|
|
else if (number == MIDI_control2)
|
|
this->setPluckPos(value * NORM_7);
|
|
else if (number == MIDI_control3)
|
|
this->setBaseLoopGain(0.97 + (value * NORM_7 * 0.03));
|
|
else if (number == MIDI_mod_wheel)
|
|
this->setDetune(1.0 - (value * NORM_7 * 0.1));
|
|
else if (number == MIDI_after_touch)
|
|
this->pluck(value * NORM_7);
|
|
else {
|
|
printf("Mandolin : Undefined Control Number!!\n");
|
|
}
|
|
}
|