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_errs.c (18779B)


      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$
     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 }