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

244 lines
5.2 KiB
C++

/*******************************************/
/* "Singing" Looped Soundfile Class, */
/* by Perry R. Cook, 1995-96 */
/* This Object contains all that's needed */
/* to make a pitched musical sound, like */
/* a simple voice or violin. In general, */
/* it will not be used alone (because of */
/* of munchinification effects from pitch */
/* shifting. It will be used as an */
/* excitation source for other instruments*/
/*******************************************/
#include "SingWave.h"
#include "swapstuf.h"
SingWave :: SingWave(char *fileName)
{
long i;
short temp;
FILE *fd;
// extern short SwapShort(short);
fd = fopen(fileName,"rb");
if (!fd) {
printf("Couldn't find soundfile %s !!!!!!!!\n",fileName);
}
i = 0;
while (fread(&temp,2,1,fd)) i++;
length = i;
fseek(fd,0,0);
data = (MY_FLOAT *) malloc(MY_FLOAT_SIZE * (length + 1));
i = 0;
while (fread(&temp,2,1,fd)) {
#ifdef __LITTLE_ENDIAN__
temp = SwapShort(temp);
#endif
data[i] = temp;
i++;
}
data[length] = data[length-1];
fclose(fd);
mytime = (MY_FLOAT) 0.0;
rate = (MY_FLOAT) 1.0;
sweepRate = (MY_FLOAT) 0.001;
modulator = new Modulatr;
modulator->setVibFreq((MY_FLOAT) 6.0);
modulator->setVibAmt((MY_FLOAT) 0.04);
modulator->setRndAmt((MY_FLOAT) 0.005);
envelope = new Envelope;
pitchEnvelope = new Envelope;
this->setFreq((MY_FLOAT) 75.0);
pitchEnvelope->setRate((MY_FLOAT) 1.0);
this->tick();
this->tick();
pitchEnvelope->setRate(sweepRate * rate);
}
SingWave :: ~SingWave()
{
delete modulator;
delete envelope;
delete pitchEnvelope;
free(data);
}
void SingWave :: reset()
{
mytime = (MY_FLOAT) 0.0;
lastOutput = (MY_FLOAT) 0.0;
}
void SingWave :: normalize()
{
long i;
MY_FLOAT max = (MY_FLOAT) 0.0;
for (i=0;i<=length;i++)
if (fabs(data[i]) > max)
max = (MY_FLOAT) fabs((double) data[i]);
if (max > 0.0) {
max = (MY_FLOAT) 1.0 / max;
for (i=0;i<=length;i++)
data[i] *= max;
}
}
void SingWave :: normalize(MY_FLOAT newPeak)
{
long i;
MY_FLOAT max = (MY_FLOAT) 0.0;
for (i=0;i<=length;i++)
if (fabs(data[i]) > max)
max = (MY_FLOAT) fabs((double) data[i]);
if (max > 0.0) {
max = (MY_FLOAT) 1.0 / max;
max *= newPeak;
for (i=0;i<=length;i++)
data[i] *= max;
}
}
void SingWave :: setFreq(MY_FLOAT aFreq)
{
MY_FLOAT temp;
temp = rate;
rate = length * ONE_OVER_SRATE * aFreq;
temp -= rate;
if (temp<0) temp = -temp;
pitchEnvelope->setTarget(rate);
pitchEnvelope->setRate(sweepRate * temp);
}
void SingWave :: setVibFreq(MY_FLOAT vibFreq)
{
modulator->setVibFreq(vibFreq);
}
void SingWave :: setVibAmt(MY_FLOAT vibAmount)
{
modulator->setVibAmt(vibAmount);
}
void SingWave :: setRndAmt(MY_FLOAT rndAmount)
{
modulator->setRndAmt(rndAmount);
}
void SingWave :: setSweepRate(MY_FLOAT swpRate)
{
sweepRate = swpRate;
}
void SingWave :: setGainRate(MY_FLOAT gainRate)
{
envelope->setRate(gainRate);
}
void SingWave :: setGainTarget(MY_FLOAT aTarget)
{
envelope->setTarget(aTarget);
}
void SingWave :: noteOn()
{
envelope->keyOn();
}
void SingWave :: noteOff()
{
envelope->keyOff();
}
MY_FLOAT SingWave :: tick()
{
long temp;
MY_FLOAT alpha, temp_rate;
temp_rate = pitchEnvelope->tick();
mytime += temp_rate; /* Update current time */
mytime += temp_rate * modulator->tick(); /* Add vibratos */
while (mytime >= length) { /* Check for end of sound */
mytime -= length; /* loop back to beginning */
}
while (mytime < 0.0) { /* Check for end of sound */
mytime += length; /* loop back to beginning */
}
temp = (long) mytime; /* Integer part of time address */
alpha = mytime - (MY_FLOAT) temp; /* fractional part of time address */
lastOutput = alpha * data[temp+1]; /* Do linear */
lastOutput += ((MY_FLOAT) 1.0 - alpha) * data[temp]; /* interpolation */
lastOutput *= envelope->tick();
return lastOutput;
}
MY_FLOAT SingWave :: lastOut()
{
return lastOutput;
}
/************ Test Main Program *****************/
/*
void main()
{
SingWave ahhWave("rawwaves/ahh.raw");
SingWave eeeWave("rawwaves/eee.raw");
SingWave oooWave("rawwaves/ooo.raw");
FILE *fd;
short data;
long i,j;
fd = fopen("test.raw","wb");
ahhWave.normalize();
ahhWave.noteOn();
for (j=0;j<6;j++) {
ahhWave.setFreq(100 * pow(2.0,j*0.25));
for (i=0;i<10000;i++) {
data = ahhWave.tick() * 32000.0;
fwrite(&data,2,1,fd);
}
}
ahhWave.noteOff();
for (i=0;i<5000;i++) {
data = ahhWave.tick() * 32000.0;
fwrite(&data,2,1,fd);
}
eeeWave.normalize();
eeeWave.noteOn();
for (j=0;j<6;j++) {
eeeWave.setFreq(100 * pow(2.0,j*0.25));
for (i=0;i<10000;i++) {
data = eeeWave.tick() * 32000.0;
fwrite(&data,2,1,fd);
}
}
eeeWave.noteOff();
for (i=0;i<5000;i++) {
data = eeeWave.tick() * 32000.0;
fwrite(&data,2,1,fd);
}
oooWave.normalize();
oooWave.noteOn();
for (j=0;j<6;j++) {
oooWave.setFreq(100 * pow(2.0,j*0.25));
for (i=0;i<10000;i++) {
data = oooWave.tick() * 32000.0;
fwrite(&data,2,1,fd);
}
}
oooWave.noteOff();
for (i=0;i<5000;i++) {
data = oooWave.tick() * 32000.0;
fwrite(&data,2,1,fd);
}
fclose(fd);
}
*/