cannam@89
|
1 /** @file paqa_latency.c
|
cannam@89
|
2 @ingroup qa_src
|
cannam@89
|
3 @brief Test latency estimates.
|
cannam@89
|
4 @author Ross Bencina <rossb@audiomulch.com>
|
cannam@89
|
5 @author Phil Burk <philburk@softsynth.com>
|
cannam@89
|
6 */
|
cannam@89
|
7 /*
|
cannam@89
|
8 * $Id: patest_sine.c 1368 2008-03-01 00:38:27Z rossb $
|
cannam@89
|
9 *
|
cannam@89
|
10 * This program uses the PortAudio Portable Audio Library.
|
cannam@89
|
11 * For more information see: http://www.portaudio.com/
|
cannam@89
|
12 * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
cannam@89
|
13 *
|
cannam@89
|
14 * Permission is hereby granted, free of charge, to any person obtaining
|
cannam@89
|
15 * a copy of this software and associated documentation files
|
cannam@89
|
16 * (the "Software"), to deal in the Software without restriction,
|
cannam@89
|
17 * including without limitation the rights to use, copy, modify, merge,
|
cannam@89
|
18 * publish, distribute, sublicense, and/or sell copies of the Software,
|
cannam@89
|
19 * and to permit persons to whom the Software is furnished to do so,
|
cannam@89
|
20 * subject to the following conditions:
|
cannam@89
|
21 *
|
cannam@89
|
22 * The above copyright notice and this permission notice shall be
|
cannam@89
|
23 * included in all copies or substantial portions of the Software.
|
cannam@89
|
24 *
|
cannam@89
|
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
cannam@89
|
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
cannam@89
|
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
cannam@89
|
28 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
cannam@89
|
29 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
cannam@89
|
30 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
cannam@89
|
31 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
cannam@89
|
32 */
|
cannam@89
|
33
|
cannam@89
|
34 /*
|
cannam@89
|
35 * The text above constitutes the entire PortAudio license; however,
|
cannam@89
|
36 * the PortAudio community also makes the following non-binding requests:
|
cannam@89
|
37 *
|
cannam@89
|
38 * Any person wishing to distribute modifications to the Software is
|
cannam@89
|
39 * requested to send the modifications to the original developer so that
|
cannam@89
|
40 * they can be incorporated into the canonical version. It is also
|
cannam@89
|
41 * requested that these non-binding requests be included along with the
|
cannam@89
|
42 * license above.
|
cannam@89
|
43 */
|
cannam@89
|
44 #include <stdio.h>
|
cannam@89
|
45 #include <math.h>
|
cannam@89
|
46 #include "portaudio.h"
|
cannam@89
|
47 #include "loopback/src/qa_tools.h"
|
cannam@89
|
48
|
cannam@89
|
49 #define NUM_SECONDS (5)
|
cannam@89
|
50 #define SAMPLE_RATE (44100)
|
cannam@89
|
51 #define FRAMES_PER_BUFFER (64)
|
cannam@89
|
52
|
cannam@89
|
53 #ifndef M_PI
|
cannam@89
|
54 #define M_PI (3.14159265)
|
cannam@89
|
55 #endif
|
cannam@89
|
56
|
cannam@89
|
57 #define TABLE_SIZE (200)
|
cannam@89
|
58 typedef struct
|
cannam@89
|
59 {
|
cannam@89
|
60 float sine[TABLE_SIZE];
|
cannam@89
|
61 int left_phase;
|
cannam@89
|
62 int right_phase;
|
cannam@89
|
63 char message[20];
|
cannam@89
|
64 int minFramesPerBuffer;
|
cannam@89
|
65 int maxFramesPerBuffer;
|
cannam@89
|
66 int callbackCount;
|
cannam@89
|
67 PaTime minDeltaDacTime;
|
cannam@89
|
68 PaTime maxDeltaDacTime;
|
cannam@89
|
69 PaStreamCallbackTimeInfo previousTimeInfo;
|
cannam@89
|
70 }
|
cannam@89
|
71 paTestData;
|
cannam@89
|
72
|
cannam@89
|
73 /* Used to tally the results of the QA tests. */
|
cannam@89
|
74 int g_testsPassed = 0;
|
cannam@89
|
75 int g_testsFailed = 0;
|
cannam@89
|
76
|
cannam@89
|
77 /* This routine will be called by the PortAudio engine when audio is needed.
|
cannam@89
|
78 ** It may called at interrupt level on some machines so don't do anything
|
cannam@89
|
79 ** that could mess up the system like calling malloc() or free().
|
cannam@89
|
80 */
|
cannam@89
|
81 static int patestCallback( const void *inputBuffer, void *outputBuffer,
|
cannam@89
|
82 unsigned long framesPerBuffer,
|
cannam@89
|
83 const PaStreamCallbackTimeInfo* timeInfo,
|
cannam@89
|
84 PaStreamCallbackFlags statusFlags,
|
cannam@89
|
85 void *userData )
|
cannam@89
|
86 {
|
cannam@89
|
87 paTestData *data = (paTestData*)userData;
|
cannam@89
|
88 float *out = (float*)outputBuffer;
|
cannam@89
|
89 unsigned long i;
|
cannam@89
|
90
|
cannam@89
|
91 (void) timeInfo; /* Prevent unused variable warnings. */
|
cannam@89
|
92 (void) statusFlags;
|
cannam@89
|
93 (void) inputBuffer;
|
cannam@89
|
94
|
cannam@89
|
95 if( data->minFramesPerBuffer > framesPerBuffer )
|
cannam@89
|
96 {
|
cannam@89
|
97 data->minFramesPerBuffer = framesPerBuffer;
|
cannam@89
|
98 }
|
cannam@89
|
99 if( data->maxFramesPerBuffer < framesPerBuffer )
|
cannam@89
|
100 {
|
cannam@89
|
101 data->maxFramesPerBuffer = framesPerBuffer;
|
cannam@89
|
102 }
|
cannam@89
|
103
|
cannam@89
|
104 /* Measure min and max output time stamp delta. */
|
cannam@89
|
105 if( data->callbackCount > 0 )
|
cannam@89
|
106 {
|
cannam@89
|
107 PaTime delta = timeInfo->outputBufferDacTime - data->previousTimeInfo.outputBufferDacTime;
|
cannam@89
|
108 if( data->minDeltaDacTime > delta )
|
cannam@89
|
109 {
|
cannam@89
|
110 data->minDeltaDacTime = delta;
|
cannam@89
|
111 }
|
cannam@89
|
112 if( data->maxDeltaDacTime < delta )
|
cannam@89
|
113 {
|
cannam@89
|
114 data->maxDeltaDacTime = delta;
|
cannam@89
|
115 }
|
cannam@89
|
116 }
|
cannam@89
|
117 data->previousTimeInfo = *timeInfo;
|
cannam@89
|
118
|
cannam@89
|
119 for( i=0; i<framesPerBuffer; i++ )
|
cannam@89
|
120 {
|
cannam@89
|
121 *out++ = data->sine[data->left_phase]; /* left */
|
cannam@89
|
122 *out++ = data->sine[data->right_phase]; /* right */
|
cannam@89
|
123 data->left_phase += 1;
|
cannam@89
|
124 if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE;
|
cannam@89
|
125 data->right_phase += 3; /* higher pitch so we can distinguish left and right. */
|
cannam@89
|
126 if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE;
|
cannam@89
|
127 }
|
cannam@89
|
128
|
cannam@89
|
129 data->callbackCount += 1;
|
cannam@89
|
130 return paContinue;
|
cannam@89
|
131 }
|
cannam@89
|
132
|
cannam@89
|
133 PaError paqaCheckLatency( PaStreamParameters *outputParamsPtr,
|
cannam@89
|
134 paTestData *dataPtr, double sampleRate, unsigned long framesPerBuffer )
|
cannam@89
|
135 {
|
cannam@89
|
136 PaError err;
|
cannam@89
|
137 PaStream *stream;
|
cannam@89
|
138 const PaStreamInfo* streamInfo;
|
cannam@89
|
139
|
cannam@89
|
140 dataPtr->minFramesPerBuffer = 9999999;
|
cannam@89
|
141 dataPtr->maxFramesPerBuffer = 0;
|
cannam@89
|
142 dataPtr->minDeltaDacTime = 9999999.0;
|
cannam@89
|
143 dataPtr->maxDeltaDacTime = 0.0;
|
cannam@89
|
144 dataPtr->callbackCount = 0;
|
cannam@89
|
145
|
cannam@89
|
146 printf("Stream parameter: suggestedOutputLatency = %g\n", outputParamsPtr->suggestedLatency );
|
cannam@89
|
147 if( framesPerBuffer == paFramesPerBufferUnspecified ){
|
cannam@89
|
148 printf("Stream parameter: user framesPerBuffer = paFramesPerBufferUnspecified\n" );
|
cannam@89
|
149 }else{
|
cannam@89
|
150 printf("Stream parameter: user framesPerBuffer = %lu\n", framesPerBuffer );
|
cannam@89
|
151 }
|
cannam@89
|
152 err = Pa_OpenStream(
|
cannam@89
|
153 &stream,
|
cannam@89
|
154 NULL, /* no input */
|
cannam@89
|
155 outputParamsPtr,
|
cannam@89
|
156 sampleRate,
|
cannam@89
|
157 framesPerBuffer,
|
cannam@89
|
158 paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
cannam@89
|
159 patestCallback,
|
cannam@89
|
160 dataPtr );
|
cannam@89
|
161 if( err != paNoError ) goto error1;
|
cannam@89
|
162
|
cannam@89
|
163 streamInfo = Pa_GetStreamInfo( stream );
|
cannam@89
|
164 printf("Stream info: inputLatency = %g\n", streamInfo->inputLatency );
|
cannam@89
|
165 printf("Stream info: outputLatency = %g\n", streamInfo->outputLatency );
|
cannam@89
|
166
|
cannam@89
|
167 err = Pa_StartStream( stream );
|
cannam@89
|
168 if( err != paNoError ) goto error2;
|
cannam@89
|
169
|
cannam@89
|
170 printf("Play for %d seconds.\n", NUM_SECONDS );
|
cannam@89
|
171 Pa_Sleep( NUM_SECONDS * 1000 );
|
cannam@89
|
172
|
cannam@89
|
173 printf(" minFramesPerBuffer = %4d\n", dataPtr->minFramesPerBuffer );
|
cannam@89
|
174 printf(" maxFramesPerBuffer = %4d\n", dataPtr->maxFramesPerBuffer );
|
cannam@89
|
175 printf(" minDeltaDacTime = %f\n", dataPtr->minDeltaDacTime );
|
cannam@89
|
176 printf(" maxDeltaDacTime = %f\n", dataPtr->maxDeltaDacTime );
|
cannam@89
|
177
|
cannam@89
|
178 err = Pa_StopStream( stream );
|
cannam@89
|
179 if( err != paNoError ) goto error2;
|
cannam@89
|
180
|
cannam@89
|
181 err = Pa_CloseStream( stream );
|
cannam@89
|
182 Pa_Sleep( 1 * 1000 );
|
cannam@89
|
183
|
cannam@89
|
184
|
cannam@89
|
185 printf("-------------------------------------\n");
|
cannam@89
|
186 return err;
|
cannam@89
|
187 error2:
|
cannam@89
|
188 Pa_CloseStream( stream );
|
cannam@89
|
189 error1:
|
cannam@89
|
190 printf("-------------------------------------\n");
|
cannam@89
|
191 return err;
|
cannam@89
|
192 }
|
cannam@89
|
193
|
cannam@89
|
194
|
cannam@89
|
195 /*******************************************************************/
|
cannam@89
|
196 static int paqaNoopCallback( const void *inputBuffer, void *outputBuffer,
|
cannam@89
|
197 unsigned long framesPerBuffer,
|
cannam@89
|
198 const PaStreamCallbackTimeInfo* timeInfo,
|
cannam@89
|
199 PaStreamCallbackFlags statusFlags,
|
cannam@89
|
200 void *userData )
|
cannam@89
|
201 {
|
cannam@89
|
202 (void)inputBuffer;
|
cannam@89
|
203 (void)outputBuffer;
|
cannam@89
|
204 (void)framesPerBuffer;
|
cannam@89
|
205 (void)timeInfo;
|
cannam@89
|
206 (void)statusFlags;
|
cannam@89
|
207 (void)userData;
|
cannam@89
|
208 return paContinue;
|
cannam@89
|
209 }
|
cannam@89
|
210
|
cannam@89
|
211 /*******************************************************************/
|
cannam@89
|
212 static int paqaCheckMultipleSuggested( PaDeviceIndex deviceIndex, int isInput )
|
cannam@89
|
213 {
|
cannam@89
|
214 int i;
|
cannam@89
|
215 int numLoops = 10;
|
cannam@89
|
216 PaError err;
|
cannam@89
|
217 PaStream *stream;
|
cannam@89
|
218 PaStreamParameters streamParameters;
|
cannam@89
|
219 const PaStreamInfo* streamInfo;
|
cannam@89
|
220 double lowLatency;
|
cannam@89
|
221 double highLatency;
|
cannam@89
|
222 double finalLatency;
|
cannam@89
|
223 double sampleRate = 44100.0;
|
cannam@89
|
224 const PaDeviceInfo *pdi = Pa_GetDeviceInfo( deviceIndex );
|
cannam@89
|
225 double previousLatency = 0.0;
|
cannam@89
|
226 int numChannels = 1;
|
cannam@89
|
227
|
cannam@89
|
228 printf("------------------------ paqaCheckMultipleSuggested - %s\n",
|
cannam@89
|
229 (isInput ? "INPUT" : "OUTPUT") );
|
cannam@89
|
230 if( isInput )
|
cannam@89
|
231 {
|
cannam@89
|
232 lowLatency = pdi->defaultLowInputLatency;
|
cannam@89
|
233 highLatency = pdi->defaultHighInputLatency;
|
cannam@89
|
234 numChannels = (pdi->maxInputChannels < 2) ? 1 : 2;
|
cannam@89
|
235 }
|
cannam@89
|
236 else
|
cannam@89
|
237 {
|
cannam@89
|
238 lowLatency = pdi->defaultLowOutputLatency;
|
cannam@89
|
239 highLatency = pdi->defaultHighOutputLatency;
|
cannam@89
|
240 numChannels = (pdi->maxOutputChannels < 2) ? 1 : 2;
|
cannam@89
|
241 }
|
cannam@89
|
242 streamParameters.channelCount = numChannels;
|
cannam@89
|
243 streamParameters.device = deviceIndex;
|
cannam@89
|
244 streamParameters.hostApiSpecificStreamInfo = NULL;
|
cannam@89
|
245 streamParameters.sampleFormat = paFloat32;
|
cannam@89
|
246
|
cannam@89
|
247 printf(" lowLatency = %g\n", lowLatency );
|
cannam@89
|
248 printf(" highLatency = %g\n", highLatency );
|
cannam@89
|
249 printf(" numChannels = %d\n", numChannels );
|
cannam@89
|
250
|
cannam@89
|
251 if( (highLatency - lowLatency) < 0.001 )
|
cannam@89
|
252 {
|
cannam@89
|
253 numLoops = 1;
|
cannam@89
|
254 }
|
cannam@89
|
255
|
cannam@89
|
256 for( i=0; i<numLoops; i++ )
|
cannam@89
|
257 {
|
cannam@89
|
258 streamParameters.suggestedLatency = lowLatency + ((highLatency - lowLatency) * i /(numLoops - 1.0));
|
cannam@89
|
259
|
cannam@89
|
260 printf(" suggestedLatency[%d] = %6.4f\n", i, streamParameters.suggestedLatency );
|
cannam@89
|
261
|
cannam@89
|
262 err = Pa_OpenStream(
|
cannam@89
|
263 &stream,
|
cannam@89
|
264 (isInput ? &streamParameters : NULL),
|
cannam@89
|
265 (isInput ? NULL : &streamParameters),
|
cannam@89
|
266 sampleRate,
|
cannam@89
|
267 paFramesPerBufferUnspecified,
|
cannam@89
|
268 paClipOff, /* we won't output out of range samples so don't bother clipping them */
|
cannam@89
|
269 paqaNoopCallback,
|
cannam@89
|
270 NULL );
|
cannam@89
|
271 if( err != paNoError ) goto error;
|
cannam@89
|
272
|
cannam@89
|
273 streamInfo = Pa_GetStreamInfo( stream );
|
cannam@89
|
274
|
cannam@89
|
275 err = Pa_CloseStream( stream );
|
cannam@89
|
276
|
cannam@89
|
277 if( isInput )
|
cannam@89
|
278 {
|
cannam@89
|
279 finalLatency = streamInfo->inputLatency;
|
cannam@89
|
280 }
|
cannam@89
|
281 else
|
cannam@89
|
282 {
|
cannam@89
|
283 finalLatency = streamInfo->outputLatency;
|
cannam@89
|
284 }
|
cannam@89
|
285 printf(" finalLatency = %6.4f\n", finalLatency );
|
cannam@89
|
286 QA_ASSERT_CLOSE( "final latency should be close to suggested latency",
|
cannam@89
|
287 streamParameters.suggestedLatency, finalLatency, (streamParameters.suggestedLatency * 0.3) );
|
cannam@89
|
288
|
cannam@89
|
289 QA_ASSERT_TRUE( " final latency should increase with suggested latency", (finalLatency > previousLatency) );
|
cannam@89
|
290 previousLatency = finalLatency;
|
cannam@89
|
291 }
|
cannam@89
|
292
|
cannam@89
|
293 return 0;
|
cannam@89
|
294 error:
|
cannam@89
|
295 return -1;
|
cannam@89
|
296 }
|
cannam@89
|
297
|
cannam@89
|
298 /*******************************************************************/
|
cannam@89
|
299 static int paqaVerifySuggestedLatency( void )
|
cannam@89
|
300 {
|
cannam@89
|
301 PaDeviceIndex id;
|
cannam@89
|
302 int result = 0;
|
cannam@89
|
303 const PaDeviceInfo *pdi;
|
cannam@89
|
304 int numDevices = Pa_GetDeviceCount();
|
cannam@89
|
305
|
cannam@89
|
306 printf("\n ------------------------ paqaVerifySuggestedLatency\n");
|
cannam@89
|
307 for( id=0; id<numDevices; id++ ) /* Iterate through all devices. */
|
cannam@89
|
308 {
|
cannam@89
|
309 pdi = Pa_GetDeviceInfo( id );
|
cannam@89
|
310 printf("Using device #%d: '%s' (%s)\n", id, pdi->name, Pa_GetHostApiInfo(pdi->hostApi)->name);
|
cannam@89
|
311 if( pdi->maxOutputChannels > 0 )
|
cannam@89
|
312 {
|
cannam@89
|
313 if( (result = paqaCheckMultipleSuggested( id, 0 )) != 0 ) goto error;
|
cannam@89
|
314 }
|
cannam@89
|
315 if( pdi->maxInputChannels > 0 )
|
cannam@89
|
316 {
|
cannam@89
|
317 if( (result = paqaCheckMultipleSuggested( id, 1 )) != 0 ) goto error;
|
cannam@89
|
318 }
|
cannam@89
|
319 }
|
cannam@89
|
320 return 0;
|
cannam@89
|
321 error:
|
cannam@89
|
322 return -1;
|
cannam@89
|
323 }
|
cannam@89
|
324
|
cannam@89
|
325 /*******************************************************************/
|
cannam@89
|
326 static int paqaVerifyDeviceInfoLatency( void )
|
cannam@89
|
327 {
|
cannam@89
|
328 PaDeviceIndex id;
|
cannam@89
|
329 const PaDeviceInfo *pdi;
|
cannam@89
|
330 int numDevices = Pa_GetDeviceCount();
|
cannam@89
|
331
|
cannam@89
|
332 printf("\n ------------------------ paqaVerifyDeviceInfoLatency\n");
|
cannam@89
|
333 for( id=0; id<numDevices; id++ ) /* Iterate through all devices. */
|
cannam@89
|
334 {
|
cannam@89
|
335 pdi = Pa_GetDeviceInfo( id );
|
cannam@89
|
336 printf("Using device #%d: '%s' (%s)\n", id, pdi->name, Pa_GetHostApiInfo(pdi->hostApi)->name);
|
cannam@89
|
337 if( pdi->maxOutputChannels > 0 )
|
cannam@89
|
338 {
|
cannam@89
|
339 printf(" Output defaultLowOutputLatency = %f seconds\n", pdi->defaultLowOutputLatency);
|
cannam@89
|
340 printf(" Output info: defaultHighOutputLatency = %f seconds\n", pdi->defaultHighOutputLatency);
|
cannam@89
|
341 QA_ASSERT_TRUE( "defaultLowOutputLatency should be > 0", (pdi->defaultLowOutputLatency > 0.0) );
|
cannam@89
|
342 QA_ASSERT_TRUE( "defaultHighOutputLatency should be > 0", (pdi->defaultHighOutputLatency > 0.0) );
|
cannam@89
|
343 //QA_ASSERT_TRUE( "defaultHighOutputLatency should be > Low", (pdi->defaultHighOutputLatency > pdi->defaultLowOutputLatency) );
|
cannam@89
|
344 }
|
cannam@89
|
345 if( pdi->maxInputChannels > 0 )
|
cannam@89
|
346 {
|
cannam@89
|
347 printf(" Input defaultLowOutputLatency = %f seconds\n", pdi->defaultLowInputLatency);
|
cannam@89
|
348 printf(" Input defaultHighOutputLatency = %f seconds\n", pdi->defaultHighInputLatency);
|
cannam@89
|
349 QA_ASSERT_TRUE( "defaultLowOutputLatency should be > 0", (pdi->defaultLowInputLatency > 0.0) );
|
cannam@89
|
350 QA_ASSERT_TRUE( "defaultHighOutputLatency should be > 0", (pdi->defaultHighInputLatency > 0.0) );
|
cannam@89
|
351 //QA_ASSERT_TRUE( "defaultHighOutputLatency should be > Low", (pdi->defaultHighInputLatency > pdi->defaultLowInputLatency) );
|
cannam@89
|
352 }
|
cannam@89
|
353 }
|
cannam@89
|
354 return 0;
|
cannam@89
|
355 error:
|
cannam@89
|
356 return -1;
|
cannam@89
|
357 }
|
cannam@89
|
358
|
cannam@89
|
359
|
cannam@89
|
360
|
cannam@89
|
361 /*******************************************************************/
|
cannam@89
|
362 int main(void);
|
cannam@89
|
363 int main(void)
|
cannam@89
|
364 {
|
cannam@89
|
365 PaStreamParameters outputParameters;
|
cannam@89
|
366 PaError err;
|
cannam@89
|
367 paTestData data;
|
cannam@89
|
368 const PaDeviceInfo *deviceInfo;
|
cannam@89
|
369 int i;
|
cannam@89
|
370 int framesPerBuffer;
|
cannam@89
|
371 double sampleRate = 44100;
|
cannam@89
|
372
|
cannam@89
|
373 printf("PortAudio QA: investigate output latency. SR = %d, BufSize = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER);
|
cannam@89
|
374
|
cannam@89
|
375 /* initialise sinusoidal wavetable */
|
cannam@89
|
376 for( i=0; i<TABLE_SIZE; i++ )
|
cannam@89
|
377 {
|
cannam@89
|
378 data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
|
cannam@89
|
379 }
|
cannam@89
|
380 data.left_phase = data.right_phase = 0;
|
cannam@89
|
381
|
cannam@89
|
382 err = Pa_Initialize();
|
cannam@89
|
383 if( err != paNoError ) goto error;
|
cannam@89
|
384
|
cannam@89
|
385 /* Run self tests. */
|
cannam@89
|
386 if( paqaVerifyDeviceInfoLatency() < 0 ) goto error;
|
cannam@89
|
387
|
cannam@89
|
388 if( paqaVerifySuggestedLatency() < 0 ) goto error;
|
cannam@89
|
389
|
cannam@89
|
390 outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
|
cannam@89
|
391 if (outputParameters.device == paNoDevice) {
|
cannam@89
|
392 fprintf(stderr,"Error: No default output device.\n");
|
cannam@89
|
393 goto error;
|
cannam@89
|
394 }
|
cannam@89
|
395
|
cannam@89
|
396 outputParameters.channelCount = 2; /* stereo output */
|
cannam@89
|
397 outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
cannam@89
|
398 deviceInfo = Pa_GetDeviceInfo( outputParameters.device );
|
cannam@89
|
399 printf("Using device #%d: '%s' (%s)\n", outputParameters.device, deviceInfo->name, Pa_GetHostApiInfo(deviceInfo->hostApi)->name);
|
cannam@89
|
400 printf("Device info: defaultLowOutputLatency = %f seconds\n", deviceInfo->defaultLowOutputLatency);
|
cannam@89
|
401 printf("Device info: defaultHighOutputLatency = %f seconds\n", deviceInfo->defaultHighOutputLatency);
|
cannam@89
|
402 outputParameters.hostApiSpecificStreamInfo = NULL;
|
cannam@89
|
403
|
cannam@89
|
404 // Try to use a small buffer that is smaller than we think the device can handle.
|
cannam@89
|
405 // Try to force combining multiple user buffers into a host buffer.
|
cannam@89
|
406 printf("------------- Try a very small buffer.\n");
|
cannam@89
|
407 framesPerBuffer = 9;
|
cannam@89
|
408 outputParameters.suggestedLatency = deviceInfo->defaultLowOutputLatency;
|
cannam@89
|
409 err = paqaCheckLatency( &outputParameters, &data, sampleRate, framesPerBuffer );
|
cannam@89
|
410 if( err != paNoError ) goto error;
|
cannam@89
|
411
|
cannam@89
|
412 printf("------------- 64 frame buffer with 1.1 * defaultLow latency.\n");
|
cannam@89
|
413 framesPerBuffer = 64;
|
cannam@89
|
414 outputParameters.suggestedLatency = deviceInfo->defaultLowOutputLatency * 1.1;
|
cannam@89
|
415 err = paqaCheckLatency( &outputParameters, &data, sampleRate, framesPerBuffer );
|
cannam@89
|
416 if( err != paNoError ) goto error;
|
cannam@89
|
417
|
cannam@89
|
418 // Try to create a huge buffer that is bigger than the allowed device maximum.
|
cannam@89
|
419 printf("------------- Try a huge buffer.\n");
|
cannam@89
|
420 framesPerBuffer = 16*1024;
|
cannam@89
|
421 outputParameters.suggestedLatency = ((double)framesPerBuffer) / sampleRate; // approximate
|
cannam@89
|
422 err = paqaCheckLatency( &outputParameters, &data, sampleRate, framesPerBuffer );
|
cannam@89
|
423 if( err != paNoError ) goto error;
|
cannam@89
|
424
|
cannam@89
|
425 printf("------------- Try suggestedLatency = 0.0\n");
|
cannam@89
|
426 outputParameters.suggestedLatency = 0.0;
|
cannam@89
|
427 err = paqaCheckLatency( &outputParameters, &data, sampleRate, paFramesPerBufferUnspecified );
|
cannam@89
|
428 if( err != paNoError ) goto error;
|
cannam@89
|
429
|
cannam@89
|
430 printf("------------- Try suggestedLatency = defaultLowOutputLatency\n");
|
cannam@89
|
431 outputParameters.suggestedLatency = deviceInfo->defaultLowOutputLatency;
|
cannam@89
|
432 err = paqaCheckLatency( &outputParameters, &data, sampleRate, paFramesPerBufferUnspecified );
|
cannam@89
|
433 if( err != paNoError ) goto error;
|
cannam@89
|
434
|
cannam@89
|
435 printf("------------- Try suggestedLatency = defaultHighOutputLatency\n");
|
cannam@89
|
436 outputParameters.suggestedLatency = deviceInfo->defaultHighOutputLatency;
|
cannam@89
|
437 err = paqaCheckLatency( &outputParameters, &data, sampleRate, paFramesPerBufferUnspecified );
|
cannam@89
|
438 if( err != paNoError ) goto error;
|
cannam@89
|
439
|
cannam@89
|
440 printf("------------- Try suggestedLatency = defaultHighOutputLatency * 4\n");
|
cannam@89
|
441 outputParameters.suggestedLatency = deviceInfo->defaultHighOutputLatency * 4;
|
cannam@89
|
442 err = paqaCheckLatency( &outputParameters, &data, sampleRate, paFramesPerBufferUnspecified );
|
cannam@89
|
443 if( err != paNoError ) goto error;
|
cannam@89
|
444
|
cannam@89
|
445
|
cannam@89
|
446 Pa_Terminate();
|
cannam@89
|
447 printf("Test finished.\n");
|
cannam@89
|
448
|
cannam@89
|
449 return err;
|
cannam@89
|
450 error:
|
cannam@89
|
451 Pa_Terminate();
|
cannam@89
|
452 fprintf( stderr, "An error occured while using the portaudio stream\n" );
|
cannam@89
|
453 fprintf( stderr, "Error number: %d\n", err );
|
cannam@89
|
454 fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
|
cannam@89
|
455 return err;
|
cannam@89
|
456 }
|