PortAudio 2.0
pa_fuzz.c
Go to the documentation of this file.
00001 
00006 /*
00007  * $Id: pa_fuzz.c 1752 2011-09-08 03:21:55Z philburk $
00008  *
00009  * This program uses the PortAudio Portable Audio Library.
00010  * For more information see: http://www.portaudio.com
00011  * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
00012  *
00013  * Permission is hereby granted, free of charge, to any person obtaining
00014  * a copy of this software and associated documentation files
00015  * (the "Software"), to deal in the Software without restriction,
00016  * including without limitation the rights to use, copy, modify, merge,
00017  * publish, distribute, sublicense, and/or sell copies of the Software,
00018  * and to permit persons to whom the Software is furnished to do so,
00019  * subject to the following conditions:
00020  *
00021  * The above copyright notice and this permission notice shall be
00022  * included in all copies or substantial portions of the Software.
00023  *
00024  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00025  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00026  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00027  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
00028  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
00029  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00030  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00031  */
00032 
00033 /*
00034  * The text above constitutes the entire PortAudio license; however, 
00035  * the PortAudio community also makes the following non-binding requests:
00036  *
00037  * Any person wishing to distribute modifications to the Software is
00038  * requested to send the modifications to the original developer so that
00039  * they can be incorporated into the canonical version. It is also 
00040  * requested that these non-binding requests be included along with the 
00041  * license above.
00042  */
00043 
00044 #include <stdio.h>
00045 #include <math.h>
00046 #include "portaudio.h"
00047 /*
00048 ** Note that many of the older ISA sound cards on PCs do NOT support
00049 ** full duplex audio (simultaneous record and playback).
00050 ** And some only support full duplex at lower sample rates.
00051 */
00052 #define SAMPLE_RATE         (44100)
00053 #define PA_SAMPLE_TYPE      paFloat32
00054 #define FRAMES_PER_BUFFER   (64)
00055 
00056 typedef float SAMPLE;
00057 
00058 float CubicAmplifier( float input );
00059 static int fuzzCallback( const void *inputBuffer, void *outputBuffer,
00060                          unsigned long framesPerBuffer,
00061                          const PaStreamCallbackTimeInfo* timeInfo,
00062                          PaStreamCallbackFlags statusFlags,
00063                          void *userData );
00064 
00065 /* Non-linear amplifier with soft distortion curve. */
00066 float CubicAmplifier( float input )
00067 {
00068     float output, temp;
00069     if( input < 0.0 )
00070     {
00071         temp = input + 1.0f;
00072         output = (temp * temp * temp) - 1.0f;
00073     }
00074     else
00075     {
00076         temp = input - 1.0f;
00077         output = (temp * temp * temp) + 1.0f;
00078     }
00079 
00080     return output;
00081 }
00082 #define FUZZ(x) CubicAmplifier(CubicAmplifier(CubicAmplifier(CubicAmplifier(x))))
00083 
00084 static int gNumNoInputs = 0;
00085 /* This routine will be called by the PortAudio engine when audio is needed.
00086 ** It may be called at interrupt level on some machines so don't do anything
00087 ** that could mess up the system like calling malloc() or free().
00088 */
00089 static int fuzzCallback( const void *inputBuffer, void *outputBuffer,
00090                          unsigned long framesPerBuffer,
00091                          const PaStreamCallbackTimeInfo* timeInfo,
00092                          PaStreamCallbackFlags statusFlags,
00093                          void *userData )
00094 {
00095     SAMPLE *out = (SAMPLE*)outputBuffer;
00096     const SAMPLE *in = (const SAMPLE*)inputBuffer;
00097     unsigned int i;
00098     (void) timeInfo; /* Prevent unused variable warnings. */
00099     (void) statusFlags;
00100     (void) userData;
00101 
00102     if( inputBuffer == NULL )
00103     {
00104         for( i=0; i<framesPerBuffer; i++ )
00105         {
00106             *out++ = 0;  /* left - silent */
00107             *out++ = 0;  /* right - silent */
00108         }
00109         gNumNoInputs += 1;
00110     }
00111     else
00112     {
00113         for( i=0; i<framesPerBuffer; i++ )
00114         {
00115             *out++ = FUZZ(*in++);  /* left - distorted */
00116             *out++ = *in++;          /* right - clean */
00117         }
00118     }
00119     
00120     return paContinue;
00121 }
00122 
00123 /*******************************************************************/
00124 int main(void);
00125 int main(void)
00126 {
00127     PaStreamParameters inputParameters, outputParameters;
00128     PaStream *stream;
00129     PaError err;
00130 
00131     err = Pa_Initialize();
00132     if( err != paNoError ) goto error;
00133 
00134     inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
00135     if (inputParameters.device == paNoDevice) {
00136       fprintf(stderr,"Error: No default input device.\n");
00137       goto error;
00138     }
00139     inputParameters.channelCount = 2;       /* stereo input */
00140     inputParameters.sampleFormat = PA_SAMPLE_TYPE;
00141     inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
00142     inputParameters.hostApiSpecificStreamInfo = NULL;
00143 
00144     outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
00145     if (outputParameters.device == paNoDevice) {
00146       fprintf(stderr,"Error: No default output device.\n");
00147       goto error;
00148     }
00149     outputParameters.channelCount = 2;       /* stereo output */
00150     outputParameters.sampleFormat = PA_SAMPLE_TYPE;
00151     outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
00152     outputParameters.hostApiSpecificStreamInfo = NULL;
00153 
00154     err = Pa_OpenStream(
00155               &stream,
00156               &inputParameters,
00157               &outputParameters,
00158               SAMPLE_RATE,
00159               FRAMES_PER_BUFFER,
00160               0, /* paClipOff, */  /* we won't output out of range samples so don't bother clipping them */
00161               fuzzCallback,
00162               NULL );
00163     if( err != paNoError ) goto error;
00164 
00165     err = Pa_StartStream( stream );
00166     if( err != paNoError ) goto error;
00167 
00168     printf("Hit ENTER to stop program.\n");
00169     getchar();
00170     err = Pa_CloseStream( stream );
00171     if( err != paNoError ) goto error;
00172 
00173     printf("Finished. gNumNoInputs = %d\n", gNumNoInputs );
00174     Pa_Terminate();
00175     return 0;
00176 
00177 error:
00178     Pa_Terminate();
00179     fprintf( stderr, "An error occured while using the portaudio stream\n" );
00180     fprintf( stderr, "Error number: %d\n", err );
00181     fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
00182     return -1;
00183 }