Mercurial > hg > sv-dependency-builds
comparison src/portaudio_20161030_catalina_patch/qa/paqa_devs.c @ 162:d43aab368df9
Duplicate for patch testing
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Wed, 30 Oct 2019 11:25:10 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
161:4797bbf470e7 | 162:d43aab368df9 |
---|---|
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$ | |
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 #define MAX_TEST_CHANNELS 4 | |
63 | |
64 typedef struct PaQaData | |
65 { | |
66 unsigned long framesLeft; | |
67 int numChannels; | |
68 int bytesPerSample; | |
69 int mode; | |
70 short sawPhase; | |
71 PaSampleFormat format; | |
72 } | |
73 PaQaData; | |
74 | |
75 /****************************************** Prototypes ***********/ | |
76 static void TestDevices( int mode ); | |
77 static void TestFormats( int mode, PaDeviceIndex deviceID, double sampleRate, | |
78 int numChannels ); | |
79 static int TestAdvance( int mode, PaDeviceIndex deviceID, double sampleRate, | |
80 int numChannels, PaSampleFormat format ); | |
81 static int QaCallback( const void *inputBuffer, void *outputBuffer, | |
82 unsigned long framesPerBuffer, | |
83 const PaStreamCallbackTimeInfo* timeInfo, | |
84 PaStreamCallbackFlags statusFlags, | |
85 void *userData ); | |
86 | |
87 /****************************************** Globals ***********/ | |
88 static int gNumPassed = 0; | |
89 static int gNumFailed = 0; | |
90 | |
91 /****************************************** Macros ***********/ | |
92 /* Print ERROR if it fails. Tally success or failure. */ | |
93 /* Odd do-while wrapper seems to be needed for some compilers. */ | |
94 #define EXPECT(_exp) \ | |
95 do \ | |
96 { \ | |
97 if ((_exp)) {\ | |
98 /* printf("SUCCESS for %s\n", #_exp ); */ \ | |
99 gNumPassed++; \ | |
100 } \ | |
101 else { \ | |
102 printf("ERROR - 0x%x - %s for %s\n", result, \ | |
103 ((result == 0) ? "-" : Pa_GetErrorText(result)), \ | |
104 #_exp ); \ | |
105 gNumFailed++; \ | |
106 goto error; \ | |
107 } \ | |
108 } while(0) | |
109 | |
110 /*******************************************************************/ | |
111 /* This routine will be called by the PortAudio engine when audio is needed. | |
112 ** It may be called at interrupt level on some machines so don't do anything | |
113 ** that could mess up the system like calling malloc() or free(). | |
114 */ | |
115 static int QaCallback( const void *inputBuffer, void *outputBuffer, | |
116 unsigned long framesPerBuffer, | |
117 const PaStreamCallbackTimeInfo* timeInfo, | |
118 PaStreamCallbackFlags statusFlags, | |
119 void *userData ) | |
120 { | |
121 unsigned long i; | |
122 short phase; | |
123 PaQaData *data = (PaQaData *) userData; | |
124 (void) inputBuffer; | |
125 | |
126 /* Play simple sawtooth wave. */ | |
127 if( data->mode == MODE_OUTPUT ) | |
128 { | |
129 phase = data->sawPhase; | |
130 switch( data->format ) | |
131 { | |
132 case paFloat32: | |
133 { | |
134 float *out = (float *) outputBuffer; | |
135 for( i=0; i<framesPerBuffer; i++ ) | |
136 { | |
137 phase += 0x123; | |
138 *out++ = (float) (phase * (1.0 / 32768.0)); | |
139 if( data->numChannels == 2 ) | |
140 { | |
141 *out++ = (float) (phase * (1.0 / 32768.0)); | |
142 } | |
143 } | |
144 } | |
145 break; | |
146 | |
147 case paInt32: | |
148 { | |
149 int *out = (int *) outputBuffer; | |
150 for( i=0; i<framesPerBuffer; i++ ) | |
151 { | |
152 phase += 0x123; | |
153 *out++ = ((int) phase ) << 16; | |
154 if( data->numChannels == 2 ) | |
155 { | |
156 *out++ = ((int) phase ) << 16; | |
157 } | |
158 } | |
159 } | |
160 break; | |
161 | |
162 case paInt16: | |
163 { | |
164 short *out = (short *) outputBuffer; | |
165 for( i=0; i<framesPerBuffer; i++ ) | |
166 { | |
167 phase += 0x123; | |
168 *out++ = phase; | |
169 if( data->numChannels == 2 ) | |
170 { | |
171 *out++ = phase; | |
172 } | |
173 } | |
174 } | |
175 break; | |
176 | |
177 default: | |
178 { | |
179 unsigned char *out = (unsigned char *) outputBuffer; | |
180 unsigned long numBytes = framesPerBuffer * data->numChannels * data->bytesPerSample; | |
181 for( i=0; i<numBytes; i++ ) | |
182 { | |
183 *out++ = 0; | |
184 } | |
185 } | |
186 break; | |
187 } | |
188 data->sawPhase = phase; | |
189 } | |
190 /* Are we through yet? */ | |
191 if( data->framesLeft > framesPerBuffer ) | |
192 { | |
193 PaUtil_AddTraceMessage("QaCallback: running. framesLeft", data->framesLeft ); | |
194 data->framesLeft -= framesPerBuffer; | |
195 return 0; | |
196 } | |
197 else | |
198 { | |
199 PaUtil_AddTraceMessage("QaCallback: DONE! framesLeft", data->framesLeft ); | |
200 data->framesLeft = 0; | |
201 return 1; | |
202 } | |
203 } | |
204 | |
205 /*******************************************************************/ | |
206 int main(void); | |
207 int main(void) | |
208 { | |
209 PaError result; | |
210 EXPECT( ((result=Pa_Initialize()) == 0) ); | |
211 printf("Test OUTPUT ---------------\n"); | |
212 TestDevices( MODE_OUTPUT ); | |
213 printf("Test INPUT ---------------\n"); | |
214 TestDevices( MODE_INPUT ); | |
215 error: | |
216 Pa_Terminate(); | |
217 printf("QA Report: %d passed, %d failed.\n", gNumPassed, gNumFailed ); | |
218 return (gNumFailed > 0) ? 1 : 0; | |
219 } | |
220 | |
221 /******************************************************************* | |
222 * Try each output device, through its full range of capabilities. */ | |
223 static void TestDevices( int mode ) | |
224 { | |
225 int id, jc, i; | |
226 int maxChannels; | |
227 const PaDeviceInfo *pdi; | |
228 static double standardSampleRates[] = { 8000.0, 9600.0, 11025.0, 12000.0, | |
229 16000.0, 22050.0, 24000.0, | |
230 32000.0, 44100.0, 48000.0, | |
231 88200.0, 96000.0, | |
232 -1.0 }; /* Negative terminated list. */ | |
233 int numDevices = Pa_GetDeviceCount(); | |
234 for( id=0; id<numDevices; id++ ) /* Iterate through all devices. */ | |
235 { | |
236 pdi = Pa_GetDeviceInfo( id ); | |
237 /* Try 1 to maxChannels on each device. */ | |
238 maxChannels = (( mode == MODE_INPUT ) ? pdi->maxInputChannels : pdi->maxOutputChannels); | |
239 if( maxChannels > MAX_TEST_CHANNELS ) | |
240 maxChannels = MAX_TEST_CHANNELS; | |
241 | |
242 for( jc=1; jc<=maxChannels; jc++ ) | |
243 { | |
244 printf("\n========================================================================\n"); | |
245 printf(" Device = %s\n", pdi->name ); | |
246 printf("========================================================================\n"); | |
247 /* Try each standard sample rate. */ | |
248 for( i=0; standardSampleRates[i] > 0; i++ ) | |
249 { | |
250 TestFormats( mode, (PaDeviceIndex)id, standardSampleRates[i], jc ); | |
251 } | |
252 } | |
253 } | |
254 } | |
255 | |
256 /*******************************************************************/ | |
257 static void TestFormats( int mode, PaDeviceIndex deviceID, double sampleRate, | |
258 int numChannels ) | |
259 { | |
260 TestAdvance( mode, deviceID, sampleRate, numChannels, paFloat32 ); | |
261 TestAdvance( mode, deviceID, sampleRate, numChannels, paInt16 ); | |
262 TestAdvance( mode, deviceID, sampleRate, numChannels, paInt32 ); | |
263 /* TestAdvance( mode, deviceID, sampleRate, numChannels, paInt24 ); */ | |
264 } | |
265 | |
266 /*******************************************************************/ | |
267 static int TestAdvance( int mode, PaDeviceIndex deviceID, double sampleRate, | |
268 int numChannels, PaSampleFormat format ) | |
269 { | |
270 PaStreamParameters inputParameters, outputParameters, *ipp, *opp; | |
271 PaStream *stream = NULL; | |
272 PaError result = paNoError; | |
273 PaQaData myData; | |
274 #define FRAMES_PER_BUFFER (64) | |
275 const int kNumSeconds = 100; | |
276 | |
277 /* Setup data for synthesis thread. */ | |
278 myData.framesLeft = (unsigned long) (sampleRate * kNumSeconds); | |
279 myData.numChannels = numChannels; | |
280 myData.mode = mode; | |
281 myData.format = format; | |
282 switch( format ) | |
283 { | |
284 case paFloat32: | |
285 case paInt32: | |
286 case paInt24: | |
287 myData.bytesPerSample = 4; | |
288 break; | |
289 /* case paPackedInt24: | |
290 myData.bytesPerSample = 3; | |
291 break; */ | |
292 default: | |
293 myData.bytesPerSample = 2; | |
294 break; | |
295 } | |
296 | |
297 if( mode == MODE_INPUT ) | |
298 { | |
299 inputParameters.device = deviceID; | |
300 inputParameters.channelCount = numChannels; | |
301 inputParameters.sampleFormat = format; | |
302 inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency; | |
303 inputParameters.hostApiSpecificStreamInfo = NULL; | |
304 ipp = &inputParameters; | |
305 } | |
306 else | |
307 { | |
308 ipp = NULL; | |
309 } | |
310 | |
311 if( mode == MODE_OUTPUT ) | |
312 { | |
313 outputParameters.device = deviceID; | |
314 outputParameters.channelCount = numChannels; | |
315 outputParameters.sampleFormat = format; | |
316 outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency; | |
317 outputParameters.hostApiSpecificStreamInfo = NULL; | |
318 opp = &outputParameters; | |
319 } | |
320 else | |
321 { | |
322 opp = NULL; | |
323 } | |
324 | |
325 if(paFormatIsSupported == Pa_IsFormatSupported( ipp, opp, sampleRate )) | |
326 { | |
327 printf("------ TestAdvance: %s, device = %d, rate = %g, numChannels = %d, format = %lu -------\n", | |
328 ( mode == MODE_INPUT ) ? "INPUT" : "OUTPUT", | |
329 deviceID, sampleRate, numChannels, (unsigned long)format); | |
330 EXPECT( ((result = Pa_OpenStream( &stream, | |
331 ipp, | |
332 opp, | |
333 sampleRate, | |
334 FRAMES_PER_BUFFER, | |
335 paClipOff, /* we won't output out of range samples so don't bother clipping them */ | |
336 QaCallback, | |
337 &myData ) ) == 0) ); | |
338 if( stream ) | |
339 { | |
340 PaTime oldStamp, newStamp; | |
341 unsigned long oldFrames; | |
342 int minDelay = ( mode == MODE_INPUT ) ? 1000 : 400; | |
343 /* Was: | |
344 int minNumBuffers = Pa_GetMinNumBuffers( FRAMES_PER_BUFFER, sampleRate ); | |
345 int msec = (int) ((minNumBuffers * 3 * 1000.0 * FRAMES_PER_BUFFER) / sampleRate); | |
346 */ | |
347 int msec = (int)( 3.0 * | |
348 (( mode == MODE_INPUT ) ? inputParameters.suggestedLatency : outputParameters.suggestedLatency )); | |
349 if( msec < minDelay ) msec = minDelay; | |
350 printf("msec = %d\n", msec); /**/ | |
351 EXPECT( ((result=Pa_StartStream( stream )) == 0) ); | |
352 /* Check to make sure PortAudio is advancing timeStamp. */ | |
353 oldStamp = Pa_GetStreamTime(stream); | |
354 Pa_Sleep(msec); | |
355 newStamp = Pa_GetStreamTime(stream); | |
356 printf("oldStamp = %9.6f, newStamp = %9.6f\n", oldStamp, newStamp ); /**/ | |
357 EXPECT( (oldStamp < newStamp) ); | |
358 /* Check to make sure callback is decrementing framesLeft. */ | |
359 oldFrames = myData.framesLeft; | |
360 Pa_Sleep(msec); | |
361 printf("oldFrames = %lu, myData.framesLeft = %lu\n", oldFrames, myData.framesLeft ); /**/ | |
362 EXPECT( (oldFrames > myData.framesLeft) ); | |
363 EXPECT( ((result=Pa_CloseStream( stream )) == 0) ); | |
364 stream = NULL; | |
365 } | |
366 } | |
367 return 0; | |
368 error: | |
369 if( stream != NULL ) Pa_CloseStream( stream ); | |
370 return -1; | |
371 } |