From e66425d00c2ee098989663b4adfea30b9fff5894 Mon Sep 17 00:00:00 2001 From: philburk Date: Thu, 28 Mar 2002 18:15:43 +0000 Subject: [PATCH] Use Interpolating sine lookup to eliminate differences in math lib performance between hosts. --- pa_tests/patest_maxsines.c | 56 ++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/pa_tests/patest_maxsines.c b/pa_tests/patest_maxsines.c index 646a77f..4a5c26b 100644 --- a/pa_tests/patest_maxsines.c +++ b/pa_tests/patest_maxsines.c @@ -40,20 +40,44 @@ #include "portaudio.h" #define MAX_SINES (500) +#define MAX_USAGE (0.8) #define SAMPLE_RATE (44100) +#define FREQ_TO_PHASE_INC(freq) (freq/(float)SAMPLE_RATE) + +#define MIN_PHASE_INC FREQ_TO_PHASE_INC(200.0f) +#define MAX_PHASE_INC (MIN_PHASE_INC * (1 << 5)) + #define FRAMES_PER_BUFFER (512) #ifndef M_PI #define M_PI (3.14159265) #endif #define TWOPI (M_PI * 2.0) +#define TABLE_SIZE (512) + typedef struct paTestData { int numSines; + float sine[TABLE_SIZE + 1]; /* add one for guard point for interpolation */ double phases[MAX_SINES]; } paTestData; +/* Convert phase between and 1.0 to sine value + * using linear interpolation. + */ +float LookupSine( paTestData *data, float phase ); +float LookupSine( paTestData *data, float phase ) +{ + float fIndex = phase*TABLE_SIZE; + int index = (int) fIndex; + float fract = fIndex - index; + float lo = data->sine[index]; + float hi = data->sine[index+1]; + float val = lo + fract*(hi-lo); + return val; +} + /* This routine will be called by the PortAudio engine when audio is needed. ** It may called at interrupt level on some machines so don't do anything ** that could mess up the system like calling malloc() or free(). @@ -65,33 +89,39 @@ static int patestCallback( void *inputBuffer, void *outputBuffer, paTestData *data = (paTestData*)userData; float *out = (float*)outputBuffer; float outSample; + float scaler; + int numForScale; unsigned long i; int j; int finished = 0; (void) outTime; /* Prevent unused variable warnings. */ (void) inputBuffer; +/* Detemine amplitude scaling factor */ + numForScale = data->numSines; + if( numForScale < 8 ) numForScale = 8; /* prevent pops at beginning */ + scaler = 1.0f / numForScale; + for( i=0; inumSines; j++ ) { /* Advance phase of next oscillator. */ phase = data->phases[j]; phase += phaseInc; - if( phase > TWOPI ) phase -= TWOPI; + if( phase >= 1.0 ) phase -= 1.0; - phaseInc *= 1.02; - if( phaseInc > 0.5 ) phaseInc *= 0.5; - - /* This is not a very efficient way to calc sines. */ - output += (float) sin( phase ); + output += LookupSine(data, phase); data->phases[j] = phase; + + phaseInc *= 1.02; + if( phaseInc > MAX_PHASE_INC ) phaseInc = MIN_PHASE_INC; } - outSample = (float) (output / data->numSines); + outSample = (float) (output * scaler); *out++ = outSample; /* Left */ *out++ = outSample; /* Right */ } @@ -102,12 +132,19 @@ static int patestCallback( void *inputBuffer, void *outputBuffer, int main(void); int main(void) { + int i; PortAudioStream *stream; PaError err; paTestData data = {0}; double load; printf("PortAudio Test: output sine wave. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER); + /* initialise sinusoidal wavetable */ + for( i=0; i