1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-08-02 08:59: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; double a,b;
int k; int k;
double frequencyQuantum;
double BlendedFrequency; double BlendedFrequency;
double BlendedAmplitude; double BlendedAmplitude;
double BlendedLogFrequency;
// calculate delta, and reposition from where we left // calculate delta, and reposition from where we left
double amplitudeQuantum = (amplitude[1]-amplitude[0]) / numSamples; double amplitudeQuantum = (amplitude[1]-amplitude[0]) / numSamples;
double frequencyQuantum = (frequency[1]-frequency[0]) / numSamples;
BlendedAmplitude = amplitude[0] + amplitudeQuantum * mSample; BlendedAmplitude = amplitude[0] + amplitudeQuantum * mSample;
// precalculations: // precalculations:
double pre2PI = 2 * M_PI; double pre2PI = 2 * M_PI;
double pre4divPI = 4. / M_PI; double pre4divPI = 4. / M_PI;
/* // initial setup should calculate deltas
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
if( mbLogInterpolation ) if( mbLogInterpolation )
{ {
// this for log interpolation
logFrequency[0] = log10( frequency[0] ); logFrequency[0] = log10( frequency[0] );
logFrequency[1] = log10( frequency[1] ); logFrequency[1] = log10( frequency[1] );
// calculate delta, and reposition from where we left // calculate delta, and reposition from where we left
double logfrequencyQuantum = (logFrequency[1]-logFrequency[0]) / numSamples; frequencyQuantum = (logFrequency[1]-logFrequency[0]) / numSamples;
double BlendedLogFrequency = logFrequency[0] + logfrequencyQuantum * mSample; BlendedLogFrequency = logFrequency[0] + frequencyQuantum * mSample;
BlendedFrequency = pow( 10.0, (double)BlendedLogFrequency );
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;
}
} else { } else {
// this for regular case, linear interpolation // this for regular case, linear interpolation
frequencyQuantum = (frequency[1]-frequency[0]) / numSamples;
BlendedFrequency = frequency[0] + frequencyQuantum * mSample; BlendedFrequency = frequency[0] + frequencyQuantum * mSample;
for (i = 0; i < len; i++) }
{
switch (waveform) { // synth loop
case 0: //sine for (i = 0; i < len; i++) {
f = (float) sin(pre2PI * mPositionInCycles/mCurRate); switch (waveform) {
break; case 0: //sine
case 1: //square f = (float) sin(pre2PI * mPositionInCycles/mCurRate);
f = (modf(mPositionInCycles/mCurRate, &throwaway) < 0.5) ? 1.0f :-1.0f; break;
break; case 1: //square
case 2: //sawtooth f = (modf(mPositionInCycles/mCurRate, &throwaway) < 0.5) ? 1.0f :-1.0f;
f = (2 * modf(mPositionInCycles/mCurRate+0.5f, &throwaway)) -1.0f; break;
break; case 2: //sawtooth
case 3: //square, no alias. Good down to 110Hz @ 44100Hz sampling. f = (2 * modf(mPositionInCycles/mCurRate+0.5f, &throwaway)) -1.0f;
//do fundamental (k=1) outside loop break;
b = (1. + cos((pre2PI * BlendedFrequency)/mCurRate))/pre4divPI; //scaling case 3: //square, no alias. Good down to 110Hz @ 44100Hz sampling.
f = (float) pre4divPI * sin(pre2PI * mPositionInCycles/mCurRate); //do fundamental (k=1) outside loop
for(k=3; (k<200) && (k * BlendedFrequency < mCurRate/2.); k+=2) b = (1. + cos((pre2PI * BlendedFrequency)/mCurRate))/pre4divPI; //scaling
{ f = (float) pre4divPI * sin(pre2PI * mPositionInCycles/mCurRate);
//Hanning Window in freq domain for(k=3; (k<200) && (k * BlendedFrequency < mCurRate/2.); k+=2)
a = 1. + cos((pre2PI * k * BlendedFrequency)/mCurRate); {
//calc harmonic, apply window, scale to amplitude of fundamental //Hanning Window in freq domain
f += (float) a * sin(pre2PI * mPositionInCycles/mCurRate * k)/(b*k); 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 // insert value in buffer
mPositionInCycles += BlendedFrequency; buffer[i] = BlendedAmplitude * f;
// update freq,amplitude
mPositionInCycles += BlendedFrequency;
BlendedAmplitude += amplitudeQuantum;
if (mbLogInterpolation) {
BlendedLogFrequency += frequencyQuantum;
BlendedFrequency = pow( 10.0, (double)BlendedLogFrequency);
} else {
BlendedFrequency += frequencyQuantum; BlendedFrequency += frequencyQuantum;
BlendedAmplitude += amplitudeQuantum;
} }
} }
// update external placeholder // update external placeholder
mSample += len; mSample += len;
return true; return true;