1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-07-31 16:09:28 +02:00

ToneGen: refactor code for linear/log cases since it is substantially more complicated and duplicated after bug 635 fix.

This commit is contained in:
mchinen 2013-05-19 10:00:20 +00:00
parent 8fd058e8ee
commit e9353e32e0

View File

@ -145,105 +145,72 @@ bool EffectToneGen::MakeTone(float *buffer, sampleCount len)
double a,b;
int k;
double frequencyQuantum;
double BlendedFrequency;
double BlendedAmplitude;
double BlendedLogFrequency;
// calculate delta, and reposition from where we left
double amplitudeQuantum = (amplitude[1]-amplitude[0]) / numSamples;
double frequencyQuantum = (frequency[1]-frequency[0]) / numSamples;
BlendedAmplitude = amplitude[0] + amplitudeQuantum * mSample;
// precalculations:
double pre2PI = 2 * M_PI;
double pre4divPI = 4. / M_PI;
/*
Duplicate the code for the two cases, log interpolation and linear interpolation
I hope this is more readable, a bit faster (only one branching in mbLogInterpolation)
Local variables are declared inside respective branch, globals are declared up.
*/
bool bLogInterpolation = mbLogInterpolation;
if( abs( frequency[1]-frequency[0] ) < 0.000000001 )
bLogInterpolation = true;
// this for log interpolation
// initial setup should calculate deltas
if( mbLogInterpolation )
{
// this for log interpolation
logFrequency[0] = log10( frequency[0] );
logFrequency[1] = log10( frequency[1] );
// calculate delta, and reposition from where we left
double logfrequencyQuantum = (logFrequency[1]-logFrequency[0]) / numSamples;
double BlendedLogFrequency = logFrequency[0] + logfrequencyQuantum * mSample;
for (i = 0; i < len; i++)
{
BlendedFrequency = pow( 10.0, (double)BlendedLogFrequency );
switch (waveform) {
case 0: //sine
f = (float) sin(pre2PI * mPositionInCycles/mCurRate);
break;
case 1: //square
f = (modf(mPositionInCycles/mCurRate, &throwaway) < 0.5) ? 1.0f :-1.0f;
break;
case 2: //sawtooth
f = (2 * modf(mPositionInCycles/mCurRate+0.5f, &throwaway)) -1.0f;
break;
case 3: //square, no alias. Good down to 110Hz @ 44100Hz sampling.
//do fundamental (k=1) outside loop
b = (1. + cos((pre2PI * BlendedFrequency)/mCurRate))/pre4divPI; //scaling
f = (float) pre4divPI * sin(pre2PI * mPositionInCycles/mCurRate);
for(k=3; (k<200) && (k * BlendedFrequency < mCurRate/2.); k+=2)
{
//Hanning Window in freq domain
a = 1. + cos((pre2PI * k * BlendedFrequency)/mCurRate);
//calc harmonic, apply window, scale to amplitude of fundamental
f += (float) a * sin(pre2PI * mPositionInCycles/mCurRate * k)/(b*k);
}
}
// insert value in buffer
buffer[i] = BlendedAmplitude * f;
// update freq,amplitude
mPositionInCycles += BlendedFrequency;
BlendedAmplitude += amplitudeQuantum;
BlendedLogFrequency += logfrequencyQuantum;
}
frequencyQuantum = (logFrequency[1]-logFrequency[0]) / numSamples;
BlendedLogFrequency = logFrequency[0] + frequencyQuantum * mSample;
BlendedFrequency = pow( 10.0, (double)BlendedLogFrequency );
} else {
// this for regular case, linear interpolation
frequencyQuantum = (frequency[1]-frequency[0]) / numSamples;
BlendedFrequency = frequency[0] + frequencyQuantum * mSample;
for (i = 0; i < len; i++)
{
switch (waveform) {
case 0: //sine
f = (float) sin(pre2PI * mPositionInCycles/mCurRate);
break;
case 1: //square
f = (modf(mPositionInCycles/mCurRate, &throwaway) < 0.5) ? 1.0f :-1.0f;
break;
case 2: //sawtooth
f = (2 * modf(mPositionInCycles/mCurRate+0.5f, &throwaway)) -1.0f;
break;
case 3: //square, no alias. Good down to 110Hz @ 44100Hz sampling.
//do fundamental (k=1) outside loop
b = (1. + cos((pre2PI * BlendedFrequency)/mCurRate))/pre4divPI; //scaling
f = (float) pre4divPI * sin(pre2PI * mPositionInCycles/mCurRate);
for(k=3; (k<200) && (k * BlendedFrequency < mCurRate/2.); k+=2)
{
//Hanning Window in freq domain
a = 1. + cos((pre2PI * k * BlendedFrequency)/mCurRate);
//calc harmonic, apply window, scale to amplitude of fundamental
f += (float) a * sin(pre2PI * mPositionInCycles/mCurRate * k)/(b*k);
}
}
// insert value in buffer
buffer[i] = BlendedAmplitude * f;
// update freq,amplitude
mPositionInCycles += BlendedFrequency;
}
// synth loop
for (i = 0; i < len; i++) {
switch (waveform) {
case 0: //sine
f = (float) sin(pre2PI * mPositionInCycles/mCurRate);
break;
case 1: //square
f = (modf(mPositionInCycles/mCurRate, &throwaway) < 0.5) ? 1.0f :-1.0f;
break;
case 2: //sawtooth
f = (2 * modf(mPositionInCycles/mCurRate+0.5f, &throwaway)) -1.0f;
break;
case 3: //square, no alias. Good down to 110Hz @ 44100Hz sampling.
//do fundamental (k=1) outside loop
b = (1. + cos((pre2PI * BlendedFrequency)/mCurRate))/pre4divPI; //scaling
f = (float) pre4divPI * sin(pre2PI * mPositionInCycles/mCurRate);
for(k=3; (k<200) && (k * BlendedFrequency < mCurRate/2.); k+=2)
{
//Hanning Window in freq domain
a = 1. + cos((pre2PI * k * BlendedFrequency)/mCurRate);
//calc harmonic, apply window, scale to amplitude of fundamental
f += (float) a * sin(pre2PI * mPositionInCycles/mCurRate * k)/(b*k);
}
}
// insert value in buffer
buffer[i] = BlendedAmplitude * f;
// update freq,amplitude
mPositionInCycles += BlendedFrequency;
BlendedAmplitude += amplitudeQuantum;
if (mbLogInterpolation) {
BlendedLogFrequency += frequencyQuantum;
BlendedFrequency = pow( 10.0, (double)BlendedLogFrequency);
} else {
BlendedFrequency += frequencyQuantum;
BlendedAmplitude += amplitudeQuantum;
}
}
// update external placeholder
mSample += len;
return true;