gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

paqa_devs.c (13780B)


      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 }