comparison src/portaudio/qa/paqa_errs.c @ 89:8a15ff55d9af

Add bzip2, zlib, liblo, portaudio sources
author Chris Cannam <cannam@all-day-breakfast.com>
date Wed, 20 Mar 2013 13:59:52 +0000
parents
children
comparison
equal deleted inserted replaced
88:fe7c3a0b0259 89:8a15ff55d9af
1 /** @file paqa_errs.c
2 @ingroup qa_src
3 @brief Self Testing Quality Assurance app for PortAudio
4 Do lots of bad things to test error reporting.
5 @author Phil Burk http://www.softsynth.com
6 Pieter Suurmond adapted to V19 API.
7 */
8 /*
9 * $Id: paqa_errs.c 1756 2011-09-08 06:09:29Z philburk $
10 *
11 * This program uses the PortAudio Portable Audio Library.
12 * For more information see: http://www.portaudio.com
13 * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
14 *
15 * Permission is hereby granted, free of charge, to any person obtaining
16 * a copy of this software and associated documentation files
17 * (the "Software"), to deal in the Software without restriction,
18 * including without limitation the rights to use, copy, modify, merge,
19 * publish, distribute, sublicense, and/or sell copies of the Software,
20 * and to permit persons to whom the Software is furnished to do so,
21 * subject to the following conditions:
22 *
23 * The above copyright notice and this permission notice shall be
24 * included in all copies or substantial portions of the Software.
25 *
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
29 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
30 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
31 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 */
34
35 /*
36 * The text above constitutes the entire PortAudio license; however,
37 * the PortAudio community also makes the following non-binding requests:
38 *
39 * Any person wishing to distribute modifications to the Software is
40 * requested to send the modifications to the original developer so that
41 * they can be incorporated into the canonical version. It is also
42 * requested that these non-binding requests be included along with the
43 * license above.
44 */
45
46 #include <stdio.h>
47 #include <math.h>
48
49 #include "portaudio.h"
50
51 /*--------- Definitions ---------*/
52 #define MODE_INPUT (0)
53 #define MODE_OUTPUT (1)
54 #define FRAMES_PER_BUFFER (64)
55 #define SAMPLE_RATE (44100.0)
56
57 typedef struct PaQaData
58 {
59 unsigned long framesLeft;
60 int numChannels;
61 int bytesPerSample;
62 int mode;
63 }
64 PaQaData;
65
66 static int gNumPassed = 0; /* Two globals */
67 static int gNumFailed = 0;
68
69 /*------------------- Macros ------------------------------*/
70 /* Print ERROR if it fails. Tally success or failure. Odd */
71 /* do-while wrapper seems to be needed for some compilers. */
72
73 #define EXPECT(_exp) \
74 do \
75 { \
76 if ((_exp)) {\
77 gNumPassed++; \
78 } \
79 else { \
80 printf("\nERROR - 0x%x - %s for %s\n", result, Pa_GetErrorText(result), #_exp ); \
81 gNumFailed++; \
82 goto error; \
83 } \
84 } while(0)
85
86 #define HOPEFOR(_exp) \
87 do \
88 { \
89 if ((_exp)) {\
90 gNumPassed++; \
91 } \
92 else { \
93 printf("\nERROR - 0x%x - %s for %s\n", result, Pa_GetErrorText(result), #_exp ); \
94 gNumFailed++; \
95 } \
96 } while(0)
97
98 /*-------------------------------------------------------------------------*/
99 /* This routine will be called by the PortAudio engine when audio is needed.
100 It may be called at interrupt level on some machines so don't do anything
101 that could mess up the system like calling malloc() or free().
102 */
103 static int QaCallback( const void* inputBuffer,
104 void* outputBuffer,
105 unsigned long framesPerBuffer,
106 const PaStreamCallbackTimeInfo* timeInfo,
107 PaStreamCallbackFlags statusFlags,
108 void* userData )
109 {
110 unsigned long i;
111 unsigned char* out = (unsigned char *) outputBuffer;
112 PaQaData* data = (PaQaData *) userData;
113
114 (void)inputBuffer; /* Prevent "unused variable" warnings. */
115
116 /* Zero out buffer so we don't hear terrible noise. */
117 if( data->mode == MODE_OUTPUT )
118 {
119 unsigned long numBytes = framesPerBuffer * data->numChannels * data->bytesPerSample;
120 for( i=0; i<numBytes; i++ )
121 {
122 *out++ = 0;
123 }
124 }
125 /* Are we through yet? */
126 if( data->framesLeft > framesPerBuffer )
127 {
128 data->framesLeft -= framesPerBuffer;
129 return 0;
130 }
131 else
132 {
133 data->framesLeft = 0;
134 return 1;
135 }
136 }
137
138 static PaDeviceIndex FindInputOnlyDevice(void)
139 {
140 PaDeviceIndex result = Pa_GetDefaultInputDevice();
141 if( result != paNoDevice && Pa_GetDeviceInfo(result)->maxOutputChannels == 0 )
142 return result;
143
144 for( result = 0; result < Pa_GetDeviceCount(); ++result )
145 {
146 if( Pa_GetDeviceInfo(result)->maxOutputChannels == 0 )
147 return result;
148 }
149
150 return paNoDevice;
151 }
152
153 static PaDeviceIndex FindOutputOnlyDevice(void)
154 {
155 PaDeviceIndex result = Pa_GetDefaultOutputDevice();
156 if( result != paNoDevice && Pa_GetDeviceInfo(result)->maxInputChannels == 0 )
157 return result;
158
159 for( result = 0; result < Pa_GetDeviceCount(); ++result )
160 {
161 if( Pa_GetDeviceInfo(result)->maxInputChannels == 0 )
162 return result;
163 }
164
165 return paNoDevice;
166 }
167
168 /*-------------------------------------------------------------------------------------------------*/
169 static int TestBadOpens( void )
170 {
171 PaStream* stream = NULL;
172 PaError result;
173 PaQaData myData;
174 PaStreamParameters ipp, opp;
175 const PaDeviceInfo* info = NULL;
176
177
178 /* Setup data for synthesis thread. */
179 myData.framesLeft = (unsigned long) (SAMPLE_RATE * 100); /* 100 seconds */
180 myData.numChannels = 1;
181 myData.mode = MODE_OUTPUT;
182
183 /*----------------------------- No devices specified: */
184 ipp.device = opp.device = paNoDevice;
185 ipp.channelCount = opp.channelCount = 0; /* Also no channels. */
186 ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
187 ipp.sampleFormat = opp.sampleFormat = paFloat32;
188 /* Take the low latency of the default device for all subsequent tests. */
189 info = Pa_GetDeviceInfo(Pa_GetDefaultInputDevice());
190 ipp.suggestedLatency = info ? info->defaultLowInputLatency : 0.100;
191 info = Pa_GetDeviceInfo(Pa_GetDefaultOutputDevice());
192 opp.suggestedLatency = info ? info->defaultLowOutputLatency : 0.100;
193 HOPEFOR(((result = Pa_OpenStream(&stream, &ipp, &opp,
194 SAMPLE_RATE, FRAMES_PER_BUFFER,
195 paClipOff, QaCallback, &myData )) == paInvalidDevice));
196
197 /*----------------------------- No devices specified #2: */
198 HOPEFOR(((result = Pa_OpenStream(&stream, NULL, NULL,
199 SAMPLE_RATE, FRAMES_PER_BUFFER,
200 paClipOff, QaCallback, &myData )) == paInvalidDevice));
201
202 /*----------------------------- Out of range input device specified: */
203 ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
204 ipp.sampleFormat = opp.sampleFormat = paFloat32;
205 ipp.channelCount = 0; ipp.device = Pa_GetDeviceCount(); /* And no output device, and no channels. */
206 opp.channelCount = 0; opp.device = paNoDevice;
207 HOPEFOR(((result = Pa_OpenStream(&stream, &ipp, NULL,
208 SAMPLE_RATE, FRAMES_PER_BUFFER,
209 paClipOff, QaCallback, &myData )) == paInvalidDevice));
210
211 /*----------------------------- Out of range output device specified: */
212 ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
213 ipp.sampleFormat = opp.sampleFormat = paFloat32;
214 ipp.channelCount = 0; ipp.device = paNoDevice; /* And no input device, and no channels. */
215 opp.channelCount = 0; opp.device = Pa_GetDeviceCount();
216 HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp,
217 SAMPLE_RATE, FRAMES_PER_BUFFER,
218 paClipOff, QaCallback, &myData )) == paInvalidDevice));
219
220 if (Pa_GetDefaultInputDevice() != paNoDevice) {
221 /*----------------------------- Zero input channels: */
222 ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
223 ipp.sampleFormat = opp.sampleFormat = paFloat32;
224 ipp.channelCount = 0; ipp.device = Pa_GetDefaultInputDevice();
225 opp.channelCount = 0; opp.device = paNoDevice; /* And no output device, and no output channels. */
226 HOPEFOR(((result = Pa_OpenStream(&stream, &ipp, NULL,
227 SAMPLE_RATE, FRAMES_PER_BUFFER,
228 paClipOff, QaCallback, &myData )) == paInvalidChannelCount));
229 }
230
231 if (Pa_GetDefaultOutputDevice() != paNoDevice) {
232 /*----------------------------- Zero output channels: */
233 ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
234 ipp.sampleFormat = opp.sampleFormat = paFloat32;
235 ipp.channelCount = 0; ipp.device = paNoDevice; /* And no input device, and no input channels. */
236 opp.channelCount = 0; opp.device = Pa_GetDefaultOutputDevice();
237 HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp,
238 SAMPLE_RATE, FRAMES_PER_BUFFER,
239 paClipOff, QaCallback, &myData )) == paInvalidChannelCount));
240 }
241 /*----------------------------- Nonzero input and output channels but no output device: */
242 ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
243 ipp.sampleFormat = opp.sampleFormat = paFloat32;
244 ipp.channelCount = 2; ipp.device = Pa_GetDefaultInputDevice(); /* Both stereo. */
245 opp.channelCount = 2; opp.device = paNoDevice;
246 HOPEFOR(((result = Pa_OpenStream(&stream, &ipp, &opp,
247 SAMPLE_RATE, FRAMES_PER_BUFFER,
248 paClipOff, QaCallback, &myData )) == paInvalidDevice));
249
250 /*----------------------------- Nonzero input and output channels but no input device: */
251 ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
252 ipp.sampleFormat = opp.sampleFormat = paFloat32;
253 ipp.channelCount = 2; ipp.device = paNoDevice;
254 opp.channelCount = 2; opp.device = Pa_GetDefaultOutputDevice();
255 HOPEFOR(((result = Pa_OpenStream(&stream, &ipp, &opp,
256 SAMPLE_RATE, FRAMES_PER_BUFFER,
257 paClipOff, QaCallback, &myData )) == paInvalidDevice));
258
259 if (Pa_GetDefaultOutputDevice() != paNoDevice) {
260 /*----------------------------- NULL stream pointer: */
261 ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
262 ipp.sampleFormat = opp.sampleFormat = paFloat32;
263 ipp.channelCount = 0; ipp.device = paNoDevice; /* Output is more likely than input. */
264 opp.channelCount = 2; opp.device = Pa_GetDefaultOutputDevice(); /* Only 2 output channels. */
265 HOPEFOR(((result = Pa_OpenStream(NULL, &ipp, &opp,
266 SAMPLE_RATE, FRAMES_PER_BUFFER,
267 paClipOff, QaCallback, &myData )) == paBadStreamPtr));
268
269 /*----------------------------- Low sample rate: */
270 ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
271 ipp.sampleFormat = opp.sampleFormat = paFloat32;
272 ipp.channelCount = 0; ipp.device = paNoDevice;
273 opp.channelCount = 2; opp.device = Pa_GetDefaultOutputDevice();
274 HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp,
275 1.0, FRAMES_PER_BUFFER, /* 1 cycle per second (1 Hz) is too low. */
276 paClipOff, QaCallback, &myData )) == paInvalidSampleRate));
277
278 /*----------------------------- High sample rate: */
279 ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
280 ipp.sampleFormat = opp.sampleFormat = paFloat32;
281 ipp.channelCount = 0; ipp.device = paNoDevice;
282 opp.channelCount = 2; opp.device = Pa_GetDefaultOutputDevice();
283 HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp,
284 10000000.0, FRAMES_PER_BUFFER, /* 10^6 cycles per second (10 MHz) is too high. */
285 paClipOff, QaCallback, &myData )) == paInvalidSampleRate));
286
287 /*----------------------------- NULL callback: */
288 /* NULL callback is valid in V19 -- it means use blocking read/write stream
289
290 ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
291 ipp.sampleFormat = opp.sampleFormat = paFloat32;
292 ipp.channelCount = 0; ipp.device = paNoDevice;
293 opp.channelCount = 2; opp.device = Pa_GetDefaultOutputDevice();
294 HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp,
295 SAMPLE_RATE, FRAMES_PER_BUFFER,
296 paClipOff,
297 NULL,
298 &myData )) == paNullCallback));
299 */
300
301 /*----------------------------- Bad flag: */
302 ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
303 ipp.sampleFormat = opp.sampleFormat = paFloat32;
304 ipp.channelCount = 0; ipp.device = paNoDevice;
305 opp.channelCount = 2; opp.device = Pa_GetDefaultOutputDevice();
306 HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp,
307 SAMPLE_RATE, FRAMES_PER_BUFFER,
308 255, /* Is 8 maybe legal V19 API? */
309 QaCallback, &myData )) == paInvalidFlag));
310 }
311
312 /*----------------------------- using input device as output device: */
313 if( FindInputOnlyDevice() != paNoDevice )
314 {
315 ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
316 ipp.sampleFormat = opp.sampleFormat = paFloat32;
317 ipp.channelCount = 0; ipp.device = paNoDevice; /* And no input device, and no channels. */
318 opp.channelCount = 2; opp.device = FindInputOnlyDevice();
319 HOPEFOR(((result = Pa_OpenStream(&stream, NULL, &opp,
320 SAMPLE_RATE, FRAMES_PER_BUFFER,
321 paClipOff, QaCallback, &myData )) == paInvalidChannelCount));
322 }
323
324 /*----------------------------- using output device as input device: */
325 if( FindOutputOnlyDevice() != paNoDevice )
326 {
327 ipp.hostApiSpecificStreamInfo = opp.hostApiSpecificStreamInfo = NULL;
328 ipp.sampleFormat = opp.sampleFormat = paFloat32;
329 ipp.channelCount = 2; ipp.device = FindOutputOnlyDevice();
330 opp.channelCount = 0; opp.device = paNoDevice; /* And no output device, and no channels. */
331 HOPEFOR(((result = Pa_OpenStream(&stream, &ipp, NULL,
332 SAMPLE_RATE, FRAMES_PER_BUFFER,
333 paClipOff, QaCallback, &myData )) == paInvalidChannelCount));
334
335 }
336
337 if( stream != NULL ) Pa_CloseStream( stream );
338 return result;
339 }
340
341 /*-----------------------------------------------------------------------------------------*/
342 static int TestBadActions( void )
343 {
344 PaStream* stream = NULL;
345 const PaDeviceInfo* deviceInfo = NULL;
346 PaError result = 0;
347 PaQaData myData;
348 PaStreamParameters opp;
349 const PaDeviceInfo* info = NULL;
350
351 /* Setup data for synthesis thread. */
352 myData.framesLeft = (unsigned long)(SAMPLE_RATE * 100); /* 100 seconds */
353 myData.numChannels = 1;
354 myData.mode = MODE_OUTPUT;
355
356 opp.device = Pa_GetDefaultOutputDevice(); /* Default output. */
357 opp.channelCount = 2; /* Stereo output. */
358 opp.hostApiSpecificStreamInfo = NULL;
359 opp.sampleFormat = paFloat32;
360 info = Pa_GetDeviceInfo(opp.device);
361 opp.suggestedLatency = info ? info->defaultLowOutputLatency : 0.100;
362
363 if (opp.device != paNoDevice) {
364 HOPEFOR(((result = Pa_OpenStream(&stream, NULL, /* Take NULL as input parame- */
365 &opp, /* ters, meaning try only output. */
366 SAMPLE_RATE, FRAMES_PER_BUFFER,
367 paClipOff, QaCallback, &myData )) == paNoError));
368 }
369
370 HOPEFOR(((deviceInfo = Pa_GetDeviceInfo(paNoDevice)) == NULL));
371 HOPEFOR(((deviceInfo = Pa_GetDeviceInfo(87654)) == NULL));
372 HOPEFOR(((result = Pa_StartStream(NULL)) == paBadStreamPtr));
373 HOPEFOR(((result = Pa_StopStream(NULL)) == paBadStreamPtr));
374 HOPEFOR(((result = Pa_IsStreamStopped(NULL)) == paBadStreamPtr));
375 HOPEFOR(((result = Pa_IsStreamActive(NULL)) == paBadStreamPtr));
376 HOPEFOR(((result = Pa_CloseStream(NULL)) == paBadStreamPtr));
377 HOPEFOR(((result = Pa_SetStreamFinishedCallback(NULL, NULL)) == paBadStreamPtr));
378 HOPEFOR(((result = !Pa_GetStreamInfo(NULL))));
379 HOPEFOR(((result = Pa_GetStreamTime(NULL)) == 0.0));
380 HOPEFOR(((result = Pa_GetStreamCpuLoad(NULL)) == 0.0));
381 HOPEFOR(((result = Pa_ReadStream(NULL, NULL, 0)) == paBadStreamPtr));
382 HOPEFOR(((result = Pa_WriteStream(NULL, NULL, 0)) == paBadStreamPtr));
383
384 /** @todo test Pa_GetStreamReadAvailable and Pa_GetStreamWriteAvailable */
385
386 if (stream != NULL) Pa_CloseStream(stream);
387 return result;
388 }
389
390 /*---------------------------------------------------------------------*/
391 int main(void);
392 int main(void)
393 {
394 PaError result;
395
396 EXPECT(((result = Pa_Initialize()) == paNoError));
397 TestBadOpens();
398 TestBadActions();
399 error:
400 Pa_Terminate();
401 printf("QA Report: %d passed, %d failed.\n", gNumPassed, gNumFailed);
402 return 0;
403 }