Mercurial > hg > sv-dependency-builds
comparison src/portaudio/qa/paqa_devs.c @ 4:e13257ea84a4
Add bzip2, zlib, liblo, portaudio sources
author | Chris Cannam |
---|---|
date | Wed, 20 Mar 2013 13:59:52 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
3:6c505a35919a | 4:e13257ea84a4 |
---|---|
1 /** @file paqa_devs.c | |
2 @ingroup qa_src | |
3 @brief Self Testing Quality Assurance app for PortAudio | |
4 Try to open each device and run through all the | |
5 possible configurations. This test does not verify | |
6 that the configuration works well. It just verifies | |
7 that it does not crash. It requires a human to listen to | |
8 the outputs. | |
9 | |
10 @author Phil Burk http://www.softsynth.com | |
11 | |
12 Pieter adapted to V19 API. Test now relies heavily on | |
13 Pa_IsFormatSupported(). Uses same 'standard' sample rates | |
14 as in test pa_devs.c. | |
15 */ | |
16 /* | |
17 * $Id: paqa_devs.c 1756 2011-09-08 06:09:29Z philburk $ | |
18 * | |
19 * This program uses the PortAudio Portable Audio Library. | |
20 * For more information see: http://www.portaudio.com | |
21 * Copyright (c) 1999-2000 Ross Bencina and Phil Burk | |
22 * | |
23 * Permission is hereby granted, free of charge, to any person obtaining | |
24 * a copy of this software and associated documentation files | |
25 * (the "Software"), to deal in the Software without restriction, | |
26 * including without limitation the rights to use, copy, modify, merge, | |
27 * publish, distribute, sublicense, and/or sell copies of the Software, | |
28 * and to permit persons to whom the Software is furnished to do so, | |
29 * subject to the following conditions: | |
30 * | |
31 * The above copyright notice and this permission notice shall be | |
32 * included in all copies or substantial portions of the Software. | |
33 * | |
34 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
35 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
36 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
37 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR | |
38 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF | |
39 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | |
40 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
41 */ | |
42 | |
43 /* | |
44 * The text above constitutes the entire PortAudio license; however, | |
45 * the PortAudio community also makes the following non-binding requests: | |
46 * | |
47 * Any person wishing to distribute modifications to the Software is | |
48 * requested to send the modifications to the original developer so that | |
49 * they can be incorporated into the canonical version. It is also | |
50 * requested that these non-binding requests be included along with the | |
51 * license above. | |
52 */ | |
53 | |
54 #include <stdio.h> | |
55 #include <math.h> | |
56 #include "portaudio.h" | |
57 #include "pa_trace.h" | |
58 | |
59 /****************************************** Definitions ***********/ | |
60 #define MODE_INPUT (0) | |
61 #define MODE_OUTPUT (1) | |
62 | |
63 typedef struct PaQaData | |
64 { | |
65 unsigned long framesLeft; | |
66 int numChannels; | |
67 int bytesPerSample; | |
68 int mode; | |
69 short sawPhase; | |
70 PaSampleFormat format; | |
71 } | |
72 PaQaData; | |
73 | |
74 /****************************************** Prototypes ***********/ | |
75 static void TestDevices( int mode ); | |
76 static void TestFormats( int mode, PaDeviceIndex deviceID, double sampleRate, | |
77 int numChannels ); | |
78 static int TestAdvance( int mode, PaDeviceIndex deviceID, double sampleRate, | |
79 int numChannels, PaSampleFormat format ); | |
80 static int QaCallback( const void *inputBuffer, void *outputBuffer, | |
81 unsigned long framesPerBuffer, | |
82 const PaStreamCallbackTimeInfo* timeInfo, | |
83 PaStreamCallbackFlags statusFlags, | |
84 void *userData ); | |
85 | |
86 /****************************************** Globals ***********/ | |
87 static int gNumPassed = 0; | |
88 static int gNumFailed = 0; | |
89 | |
90 /****************************************** Macros ***********/ | |
91 /* Print ERROR if it fails. Tally success or failure. */ | |
92 /* Odd do-while wrapper seems to be needed for some compilers. */ | |
93 #define EXPECT(_exp) \ | |
94 do \ | |
95 { \ | |
96 if ((_exp)) {\ | |
97 /* printf("SUCCESS for %s\n", #_exp ); */ \ | |
98 gNumPassed++; \ | |
99 } \ | |
100 else { \ | |
101 printf("ERROR - 0x%x - %s for %s\n", result, \ | |
102 ((result == 0) ? "-" : Pa_GetErrorText(result)), \ | |
103 #_exp ); \ | |
104 gNumFailed++; \ | |
105 goto error; \ | |
106 } \ | |
107 } while(0) | |
108 | |
109 /*******************************************************************/ | |
110 /* This routine will be called by the PortAudio engine when audio is needed. | |
111 ** It may be called at interrupt level on some machines so don't do anything | |
112 ** that could mess up the system like calling malloc() or free(). | |
113 */ | |
114 static int QaCallback( const void *inputBuffer, void *outputBuffer, | |
115 unsigned long framesPerBuffer, | |
116 const PaStreamCallbackTimeInfo* timeInfo, | |
117 PaStreamCallbackFlags statusFlags, | |
118 void *userData ) | |
119 { | |
120 unsigned long i; | |
121 short phase; | |
122 PaQaData *data = (PaQaData *) userData; | |
123 (void) inputBuffer; | |
124 | |
125 /* Play simple sawtooth wave. */ | |
126 if( data->mode == MODE_OUTPUT ) | |
127 { | |
128 phase = data->sawPhase; | |
129 switch( data->format ) | |
130 { | |
131 case paFloat32: | |
132 { | |
133 float *out = (float *) outputBuffer; | |
134 for( i=0; i<framesPerBuffer; i++ ) | |
135 { | |
136 phase += 0x123; | |
137 *out++ = (float) (phase * (1.0 / 32768.0)); | |
138 if( data->numChannels == 2 ) | |
139 { | |
140 *out++ = (float) (phase * (1.0 / 32768.0)); | |
141 } | |
142 } | |
143 } | |
144 break; | |
145 | |
146 case paInt32: | |
147 { | |
148 int *out = (int *) outputBuffer; | |
149 for( i=0; i<framesPerBuffer; i++ ) | |
150 { | |
151 phase += 0x123; | |
152 *out++ = ((int) phase ) << 16; | |
153 if( data->numChannels == 2 ) | |
154 { | |
155 *out++ = ((int) phase ) << 16; | |
156 } | |
157 } | |
158 } | |
159 break; | |
160 | |
161 case paInt16: | |
162 { | |
163 short *out = (short *) outputBuffer; | |
164 for( i=0; i<framesPerBuffer; i++ ) | |
165 { | |
166 phase += 0x123; | |
167 *out++ = phase; | |
168 if( data->numChannels == 2 ) | |
169 { | |
170 *out++ = phase; | |
171 } | |
172 } | |
173 } | |
174 break; | |
175 | |
176 default: | |
177 { | |
178 unsigned char *out = (unsigned char *) outputBuffer; | |
179 unsigned long numBytes = framesPerBuffer * data->numChannels * data->bytesPerSample; | |
180 for( i=0; i<numBytes; i++ ) | |
181 { | |
182 *out++ = 0; | |
183 } | |
184 } | |
185 break; | |
186 } | |
187 data->sawPhase = phase; | |
188 } | |
189 /* Are we through yet? */ | |
190 if( data->framesLeft > framesPerBuffer ) | |
191 { | |
192 PaUtil_AddTraceMessage("QaCallback: running. framesLeft", data->framesLeft ); | |
193 data->framesLeft -= framesPerBuffer; | |
194 return 0; | |
195 } | |
196 else | |
197 { | |
198 PaUtil_AddTraceMessage("QaCallback: DONE! framesLeft", data->framesLeft ); | |
199 data->framesLeft = 0; | |
200 return 1; | |
201 } | |
202 } | |
203 | |
204 /*******************************************************************/ | |
205 int main(void); | |
206 int main(void) | |
207 { | |
208 PaError result; | |
209 EXPECT( ((result=Pa_Initialize()) == 0) ); | |
210 printf("Test OUTPUT ---------------\n"); | |
211 TestDevices( MODE_OUTPUT ); | |
212 printf("Test INPUT ---------------\n"); | |
213 TestDevices( MODE_INPUT ); | |
214 error: | |
215 Pa_Terminate(); | |
216 printf("QA Report: %d passed, %d failed.\n", gNumPassed, gNumFailed ); | |
217 return (gNumFailed > 0) ? 1 : 0; | |
218 } | |
219 | |
220 /******************************************************************* | |
221 * Try each output device, through its full range of capabilities. */ | |
222 static void TestDevices( int mode ) | |
223 { | |
224 int id, jc, i; | |
225 int maxChannels; | |
226 const PaDeviceInfo *pdi; | |
227 static double standardSampleRates[] = { 8000.0, 9600.0, 11025.0, 12000.0, | |
228 16000.0, 22050.0, 24000.0, | |
229 32000.0, 44100.0, 48000.0, | |
230 88200.0, 96000.0, | |
231 -1.0 }; /* Negative terminated list. */ | |
232 int numDevices = Pa_GetDeviceCount(); | |
233 for( id=0; id<numDevices; id++ ) /* Iterate through all devices. */ | |
234 { | |
235 pdi = Pa_GetDeviceInfo( id ); | |
236 /* Try 1 to maxChannels on each device. */ | |
237 maxChannels = (( mode == MODE_INPUT ) ? pdi->maxInputChannels : pdi->maxOutputChannels); | |
238 | |
239 for( jc=1; jc<=maxChannels; jc++ ) | |
240 { | |
241 printf("\n========================================================================\n"); | |
242 printf(" Device = %s\n", pdi->name ); | |
243 printf("========================================================================\n"); | |
244 /* Try each standard sample rate. */ | |
245 for( i=0; standardSampleRates[i] > 0; i++ ) | |
246 { | |
247 TestFormats( mode, (PaDeviceIndex)id, standardSampleRates[i], jc ); | |
248 } | |
249 } | |
250 } | |
251 } | |
252 | |
253 /*******************************************************************/ | |
254 static void TestFormats( int mode, PaDeviceIndex deviceID, double sampleRate, | |
255 int numChannels ) | |
256 { | |
257 TestAdvance( mode, deviceID, sampleRate, numChannels, paFloat32 ); | |
258 TestAdvance( mode, deviceID, sampleRate, numChannels, paInt16 ); | |
259 TestAdvance( mode, deviceID, sampleRate, numChannels, paInt32 ); | |
260 /* TestAdvance( mode, deviceID, sampleRate, numChannels, paInt24 ); */ | |
261 } | |
262 | |
263 /*******************************************************************/ | |
264 static int TestAdvance( int mode, PaDeviceIndex deviceID, double sampleRate, | |
265 int numChannels, PaSampleFormat format ) | |
266 { | |
267 PaStreamParameters inputParameters, outputParameters, *ipp, *opp; | |
268 PaStream *stream = NULL; | |
269 PaError result = paNoError; | |
270 PaQaData myData; | |
271 #define FRAMES_PER_BUFFER (64) | |
272 const int kNumSeconds = 100; | |
273 | |
274 /* Setup data for synthesis thread. */ | |
275 myData.framesLeft = (unsigned long) (sampleRate * kNumSeconds); | |
276 myData.numChannels = numChannels; | |
277 myData.mode = mode; | |
278 myData.format = format; | |
279 switch( format ) | |
280 { | |
281 case paFloat32: | |
282 case paInt32: | |
283 case paInt24: | |
284 myData.bytesPerSample = 4; | |
285 break; | |
286 /* case paPackedInt24: | |
287 myData.bytesPerSample = 3; | |
288 break; */ | |
289 default: | |
290 myData.bytesPerSample = 2; | |
291 break; | |
292 } | |
293 | |
294 if( mode == MODE_INPUT ) | |
295 { | |
296 inputParameters.device = deviceID; | |
297 inputParameters.channelCount = numChannels; | |
298 inputParameters.sampleFormat = format; | |
299 inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency; | |
300 inputParameters.hostApiSpecificStreamInfo = NULL; | |
301 ipp = &inputParameters; | |
302 } | |
303 else | |
304 { | |
305 ipp = NULL; | |
306 } | |
307 | |
308 if( mode == MODE_OUTPUT ) | |
309 { | |
310 outputParameters.device = deviceID; | |
311 outputParameters.channelCount = numChannels; | |
312 outputParameters.sampleFormat = format; | |
313 outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; | |
314 outputParameters.hostApiSpecificStreamInfo = NULL; | |
315 opp = &outputParameters; | |
316 } | |
317 else | |
318 { | |
319 opp = NULL; | |
320 } | |
321 | |
322 if(paFormatIsSupported == Pa_IsFormatSupported( ipp, opp, sampleRate )) | |
323 { | |
324 printf("------ TestAdvance: %s, device = %d, rate = %g, numChannels = %d, format = %lu -------\n", | |
325 ( mode == MODE_INPUT ) ? "INPUT" : "OUTPUT", | |
326 deviceID, sampleRate, numChannels, (unsigned long)format); | |
327 EXPECT( ((result = Pa_OpenStream( &stream, | |
328 ipp, | |
329 opp, | |
330 sampleRate, | |
331 FRAMES_PER_BUFFER, | |
332 paClipOff, /* we won't output out of range samples so don't bother clipping them */ | |
333 QaCallback, | |
334 &myData ) ) == 0) ); | |
335 if( stream ) | |
336 { | |
337 PaTime oldStamp, newStamp; | |
338 unsigned long oldFrames; | |
339 int minDelay = ( mode == MODE_INPUT ) ? 1000 : 400; | |
340 /* Was: | |
341 int minNumBuffers = Pa_GetMinNumBuffers( FRAMES_PER_BUFFER, sampleRate ); | |
342 int msec = (int) ((minNumBuffers * 3 * 1000.0 * FRAMES_PER_BUFFER) / sampleRate); | |
343 */ | |
344 int msec = (int)( 3.0 * | |
345 (( mode == MODE_INPUT ) ? inputParameters.suggestedLatency : outputParameters.suggestedLatency )); | |
346 if( msec < minDelay ) msec = minDelay; | |
347 printf("msec = %d\n", msec); /**/ | |
348 EXPECT( ((result=Pa_StartStream( stream )) == 0) ); | |
349 /* Check to make sure PortAudio is advancing timeStamp. */ | |
350 oldStamp = Pa_GetStreamTime(stream); | |
351 Pa_Sleep(msec); | |
352 newStamp = Pa_GetStreamTime(stream); | |
353 printf("oldStamp = %g, newStamp = %g\n", oldStamp, newStamp ); /**/ | |
354 EXPECT( (oldStamp < newStamp) ); | |
355 /* Check to make sure callback is decrementing framesLeft. */ | |
356 oldFrames = myData.framesLeft; | |
357 Pa_Sleep(msec); | |
358 printf("oldFrames = %lu, myData.framesLeft = %lu\n", oldFrames, myData.framesLeft ); /**/ | |
359 EXPECT( (oldFrames > myData.framesLeft) ); | |
360 EXPECT( ((result=Pa_CloseStream( stream )) == 0) ); | |
361 stream = NULL; | |
362 } | |
363 } | |
364 return 0; | |
365 error: | |
366 if( stream != NULL ) Pa_CloseStream( stream ); | |
367 return -1; | |
368 } |