From a4dd0ad63c00f4dee3b86dfd3075d1d61b2b3180 Mon Sep 17 00:00:00 2001 From: sanine Date: Sat, 27 Aug 2022 23:52:56 -0500 Subject: add plibsys --- portaudio/qa/loopback/src/test_audio_analyzer.c | 718 ------------------------ 1 file changed, 718 deletions(-) delete mode 100644 portaudio/qa/loopback/src/test_audio_analyzer.c (limited to 'portaudio/qa/loopback/src/test_audio_analyzer.c') diff --git a/portaudio/qa/loopback/src/test_audio_analyzer.c b/portaudio/qa/loopback/src/test_audio_analyzer.c deleted file mode 100644 index 82fa859..0000000 --- a/portaudio/qa/loopback/src/test_audio_analyzer.c +++ /dev/null @@ -1,718 +0,0 @@ - -/* - * PortAudio Portable Real-Time Audio Library - * Latest Version at: http://www.portaudio.com - * - * Copyright (c) 1999-2010 Phil Burk and Ross Bencina - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * 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 - * license above. - */ - -#include -#include -#include -#include "qa_tools.h" -#include "audio_analyzer.h" -#include "test_audio_analyzer.h" -#include "write_wav.h" -#include "biquad_filter.h" - -#define FRAMES_PER_BLOCK (64) -#define PRINT_REPORTS 0 - -#define TEST_SAVED_WAVE (0) - -/*==========================================================================================*/ -/** - * Detect a single tone. - */ -static int TestSingleMonoTone( void ) -{ - int result = 0; - PaQaSineGenerator generator; - PaQaRecording recording; - float buffer[FRAMES_PER_BLOCK]; - double sampleRate = 44100.0; - int maxFrames = ((int)sampleRate) * 1; - int samplesPerFrame = 1; - int stride = 1; - int done = 0; - - double freq = 234.5; - double amp = 0.5; - - double mag1, mag2; - - // Setup a sine oscillator. - PaQa_SetupSineGenerator( &generator, freq, amp, sampleRate ); - - result = PaQa_InitializeRecording( &recording, maxFrames, (int) sampleRate ); - QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result ); - - done = 0; - while (!done) - { - PaQa_EraseBuffer( buffer, FRAMES_PER_BLOCK, samplesPerFrame ); - PaQa_MixSine( &generator, buffer, FRAMES_PER_BLOCK, stride ); - done = PaQa_WriteRecording( &recording, buffer, FRAMES_PER_BLOCK, samplesPerFrame ); - } - - mag1 = PaQa_CorrelateSine( &recording, freq, sampleRate, 0, recording.numFrames, NULL ); - QA_ASSERT_CLOSE( "exact frequency match", amp, mag1, 0.01 ); - - mag2 = PaQa_CorrelateSine( &recording, freq * 1.23, sampleRate, 0, recording.numFrames, NULL ); - QA_ASSERT_CLOSE( "wrong frequency", 0.0, mag2, 0.01 ); - - PaQa_TerminateRecording( &recording ); - return 0; - -error: - PaQa_TerminateRecording( &recording); - return 1; - -} - -/*==========================================================================================*/ -/** - * Mix multiple tones and then detect them. - */ - -static int TestMixedMonoTones( void ) -{ - int i; - int result = 0; -#define NUM_TONES (5) - PaQaSineGenerator generators[NUM_TONES]; - PaQaRecording recording; - float buffer[FRAMES_PER_BLOCK]; - double sampleRate = 44100.0; - int maxFrames = ((int)sampleRate) * 1; - int samplesPerFrame = 1; - - double baseFreq = 234.5; - double amp = 0.1; - - double mag2; - - int stride = samplesPerFrame; - int done = 0; - - // Setup a sine oscillator. - for( i=0; istartDelay; - - int stride = 1; - // Record some initial silence. - int done = PaQa_WriteSilence( recording, testTone->startDelay ); - - // Setup a sine oscillator. - PaQa_SetupSineGenerator( &generator, testTone->frequency, testTone->amplitude, testTone->sampleRate ); - - while (!done) - { - int framesThisLoop = BUFFER_SIZE; - - if( frameCounter == glitchPosition ) - { - if( framesToAdd > 0 ) - { - // Record some frozen data without advancing the sine generator. - done = PaQa_RecordFreeze( recording, framesToAdd ); - frameCounter += framesToAdd; - } - else if( framesToAdd < 0 ) - { - // Advance sine generator a few frames. - PaQa_MixSine( &generator, buffer, 0 - framesToAdd, stride ); - } - - } - else if( (frameCounter < glitchPosition) && ((frameCounter + framesThisLoop) > glitchPosition) ) - { - // Go right up to the glitchPosition. - framesThisLoop = glitchPosition - frameCounter; - } - - if( framesThisLoop > 0 ) - { - PaQa_EraseBuffer( buffer, framesThisLoop, testTone->samplesPerFrame ); - PaQa_MixSine( &generator, buffer, framesThisLoop, stride ); - done = PaQa_WriteRecording( recording, buffer, framesThisLoop, testTone->samplesPerFrame ); - } - frameCounter += framesThisLoop; - } -} - - -/*==========================================================================================*/ -/** - * Generate a clean recording. - */ - -static void MakeCleanRecording( PaQaRecording *recording, PaQaTestTone *testTone ) -{ - PaQaSineGenerator generator; -#define BUFFER_SIZE 512 - float buffer[BUFFER_SIZE]; - - int stride = 1; - // Record some initial silence. - int done = PaQa_WriteSilence( recording, testTone->startDelay ); - - // Setup a sine oscillator. - PaQa_SetupSineGenerator( &generator, testTone->frequency, testTone->amplitude, testTone->sampleRate ); - - // Generate recording with good phase. - while (!done) - { - PaQa_EraseBuffer( buffer, BUFFER_SIZE, testTone->samplesPerFrame ); - PaQa_MixSine( &generator, buffer, BUFFER_SIZE, stride ); - done = PaQa_WriteRecording( recording, buffer, BUFFER_SIZE, testTone->samplesPerFrame ); - } -} - -/*==========================================================================================*/ -/** - * Generate a recording with pop. - */ - -static void MakeRecordingWithPop( PaQaRecording *recording, PaQaTestTone *testTone, int popPosition, int popWidth, double popAmplitude ) -{ - int i; - - MakeCleanRecording( recording, testTone ); - - // Apply glitch to good recording. - if( (popPosition + popWidth) >= recording->numFrames ) - { - popWidth = (recording->numFrames - popPosition) - 1; - } - - for( i=0; ibuffer[i+popPosition]; - float bad = (good > 0.0) ? (good - popAmplitude) : (good + popAmplitude); - recording->buffer[i+popPosition] = bad; - } -} - -/*==========================================================================================*/ -/** - * Detect one phase error in a recording. - */ -static int TestDetectSinglePhaseError( double sampleRate, int cycleSize, int latencyFrames, int glitchPosition, int framesAdded ) -{ - int result = 0; - PaQaRecording recording; - PaQaTestTone testTone; - PaQaAnalysisResult analysisResult = { 0.0 }; - int framesDropped = 0; - int maxFrames = ((int)sampleRate) * 2; - - testTone.samplesPerFrame = 1; - testTone.sampleRate = sampleRate; - testTone.frequency = sampleRate / cycleSize; - testTone.amplitude = 0.5; - testTone.startDelay = latencyFrames; - - result = PaQa_InitializeRecording( &recording, maxFrames, (int) sampleRate ); - QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result ); - - MakeRecordingWithAddedFrames( &recording, &testTone, glitchPosition, framesAdded ); - - PaQa_AnalyseRecording( &recording, &testTone, &analysisResult ); - - if( framesAdded < 0 ) - { - framesDropped = -framesAdded; - framesAdded = 0; - } - -#if PRINT_REPORTS - printf("\n=== Dropped Frame Analysis ===================\n"); - printf(" expected actual\n"); - printf(" latency: %10.3f %10.3f\n", (double)latencyFrames, analysisResult.latency ); - printf(" num added frames: %10.3f %10.3f\n", (double)framesAdded, analysisResult.numAddedFrames ); - printf(" added frames at: %10.3f %10.3f\n", (double)glitchPosition, analysisResult.addedFramesPosition ); - printf(" num dropped frames: %10.3f %10.3f\n", (double)framesDropped, analysisResult.numDroppedFrames ); - printf(" dropped frames at: %10.3f %10.3f\n", (double)glitchPosition, analysisResult.droppedFramesPosition ); -#endif - - QA_ASSERT_CLOSE( "PaQa_AnalyseRecording latency", latencyFrames, analysisResult.latency, 0.5 ); - QA_ASSERT_CLOSE( "PaQa_AnalyseRecording framesAdded", framesAdded, analysisResult.numAddedFrames, 1.0 ); - QA_ASSERT_CLOSE( "PaQa_AnalyseRecording framesDropped", framesDropped, analysisResult.numDroppedFrames, 1.0 ); -// QA_ASSERT_CLOSE( "PaQa_AnalyseRecording glitchPosition", glitchPosition, analysisResult.glitchPosition, cycleSize ); - - PaQa_TerminateRecording( &recording ); - return 0; - -error: - PaQa_TerminateRecording( &recording); - return 1; -} - -/*==========================================================================================*/ -/** - * Test various dropped sample scenarios. - */ -static int TestDetectPhaseErrors( void ) -{ - int result; - - result = TestDetectSinglePhaseError( 44100, 200, 477, -1, 0 ); - if( result < 0 ) return result; -/* - result = TestDetectSinglePhaseError( 44100, 200, 77, -1, 0 ); - if( result < 0 ) return result; - - result = TestDetectSinglePhaseError( 44100, 200, 83, 3712, 9 ); - if( result < 0 ) return result; - - result = TestDetectSinglePhaseError( 44100, 280, 83, 3712, 27 ); - if( result < 0 ) return result; - - result = TestDetectSinglePhaseError( 44100, 200, 234, 3712, -9 ); - if( result < 0 ) return result; - - result = TestDetectSinglePhaseError( 44100, 200, 2091, 8923, -2 ); - if( result < 0 ) return result; - - result = TestDetectSinglePhaseError( 44100, 120, 1782, 5772, -18 ); - if( result < 0 ) return result; - - // Note that if the frequency is too high then it is hard to detect single dropped frames. - result = TestDetectSinglePhaseError( 44100, 200, 500, 4251, -1 ); - if( result < 0 ) return result; -*/ - return 0; -} - -/*==========================================================================================*/ -/** - * Detect one pop in a recording. - */ -static int TestDetectSinglePop( double sampleRate, int cycleSize, int latencyFrames, int popPosition, int popWidth, double popAmplitude ) -{ - int result = 0; - PaQaRecording recording; - PaQaTestTone testTone; - PaQaAnalysisResult analysisResult = { 0.0 }; - int maxFrames = ((int)sampleRate) * 2; - - testTone.samplesPerFrame = 1; - testTone.sampleRate = sampleRate; - testTone.frequency = sampleRate / cycleSize; - testTone.amplitude = 0.5; - testTone.startDelay = latencyFrames; - - result = PaQa_InitializeRecording( &recording, maxFrames, (int) sampleRate ); - QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result ); - - MakeRecordingWithPop( &recording, &testTone, popPosition, popWidth, popAmplitude ); - - PaQa_AnalyseRecording( &recording, &testTone, &analysisResult ); - -#if PRINT_REPORTS - printf("\n=== Pop Analysis ===================\n"); - printf(" expected actual\n"); - printf(" latency: %10.3f %10.3f\n", (double)latencyFrames, analysisResult.latency ); - printf(" popPosition: %10.3f %10.3f\n", (double)popPosition, analysisResult.popPosition ); - printf(" popAmplitude: %10.3f %10.3f\n", popAmplitude, analysisResult.popAmplitude ); - printf(" cycleSize: %6d\n", cycleSize ); - printf(" num added frames: %10.3f\n", analysisResult.numAddedFrames ); - printf(" added frames at: %10.3f\n", analysisResult.addedFramesPosition ); - printf(" num dropped frames: %10.3f\n", analysisResult.numDroppedFrames ); - printf(" dropped frames at: %10.3f\n", analysisResult.droppedFramesPosition ); -#endif - - QA_ASSERT_CLOSE( "PaQa_AnalyseRecording latency", latencyFrames, analysisResult.latency, 0.5 ); - QA_ASSERT_CLOSE( "PaQa_AnalyseRecording popPosition", popPosition, analysisResult.popPosition, 10 ); - if( popWidth > 0 ) - { - QA_ASSERT_CLOSE( "PaQa_AnalyseRecording popAmplitude", popAmplitude, analysisResult.popAmplitude, 0.1 * popAmplitude ); - } - - PaQa_TerminateRecording( &recording ); - return 0; - -error: - PaQa_SaveRecordingToWaveFile( &recording, "bad_recording.wav" ); - PaQa_TerminateRecording( &recording); - return 1; -} - -/*==========================================================================================*/ -/** - * Analyse recording with a DC offset. - */ -static int TestSingleInitialSpike( double sampleRate, int stepPosition, int cycleSize, int latencyFrames, double stepAmplitude ) -{ - int i; - int result = 0; - // Account for highpass filter offset. - int expectedLatency = latencyFrames + 1; - PaQaRecording recording; - - PaQaRecording hipassOutput = { 0 }; - BiquadFilter hipassFilter; - - PaQaTestTone testTone; - PaQaAnalysisResult analysisResult = { 0.0 }; - int maxFrames = ((int)sampleRate) * 2; - - testTone.samplesPerFrame = 1; - testTone.sampleRate = sampleRate; - testTone.frequency = sampleRate / cycleSize; - testTone.amplitude = -0.5; - testTone.startDelay = latencyFrames; - - result = PaQa_InitializeRecording( &recording, maxFrames, (int) sampleRate ); - QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result ); - - result = PaQa_InitializeRecording( &hipassOutput, maxFrames, (int) sampleRate ); - QA_ASSERT_EQUALS( "PaQa_InitializeRecording failed", 0, result ); - - MakeCleanRecording( &recording, &testTone ); - - // Apply DC step. - for( i=stepPosition; i