summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/portaudio/qa/loopback/src/audio_analyzer.c
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/portaudio/qa/loopback/src/audio_analyzer.c')
-rw-r--r--3rdparty/portaudio/qa/loopback/src/audio_analyzer.c901
1 files changed, 450 insertions, 451 deletions
diff --git a/3rdparty/portaudio/qa/loopback/src/audio_analyzer.c b/3rdparty/portaudio/qa/loopback/src/audio_analyzer.c
index 0a3dbdf9232..fbdd6318205 100644
--- a/3rdparty/portaudio/qa/loopback/src/audio_analyzer.c
+++ b/3rdparty/portaudio/qa/loopback/src/audio_analyzer.c
@@ -26,13 +26,13 @@
*/
/*
- * The text above constitutes the entire PortAudio license; however,
+ * The text above constitutes the entire PortAudio license; however,
* the PortAudio community also makes the following non-binding requests:
*
* Any person wishing to distribute modifications to the Software is
* requested to send the modifications to the original developer so that
- * they can be incorporated into the canonical version. It is also
- * requested that these non-binding requests be included along with the
+ * they can be incorporated into the canonical version. It is also
+ * requested that these non-binding requests be included along with the
* license above.
*/
@@ -50,153 +50,153 @@
/*==========================================================================================*/
double PaQa_GetNthFrequency( double baseFrequency, int index )
{
- // Use 13 tone equal tempered scale because it does not generate harmonic ratios.
- return baseFrequency * pow( 2.0, index / 13.0 );
+ // Use 13 tone equal tempered scale because it does not generate harmonic ratios.
+ return baseFrequency * pow( 2.0, index / 13.0 );
}
/*==========================================================================================*/
void PaQa_EraseBuffer( float *buffer, int numFrames, int samplesPerFrame )
{
- int i;
- int numSamples = numFrames * samplesPerFrame;
- for( i=0; i<numSamples; i++ )
- {
- *buffer++ = 0.0;
- }
+ int i;
+ int numSamples = numFrames * samplesPerFrame;
+ for( i=0; i<numSamples; i++ )
+ {
+ *buffer++ = 0.0;
+ }
}
/*==========================================================================================*/
void PaQa_SetupSineGenerator( PaQaSineGenerator *generator, double frequency, double amplitude, double frameRate )
{
- generator->phase = 0.0;
- generator->amplitude = amplitude;
- generator->frequency = frequency;
- generator->phaseIncrement = 2.0 * frequency * MATH_PI / frameRate;
+ generator->phase = 0.0;
+ generator->amplitude = amplitude;
+ generator->frequency = frequency;
+ generator->phaseIncrement = 2.0 * frequency * MATH_PI / frameRate;
}
/*==========================================================================================*/
void PaQa_MixSine( PaQaSineGenerator *generator, float *buffer, int numSamples, int stride )
{
- int i;
- for( i=0; i<numSamples; i++ )
- {
- float value = sinf( (float) generator->phase ) * generator->amplitude;
- *buffer += value; // Mix with existing value.
- buffer += stride;
- // Advance phase and wrap around.
- generator->phase += generator->phaseIncrement;
- if (generator->phase > MATH_TWO_PI)
- {
- generator->phase -= MATH_TWO_PI;
- }
- }
+ int i;
+ for( i=0; i<numSamples; i++ )
+ {
+ float value = sinf( (float) generator->phase ) * generator->amplitude;
+ *buffer += value; // Mix with existing value.
+ buffer += stride;
+ // Advance phase and wrap around.
+ generator->phase += generator->phaseIncrement;
+ if (generator->phase > MATH_TWO_PI)
+ {
+ generator->phase -= MATH_TWO_PI;
+ }
+ }
}
/*==========================================================================================*/
void PaQa_GenerateCrackDISABLED( float *buffer, int numSamples, int stride )
{
- int i;
- int offset = numSamples/2;
- for( i=0; i<numSamples; i++ )
- {
- float phase = (MATH_TWO_PI * 0.5 * (i - offset)) / numSamples;
- float cosp = cosf( phase );
- float cos2 = cosp * cosp;
- // invert second half of signal
- float value = (i < offset) ? cos2 : (0-cos2);
- *buffer = value;
- buffer += stride;
- }
+ int i;
+ int offset = numSamples/2;
+ for( i=0; i<numSamples; i++ )
+ {
+ float phase = (MATH_TWO_PI * 0.5 * (i - offset)) / numSamples;
+ float cosp = cosf( phase );
+ float cos2 = cosp * cosp;
+ // invert second half of signal
+ float value = (i < offset) ? cos2 : (0-cos2);
+ *buffer = value;
+ buffer += stride;
+ }
}
/*==========================================================================================*/
int PaQa_InitializeRecording( PaQaRecording *recording, int maxFrames, int frameRate )
{
- int numBytes = maxFrames * sizeof(float);
- recording->buffer = (float*)malloc(numBytes);
- QA_ASSERT_TRUE( "Allocate recording buffer.", (recording->buffer != NULL) );
- recording->maxFrames = maxFrames; recording->sampleRate = frameRate;
- recording->numFrames = 0;
- return 0;
+ int numBytes = maxFrames * sizeof(float);
+ recording->buffer = (float*)malloc(numBytes);
+ QA_ASSERT_TRUE( "Allocate recording buffer.", (recording->buffer != NULL) );
+ recording->maxFrames = maxFrames; recording->sampleRate = frameRate;
+ recording->numFrames = 0;
+ return 0;
error:
- return 1;
+ return 1;
}
/*==========================================================================================*/
void PaQa_TerminateRecording( PaQaRecording *recording )
-{
- if (recording->buffer != NULL)
- {
- free( recording->buffer );
- recording->buffer = NULL;
- }
- recording->maxFrames = 0;
+{
+ if (recording->buffer != NULL)
+ {
+ free( recording->buffer );
+ recording->buffer = NULL;
+ }
+ recording->maxFrames = 0;
}
/*==========================================================================================*/
int PaQa_WriteRecording( PaQaRecording *recording, float *buffer, int numFrames, int stride )
{
- int i;
- int framesToWrite;
+ int i;
+ int framesToWrite;
float *data = &recording->buffer[recording->numFrames];
framesToWrite = numFrames;
- if ((framesToWrite + recording->numFrames) > recording->maxFrames)
- {
- framesToWrite = recording->maxFrames - recording->numFrames;
- }
-
- for( i=0; i<framesToWrite; i++ )
- {
- *data++ = *buffer;
- buffer += stride;
- }
- recording->numFrames += framesToWrite;
- return (recording->numFrames >= recording->maxFrames);
+ if ((framesToWrite + recording->numFrames) > recording->maxFrames)
+ {
+ framesToWrite = recording->maxFrames - recording->numFrames;
+ }
+
+ for( i=0; i<framesToWrite; i++ )
+ {
+ *data++ = *buffer;
+ buffer += stride;
+ }
+ recording->numFrames += framesToWrite;
+ return (recording->numFrames >= recording->maxFrames);
}
/*==========================================================================================*/
int PaQa_WriteSilence( PaQaRecording *recording, int numFrames )
{
- int i;
- int framesToRecord;
+ int i;
+ int framesToRecord;
float *data = &recording->buffer[recording->numFrames];
framesToRecord = numFrames;
- if ((framesToRecord + recording->numFrames) > recording->maxFrames)
- {
- framesToRecord = recording->maxFrames - recording->numFrames;
- }
-
- for( i=0; i<framesToRecord; i++ )
- {
- *data++ = 0.0f;
- }
- recording->numFrames += framesToRecord;
- return (recording->numFrames >= recording->maxFrames);
+ if ((framesToRecord + recording->numFrames) > recording->maxFrames)
+ {
+ framesToRecord = recording->maxFrames - recording->numFrames;
+ }
+
+ for( i=0; i<framesToRecord; i++ )
+ {
+ *data++ = 0.0f;
+ }
+ recording->numFrames += framesToRecord;
+ return (recording->numFrames >= recording->maxFrames);
}
/*==========================================================================================*/
int PaQa_RecordFreeze( PaQaRecording *recording, int numFrames )
{
- int i;
- int framesToRecord;
+ int i;
+ int framesToRecord;
float *data = &recording->buffer[recording->numFrames];
framesToRecord = numFrames;
- if ((framesToRecord + recording->numFrames) > recording->maxFrames)
- {
- framesToRecord = recording->maxFrames - recording->numFrames;
- }
-
- for( i=0; i<framesToRecord; i++ )
- {
- // Copy old value forward as if the signal had frozen.
- data[i] = data[i-1];
- }
- recording->numFrames += framesToRecord;
- return (recording->numFrames >= recording->maxFrames);
+ if ((framesToRecord + recording->numFrames) > recording->maxFrames)
+ {
+ framesToRecord = recording->maxFrames - recording->numFrames;
+ }
+
+ for( i=0; i<framesToRecord; i++ )
+ {
+ // Copy old value forward as if the signal had frozen.
+ data[i] = data[i-1];
+ }
+ recording->numFrames += framesToRecord;
+ return (recording->numFrames >= recording->maxFrames);
}
/*==========================================================================================*/
@@ -209,37 +209,37 @@ int PaQa_SaveRecordingToWaveFile( PaQaRecording *recording, const char *filename
int result = 0;
#define NUM_SAMPLES (200)
short data[NUM_SAMPLES];
- const int samplesPerFrame = 1;
+ const int samplesPerFrame = 1;
int numLeft = recording->numFrames;
- float *buffer = &recording->buffer[0];
+ float *buffer = &recording->buffer[0];
result = Audio_WAV_OpenWriter( &writer, filename, recording->sampleRate, samplesPerFrame );
if( result < 0 ) goto error;
-
- while( numLeft > 0 )
+
+ while( numLeft > 0 )
{
- int i;
+ int i;
int numToSave = (numLeft > NUM_SAMPLES) ? NUM_SAMPLES : numLeft;
- // Convert double samples to shorts.
- for( i=0; i<numToSave; i++ )
- {
- double fval = *buffer++;
- // Convert float to int and clip to short range.
- int ival = fval * 32768.0;
- if( ival > 32767 ) ival = 32767;
- else if( ival < -32768 ) ival = -32768;
- data[i] = ival;
- }
- result = Audio_WAV_WriteShorts( &writer, data, numToSave );
+ // Convert double samples to shorts.
+ for( i=0; i<numToSave; i++ )
+ {
+ double fval = *buffer++;
+ // Convert float to int and clip to short range.
+ int ival = fval * 32768.0;
+ if( ival > 32767 ) ival = 32767;
+ else if( ival < -32768 ) ival = -32768;
+ data[i] = ival;
+ }
+ result = Audio_WAV_WriteShorts( &writer, data, numToSave );
if( result < 0 ) goto error;
- numLeft -= numToSave;
+ numLeft -= numToSave;
}
-
+
result = Audio_WAV_CloseWriter( &writer );
if( result < 0 ) goto error;
-
+
return 0;
-
+
error:
printf("ERROR: result = %d\n", result );
return result;
@@ -250,29 +250,29 @@ error:
double PaQa_MeasureCrossingSlope( float *buffer, int numFrames )
{
- int i;
- double slopeTotal = 0.0;
- int slopeCount = 0;
- float previous;
- double averageSlope = 0.0;
-
- previous = buffer[0];
- for( i=1; i<numFrames; i++ )
- {
- float current = buffer[i];
- if( (current > 0.0) && (previous < 0.0) )
- {
- double delta = current - previous;
- slopeTotal += delta;
- slopeCount += 1;
- }
- previous = current;
- }
- if( slopeCount > 0 )
- {
- averageSlope = slopeTotal / slopeCount;
- }
- return averageSlope;
+ int i;
+ double slopeTotal = 0.0;
+ int slopeCount = 0;
+ float previous;
+ double averageSlope = 0.0;
+
+ previous = buffer[0];
+ for( i=1; i<numFrames; i++ )
+ {
+ float current = buffer[i];
+ if( (current > 0.0) && (previous < 0.0) )
+ {
+ double delta = current - previous;
+ slopeTotal += delta;
+ slopeCount += 1;
+ }
+ previous = current;
+ }
+ if( slopeCount > 0 )
+ {
+ averageSlope = slopeTotal / slopeCount;
+ }
+ return averageSlope;
}
/*==========================================================================================*/
@@ -285,63 +285,63 @@ double PaQa_MeasureCrossingSlope( float *buffer, int numFrames )
*
*/
double PaQa_MeasureSineAmplitudeBySlope( PaQaRecording *recording,
- double frequency, double frameRate,
- int startFrame, int numFrames )
+ double frequency, double frameRate,
+ int startFrame, int numFrames )
{
- float *buffer = &recording->buffer[startFrame];
- double measuredSlope = PaQa_MeasureCrossingSlope( buffer, numFrames );
- double unitySlope = sin( MATH_TWO_PI * frequency / frameRate );
- double estimatedAmplitude = measuredSlope / unitySlope;
- return estimatedAmplitude;
+ float *buffer = &recording->buffer[startFrame];
+ double measuredSlope = PaQa_MeasureCrossingSlope( buffer, numFrames );
+ double unitySlope = sin( MATH_TWO_PI * frequency / frameRate );
+ double estimatedAmplitude = measuredSlope / unitySlope;
+ return estimatedAmplitude;
}
/*==========================================================================================*/
double PaQa_CorrelateSine( PaQaRecording *recording, double frequency, double frameRate,
- int startFrame, int numFrames, double *phasePtr )
+ int startFrame, int numFrames, double *phasePtr )
{
- double magnitude = 0.0;
+ double magnitude = 0.0;
int numLeft = numFrames;
- double phase = 0.0;
- double phaseIncrement = 2.0 * MATH_PI * frequency / frameRate;
- double sinAccumulator = 0.0;
- double cosAccumulator = 0.0;
- float *data = &recording->buffer[startFrame];
+ double phase = 0.0;
+ double phaseIncrement = 2.0 * MATH_PI * frequency / frameRate;
+ double sinAccumulator = 0.0;
+ double cosAccumulator = 0.0;
+ float *data = &recording->buffer[startFrame];
QA_ASSERT_TRUE( "startFrame out of bounds", (startFrame < recording->numFrames) );
- QA_ASSERT_TRUE( "numFrames out of bounds", ((startFrame+numFrames) <= recording->numFrames) );
-
- while( numLeft > 0 )
- {
- double sample = (double) *data++;
- sinAccumulator += sample * sin( phase );
- cosAccumulator += sample * cos( phase );
- phase += phaseIncrement;
- if (phase > MATH_TWO_PI)
- {
- phase -= MATH_TWO_PI;
- }
- numLeft -= 1;
- }
- sinAccumulator = sinAccumulator / numFrames;
- cosAccumulator = cosAccumulator / numFrames;
- // TODO Why do I have to multiply by 2.0? Need it to make result come out right.
- magnitude = 2.0 * sqrt( (sinAccumulator * sinAccumulator) + (cosAccumulator * cosAccumulator ));
- if( phasePtr != NULL )
- {
- double phase = atan2( cosAccumulator, sinAccumulator );
- *phasePtr = phase;
- }
- return magnitude;
+ QA_ASSERT_TRUE( "numFrames out of bounds", ((startFrame+numFrames) <= recording->numFrames) );
+
+ while( numLeft > 0 )
+ {
+ double sample = (double) *data++;
+ sinAccumulator += sample * sin( phase );
+ cosAccumulator += sample * cos( phase );
+ phase += phaseIncrement;
+ if (phase > MATH_TWO_PI)
+ {
+ phase -= MATH_TWO_PI;
+ }
+ numLeft -= 1;
+ }
+ sinAccumulator = sinAccumulator / numFrames;
+ cosAccumulator = cosAccumulator / numFrames;
+ // TODO Why do I have to multiply by 2.0? Need it to make result come out right.
+ magnitude = 2.0 * sqrt( (sinAccumulator * sinAccumulator) + (cosAccumulator * cosAccumulator ));
+ if( phasePtr != NULL )
+ {
+ double phase = atan2( cosAccumulator, sinAccumulator );
+ *phasePtr = phase;
+ }
+ return magnitude;
error:
- return -1.0;
+ return -1.0;
}
/*==========================================================================================*/
void PaQa_FilterRecording( PaQaRecording *input, PaQaRecording *output, BiquadFilter *filter )
{
- int numToFilter = (input->numFrames > output->maxFrames) ? output->maxFrames : input->numFrames;
- BiquadFilter_Filter( filter, &input->buffer[0], &output->buffer[0], numToFilter );
- output->numFrames = numToFilter;
+ int numToFilter = (input->numFrames > output->maxFrames) ? output->maxFrames : input->numFrames;
+ BiquadFilter_Filter( filter, &input->buffer[0], &output->buffer[0], numToFilter );
+ output->numFrames = numToFilter;
}
/*==========================================================================================*/
@@ -351,92 +351,92 @@ void PaQa_FilterRecording( PaQaRecording *input, PaQaRecording *output, BiquadFi
*/
double PaQa_FindFirstMatch( PaQaRecording *recording, float *buffer, int numFrames, double threshold )
{
- int ic,is;
- // How many buffers will fit in the recording?
- int maxCorrelations = recording->numFrames - numFrames;
- double maxSum = 0.0;
- int peakIndex = -1;
- double inverseMaxSum = 0.0;
- int inversePeakIndex = -1;
- double location = -1.0;
+ int ic,is;
+ // How many buffers will fit in the recording?
+ int maxCorrelations = recording->numFrames - numFrames;
+ double maxSum = 0.0;
+ int peakIndex = -1;
+ double inverseMaxSum = 0.0;
+ int inversePeakIndex = -1;
+ double location = -1.0;
QA_ASSERT_TRUE( "numFrames out of bounds", (numFrames < recording->numFrames) );
- for( ic=0; ic<maxCorrelations; ic++ )
- {
- int pastPeak;
- int inversePastPeak;
-
- double sum = 0.0;
- // Correlate buffer against the recording.
- float *recorded = &recording->buffer[ ic ];
- for( is=0; is<numFrames; is++ )
- {
- float s1 = buffer[is];
- float s2 = *recorded++;
- sum += s1 * s2;
- }
- if( (sum > maxSum) )
- {
- maxSum = sum;
- peakIndex = ic;
- }
- if( ((-sum) > inverseMaxSum) )
- {
- inverseMaxSum = -sum;
- inversePeakIndex = ic;
- }
- pastPeak = (maxSum > threshold) && (sum < 0.5*maxSum);
- inversePastPeak = (inverseMaxSum > threshold) && ((-sum) < 0.5*inverseMaxSum);
- //printf("PaQa_FindFirstMatch: ic = %4d, sum = %8f, maxSum = %8f, inverseMaxSum = %8f\n", ic, sum, maxSum, inverseMaxSum );
- if( pastPeak && inversePastPeak )
- {
- if( maxSum > inverseMaxSum )
- {
- location = peakIndex;
- }
- else
- {
- location = inversePeakIndex;
- }
- break;
- }
-
- }
- //printf("PaQa_FindFirstMatch: location = %4d\n", (int)location );
- return location;
+ for( ic=0; ic<maxCorrelations; ic++ )
+ {
+ int pastPeak;
+ int inversePastPeak;
+
+ double sum = 0.0;
+ // Correlate buffer against the recording.
+ float *recorded = &recording->buffer[ ic ];
+ for( is=0; is<numFrames; is++ )
+ {
+ float s1 = buffer[is];
+ float s2 = *recorded++;
+ sum += s1 * s2;
+ }
+ if( (sum > maxSum) )
+ {
+ maxSum = sum;
+ peakIndex = ic;
+ }
+ if( ((-sum) > inverseMaxSum) )
+ {
+ inverseMaxSum = -sum;
+ inversePeakIndex = ic;
+ }
+ pastPeak = (maxSum > threshold) && (sum < 0.5*maxSum);
+ inversePastPeak = (inverseMaxSum > threshold) && ((-sum) < 0.5*inverseMaxSum);
+ //printf("PaQa_FindFirstMatch: ic = %4d, sum = %8f, maxSum = %8f, inverseMaxSum = %8f\n", ic, sum, maxSum, inverseMaxSum );
+ if( pastPeak && inversePastPeak )
+ {
+ if( maxSum > inverseMaxSum )
+ {
+ location = peakIndex;
+ }
+ else
+ {
+ location = inversePeakIndex;
+ }
+ break;
+ }
+
+ }
+ //printf("PaQa_FindFirstMatch: location = %4d\n", (int)location );
+ return location;
error:
- return -1.0;
+ return -1.0;
}
/*==========================================================================================*/
// Measure the area under the curve by summing absolute value of each value.
double PaQa_MeasureArea( float *buffer, int numFrames, int stride )
{
- int is;
- double area = 0.0;
- for( is=0; is<numFrames; is++ )
- {
- area += fabs( *buffer );
- buffer += stride;
- }
- return area;
+ int is;
+ double area = 0.0;
+ for( is=0; is<numFrames; is++ )
+ {
+ area += fabs( *buffer );
+ buffer += stride;
+ }
+ return area;
}
/*==========================================================================================*/
// Measure the area under the curve by summing absolute value of each value.
double PaQa_MeasureRootMeanSquare( float *buffer, int numFrames )
{
- int is;
- double area = 0.0;
- double root;
- for( is=0; is<numFrames; is++ )
- {
- float value = *buffer++;
- area += value * value;
- }
- root = sqrt( area );
- return root / numFrames;
+ int is;
+ double area = 0.0;
+ double root;
+ for( is=0; is<numFrames; is++ )
+ {
+ float value = *buffer++;
+ area += value * value;
+ }
+ root = sqrt( area );
+ return root / numFrames;
}
@@ -446,92 +446,92 @@ double PaQa_MeasureRootMeanSquare( float *buffer, int numFrames )
double PaQa_CompareAmplitudes( PaQaRecording *recording, int startAt, float *buffer, int numFrames )
{
- QA_ASSERT_TRUE( "startAt+numFrames out of bounds", ((startAt+numFrames) < recording->numFrames) );
+ QA_ASSERT_TRUE( "startAt+numFrames out of bounds", ((startAt+numFrames) < recording->numFrames) );
{
- double recordedArea = PaQa_MeasureArea( &recording->buffer[startAt], numFrames, 1 );
- double bufferArea = PaQa_MeasureArea( buffer, numFrames, 1 );
- if( bufferArea == 0.0 ) return 100000000.0;
- return recordedArea / bufferArea;
+ double recordedArea = PaQa_MeasureArea( &recording->buffer[startAt], numFrames, 1 );
+ double bufferArea = PaQa_MeasureArea( buffer, numFrames, 1 );
+ if( bufferArea == 0.0 ) return 100000000.0;
+ return recordedArea / bufferArea;
}
error:
- return -1.0;
+ return -1.0;
}
/*==========================================================================================*/
double PaQa_ComputePhaseDifference( double phase1, double phase2 )
{
- double delta = phase1 - phase2;
- while( delta > MATH_PI )
- {
- delta -= MATH_TWO_PI;
- }
- while( delta < -MATH_PI )
- {
- delta += MATH_TWO_PI;
- }
- return delta;
+ double delta = phase1 - phase2;
+ while( delta > MATH_PI )
+ {
+ delta -= MATH_TWO_PI;
+ }
+ while( delta < -MATH_PI )
+ {
+ delta += MATH_TWO_PI;
+ }
+ return delta;
}
/*==========================================================================================*/
int PaQa_MeasureLatency( PaQaRecording *recording, PaQaTestTone *testTone, PaQaAnalysisResult *analysisResult )
{
- double threshold;
- PaQaSineGenerator generator;
+ double threshold;
+ PaQaSineGenerator generator;
#define MAX_BUFFER_SIZE 2048
- float buffer[MAX_BUFFER_SIZE];
- double period = testTone->sampleRate / testTone->frequency;
- int cycleSize = (int) (period + 0.5);
- //printf("PaQa_AnalyseRecording: frequency = %8f, frameRate = %8f, period = %8f, cycleSize = %8d\n",
- // testTone->frequency, testTone->sampleRate, period, cycleSize );
- analysisResult->latency = -1;
- analysisResult->valid = (0);
-
- // Set up generator to find matching first cycle.
- QA_ASSERT_TRUE( "cycleSize out of bounds", (cycleSize < MAX_BUFFER_SIZE) );
- PaQa_SetupSineGenerator( &generator, testTone->frequency, testTone->amplitude, testTone->sampleRate );
- PaQa_EraseBuffer( buffer, cycleSize, testTone->samplesPerFrame );
- PaQa_MixSine( &generator, buffer, cycleSize, testTone->samplesPerFrame );
-
- threshold = cycleSize * 0.02;
- analysisResult->latency = PaQa_FindFirstMatch( recording, buffer, cycleSize, threshold );
- QA_ASSERT_TRUE( "Could not find the start of the signal.", (analysisResult->latency >= 0) );
- analysisResult->amplitudeRatio = PaQa_CompareAmplitudes( recording, analysisResult->latency, buffer, cycleSize );
- return 0;
+ float buffer[MAX_BUFFER_SIZE];
+ double period = testTone->sampleRate / testTone->frequency;
+ int cycleSize = (int) (period + 0.5);
+ //printf("PaQa_AnalyseRecording: frequency = %8f, frameRate = %8f, period = %8f, cycleSize = %8d\n",
+ // testTone->frequency, testTone->sampleRate, period, cycleSize );
+ analysisResult->latency = -1;
+ analysisResult->valid = (0);
+
+ // Set up generator to find matching first cycle.
+ QA_ASSERT_TRUE( "cycleSize out of bounds", (cycleSize < MAX_BUFFER_SIZE) );
+ PaQa_SetupSineGenerator( &generator, testTone->frequency, testTone->amplitude, testTone->sampleRate );
+ PaQa_EraseBuffer( buffer, cycleSize, testTone->samplesPerFrame );
+ PaQa_MixSine( &generator, buffer, cycleSize, testTone->samplesPerFrame );
+
+ threshold = cycleSize * 0.02;
+ analysisResult->latency = PaQa_FindFirstMatch( recording, buffer, cycleSize, threshold );
+ QA_ASSERT_TRUE( "Could not find the start of the signal.", (analysisResult->latency >= 0) );
+ analysisResult->amplitudeRatio = PaQa_CompareAmplitudes( recording, analysisResult->latency, buffer, cycleSize );
+ return 0;
error:
- return -1;
+ return -1;
}
/*==========================================================================================*/
// Apply cosine squared window.
void PaQa_FadeInRecording( PaQaRecording *recording, int startFrame, int count )
{
- int is;
- double phase = 0.5 * MATH_PI;
- // Advance a quarter wave
- double phaseIncrement = 0.25 * 2.0 * MATH_PI / count;
-
+ int is;
+ double phase = 0.5 * MATH_PI;
+ // Advance a quarter wave
+ double phaseIncrement = 0.25 * 2.0 * MATH_PI / count;
+
assert( startFrame >= 0 );
- assert( count > 0 );
-
+ assert( count > 0 );
+
/* Zero out initial part of the recording. */
- for( is=0; is<startFrame; is++ )
- {
+ for( is=0; is<startFrame; is++ )
+ {
recording->buffer[ is ] = 0.0f;
}
/* Fade in where signal begins. */
for( is=0; is<count; is++ )
{
- double c = cos( phase );
- double w = c * c;
- float x = recording->buffer[ is + startFrame ];
- float y = x * w;
- //printf("FADE %d : w=%f, x=%f, y=%f\n", is, w, x, y );
- recording->buffer[ is + startFrame ] = y;
+ double c = cos( phase );
+ double w = c * c;
+ float x = recording->buffer[ is + startFrame ];
+ float y = x * w;
+ //printf("FADE %d : w=%f, x=%f, y=%f\n", is, w, x, y );
+ recording->buffer[ is + startFrame ] = y;
phase += phaseIncrement;
- }
+ }
}
@@ -539,146 +539,146 @@ void PaQa_FadeInRecording( PaQaRecording *recording, int startFrame, int count )
/** Apply notch filter and high pass filter then detect remaining energy.
*/
int PaQa_DetectPop( PaQaRecording *recording, PaQaTestTone *testTone, PaQaAnalysisResult *analysisResult )
-{
+{
int result = 0;
- int i;
+ int i;
double maxAmplitude;
- int maxPosition;
-
- PaQaRecording notchOutput = { 0 };
- BiquadFilter notchFilter;
-
- PaQaRecording hipassOutput = { 0 };
- BiquadFilter hipassFilter;
-
- int frameRate = (int) recording->sampleRate;
-
- analysisResult->popPosition = -1;
- analysisResult->popAmplitude = 0.0;
-
- result = PaQa_InitializeRecording( &notchOutput, recording->numFrames, frameRate );
- QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result );
-
- result = PaQa_InitializeRecording( &hipassOutput, recording->numFrames, frameRate );
- QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result );
-
- // Use notch filter to remove test tone.
- BiquadFilter_SetupNotch( &notchFilter, testTone->frequency / frameRate, 0.5 );
- PaQa_FilterRecording( recording, &notchOutput, &notchFilter );
- //result = PaQa_SaveRecordingToWaveFile( &notchOutput, "notch_output.wav" );
- //QA_ASSERT_EQUALS( "PaQa_SaveRecordingToWaveFile failed", 0, result );
-
- // Apply fade-in window.
- PaQa_FadeInRecording( &notchOutput, (int) analysisResult->latency, 500 );
-
- // Use high pass to accentuate the edges of a pop. At higher frequency!
- BiquadFilter_SetupHighPass( &hipassFilter, 2.0 * testTone->frequency / frameRate, 0.5 );
- PaQa_FilterRecording( &notchOutput, &hipassOutput, &hipassFilter );
- //result = PaQa_SaveRecordingToWaveFile( &hipassOutput, "hipass_output.wav" );
- //QA_ASSERT_EQUALS( "PaQa_SaveRecordingToWaveFile failed", 0, result );
-
- // Scan remaining signal looking for peak.
- maxAmplitude = 0.0;
- maxPosition = -1;
- for( i=(int) analysisResult->latency; i<hipassOutput.numFrames; i++ )
- {
- float x = hipassOutput.buffer[i];
- float mag = fabs( x );
- if( mag > maxAmplitude )
- {
- maxAmplitude = mag;
- maxPosition = i;
- }
- }
-
- if( maxAmplitude > PAQA_POP_THRESHOLD )
- {
- analysisResult->popPosition = maxPosition;
- analysisResult->popAmplitude = maxAmplitude;
- }
-
- PaQa_TerminateRecording( &notchOutput );
- PaQa_TerminateRecording( &hipassOutput );
- return 0;
-
+ int maxPosition;
+
+ PaQaRecording notchOutput = { 0 };
+ BiquadFilter notchFilter;
+
+ PaQaRecording hipassOutput = { 0 };
+ BiquadFilter hipassFilter;
+
+ int frameRate = (int) recording->sampleRate;
+
+ analysisResult->popPosition = -1;
+ analysisResult->popAmplitude = 0.0;
+
+ result = PaQa_InitializeRecording( &notchOutput, recording->numFrames, frameRate );
+ QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result );
+
+ result = PaQa_InitializeRecording( &hipassOutput, recording->numFrames, frameRate );
+ QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result );
+
+ // Use notch filter to remove test tone.
+ BiquadFilter_SetupNotch( &notchFilter, testTone->frequency / frameRate, 0.5 );
+ PaQa_FilterRecording( recording, &notchOutput, &notchFilter );
+ //result = PaQa_SaveRecordingToWaveFile( &notchOutput, "notch_output.wav" );
+ //QA_ASSERT_EQUALS( "PaQa_SaveRecordingToWaveFile failed", 0, result );
+
+ // Apply fade-in window.
+ PaQa_FadeInRecording( &notchOutput, (int) analysisResult->latency, 500 );
+
+ // Use high pass to accentuate the edges of a pop. At higher frequency!
+ BiquadFilter_SetupHighPass( &hipassFilter, 2.0 * testTone->frequency / frameRate, 0.5 );
+ PaQa_FilterRecording( &notchOutput, &hipassOutput, &hipassFilter );
+ //result = PaQa_SaveRecordingToWaveFile( &hipassOutput, "hipass_output.wav" );
+ //QA_ASSERT_EQUALS( "PaQa_SaveRecordingToWaveFile failed", 0, result );
+
+ // Scan remaining signal looking for peak.
+ maxAmplitude = 0.0;
+ maxPosition = -1;
+ for( i=(int) analysisResult->latency; i<hipassOutput.numFrames; i++ )
+ {
+ float x = hipassOutput.buffer[i];
+ float mag = fabs( x );
+ if( mag > maxAmplitude )
+ {
+ maxAmplitude = mag;
+ maxPosition = i;
+ }
+ }
+
+ if( maxAmplitude > PAQA_POP_THRESHOLD )
+ {
+ analysisResult->popPosition = maxPosition;
+ analysisResult->popAmplitude = maxAmplitude;
+ }
+
+ PaQa_TerminateRecording( &notchOutput );
+ PaQa_TerminateRecording( &hipassOutput );
+ return 0;
+
error:
- PaQa_TerminateRecording( &notchOutput );
- PaQa_TerminateRecording( &hipassOutput );
- return -1;
+ PaQa_TerminateRecording( &notchOutput );
+ PaQa_TerminateRecording( &hipassOutput );
+ return -1;
}
/*==========================================================================================*/
int PaQa_DetectPhaseError( PaQaRecording *recording, PaQaTestTone *testTone, PaQaAnalysisResult *analysisResult )
-{
- int i;
- double period = testTone->sampleRate / testTone->frequency;
- int cycleSize = (int) (period + 0.5);
-
- double maxAddedFrames = 0.0;
- double maxDroppedFrames = 0.0;
-
- double previousPhase = 0.0;
- double previousFrameError = 0;
- int loopCount = 0;
- int skip = cycleSize;
- int windowSize = cycleSize;
+{
+ int i;
+ double period = testTone->sampleRate / testTone->frequency;
+ int cycleSize = (int) (period + 0.5);
+
+ double maxAddedFrames = 0.0;
+ double maxDroppedFrames = 0.0;
+
+ double previousPhase = 0.0;
+ double previousFrameError = 0;
+ int loopCount = 0;
+ int skip = cycleSize;
+ int windowSize = cycleSize;
// Scan recording starting with first cycle, looking for phase errors.
- analysisResult->numDroppedFrames = 0.0;
- analysisResult->numAddedFrames = 0.0;
- analysisResult->droppedFramesPosition = -1.0;
- analysisResult->addedFramesPosition = -1.0;
-
- for( i=analysisResult->latency; i<(recording->numFrames - windowSize); i += skip )
- {
- double expectedPhase = previousPhase + (skip * MATH_TWO_PI / period);
- double expectedPhaseIncrement = PaQa_ComputePhaseDifference( expectedPhase, previousPhase );
-
- double phase = 666.0;
- double mag = PaQa_CorrelateSine( recording, testTone->frequency, testTone->sampleRate, i, windowSize, &phase );
- if( (loopCount > 1) && (mag > 0.0) )
- {
- double phaseDelta = PaQa_ComputePhaseDifference( phase, previousPhase );
- double phaseError = PaQa_ComputePhaseDifference( phaseDelta, expectedPhaseIncrement );
- // Convert phaseError to equivalent number of frames.
- double frameError = period * phaseError / MATH_TWO_PI;
- double consecutiveFrameError = frameError + previousFrameError;
-// if( fabs(frameError) > 0.01 )
-// {
-// printf("FFFFFFFFFFFFF frameError = %f, at %d\n", frameError, i );
-// }
- if( consecutiveFrameError > 0.8 )
- {
- double droppedFrames = consecutiveFrameError;
- if (droppedFrames > (maxDroppedFrames * 1.001))
- {
- analysisResult->numDroppedFrames = droppedFrames;
- analysisResult->droppedFramesPosition = i + (windowSize/2);
- maxDroppedFrames = droppedFrames;
- }
- }
- else if( consecutiveFrameError < -0.8 )
- {
- double addedFrames = 0 - consecutiveFrameError;
- if (addedFrames > (maxAddedFrames * 1.001))
- {
- analysisResult->numAddedFrames = addedFrames;
- analysisResult->addedFramesPosition = i + (windowSize/2);
- maxAddedFrames = addedFrames;
- }
- }
- previousFrameError = frameError;
-
-
- //if( i<8000 )
- //{
- // printf("%d: phase = %8f, expected = %8f, delta = %8f, frameError = %8f\n", i, phase, expectedPhaseIncrement, phaseDelta, frameError );
- //}
- }
- previousPhase = phase;
- loopCount += 1;
- }
- return 0;
+ analysisResult->numDroppedFrames = 0.0;
+ analysisResult->numAddedFrames = 0.0;
+ analysisResult->droppedFramesPosition = -1.0;
+ analysisResult->addedFramesPosition = -1.0;
+
+ for( i=analysisResult->latency; i<(recording->numFrames - windowSize); i += skip )
+ {
+ double expectedPhase = previousPhase + (skip * MATH_TWO_PI / period);
+ double expectedPhaseIncrement = PaQa_ComputePhaseDifference( expectedPhase, previousPhase );
+
+ double phase = 666.0;
+ double mag = PaQa_CorrelateSine( recording, testTone->frequency, testTone->sampleRate, i, windowSize, &phase );
+ if( (loopCount > 1) && (mag > 0.0) )
+ {
+ double phaseDelta = PaQa_ComputePhaseDifference( phase, previousPhase );
+ double phaseError = PaQa_ComputePhaseDifference( phaseDelta, expectedPhaseIncrement );
+ // Convert phaseError to equivalent number of frames.
+ double frameError = period * phaseError / MATH_TWO_PI;
+ double consecutiveFrameError = frameError + previousFrameError;
+// if( fabs(frameError) > 0.01 )
+// {
+// printf("FFFFFFFFFFFFF frameError = %f, at %d\n", frameError, i );
+// }
+ if( consecutiveFrameError > 0.8 )
+ {
+ double droppedFrames = consecutiveFrameError;
+ if (droppedFrames > (maxDroppedFrames * 1.001))
+ {
+ analysisResult->numDroppedFrames = droppedFrames;
+ analysisResult->droppedFramesPosition = i + (windowSize/2);
+ maxDroppedFrames = droppedFrames;
+ }
+ }
+ else if( consecutiveFrameError < -0.8 )
+ {
+ double addedFrames = 0 - consecutiveFrameError;
+ if (addedFrames > (maxAddedFrames * 1.001))
+ {
+ analysisResult->numAddedFrames = addedFrames;
+ analysisResult->addedFramesPosition = i + (windowSize/2);
+ maxAddedFrames = addedFrames;
+ }
+ }
+ previousFrameError = frameError;
+
+
+ //if( i<8000 )
+ //{
+ // printf("%d: phase = %8f, expected = %8f, delta = %8f, frameError = %8f\n", i, phase, expectedPhaseIncrement, phaseDelta, frameError );
+ //}
+ }
+ previousPhase = phase;
+ loopCount += 1;
+ }
+ return 0;
}
/*==========================================================================================*/
@@ -686,22 +686,21 @@ int PaQa_AnalyseRecording( PaQaRecording *recording, PaQaTestTone *testTone, PaQ
{
int result = 0;
- memset( analysisResult, 0, sizeof(PaQaAnalysisResult) );
- result = PaQa_MeasureLatency( recording, testTone, analysisResult );
+ memset( analysisResult, 0, sizeof(PaQaAnalysisResult) );
+ result = PaQa_MeasureLatency( recording, testTone, analysisResult );
QA_ASSERT_EQUALS( "latency measurement", 0, result );
-
- if( (analysisResult->latency >= 0) && (analysisResult->amplitudeRatio > 0.1) )
- {
- analysisResult->valid = (1);
-
- result = PaQa_DetectPop( recording, testTone, analysisResult );
- QA_ASSERT_EQUALS( "detect pop", 0, result );
-
- result = PaQa_DetectPhaseError( recording, testTone, analysisResult );
- QA_ASSERT_EQUALS( "detect phase error", 0, result );
- }
- return 0;
+
+ if( (analysisResult->latency >= 0) && (analysisResult->amplitudeRatio > 0.1) )
+ {
+ analysisResult->valid = (1);
+
+ result = PaQa_DetectPop( recording, testTone, analysisResult );
+ QA_ASSERT_EQUALS( "detect pop", 0, result );
+
+ result = PaQa_DetectPhaseError( recording, testTone, analysisResult );
+ QA_ASSERT_EQUALS( "detect phase error", 0, result );
+ }
+ return 0;
error:
- return -1;
+ return -1;
}
-