summaryrefslogtreecommitdiff
path: root/portaudio/test/patest_dsound_find_best_latency_params.c
diff options
context:
space:
mode:
Diffstat (limited to 'portaudio/test/patest_dsound_find_best_latency_params.c')
-rw-r--r--portaudio/test/patest_dsound_find_best_latency_params.c513
1 files changed, 0 insertions, 513 deletions
diff --git a/portaudio/test/patest_dsound_find_best_latency_params.c b/portaudio/test/patest_dsound_find_best_latency_params.c
deleted file mode 100644
index 1c074ab..0000000
--- a/portaudio/test/patest_dsound_find_best_latency_params.c
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * $Id: $
- * Portable Audio I/O Library
- * Windows DirectSound low level buffer user guided parameters search
- *
- * Copyright (c) 2010-2011 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 <stdio.h>
-#include <time.h>
-#include <math.h>
-
-#define _WIN32_WINNT 0x0501 /* for GetNativeSystemInfo */
-#include <windows.h>
-//#include <mmsystem.h> /* required when using pa_win_wmme.h */
-
-#include <conio.h> /* for _getch */
-
-
-#include "portaudio.h"
-#include "pa_win_ds.h"
-
-
-#define DEFAULT_SAMPLE_RATE (44100.)
-
-#ifndef M_PI
-#define M_PI (3.14159265)
-#endif
-
-#define TABLE_SIZE (2048)
-
-#define CHANNEL_COUNT (2)
-
-
-/*******************************************************************/
-/* functions to query and print Windows version information */
-
-typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
-
-LPFN_ISWOW64PROCESS fnIsWow64Process;
-
-static BOOL IsWow64()
-{
- BOOL bIsWow64 = FALSE;
-
- //IsWow64Process is not available on all supported versions of Windows.
- //Use GetModuleHandle to get a handle to the DLL that contains the function
- //and GetProcAddress to get a pointer to the function if available.
-
- fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
- GetModuleHandle(TEXT("kernel32")),"IsWow64Process" );
-
- if(NULL != fnIsWow64Process)
- {
- if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
- {
- //handle error
- }
- }
- return bIsWow64;
-}
-
-static void printWindowsVersionInfo( FILE *fp )
-{
- OSVERSIONINFOEX osVersionInfoEx;
- SYSTEM_INFO systemInfo;
- const char *osName = "Unknown";
- const char *osProductType = "";
- const char *processorArchitecture = "Unknown";
-
- memset( &osVersionInfoEx, 0, sizeof(OSVERSIONINFOEX) );
- osVersionInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
- GetVersionEx( &osVersionInfoEx );
-
-
- if( osVersionInfoEx.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ){
- switch( osVersionInfoEx.dwMinorVersion ){
- case 0: osName = "Windows 95"; break;
- case 10: osName = "Windows 98"; break; // could also be 98SE (I've seen code discriminate based
- // on osInfo.Version.Revision.ToString() == "2222A")
- case 90: osName = "Windows Me"; break;
- }
- }else if( osVersionInfoEx.dwPlatformId == VER_PLATFORM_WIN32_NT ){
- switch( osVersionInfoEx.dwMajorVersion ){
- case 3: osName = "Windows NT 3.51"; break;
- case 4: osName = "Windows NT 4.0"; break;
- case 5: switch( osVersionInfoEx.dwMinorVersion ){
- case 0: osName = "Windows 2000"; break;
- case 1: osName = "Windows XP"; break;
- case 2:
- if( osVersionInfoEx.wSuiteMask & 0x00008000 /*VER_SUITE_WH_SERVER*/ ){
- osName = "Windows Home Server";
- }else{
- if( osVersionInfoEx.wProductType == VER_NT_WORKSTATION ){
- osName = "Windows XP Professional x64 Edition (?)";
- }else{
- if( GetSystemMetrics(/*SM_SERVERR2*/89) == 0 )
- osName = "Windows Server 2003";
- else
- osName = "Windows Server 2003 R2";
- }
- }break;
- }break;
- case 6:switch( osVersionInfoEx.dwMinorVersion ){
- case 0:
- if( osVersionInfoEx.wProductType == VER_NT_WORKSTATION )
- osName = "Windows Vista";
- else
- osName = "Windows Server 2008";
- break;
- case 1:
- if( osVersionInfoEx.wProductType == VER_NT_WORKSTATION )
- osName = "Windows 7";
- else
- osName = "Windows Server 2008 R2";
- break;
- }break;
- }
- }
-
- if(osVersionInfoEx.dwMajorVersion == 4)
- {
- if(osVersionInfoEx.wProductType == VER_NT_WORKSTATION)
- osProductType = "Workstation";
- else if(osVersionInfoEx.wProductType == VER_NT_SERVER)
- osProductType = "Server";
- }
- else if(osVersionInfoEx.dwMajorVersion == 5)
- {
- if(osVersionInfoEx.wProductType == VER_NT_WORKSTATION)
- {
- if((osVersionInfoEx.wSuiteMask & VER_SUITE_PERSONAL) == VER_SUITE_PERSONAL)
- osProductType = "Home Edition"; // Windows XP Home Edition
- else
- osProductType = "Professional"; // Windows XP / Windows 2000 Professional
- }
- else if(osVersionInfoEx.wProductType == VER_NT_SERVER)
- {
- if(osVersionInfoEx.dwMinorVersion == 0)
- {
- if((osVersionInfoEx.wSuiteMask & VER_SUITE_DATACENTER) == VER_SUITE_DATACENTER)
- osProductType = "Datacenter Server"; // Windows 2000 Datacenter Server
- else if((osVersionInfoEx.wSuiteMask & VER_SUITE_ENTERPRISE) == VER_SUITE_ENTERPRISE)
- osProductType = "Advanced Server"; // Windows 2000 Advanced Server
- else
- osProductType = "Server"; // Windows 2000 Server
- }
- }
- else
- {
- if((osVersionInfoEx.wSuiteMask & VER_SUITE_DATACENTER) == VER_SUITE_DATACENTER)
- osProductType = "Datacenter Edition"; // Windows Server 2003 Datacenter Edition
- else if((osVersionInfoEx.wSuiteMask & VER_SUITE_ENTERPRISE) == VER_SUITE_ENTERPRISE)
- osProductType = "Enterprise Edition"; // Windows Server 2003 Enterprise Edition
- else if((osVersionInfoEx.wSuiteMask & VER_SUITE_BLADE) == VER_SUITE_BLADE)
- osProductType = "Web Edition"; // Windows Server 2003 Web Edition
- else
- osProductType = "Standard Edition"; // Windows Server 2003 Standard Edition
- }
- }
-
- memset( &systemInfo, 0, sizeof(SYSTEM_INFO) );
- GetNativeSystemInfo( &systemInfo );
-
- if( systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL )
- processorArchitecture = "x86";
- else if( systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 )
- processorArchitecture = "x64";
- else if( systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 )
- processorArchitecture = "Itanium";
-
-
- fprintf( fp, "OS name and edition: %s %s\n", osName, osProductType );
- fprintf( fp, "OS version: %d.%d.%d %S\n",
- osVersionInfoEx.dwMajorVersion, osVersionInfoEx.dwMinorVersion,
- osVersionInfoEx.dwBuildNumber, osVersionInfoEx.szCSDVersion );
- fprintf( fp, "Processor architecture: %s\n", processorArchitecture );
- fprintf( fp, "WoW64 process: %s\n", IsWow64() ? "Yes" : "No" );
-}
-
-static void printTimeAndDate( FILE *fp )
-{
- struct tm *local;
- time_t t;
-
- t = time(NULL);
- local = localtime(&t);
- fprintf(fp, "Local time and date: %s", asctime(local));
- local = gmtime(&t);
- fprintf(fp, "UTC time and date: %s", asctime(local));
-}
-
-/*******************************************************************/
-
-typedef struct
-{
- float sine[TABLE_SIZE];
- double phase;
- double phaseIncrement;
- volatile int fadeIn;
- volatile int fadeOut;
- double amp;
-}
-paTestData;
-
-static paTestData data;
-
-/* 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().
-*/
-static int patestCallback( const void *inputBuffer, void *outputBuffer,
- unsigned long framesPerBuffer,
- const PaStreamCallbackTimeInfo* timeInfo,
- PaStreamCallbackFlags statusFlags,
- void *userData )
-{
- paTestData *data = (paTestData*)userData;
- float *out = (float*)outputBuffer;
- unsigned long i,j;
-
- (void) timeInfo; /* Prevent unused variable warnings. */
- (void) statusFlags;
- (void) inputBuffer;
-
- for( i=0; i<framesPerBuffer; i++ )
- {
- float x = data->sine[(int)data->phase];
- data->phase += data->phaseIncrement;
- if( data->phase >= TABLE_SIZE ){
- data->phase -= TABLE_SIZE;
- }
-
- x *= data->amp;
- if( data->fadeIn ){
- data->amp += .001;
- if( data->amp >= 1. )
- data->fadeIn = 0;
- }else if( data->fadeOut ){
- if( data->amp > 0 )
- data->amp -= .001;
- }
-
- for( j = 0; j < CHANNEL_COUNT; ++j ){
- *out++ = x;
- }
- }
-
- if( data->amp > 0 )
- return paContinue;
- else
- return paComplete;
-}
-
-
-#define YES 1
-#define NO 0
-
-
-static int playUntilKeyPress( int deviceIndex, float sampleRate,
- int framesPerUserBuffer, int framesPerDSoundBuffer )
-{
- PaStreamParameters outputParameters;
- PaWinDirectSoundStreamInfo directSoundStreamInfo;
- PaStream *stream;
- PaError err;
- int c;
-
- outputParameters.device = deviceIndex;
- outputParameters.channelCount = CHANNEL_COUNT;
- outputParameters.sampleFormat = paFloat32; /* 32 bit floating point processing */
- outputParameters.suggestedLatency = 0; /*Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;*/
- outputParameters.hostApiSpecificStreamInfo = NULL;
-
- directSoundStreamInfo.size = sizeof(PaWinDirectSoundStreamInfo);
- directSoundStreamInfo.hostApiType = paDirectSound;
- directSoundStreamInfo.version = 2;
- directSoundStreamInfo.flags = paWinDirectSoundUseLowLevelLatencyParameters;
- directSoundStreamInfo.framesPerBuffer = framesPerDSoundBuffer;
- outputParameters.hostApiSpecificStreamInfo = &directSoundStreamInfo;
-
- err = Pa_OpenStream(
- &stream,
- NULL, /* no input */
- &outputParameters,
- sampleRate,
- framesPerUserBuffer,
- paClipOff | paPrimeOutputBuffersUsingStreamCallback, /* we won't output out of range samples so don't bother clipping them */
- patestCallback,
- &data );
- if( err != paNoError ) goto error;
-
- data.amp = 0;
- data.fadeIn = 1;
- data.fadeOut = 0;
- data.phase = 0;
- data.phaseIncrement = 15 + ((rand()%100) / 10); // randomise pitch
-
- err = Pa_StartStream( stream );
- if( err != paNoError ) goto error;
-
-
- do{
- printf( "Trying buffer size %d.\nIf it sounds smooth (without clicks or glitches) press 'y', if it sounds bad press 'n' ('q' to quit)\n", framesPerDSoundBuffer );
- c = tolower(_getch());
- if( c == 'q' ){
- Pa_Terminate();
- exit(0);
- }
- }while( c != 'y' && c != 'n' );
-
- data.fadeOut = 1;
- while( Pa_IsStreamActive(stream) == 1 )
- Pa_Sleep( 100 );
-
- err = Pa_StopStream( stream );
- if( err != paNoError ) goto error;
-
- err = Pa_CloseStream( stream );
- if( err != paNoError ) goto error;
-
- return (c == 'y') ? YES : NO;
-
-error:
- return err;
-}
-
-/*******************************************************************/
-static void usage( int dsoundHostApiIndex )
-{
- int i;
-
- fprintf( stderr, "PortAudio DirectSound output latency user guided test\n" );
- fprintf( stderr, "Usage: x.exe dsound-device-index [sampleRate]\n" );
- fprintf( stderr, "Invalid device index. Use one of these:\n" );
- for( i=0; i < Pa_GetDeviceCount(); ++i ){
-
- if( Pa_GetDeviceInfo(i)->hostApi == dsoundHostApiIndex && Pa_GetDeviceInfo(i)->maxOutputChannels > 0 )
- fprintf( stderr, "%d (%s)\n", i, Pa_GetDeviceInfo(i)->name );
- }
- Pa_Terminate();
- exit(-1);
-}
-
-/*
- ideas:
- o- could be testing with 80% CPU load
- o- could test with different channel counts
-*/
-
-int main(int argc, char* argv[])
-{
- PaError err;
- int i;
- int deviceIndex;
- int dsoundBufferSize, smallestWorkingBufferSize;
- int smallestWorkingBufferingLatencyFrames;
- int min, max, mid;
- int testResult;
- FILE *resultsFp;
- int dsoundHostApiIndex;
- const PaHostApiInfo *dsoundHostApiInfo;
- double sampleRate = DEFAULT_SAMPLE_RATE;
-
- err = Pa_Initialize();
- if( err != paNoError ) goto error;
-
- dsoundHostApiIndex = Pa_HostApiTypeIdToHostApiIndex( paDirectSound );
- dsoundHostApiInfo = Pa_GetHostApiInfo( dsoundHostApiIndex );
-
- if( argc > 3 )
- usage(dsoundHostApiIndex);
-
- deviceIndex = dsoundHostApiInfo->defaultOutputDevice;
- if( argc >= 2 ){
- deviceIndex = -1;
- if( sscanf( argv[1], "%d", &deviceIndex ) != 1 )
- usage(dsoundHostApiInfo);
- if( deviceIndex < 0 || deviceIndex >= Pa_GetDeviceCount() || Pa_GetDeviceInfo(deviceIndex)->hostApi != dsoundHostApiIndex ){
- usage(dsoundHostApiInfo);
- }
- }
-
- printf( "Using device id %d (%s)\n", deviceIndex, Pa_GetDeviceInfo(deviceIndex)->name );
-
- if( argc >= 3 ){
- if( sscanf( argv[2], "%lf", &sampleRate ) != 1 )
- usage(dsoundHostApiIndex);
- }
-
- printf( "Testing with sample rate %f.\n", (float)sampleRate );
-
-
-
- /* initialise sinusoidal wavetable */
- for( i=0; i<TABLE_SIZE; i++ )
- {
- data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
- }
-
- data.phase = 0;
-
- resultsFp = fopen( "results.txt", "at" );
- fprintf( resultsFp, "*** DirectSound smallest working output buffer sizes\n" );
-
- printTimeAndDate( resultsFp );
- printWindowsVersionInfo( resultsFp );
-
- fprintf( resultsFp, "audio device: %s\n", Pa_GetDeviceInfo( deviceIndex )->name );
- fflush( resultsFp );
-
- fprintf( resultsFp, "Sample rate: %f\n", (float)sampleRate );
- fprintf( resultsFp, "Smallest working buffer size (frames), Smallest working buffering latency (frames), Smallest working buffering latency (Seconds)\n" );
-
-
- /*
- Binary search after Niklaus Wirth
- from http://en.wikipedia.org/wiki/Binary_search_algorithm#The_algorithm
- */
- min = 1;
- max = (int)(sampleRate * .3); /* we assume that this size works 300ms */
- smallestWorkingBufferSize = 0;
-
- do{
- mid = min + ((max - min) / 2);
-
- dsoundBufferSize = mid;
- testResult = playUntilKeyPress( deviceIndex, sampleRate, 0, dsoundBufferSize );
-
- if( testResult == YES ){
- max = mid - 1;
- smallestWorkingBufferSize = dsoundBufferSize;
- }else{
- min = mid + 1;
- }
-
- }while( (min <= max) && (testResult == YES || testResult == NO) );
-
- smallestWorkingBufferingLatencyFrames = smallestWorkingBufferSize; /* not strictly true, but we're using an unspecified callback size, so kind of */
-
- printf( "Smallest working buffer size is: %d\n", smallestWorkingBufferSize );
- printf( "Corresponding to buffering latency of %d frames, or %f seconds.\n", smallestWorkingBufferingLatencyFrames, smallestWorkingBufferingLatencyFrames / sampleRate );
-
- fprintf( resultsFp, "%d, %d, %f\n", smallestWorkingBufferSize, smallestWorkingBufferingLatencyFrames, smallestWorkingBufferingLatencyFrames / sampleRate );
- fflush( resultsFp );
-
-
- /* power of 2 test. iterate to the smallest power of two that works */
-
- smallestWorkingBufferSize = 0;
- dsoundBufferSize = 64;
-
- do{
- testResult = playUntilKeyPress( deviceIndex, sampleRate, 0, dsoundBufferSize );
-
- if( testResult == YES ){
- smallestWorkingBufferSize = dsoundBufferSize;
- }else{
- dsoundBufferSize *= 2;
- }
-
- }while( (dsoundBufferSize <= (int)(sampleRate * .3)) && testResult == NO );
-
- smallestWorkingBufferingLatencyFrames = smallestWorkingBufferSize; /* not strictly true, but we're using an unspecified callback size, so kind of */
-
- fprintf( resultsFp, "%d, %d, %f\n", smallestWorkingBufferSize, smallestWorkingBufferingLatencyFrames, smallestWorkingBufferingLatencyFrames / sampleRate );
- fflush( resultsFp );
-
-
- fprintf( resultsFp, "###\n" );
- fclose( resultsFp );
-
- Pa_Terminate();
- printf("Test finished.\n");
-
- return err;
-error:
- Pa_Terminate();
- fprintf( stderr, "An error occurred while using the PortAudio stream\n" );
- fprintf( stderr, "Error number: %d\n", err );
- fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
- return err;
-}