Files
stk/VoicForm.cpp
Gary Scavone ea749b71d2 Version 2.01
2013-09-29 22:39:45 +02:00

236 lines
6.7 KiB
C++

/*******************************************/
/* 4 Formant Synthesis Instrument */
/* by Perry R. Cook, 1995-96 */
/* This instrument contains an excitation */
/* singing wavetable (looping wave with */
/* random and periodic vibrato, smoothing */
/* on frequency, etc.), excitation noise, */
/* and four sweepable complex resonances. */
/* */
/* Measured Formant data (from me) is */
/* included, and enough data is there to */
/* support either parallel or cascade */
/* synthesis. In the floating point case */
/* cascade synthesis is the most natural */
/* so that's what you'll find here. */
/* */
/* For right now, there's a simple command*/
/* line score interface consisting of 3 */
/* letter symbols for the phonemes, =xx */
/* sets the pitch to x, + and - add and */
/* subtract a half step, and ... makes it */
/* keep doing what it's doing for longer. */
/*******************************************/
#include "VoicForm.h"
#include "SKINI11.msg"
VoicForm :: VoicForm() : Instrmnt()
{
voiced = new SingWave("rawwaves/impuls40.raw");
voiced->normalize();
voiced->setGainRate((MY_FLOAT) 0.001);
voiced->setGainTarget((MY_FLOAT) 0.0);
noise = new Noise;
filters[0] = new FormSwep;
filters[1] = new FormSwep;
filters[2] = new FormSwep;
filters[3] = new FormSwep;
filters[0]->setSweepRate((MY_FLOAT) 0.001);
filters[1]->setSweepRate((MY_FLOAT) 0.001);
filters[2]->setSweepRate((MY_FLOAT) 0.001);
filters[3]->setSweepRate((MY_FLOAT) 0.001);
onezero = new OneZero;
onezero->setCoeff((MY_FLOAT) -0.9);
onepole = new OnePole;
onepole->setPole((MY_FLOAT) 0.9);
noiseEnv = new Envelope;
noiseEnv->setRate((MY_FLOAT) 0.001);
noiseEnv->setTarget((MY_FLOAT) 0.0);
this->setPhoneme("eee");
this->clear();
}
VoicForm :: ~VoicForm()
{
delete voiced;
delete noise;
delete filters[0];
delete filters[1];
delete filters[2];
delete filters[3];
delete onezero;
delete onepole;
delete noiseEnv;
}
void VoicForm :: clear()
{
onezero->clear();
onepole->clear();
filters[0]->clear();
filters[1]->clear();
filters[2]->clear();
filters[3]->clear();
}
void VoicForm :: setFreq(MY_FLOAT frequency)
{
voiced->setFreq(frequency);
}
void VoicForm :: setFormantAll(int whichOne, MY_FLOAT freq,MY_FLOAT reson,MY_FLOAT gain)
{
filters[whichOne]->setTargets(freq,reson,gain);
}
#include "phontabl.h"
int VoicForm :: setPhoneme(char *phoneme)
{
int i=0,found=0;
while(i<32 && !found) {
if (!strcmp(phonemes[i],phoneme)) {
found = 1;
this->setFormantAll(0,(MY_FLOAT) phonParams[i][0][0],(MY_FLOAT) phonParams[i][0][1],(MY_FLOAT) pow(10.0,phonParams[i][0][2] / 20.0));
this->setFormantAll(1,(MY_FLOAT) phonParams[i][1][0],(MY_FLOAT) phonParams[i][1][1],(MY_FLOAT) 1.0);
this->setFormantAll(2,(MY_FLOAT) phonParams[i][2][0],(MY_FLOAT) phonParams[i][2][1],(MY_FLOAT) 1.0);
this->setFormantAll(3,(MY_FLOAT) phonParams[i][3][0],(MY_FLOAT) phonParams[i][3][1],(MY_FLOAT) 1.0);
this->setVoicedUnVoiced((MY_FLOAT) phonGains[i][0],(MY_FLOAT) phonGains[i][1]);
printf("Found Formant: %s (number %i)\n",phoneme,i);
}
i++;
}
if (!found) printf("Phoneme %s not found\n",phoneme);
return found;
}
void VoicForm :: setVoiced(MY_FLOAT vGain)
{
voiced->setGainTarget(vGain);
//voiced->setGainTarget(vGain*0.5);
}
void VoicForm :: setUnVoiced(MY_FLOAT nGain)
{
noiseEnv->setTarget(nGain);
//noiseEnv->setTarget(nGain*0.5);
}
void VoicForm :: setVoicedUnVoiced(MY_FLOAT vGain, MY_FLOAT nGain)
{
this->setVoiced(vGain);
//this->setVoiced(vGain*0.5);
this->setUnVoiced(nGain);
//this->setUnVoiced(nGain*0.5);
}
void VoicForm :: setFiltSweepRate(int whichOne,MY_FLOAT rate)
{
filters[whichOne]->setSweepRate(rate);
}
void VoicForm :: setPitchSweepRate(MY_FLOAT rate)
{
voiced->setSweepRate(rate);
}
void VoicForm :: speak()
{
voiced->noteOn();
}
void VoicForm :: quiet()
{
voiced->noteOff();
noiseEnv->setTarget((MY_FLOAT) 0.0);
}
void VoicForm :: noteOn(MY_FLOAT freq, MY_FLOAT amp)
{
voiced->setGainTarget(amp);
//voiced->setGainTarget(amp*0.5);
onepole->setPole((MY_FLOAT) 0.95 - (amp * (MY_FLOAT) NORM_7 * (MY_FLOAT) 0.2));
//onepole->setPole((MY_FLOAT) 0.9 - (amp * (MY_FLOAT) 0.2));
voiced->setFreq(freq);
}
void VoicForm :: noteOff(MY_FLOAT amp)
{
voiced->noteOff();
}
MY_FLOAT VoicForm :: tick()
{
MY_FLOAT temp;
temp = onepole->tick(onezero->tick(voiced->tick()));
temp += noiseEnv->tick() * noise->tick();
lastOutput = filters[0]->tick(temp);
lastOutput = filters[1]->tick(lastOutput);
lastOutput = filters[2]->tick(lastOutput);
lastOutput = filters[3]->tick(lastOutput);
//lastOutput *= (MY_FLOAT) 0.02;
lastOutput *= (MY_FLOAT) 0.005;
return lastOutput;
}
void VoicForm :: controlChange(int number, MY_FLOAT value)
{
MY_FLOAT temp;
int tempi;
#if defined(_debug_)
printf("VoicForm : ControlChange: Number=%i Value=%f\n",number,value);
#endif
if (number == __SK_Breath_) {
this->setVoiced((MY_FLOAT) 1.0 - (value *(MY_FLOAT) NORM_7));
this->setUnVoiced((MY_FLOAT) 0.01 * value * (MY_FLOAT) NORM_7);
}
else if (number == __SK_FootControl_) {
tempi = (int) (value / 2);
if (tempi < 16) {
tempi = tempi;
temp = (MY_FLOAT) 0.9;
}
else if (tempi < 32) {
tempi = tempi - 16;
temp = (MY_FLOAT) 1.0;
}
else if (tempi < 48) {
tempi = tempi - 32;
temp = (MY_FLOAT) 1.1;
}
else if (tempi <= 64) {
tempi = tempi - 48;
temp = (MY_FLOAT) 1.2;
}
this->setFormantAll(0,temp*(MY_FLOAT) phonParams[tempi][0][0],
(MY_FLOAT) phonParams[tempi][0][1],
(MY_FLOAT) pow(10.0,phonParams[tempi][0][2] / 20.0));
this->setFormantAll(1,temp*(MY_FLOAT) phonParams[tempi][1][0],
(MY_FLOAT) phonParams[tempi][1][1],(MY_FLOAT) 1.0);
this->setFormantAll(2,temp*(MY_FLOAT) phonParams[tempi][2][0],
(MY_FLOAT) phonParams[tempi][2][1],(MY_FLOAT) 1.0);
this->setFormantAll(3,temp*(MY_FLOAT) phonParams[tempi][3][0],
(MY_FLOAT) phonParams[tempi][3][1],(MY_FLOAT) 1.0);
}
else if (number == __SK_ModFrequency_)
voiced->setVibFreq(value * (MY_FLOAT) NORM_7 * (MY_FLOAT) 12.0); /* 0 to 12 Hz */
else if (number == __SK_ModWheel_)
voiced->setVibAmt(value * (MY_FLOAT) NORM_7 * (MY_FLOAT) 0.2);
else if (number == __SK_AfterTouch_Cont_) {
this->setVoiced(value*NORM_7);
onepole->setPole((MY_FLOAT) 0.99 - (value *(MY_FLOAT) NORM_7 * (MY_FLOAT) 0.2));
//onepole->setPole((MY_FLOAT) 0.5 - (value * (MY_FLOAT) NORM_7 * (MY_FLOAT) 0.2));
}
else {
printf("VoicForm : Undefined Control Number!!\n");
}
}