diff options
author | Guenter Geiger <ggeiger@users.sourceforge.net> | 2002-07-29 17:06:19 +0000 |
---|---|---|
committer | Guenter Geiger <ggeiger@users.sourceforge.net> | 2002-07-29 17:06:19 +0000 |
commit | 57045df5fe3ec557e57dc7434ac1a07b5521bffc (patch) | |
tree | 7174058b41b73c808107c7090d9a4e93ee202341 /pd/portaudio/pa_common | |
parent | da38b3424229e59f956252c3d89895e43e84e278 (diff) |
This commit was generated by cvs2svn to compensate for changes in r58,
which included commits to RCS files with non-trunk default branches.
svn path=/trunk/; revision=59
Diffstat (limited to 'pd/portaudio/pa_common')
-rw-r--r-- | pd/portaudio/pa_common/pa_convert.c | 402 | ||||
-rw-r--r-- | pd/portaudio/pa_common/pa_host.h | 185 | ||||
-rw-r--r-- | pd/portaudio/pa_common/pa_lib.c | 806 | ||||
-rw-r--r-- | pd/portaudio/pa_common/pa_trace.c | 83 | ||||
-rw-r--r-- | pd/portaudio/pa_common/pa_trace.h | 67 | ||||
-rw-r--r-- | pd/portaudio/pa_common/portaudio.h | 463 |
6 files changed, 2006 insertions, 0 deletions
diff --git a/pd/portaudio/pa_common/pa_convert.c b/pd/portaudio/pa_common/pa_convert.c new file mode 100644 index 00000000..377a9554 --- /dev/null +++ b/pd/portaudio/pa_common/pa_convert.c @@ -0,0 +1,402 @@ +/* + * pa_conversions.c + * portaudio + * + * Created by Phil Burk on Mon Mar 18 2002. + * + */ +#include <stdio.h> + +#include "portaudio.h" +#include "pa_host.h" + +#define CLIP( val, min, max ) { val = ((val) < (min)) ? min : (((val) < (max)) ? (max) : (val)); } + +/*************************************************************************/ +static void PaConvert_Float32_Int16( + float *sourceBuffer, int sourceStride, + short *targetBuffer, int targetStride, + int numSamples ) +{ + int i; + for( i=0; i<numSamples; i++ ) + { + short samp = (short) (*sourceBuffer * (32767.0f)); + *targetBuffer = samp; + sourceBuffer += sourceStride; + targetBuffer += targetStride; + } +} + +/*************************************************************************/ +static void PaConvert_Float32_Int16_Clip( + float *sourceBuffer, int sourceStride, + short *targetBuffer, int targetStride, + int numSamples ) +{ + int i; + for( i=0; i<numSamples; i++ ) + { + long samp = (long) (*sourceBuffer * (32767.0f)); + CLIP( samp, -0x8000, 0x7FFF ); + *targetBuffer = (short) samp; + sourceBuffer += sourceStride; + targetBuffer += targetStride; + } +} + +/*************************************************************************/ +static void PaConvert_Float32_Int16_ClipDither( + float *sourceBuffer, int sourceStride, + short *targetBuffer, int targetStride, + int numSamples ) +{ + int i; + for( i=0; i<numSamples; i++ ) + { + // use smaller scaler to prevent overflow when we add the dither + float dither = PaConvert_TriangularDither() * PA_DITHER_SCALE; + float dithered = (*sourceBuffer * (32766.0f)) + dither; + long samp = (long) dithered; + CLIP( samp, -0x8000, 0x7FFF ); + *targetBuffer = (short) samp; + sourceBuffer += sourceStride; + targetBuffer += targetStride; + } +} + +/*************************************************************************/ +static void PaConvert_Float32_Int16_Dither( + float *sourceBuffer, int sourceStride, + short *targetBuffer, int targetStride, + int numSamples ) +{ + int i; + for( i=0; i<numSamples; i++ ) + { + // use smaller scaler to prevent overflow when we add the dither + float dither = PaConvert_TriangularDither() * PA_DITHER_SCALE; + float dithered = (*sourceBuffer * (32766.0f)) + dither; + *targetBuffer = (short) dithered; + sourceBuffer += sourceStride; + targetBuffer += targetStride; + } +} + + +/*************************************************************************/ +static void PaConvert_Int16_Float32( + short *sourceBuffer, int sourceStride, + float *targetBuffer, int targetStride, + int numSamples ) +{ + int i; + for( i=0; i<numSamples; i++ ) + { + float samp = *sourceBuffer * (1.0f / 32768.0f); + *targetBuffer = samp; + sourceBuffer += sourceStride; + targetBuffer += targetStride; + } +} + +/*************************************************************************/ +static void PaConvert_Float32_Int8( + float *sourceBuffer, int sourceStride, + char *targetBuffer, int targetStride, + int numSamples ) +{ + int i; + for( i=0; i<numSamples; i++ ) + { + char samp = (char) (*sourceBuffer * (127.0)); + *targetBuffer = samp; + sourceBuffer += sourceStride; + targetBuffer += targetStride; + } +} + + +/*************************************************************************/ +static void PaConvert_Float32_Int8_Clip( + float *sourceBuffer, int sourceStride, + char *targetBuffer, int targetStride, + int numSamples ) +{ + int i; + for( i=0; i<numSamples; i++ ) + { + long samp = *sourceBuffer * 127.0f; + CLIP( samp, -0x80, 0x7F ); + *targetBuffer = (char) samp; + sourceBuffer += sourceStride; + targetBuffer += targetStride; + } +} + +/*************************************************************************/ +static void PaConvert_Float32_Int8_ClipDither( + float *sourceBuffer, int sourceStride, + char *targetBuffer, int targetStride, + int numSamples ) +{ + int i; + for( i=0; i<numSamples; i++ ) + { + // use smaller scaler to prevent overflow when we add the dither + float dither = PaConvert_TriangularDither() * PA_DITHER_SCALE; + float dithered = (*sourceBuffer * (126.0f)) + dither; + long samp = (long) dithered; + CLIP( samp, -0x80, 0x7F ); + *targetBuffer = (char) samp; + sourceBuffer += sourceStride; + targetBuffer += targetStride; + } +} + +/*************************************************************************/ +static void PaConvert_Float32_Int8_Dither( + float *sourceBuffer, int sourceStride, + char *targetBuffer, int targetStride, + int numSamples ) +{ + int i; + for( i=0; i<numSamples; i++ ) + { + // use smaller scaler to prevent overflow when we add the dither + float dither = PaConvert_TriangularDither() * PA_DITHER_SCALE; //FIXME + float dithered = (*sourceBuffer * (126.0f)) + dither; + long samp = (long) dithered; + *targetBuffer = (char) samp; + sourceBuffer += sourceStride; + targetBuffer += targetStride; + } +} + +/*************************************************************************/ +static void PaConvert_Int8_Float32( + char *sourceBuffer, int sourceStride, + float *targetBuffer, int targetStride, + int numSamples ) +{ + int i; + for( i=0; i<numSamples; i++ ) + { + float samp = *sourceBuffer * (1.0f / 128.0f); + *targetBuffer = samp; + sourceBuffer += sourceStride; + targetBuffer += targetStride; + } +} + +/*************************************************************************/ +static void PaConvert_Float32_UInt8( + float *sourceBuffer, int sourceStride, + unsigned char *targetBuffer, int targetStride, + int numSamples ) +{ + int i; + for( i=0; i<numSamples; i++ ) + { + unsigned char samp = 128 + (unsigned char) (*sourceBuffer * (127.0)); + *targetBuffer = samp; + sourceBuffer += sourceStride; + targetBuffer += targetStride; + } +} + +/*************************************************************************/ +static void PaConvert_UInt8_Float32( + unsigned char *sourceBuffer, int sourceStride, + float *targetBuffer, int targetStride, + int numSamples ) +{ + int i; + for( i=0; i<numSamples; i++ ) + { + float samp = (*sourceBuffer - 128) * (1.0f / 128.0f); + *targetBuffer = samp; + sourceBuffer += sourceStride; + targetBuffer += targetStride; + } +} + +/*************************************************************************/ +static PortAudioConverter *PaConvert_SelectProc( PaSampleFormat sourceFormat, + PaSampleFormat targetFormat, int ifClip, int ifDither ) +{ + PortAudioConverter *proc = NULL; + switch( sourceFormat ) + { + case paUInt8: + switch( targetFormat ) + { + case paFloat32: + proc = (PortAudioConverter *) PaConvert_UInt8_Float32; + break; + default: + break; + } + break; + case paInt8: + switch( targetFormat ) + { + case paFloat32: + proc = (PortAudioConverter *) PaConvert_Int8_Float32; + break; + default: + break; + } + break; + case paInt16: + switch( targetFormat ) + { + case paFloat32: + proc = (PortAudioConverter *) PaConvert_Int16_Float32; + break; + default: + break; + } + break; + case paFloat32: + switch( targetFormat ) + { + case paUInt8: + proc = (PortAudioConverter *) PaConvert_Float32_UInt8; + break; + case paInt8: + if( ifClip && ifDither ) proc = (PortAudioConverter *) PaConvert_Float32_Int8_ClipDither; + else if( ifClip ) proc = (PortAudioConverter *) PaConvert_Float32_Int8_Clip; + else if( ifDither ) proc = (PortAudioConverter *) PaConvert_Float32_Int8_Dither; + else proc = (PortAudioConverter *) PaConvert_Float32_Int8; + break; + case paInt16: + if( ifClip && ifDither ) proc = (PortAudioConverter *) PaConvert_Float32_Int16_ClipDither; + else if( ifClip ) proc = (PortAudioConverter *) PaConvert_Float32_Int16_Clip; + else if( ifDither ) proc = (PortAudioConverter *) PaConvert_Float32_Int16_Dither; + else proc = (PortAudioConverter *) PaConvert_Float32_Int16; + break; + default: + break; + } + break; + default: + break; + } + return proc; + +} + +/*************************************************************************/ +PaError PaConvert_SetupInput( internalPortAudioStream *past, + PaSampleFormat nativeInputSampleFormat ) +{ + past->past_NativeInputSampleFormat = nativeInputSampleFormat; + past->past_InputConversionSourceStride = 1; + past->past_InputConversionTargetStride = 1; + + if( nativeInputSampleFormat != past->past_InputSampleFormat ) + { + int ifDither = (past->past_Flags & paDitherOff) == 0; + past->past_InputConversionProc = PaConvert_SelectProc( nativeInputSampleFormat, + past->past_InputSampleFormat, 0, ifDither ); + if( past->past_InputConversionProc == NULL ) return paSampleFormatNotSupported; + } + else + { + past->past_InputConversionProc = NULL; /* no conversion necessary */ + } + + return paNoError; +} + +/*************************************************************************/ +PaError PaConvert_SetupOutput( internalPortAudioStream *past, + PaSampleFormat nativeOutputSampleFormat ) +{ + + past->past_NativeOutputSampleFormat = nativeOutputSampleFormat; + past->past_OutputConversionSourceStride = 1; + past->past_OutputConversionTargetStride = 1; + + if( nativeOutputSampleFormat != past->past_OutputSampleFormat ) + { + int ifDither = (past->past_Flags & paDitherOff) == 0; + int ifClip = (past->past_Flags & paClipOff) == 0; + + past->past_OutputConversionProc = PaConvert_SelectProc( past->past_OutputSampleFormat, + nativeOutputSampleFormat, ifClip, ifDither ); + if( past->past_OutputConversionProc == NULL ) return paSampleFormatNotSupported; + } + else + { + past->past_OutputConversionProc = NULL; /* no conversion necessary */ + } + + return paNoError; +} + +/************************************************************************* +** Called by host code. +** Convert input from native format to user format, +** call user code, +** then convert output to native format. +** Returns result from user callback. +*/ +long PaConvert_Process( internalPortAudioStream *past, + void *nativeInputBuffer, + void *nativeOutputBuffer ) +{ + int userResult; + void *inputBuffer = NULL; + void *outputBuffer = NULL; + + /* Get native input data. */ + if( (past->past_NumInputChannels > 0) && (nativeInputBuffer != NULL) ) + { + if( past->past_InputSampleFormat == past->past_NativeInputSampleFormat ) + { + /* Already in native format so just read directly from native buffer. */ + inputBuffer = nativeInputBuffer; + } + else + { + inputBuffer = past->past_InputBuffer; + /* Convert input data to user format. */ + (*past->past_InputConversionProc)(nativeInputBuffer, past->past_InputConversionSourceStride, + inputBuffer, past->past_InputConversionTargetStride, + past->past_FramesPerUserBuffer * past->past_NumInputChannels ); + } + } + + /* Are we doing output? */ + if( (past->past_NumOutputChannels > 0) && (nativeOutputBuffer != NULL) ) + { + outputBuffer = (past->past_OutputConversionProc == NULL) ? + nativeOutputBuffer : past->past_OutputBuffer; + } + /* + AddTraceMessage("Pa_CallConvertInt16: inputBuffer = ", (int) inputBuffer ); + AddTraceMessage("Pa_CallConvertInt16: outputBuffer = ", (int) outputBuffer ); + */ + /* Call user callback routine. */ + userResult = past->past_Callback( + inputBuffer, + outputBuffer, + past->past_FramesPerUserBuffer, + past->past_FrameCount, + past->past_UserData ); + + /* Advance frame counter for timestamp. */ + past->past_FrameCount += past->past_FramesPerUserBuffer; // FIXME - should this be in here? + + /* Convert to native format if necessary. */ + if( (past->past_OutputConversionProc != NULL ) && (outputBuffer != NULL) ) + { + (*past->past_OutputConversionProc)( outputBuffer, past->past_OutputConversionSourceStride, + nativeOutputBuffer, past->past_OutputConversionTargetStride, + past->past_FramesPerUserBuffer * past->past_NumOutputChannels ); + } + + return userResult; +} diff --git a/pd/portaudio/pa_common/pa_host.h b/pd/portaudio/pa_common/pa_host.h new file mode 100644 index 00000000..d9cd71ab --- /dev/null +++ b/pd/portaudio/pa_common/pa_host.h @@ -0,0 +1,185 @@ +#ifndef PA_HOST_H +#define PA_HOST_H + +/* + * $Id: pa_host.h,v 1.1.1.1 2002-07-29 17:06:18 ggeiger Exp $ + * Host dependant internal API for PortAudio + * + * Author: Phil Burk <philburk@softsynth.com> + * + * PortAudio Portable Real-Time Audio Library + * Latest Version at: http://www.softsynth.com/portaudio/ + * DirectSound and Macintosh Implementation + * Copyright (c) 1999-2000 Phil Burk + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "portaudio.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#ifndef SUPPORT_AUDIO_CAPTURE +#define SUPPORT_AUDIO_CAPTURE (1) +#endif + +#ifndef int32 + typedef long int32; +#endif +#ifndef uint32 + typedef unsigned long uint32; +#endif +#ifndef int16 + typedef short int16; +#endif +#ifndef uint16 + typedef unsigned short uint16; +#endif + +/* Used to convert between various sample formats. */ +typedef void (PortAudioConverter)( + void *inputBuffer, int inputStride, + void *outputBuffer, int outputStride, + int numSamples ); + +#define PA_MAGIC (0x18273645) + +/************************************************************************************/ +/****************** Structures ******************************************************/ +/************************************************************************************/ + +typedef struct internalPortAudioStream +{ + uint32 past_Magic; /* ID for struct to catch bugs. */ + /* User specified information. */ + uint32 past_FramesPerUserBuffer; + uint32 past_NumUserBuffers; + double past_SampleRate; /* Closest supported sample rate. */ + int past_NumInputChannels; + int past_NumOutputChannels; + PaDeviceID past_InputDeviceID; + PaDeviceID past_OutputDeviceID; + PaSampleFormat past_NativeInputSampleFormat; + PaSampleFormat past_InputSampleFormat; + PaSampleFormat past_NativeOutputSampleFormat; + PaSampleFormat past_OutputSampleFormat; + void *past_DeviceData; + PortAudioCallback *past_Callback; + void *past_UserData; + uint32 past_Flags; + /* Flags for communicating between foreground and background. */ + volatile int past_IsActive; /* Background is still playing. */ + volatile int past_StopSoon; /* Background should keep playing when buffers empty. */ + volatile int past_StopNow; /* Background should stop playing now. */ + /* These buffers are used when the native format does not match the user format. */ + void *past_InputBuffer; + uint32 past_InputBufferSize; + void *past_OutputBuffer; + uint32 past_OutputBufferSize; + /* Measurements */ + uint32 past_NumCallbacks; + PaTimestamp past_FrameCount; /* Frames output to buffer. */ + /* For measuring CPU utilization. */ + double past_AverageInsideCount; + double past_AverageTotalCount; + double past_Usage; + int past_IfLastExitValid; + /* Format Conversion */ + /* These are setup by PaConversion_Setup() */ + PortAudioConverter *past_InputConversionProc; + int past_InputConversionSourceStride; + int past_InputConversionTargetStride; + PortAudioConverter *past_OutputConversionProc; + int past_OutputConversionSourceStride; + int past_OutputConversionTargetStride; +} +internalPortAudioStream; + +/************************************************************************************/ +/******** These functions must be provided by a platform implementation. ************/ +/************************************************************************************/ + +PaError PaHost_Init( void ); +PaError PaHost_Term( void ); + +PaError PaHost_OpenStream( internalPortAudioStream *past ); +PaError PaHost_CloseStream( internalPortAudioStream *past ); + +PaError PaHost_StartOutput( internalPortAudioStream *past ); +PaError PaHost_StopOutput( internalPortAudioStream *past, int abort ); +PaError PaHost_StartInput( internalPortAudioStream *past ); +PaError PaHost_StopInput( internalPortAudioStream *past, int abort ); +PaError PaHost_StartEngine( internalPortAudioStream *past ); +PaError PaHost_StopEngine( internalPortAudioStream *past, int abort ); +PaError PaHost_StreamActive( internalPortAudioStream *past ); + +void *PaHost_AllocateFastMemory( long numBytes ); +void PaHost_FreeFastMemory( void *addr, long numBytes ); + +/* This only called if PA_VALIDATE_RATE IS CALLED. */ +PaError PaHost_ValidateSampleRate( PaDeviceID id, double requestedFrameRate, + double *closestFrameRatePtr ); + +/**********************************************************************/ +/************ Common Utility Routines provided by PA ******************/ +/**********************************************************************/ + +/* PaHost_IsInitialized() returns non-zero if PA is initialized, 0 otherwise */ +int PaHost_IsInitialized( void ); + +internalPortAudioStream* PaHost_GetStreamRepresentation( PortAudioStream *stream ); + +int PaHost_FindClosestTableEntry( double allowableError, const double *rateTable, + int numRates, double frameRate ); + +long Pa_CallConvertInt16( internalPortAudioStream *past, + short *nativeInputBuffer, + short *nativeOutputBuffer ); + +/* Calculate 2 LSB dither signal with a triangular distribution. +** Ranged properly for adding to a 32 bit 1.31 fixed point value prior to >>15. +** Range of output is +/- 65535 +** Multiply by PA_DITHER_SCALE to get a float between -2.0 and 2.0. */ +#define PA_DITHER_BITS (15) +#define PA_DITHER_SCALE (1.0f / ((1<<PA_DITHER_BITS)-1)) +long PaConvert_TriangularDither( void ); + +PaError PaConvert_SetupInput( internalPortAudioStream *past, + PaSampleFormat nativeInputSampleFormat ); + +PaError PaConvert_SetupOutput( internalPortAudioStream *past, + PaSampleFormat nativeOutputSampleFormat ); + +long PaConvert_Process( internalPortAudioStream *past, + void *nativeInputBuffer, + void *nativeOutputBuffer ); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* PA_HOST_H */ diff --git a/pd/portaudio/pa_common/pa_lib.c b/pd/portaudio/pa_common/pa_lib.c new file mode 100644 index 00000000..ade2d82b --- /dev/null +++ b/pd/portaudio/pa_common/pa_lib.c @@ -0,0 +1,806 @@ +/* + * $Id: pa_lib.c,v 1.1.1.1 2002-07-29 17:06:18 ggeiger Exp $ + * Portable Audio I/O Library + * Host Independant Layer + * + * Based on the Open Source API proposed by Ross Bencina + * Copyright (c) 1999-2000 Phil Burk + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +/* Modification History: + PLB20010422 - apply Mike Berry's changes for CodeWarrior on PC + PLB20010820 - fix dither and shift for recording PaUInt8 format +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +/* PLB20010422 - "memory.h" doesn't work on CodeWarrior for PC. Thanks Mike Berry for the mod. */ +#ifdef _WIN32 +#ifndef __MWERKS__ +#include <memory.h> +#endif /* __MWERKS__ */ +#else /* !_WIN32 */ +#include <memory.h> +#endif /* _WIN32 */ + +#include "portaudio.h" +#include "pa_host.h" +#include "pa_trace.h" + +/* The reason we might NOT want to validate the rate before opening the stream + * is because many DirectSound drivers lie about the rates they actually support. + */ +#define PA_VALIDATE_RATE (0) /* If true validate sample rate against driver info. */ + +/* +O- maybe not allocate past_InputBuffer and past_OutputBuffer if not needed for conversion +*/ + +#ifndef FALSE + #define FALSE (0) + #define TRUE (!FALSE) +#endif + +#define PRINT(x) { printf x; fflush(stdout); } +#define ERR_RPT(x) PRINT(x) +#define DBUG(x) /* PRINT(x) */ +#define DBUGX(x) /* PRINT(x) */ + +static int gInitCount = 0; /* Count number of times Pa_Initialize() called to allow nesting and overlapping. */ + +static PaError Pa_KillStream( PortAudioStream *stream, int abort ); + +/***********************************************************************/ +int PaHost_FindClosestTableEntry( double allowableError, const double *rateTable, int numRates, double frameRate ) +{ + double err, minErr = allowableError; + int i, bestFit = -1; + + for( i=0; i<numRates; i++ ) + { + err = fabs( frameRate - rateTable[i] ); + if( err < minErr ) + { + minErr = err; + bestFit = i; + } + } + return bestFit; +} + +/************************************************************************** +** Make sure sample rate is legal and also convert to enumeration for driver. +*/ +PaError PaHost_ValidateSampleRate( PaDeviceID id, double requestedFrameRate, + double *closestFrameRatePtr ) +{ + long bestRateIndex; + const PaDeviceInfo *pdi; + pdi = Pa_GetDeviceInfo( id ); + if( pdi == NULL ) + { + return paInvalidDeviceId; + } + + if( pdi->numSampleRates == -1 ) + { + /* Is it out of range? */ + if( (requestedFrameRate < pdi->sampleRates[0]) || + (requestedFrameRate > pdi->sampleRates[1]) ) + { + return paInvalidSampleRate; + } + + *closestFrameRatePtr = requestedFrameRate; + } + else + { + bestRateIndex = PaHost_FindClosestTableEntry( 1.0, pdi->sampleRates, pdi->numSampleRates, requestedFrameRate ); + if( bestRateIndex < 0 ) return paInvalidSampleRate; + *closestFrameRatePtr = pdi->sampleRates[bestRateIndex]; + } + return paNoError; +} + +/*************************************************************************/ +PaError Pa_OpenStream( + PortAudioStream** streamPtrPtr, + PaDeviceID inputDeviceID, + int numInputChannels, + PaSampleFormat inputSampleFormat, + void *inputDriverInfo, + PaDeviceID outputDeviceID, + int numOutputChannels, + PaSampleFormat outputSampleFormat, + void *outputDriverInfo, + double sampleRate, + unsigned long framesPerBuffer, + unsigned long numberOfBuffers, + unsigned long streamFlags, + PortAudioCallback *callback, + void *userData ) +{ + internalPortAudioStream *past = NULL; + PaError result = paNoError; + int bitsPerInputSample; + int bitsPerOutputSample; + /* Print passed parameters. */ + DBUG(("Pa_OpenStream( %p, %d, %d, %d, %p, /* input */ \n", + streamPtrPtr, inputDeviceID, numInputChannels, + inputSampleFormat, inputDriverInfo )); + DBUG((" %d, %d, %d, %p, /* output */\n", + outputDeviceID, numOutputChannels, + outputSampleFormat, outputDriverInfo )); + DBUG((" %g, %d, %d, 0x%x, , %p )\n", + sampleRate, framesPerBuffer, numberOfBuffers, + streamFlags, userData )); + + /* Check for parameter errors. */ + if( (streamFlags & ~(paClipOff | paDitherOff)) != 0 ) return paInvalidFlag; + if( streamPtrPtr == NULL ) return paBadStreamPtr; + if( inputDriverInfo != NULL ) return paHostError; /* REVIEW */ + if( outputDriverInfo != NULL ) return paHostError; /* REVIEW */ + if( (inputDeviceID < 0) && ( outputDeviceID < 0) ) return paInvalidDeviceId; + if( (outputDeviceID >= Pa_CountDevices()) || (inputDeviceID >= Pa_CountDevices()) ) + { + return paInvalidDeviceId; + } + if( (numInputChannels <= 0) && ( numOutputChannels <= 0) ) return paInvalidChannelCount; + +#if SUPPORT_AUDIO_CAPTURE + if( inputDeviceID >= 0 ) + { + PaError size = Pa_GetSampleSize( inputSampleFormat ); + if( size < 0 ) return size; + bitsPerInputSample = 8 * size; + if( (numInputChannels <= 0) ) return paInvalidChannelCount; + } +#else + if( inputDeviceID >= 0 ) + { + return paInvalidChannelCount; + } +#endif /* SUPPORT_AUDIO_CAPTURE */ + else + { + if( numInputChannels > 0 ) return paInvalidChannelCount; + bitsPerInputSample = 0; + } + + if( outputDeviceID >= 0 ) + { + PaError size = Pa_GetSampleSize( outputSampleFormat ); + if( size < 0 ) return size; + bitsPerOutputSample = 8 * size; + if( (numOutputChannels <= 0) ) return paInvalidChannelCount; + } + else + { + if( numOutputChannels > 0 ) return paInvalidChannelCount; + bitsPerOutputSample = 0; + } + + if( callback == NULL ) return paNullCallback; + + /* Allocate and clear stream structure. */ + past = (internalPortAudioStream *) PaHost_AllocateFastMemory( sizeof(internalPortAudioStream) ); + if( past == NULL ) return paInsufficientMemory; + memset( past, 0, sizeof(internalPortAudioStream) ); + AddTraceMessage("Pa_OpenStream: past", (long) past ); + + past->past_Magic = PA_MAGIC; /* Set ID to catch bugs. */ + past->past_FramesPerUserBuffer = framesPerBuffer; + past->past_NumUserBuffers = numberOfBuffers; /* NOTE - PaHost_OpenStream() MUST CHECK FOR ZERO! */ + past->past_Callback = callback; + past->past_UserData = userData; + past->past_OutputSampleFormat = outputSampleFormat; + past->past_InputSampleFormat = inputSampleFormat; + past->past_OutputDeviceID = outputDeviceID; + past->past_InputDeviceID = inputDeviceID; + past->past_NumInputChannels = numInputChannels; + past->past_NumOutputChannels = numOutputChannels; + past->past_Flags = streamFlags; + + /* Check for absurd sample rates. */ + if( (sampleRate < 1000.0) || (sampleRate > 200000.0) ) + { + result = paInvalidSampleRate; + goto cleanup; + } + + /* Allocate buffers that may be used for format conversion from user to native buffers. */ + if( numInputChannels > 0 ) + { + +#if PA_VALIDATE_RATE + result = PaHost_ValidateSampleRate( inputDeviceID, sampleRate, &past->past_SampleRate ); + if( result < 0 ) + { + goto cleanup; + } +#else + past->past_SampleRate = sampleRate; +#endif + /* Allocate single Input buffer for passing formatted samples to user callback. */ + past->past_InputBufferSize = framesPerBuffer * numInputChannels * ((bitsPerInputSample+7) / 8); + past->past_InputBuffer = PaHost_AllocateFastMemory(past->past_InputBufferSize); + if( past->past_InputBuffer == NULL ) + { + result = paInsufficientMemory; + goto cleanup; + } + } + else + { + past->past_InputBuffer = NULL; + } + + /* Allocate single Output buffer. */ + if( numOutputChannels > 0 ) + { +#if PA_VALIDATE_RATE + result = PaHost_ValidateSampleRate( outputDeviceID, sampleRate, &past->past_SampleRate ); + if( result < 0 ) + { + goto cleanup; + } +#else + past->past_SampleRate = sampleRate; +#endif + past->past_OutputBufferSize = framesPerBuffer * numOutputChannels * ((bitsPerOutputSample+7) / 8); + past->past_OutputBuffer = PaHost_AllocateFastMemory(past->past_OutputBufferSize); + if( past->past_OutputBuffer == NULL ) + { + result = paInsufficientMemory; + goto cleanup; + } + } + else + { + past->past_OutputBuffer = NULL; + } + + result = PaHost_OpenStream( past ); + if( result < 0 ) goto cleanup; + + *streamPtrPtr = (void *) past; + + return result; + +cleanup: + if( past != NULL ) Pa_CloseStream( past ); + *streamPtrPtr = NULL; + return result; +} + + +/*************************************************************************/ +PaError Pa_OpenDefaultStream( PortAudioStream** stream, + int numInputChannels, + int numOutputChannels, + PaSampleFormat sampleFormat, + double sampleRate, + unsigned long framesPerBuffer, + unsigned long numberOfBuffers, + PortAudioCallback *callback, + void *userData ) +{ + return Pa_OpenStream( + stream, + ((numInputChannels > 0) ? Pa_GetDefaultInputDeviceID() : paNoDevice), + numInputChannels, sampleFormat, NULL, + ((numOutputChannels > 0) ? Pa_GetDefaultOutputDeviceID() : paNoDevice), + numOutputChannels, sampleFormat, NULL, + sampleRate, framesPerBuffer, numberOfBuffers, paNoFlag, callback, userData ); +} + +/*************************************************************************/ +PaError Pa_CloseStream( PortAudioStream* stream) +{ + PaError result; + internalPortAudioStream *past; + + DBUG(("Pa_CloseStream()\n")); + if( stream == NULL ) return paBadStreamPtr; + past = (internalPortAudioStream *) stream; + + Pa_AbortStream( past ); + result = PaHost_CloseStream( past ); + + if( past->past_InputBuffer ) PaHost_FreeFastMemory( past->past_InputBuffer, past->past_InputBufferSize ); + if( past->past_OutputBuffer ) PaHost_FreeFastMemory( past->past_OutputBuffer, past->past_OutputBufferSize ); + PaHost_FreeFastMemory( past, sizeof(internalPortAudioStream) ); + + return result; +} + +/*************************************************************************/ +PaError Pa_StartStream( PortAudioStream *stream ) +{ + PaError result = paHostError; + internalPortAudioStream *past; + + if( stream == NULL ) return paBadStreamPtr; + past = (internalPortAudioStream *) stream; + + past->past_FrameCount = 0.0; + + if( past->past_NumInputChannels > 0 ) + { + result = PaHost_StartInput( past ); + DBUG(("Pa_StartStream: PaHost_StartInput returned = 0x%X.\n", result)); + if( result < 0 ) goto error; + } + + if( past->past_NumOutputChannels > 0 ) + { + result = PaHost_StartOutput( past ); + DBUG(("Pa_StartStream: PaHost_StartOutput returned = 0x%X.\n", result)); + if( result < 0 ) goto error; + } + + result = PaHost_StartEngine( past ); + DBUG(("Pa_StartStream: PaHost_StartEngine returned = 0x%X.\n", result)); + if( result < 0 ) goto error; + + return paNoError; + +error: + return result; +} + +/*************************************************************************/ +PaError Pa_StopStream( PortAudioStream *stream ) +{ + return Pa_KillStream( stream, 0 ); +} + +/*************************************************************************/ +PaError Pa_AbortStream( PortAudioStream *stream ) +{ + return Pa_KillStream( stream, 1 ); +} + +/*************************************************************************/ +static PaError Pa_KillStream( PortAudioStream *stream, int abort ) +{ + PaError result = paNoError; + internalPortAudioStream *past; + + DBUG(("Pa_StopStream().\n")); + if( stream == NULL ) return paBadStreamPtr; + past = (internalPortAudioStream *) stream; + + if( (past->past_NumInputChannels > 0) || (past->past_NumOutputChannels > 0) ) + { + result = PaHost_StopEngine( past, abort ); + DBUG(("Pa_StopStream: PaHost_StopEngine returned = 0x%X.\n", result)); + if( result < 0 ) goto error; + } + + if( past->past_NumInputChannels > 0 ) + { + result = PaHost_StopInput( past, abort ); + DBUG(("Pa_StopStream: PaHost_StopInput returned = 0x%X.\n", result)); + if( result != paNoError ) goto error; + } + + if( past->past_NumOutputChannels > 0 ) + { + result = PaHost_StopOutput( past, abort ); + DBUG(("Pa_StopStream: PaHost_StopOutput returned = 0x%X.\n", result)); + if( result != paNoError ) goto error; + } + +error: + past->past_Usage = 0; + past->past_IfLastExitValid = 0; + + return result; +} + +/*************************************************************************/ +PaError Pa_StreamActive( PortAudioStream *stream ) +{ + internalPortAudioStream *past; + if( stream == NULL ) return paBadStreamPtr; + past = (internalPortAudioStream *) stream; + return PaHost_StreamActive( past ); +} + +/*************************************************************************/ +const char *Pa_GetErrorText( PaError errnum ) +{ + const char *msg; + + switch(errnum) + { + case paNoError: msg = "Success"; break; + case paHostError: msg = "Host error."; break; + case paInvalidChannelCount: msg = "Invalid number of channels."; break; + case paInvalidSampleRate: msg = "Invalid sample rate."; break; + case paInvalidDeviceId: msg = "Invalid device ID."; break; + case paInvalidFlag: msg = "Invalid flag."; break; + case paSampleFormatNotSupported: msg = "Sample format not supported"; break; + case paBadIODeviceCombination: msg = "Illegal combination of I/O devices."; break; + case paInsufficientMemory: msg = "Insufficient memory."; break; + case paBufferTooBig: msg = "Buffer too big."; break; + case paBufferTooSmall: msg = "Buffer too small."; break; + case paNullCallback: msg = "No callback routine specified."; break; + case paBadStreamPtr: msg = "Invalid stream pointer."; break; + case paTimedOut : msg = "Wait Timed Out."; break; + case paInternalError: msg = "Internal PortAudio Error."; break; + case paDeviceUnavailable: msg = "Device Unavailable."; break; + default: msg = "Illegal error number."; break; + } + return msg; +} + +/* + Get CPU Load as a fraction of total CPU time. + A value of 0.5 would imply that PortAudio and the sound generating + callback was consuming roughly 50% of the available CPU time. + The amount may vary depending on CPU load. + This function may be called from the callback function. +*/ +double Pa_GetCPULoad( PortAudioStream* stream) +{ + internalPortAudioStream *past; + if( stream == NULL ) return (double) paBadStreamPtr; + past = (internalPortAudioStream *) stream; + return past->past_Usage; +} + +/*************************************************************************/ +internalPortAudioStream* PaHost_GetStreamRepresentation( PortAudioStream *stream ) +{ + internalPortAudioStream* result = (internalPortAudioStream*) stream; + + if( result == NULL || result->past_Magic != PA_MAGIC ) + return NULL; + else + return result; +} + +/************************************************************* +** Calculate 2 LSB dither signal with a triangular distribution. +** Ranged properly for adding to a 32 bit integer prior to >>15. +** Range of output is +/- 32767 +*/ +#define PA_DITHER_BITS (15) +#define PA_DITHER_SCALE (1.0f / ((1<<PA_DITHER_BITS)-1)) +long PaConvert_TriangularDither( void ) +{ + static unsigned long previous = 0; + static unsigned long randSeed1 = 22222; + static unsigned long randSeed2 = 5555555; + long current, highPass; + /* Generate two random numbers. */ + randSeed1 = (randSeed1 * 196314165) + 907633515; + randSeed2 = (randSeed2 * 196314165) + 907633515; + /* Generate triangular distribution about 0. + * Shift before adding to prevent overflow which would skew the distribution. + * Also shift an extra bit for the high pass filter. + */ +#define DITHER_SHIFT ((32 - PA_DITHER_BITS) + 1) + current = (((long)randSeed1)>>DITHER_SHIFT) + (((long)randSeed2)>>DITHER_SHIFT); + /* High pass filter to reduce audibility. */ + highPass = current - previous; + previous = current; + return highPass; +} + +/************************************************************************* +** Called by host code. +** Convert input from Int16, call user code, then convert output +** to Int16 format for native use. +** Assumes host native format is paInt16. +** Returns result from user callback. +*/ +long Pa_CallConvertInt16( internalPortAudioStream *past, + short *nativeInputBuffer, + short *nativeOutputBuffer ) +{ + long temp; + int userResult; + unsigned int i; + void *inputBuffer = NULL; + void *outputBuffer = NULL; + +#if SUPPORT_AUDIO_CAPTURE + /* Get native data from DirectSound. */ + if( (past->past_NumInputChannels > 0) && (nativeInputBuffer != NULL) ) + { + /* Convert from native format to PA format. */ + unsigned int samplesPerBuffer = past->past_FramesPerUserBuffer * past->past_NumInputChannels; + switch(past->past_InputSampleFormat) + { + + case paFloat32: + { + float *inBufPtr = (float *) past->past_InputBuffer; + inputBuffer = past->past_InputBuffer; + for( i=0; i<samplesPerBuffer; i++ ) + { + inBufPtr[i] = nativeInputBuffer[i] * (1.0f / 32767.0f); + } + break; + } + + case paInt32: + { + /* Convert 16 bit data to 32 bit integers */ + int *inBufPtr = (int *) past->past_InputBuffer; + inputBuffer = past->past_InputBuffer; + for( i=0; i<samplesPerBuffer; i++ ) + { + inBufPtr[i] = nativeInputBuffer[i] << 16; + } + break; + } + + case paInt16: + { + /* Already in correct format so don't copy. */ + inputBuffer = nativeInputBuffer; + break; + } + + case paInt8: + { + /* Convert 16 bit data to 8 bit chars */ + char *inBufPtr = (char *) past->past_InputBuffer; + inputBuffer = past->past_InputBuffer; + if( past->past_Flags & paDitherOff ) + { + for( i=0; i<samplesPerBuffer; i++ ) + { + inBufPtr[i] = (char)(nativeInputBuffer[i] >> 8); + } + } + else + { + for( i=0; i<samplesPerBuffer; i++ ) + { + temp = nativeInputBuffer[i]; + temp += PaConvert_TriangularDither() >> 8; /* PLB20010820 */ + temp = ((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp)); + inBufPtr[i] = (char)(temp >> 8); + } + } + break; + } + + case paUInt8: + { + /* Convert 16 bit data to 8 bit unsigned chars */ + unsigned char *inBufPtr = (unsigned char *) past->past_InputBuffer; + inputBuffer = past->past_InputBuffer; + if( past->past_Flags & paDitherOff ) + { + for( i=0; i<samplesPerBuffer; i++ ) + { + inBufPtr[i] = ((unsigned char)(nativeInputBuffer[i] >> 8)) + 0x80; + } + } + else + { + /* If you dither then you have to clip because dithering could push the signal out of range! */ + for( i=0; i<samplesPerBuffer; i++ ) + { + temp = nativeInputBuffer[i]; + temp += PaConvert_TriangularDither() >> 8; /* PLB20010820 */ + temp = ((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp)); + inBufPtr[i] = (unsigned char)((temp>>8) + 0x80); /* PLB20010820 */ + } + } + break; + } + + default: + break; + } + } +#endif /* SUPPORT_AUDIO_CAPTURE */ + + /* Are we doing output time? */ + if( (past->past_NumOutputChannels > 0) && (nativeOutputBuffer != NULL) ) + { + /* May already be in native format so just write directly to native buffer. */ + outputBuffer = (past->past_OutputSampleFormat == paInt16) ? + nativeOutputBuffer : past->past_OutputBuffer; + } + /* + AddTraceMessage("Pa_CallConvertInt16: inputBuffer = ", (int) inputBuffer ); + AddTraceMessage("Pa_CallConvertInt16: outputBuffer = ", (int) outputBuffer ); + */ + /* Call user callback routine. */ + userResult = past->past_Callback( + inputBuffer, + outputBuffer, + past->past_FramesPerUserBuffer, + past->past_FrameCount, + past->past_UserData ); + + past->past_FrameCount += (PaTimestamp) past->past_FramesPerUserBuffer; + + /* Convert to native format if necessary. */ + if( outputBuffer != NULL ) + { + unsigned int samplesPerBuffer = past->past_FramesPerUserBuffer * past->past_NumOutputChannels; + switch(past->past_OutputSampleFormat) + { + case paFloat32: + { + float *outBufPtr = (float *) past->past_OutputBuffer; + if( past->past_Flags & paDitherOff ) + { + if( past->past_Flags & paClipOff ) /* NOTHING */ + { + for( i=0; i<samplesPerBuffer; i++ ) + { + *nativeOutputBuffer++ = (short) (outBufPtr[i] * (32767.0f)); + } + } + else /* CLIP */ + { + for( i=0; i<samplesPerBuffer; i++ ) + { + temp = (long)(outBufPtr[i] * 32767.0f); + *nativeOutputBuffer++ = (short)((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp)); + } + } + } + else + { + /* If you dither then you have to clip because dithering could push the signal out of range! */ + for( i=0; i<samplesPerBuffer; i++ ) + { + float dither = PaConvert_TriangularDither()*PA_DITHER_SCALE; + float dithered = (outBufPtr[i] * (32767.0f)) + dither; + temp = (long) (dithered); + *nativeOutputBuffer++ = (short)((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp)); + } + } + break; + } + + case paInt32: + { + int *outBufPtr = (int *) past->past_OutputBuffer; + if( past->past_Flags & paDitherOff ) + { + for( i=0; i<samplesPerBuffer; i++ ) + { + *nativeOutputBuffer++ = (short) (outBufPtr[i] >> 16 ); + } + } + else + { + for( i=0; i<samplesPerBuffer; i++ ) + { + /* Shift one bit down before dithering so that we have room for overflow from add. */ + temp = (outBufPtr[i] >> 1) + PaConvert_TriangularDither(); + temp = temp >> 15; + *nativeOutputBuffer++ = (short)((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp)); + } + } + break; + } + + case paInt8: + { + char *outBufPtr = (char *) past->past_OutputBuffer; + for( i=0; i<samplesPerBuffer; i++ ) + { + *nativeOutputBuffer++ = ((short)outBufPtr[i]) << 8; + } + break; + } + + case paUInt8: + { + unsigned char *outBufPtr = (unsigned char *) past->past_OutputBuffer; + for( i=0; i<samplesPerBuffer; i++ ) + { + *nativeOutputBuffer++ = ((short)(outBufPtr[i] - 0x80)) << 8; + } + break; + } + + default: + break; + } + + } + + return userResult; +} + +/*************************************************************************/ +PaError Pa_Initialize( void ) +{ + if( gInitCount++ > 0 ) return paNoError; + ResetTraceMessages(); + return PaHost_Init(); +} + +PaError Pa_Terminate( void ) +{ + PaError result = paNoError; + + if( gInitCount == 0 ) return paNoError; + else if( --gInitCount == 0 ) + { + result = PaHost_Term(); + DumpTraceMessages(); + } + return result; +} + +int PaHost_IsInitialized() +{ + return gInitCount; +} + +/*************************************************************************/ +PaError Pa_GetSampleSize( PaSampleFormat format ) +{ + int size; + switch(format ) + { + + case paUInt8: + case paInt8: + size = 1; + break; + + case paInt16: + size = 2; + break; + + case paPackedInt24: + size = 3; + break; + + case paFloat32: + case paInt32: + case paInt24: + size = 4; + break; + + default: + size = paSampleFormatNotSupported; + break; + } + return (PaError) size; +} + + diff --git a/pd/portaudio/pa_common/pa_trace.c b/pd/portaudio/pa_common/pa_trace.c new file mode 100644 index 00000000..d55a6d37 --- /dev/null +++ b/pd/portaudio/pa_common/pa_trace.c @@ -0,0 +1,83 @@ +/* + * $Id: pa_trace.c,v 1.1.1.1 2002/01/22 00:52:11 phil Exp $ + * Portable Audio I/O Library Trace Facility + * Store trace information in real-time for later printing. + * + * Based on the Open Source API proposed by Ross Bencina + * Copyright (c) 1999-2000 Phil Burk + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "pa_trace.h" + +#if TRACE_REALTIME_EVENTS + +static char *traceTextArray[MAX_TRACE_RECORDS]; +static int traceIntArray[MAX_TRACE_RECORDS]; +static int traceIndex = 0; +static int traceBlock = 0; + +/*********************************************************************/ +void ResetTraceMessages() +{ + traceIndex = 0; +} + +/*********************************************************************/ +void DumpTraceMessages() +{ + int i; + int numDump = (traceIndex < MAX_TRACE_RECORDS) ? traceIndex : MAX_TRACE_RECORDS; + + printf("DumpTraceMessages: traceIndex = %d\n", traceIndex ); + for( i=0; i<numDump; i++ ) + { + printf("%3d: %s = 0x%08X\n", + i, traceTextArray[i], traceIntArray[i] ); + } + ResetTraceMessages(); + fflush(stdout); +} + +/*********************************************************************/ +void AddTraceMessage( char *msg, int data ) +{ + if( (traceIndex == MAX_TRACE_RECORDS) && (traceBlock == 0) ) + { + traceBlock = 1; + /* DumpTraceMessages(); */ + } + else if( traceIndex < MAX_TRACE_RECORDS ) + { + traceTextArray[traceIndex] = msg; + traceIntArray[traceIndex] = data; + traceIndex++; + } +} + +#endif diff --git a/pd/portaudio/pa_common/pa_trace.h b/pd/portaudio/pa_common/pa_trace.h new file mode 100644 index 00000000..d0fc904c --- /dev/null +++ b/pd/portaudio/pa_common/pa_trace.h @@ -0,0 +1,67 @@ +#ifndef PA_TRACE_H +#define PA_TRACE_H +/* + * $Id: pa_trace.h,v 1.1.1.1 2002/01/22 00:52:11 phil Exp $ + * Portable Audio I/O Library Trace Facility + * Store trace information in real-time for later printing. + * + * Based on the Open Source API proposed by Ross Bencina + * Copyright (c) 1999-2000 Phil Burk + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#define TRACE_REALTIME_EVENTS (0) /* Keep log of various real-time events. */ +#define MAX_TRACE_RECORDS (2048) + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + + + /************************************************************************************/ + /****************** Prototypes ******************************************************/ + /************************************************************************************/ + +#if TRACE_REALTIME_EVENTS + + void DumpTraceMessages(); + void ResetTraceMessages(); + void AddTraceMessage( char *msg, int data ); + +#else + +#define AddTraceMessage(msg,data) /* noop */ +#define ResetTraceMessages() /* noop */ +#define DumpTraceMessages() /* noop */ + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* PA_TRACE_H */ diff --git a/pd/portaudio/pa_common/portaudio.h b/pd/portaudio/pa_common/portaudio.h new file mode 100644 index 00000000..06f7079b --- /dev/null +++ b/pd/portaudio/pa_common/portaudio.h @@ -0,0 +1,463 @@ +#ifndef PORT_AUDIO_H +#define PORT_AUDIO_H + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * $Id: portaudio.h,v 1.5 2002/03/26 18:04:22 philburk Exp $ + * PortAudio Portable Real-Time Audio Library + * PortAudio API Header File + * Latest version available at: http://www.audiomulch.com/portaudio/ + * + * Copyright (c) 1999-2000 Ross Bencina and Phil Burk + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files + * (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * Any person wishing to distribute modifications to the Software is + * requested to send the modifications to the original developer so that + * they can be incorporated into the canonical version. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +typedef int PaError; +typedef enum { + paNoError = 0, + + paHostError = -10000, + paInvalidChannelCount, + paInvalidSampleRate, + paInvalidDeviceId, + paInvalidFlag, + paSampleFormatNotSupported, + paBadIODeviceCombination, + paInsufficientMemory, + paBufferTooBig, + paBufferTooSmall, + paNullCallback, + paBadStreamPtr, + paTimedOut, + paInternalError, + paDeviceUnavailable +} PaErrorNum; + +/* + Pa_Initialize() is the library initialisation function - call this before + using the library. + +*/ + +PaError Pa_Initialize( void ); + +/* + Pa_Terminate() is the library termination function - call this after + using the library. + +*/ + +PaError Pa_Terminate( void ); + +/* + Pa_GetHostError() returns a host specific error code. + This can be called after receiving a PortAudio error code of paHostError. + +*/ + +long Pa_GetHostError( void ); + +/* + Pa_GetErrorText() translates the supplied PortAudio error number + into a human readable message. + +*/ + +const char *Pa_GetErrorText( PaError errnum ); + +/* + Sample formats + + These are formats used to pass sound data between the callback and the + stream. Each device has a "native" format which may be used when optimum + efficiency or control over conversion is required. + + Formats marked "always available" are supported (emulated) by all + PortAudio implementations. + + The floating point representation (paFloat32) uses +1.0 and -1.0 as the + maximum and minimum respectively. + + paUInt8 is an unsigned 8 bit format where 128 is considered "ground" + +*/ + +typedef unsigned long PaSampleFormat; +#define paFloat32 ((PaSampleFormat) (1<<0)) /*always available*/ +#define paInt16 ((PaSampleFormat) (1<<1)) /*always available*/ +#define paInt32 ((PaSampleFormat) (1<<2)) /*always available*/ +#define paInt24 ((PaSampleFormat) (1<<3)) +#define paPackedInt24 ((PaSampleFormat) (1<<4)) +#define paInt8 ((PaSampleFormat) (1<<5)) +#define paUInt8 ((PaSampleFormat) (1<<6)) +#define paCustomFormat ((PaSampleFormat) (1<<16)) + +/* + Device enumeration mechanism. + + Device ids range from 0 to Pa_CountDevices()-1. + + Devices may support input, output or both. + +*/ + +typedef int PaDeviceID; +#define paNoDevice -1 + +int Pa_CountDevices( void ); + +typedef struct +{ + int structVersion; + const char *name; + int maxInputChannels; + int maxOutputChannels; + /* Number of discrete rates, or -1 if range supported. */ + int numSampleRates; + /* Array of supported sample rates, or {min,max} if range supported. */ + const double *sampleRates; + PaSampleFormat nativeSampleFormats; +} +PaDeviceInfo; + +/* + Pa_GetDefaultInputDeviceID(), Pa_GetDefaultOutputDeviceID() return the + default device ids for input and output respectively, or paNoDevice if + no device is available. + The result can be passed to Pa_OpenStream(). + + On the PC, the user can specify a default device by + setting an environment variable. For example, to use device #1. + + set PA_RECOMMENDED_OUTPUT_DEVICE=1 + + The user should first determine the available device ids by using + the supplied application "pa_devs". + +*/ + +PaDeviceID Pa_GetDefaultInputDeviceID( void ); +PaDeviceID Pa_GetDefaultOutputDeviceID( void ); + + + +/* + Pa_GetDeviceInfo() returns a pointer to an immutable PaDeviceInfo structure + for the device specified. + If the device parameter is out of range the function returns NULL. + + PortAudio manages the memory referenced by the returned pointer, the client + must not manipulate or free the memory. The pointer is only guaranteed to be + valid between calls to Pa_Initialize() and Pa_Terminate(). + +*/ + +const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID device ); + +/* + PaTimestamp is used to represent a continuous sample clock with arbitrary + start time that can be used for syncronization. The type is used for the + outTime argument to the PortAudioCallback and as the result of Pa_StreamTime() + +*/ + +typedef double PaTimestamp; + +/* + PortAudioCallback is implemented by PortAudio clients. + + inputBuffer and outputBuffer are arrays of interleaved samples, + the format, packing and number of channels used by the buffers are + determined by parameters to Pa_OpenStream() (see below). + + framesPerBuffer is the number of sample frames to be processed by the callback. + + outTime is the time in samples when the buffer(s) processed by + this callback will begin being played at the audio output. + See also Pa_StreamTime() + + userData is the value of a user supplied pointer passed to Pa_OpenStream() + intended for storing synthesis data etc. + + return value: + The callback can return a non-zero value to stop the stream. This may be + useful in applications such as soundfile players where a specific duration + of output is required. However, it is not necessary to utilise this mechanism + as StopStream() will also terminate the stream. A callback returning a + non-zero value must fill the entire outputBuffer. + + NOTE: None of the other stream functions may be called from within the + callback function except for Pa_GetCPULoad(). + +*/ + +typedef int (PortAudioCallback)( + void *inputBuffer, void *outputBuffer, + unsigned long framesPerBuffer, + PaTimestamp outTime, void *userData ); + + +/* + Stream flags + + These flags may be supplied (ored together) in the streamFlags argument to + the Pa_OpenStream() function. + +*/ + +#define paNoFlag (0) +#define paClipOff (1<<0) /* disable default clipping of out of range samples */ +#define paDitherOff (1<<1) /* disable default dithering */ +#define paPlatformSpecificFlags (0x00010000) +typedef unsigned long PaStreamFlags; + +/* + A single PortAudioStream provides multiple channels of real-time + input and output audio streaming to a client application. + Pointers to PortAudioStream objects are passed between PortAudio functions. +*/ + +typedef void PortAudioStream; +#define PaStream PortAudioStream + +/* + Pa_OpenStream() opens a stream for either input, output or both. + + stream is the address of a PortAudioStream pointer which will receive + a pointer to the newly opened stream. + + inputDevice is the id of the device used for input (see PaDeviceID above.) + inputDevice may be paNoDevice to indicate that an input device is not required. + + numInputChannels is the number of channels of sound to be delivered to the + callback. It can range from 1 to the value of maxInputChannels in the + PaDeviceInfo record for the device specified by the inputDevice parameter. + If inputDevice is paNoDevice numInputChannels is ignored. + + inputSampleFormat is the sample format of inputBuffer provided to the callback + function. inputSampleFormat may be any of the formats described by the + PaSampleFormat enumeration (see above). PortAudio guarantees support for + the device's native formats (nativeSampleFormats in the device info record) + and additionally 16 and 32 bit integer and 32 bit floating point formats. + Support for other formats is implementation defined. + + inputDriverInfo is a pointer to an optional driver specific data structure + containing additional information for device setup or stream processing. + inputDriverInfo is never required for correct operation. If not used + inputDriverInfo should be NULL. + + outputDevice is the id of the device used for output (see PaDeviceID above.) + outputDevice may be paNoDevice to indicate that an output device is not required. + + numOutputChannels is the number of channels of sound to be supplied by the + callback. See the definition of numInputChannels above for more details. + + outputSampleFormat is the sample format of the outputBuffer filled by the + callback function. See the definition of inputSampleFormat above for more + details. + + outputDriverInfo is a pointer to an optional driver specific data structure + containing additional information for device setup or stream processing. + outputDriverInfo is never required for correct operation. If not used + outputDriverInfo should be NULL. + + sampleRate is the desired sampleRate. For full-duplex streams it is the + sample rate for both input and output + + framesPerBuffer is the length in sample frames of all internal sample buffers + used for communication with platform specific audio routines. Wherever + possible this corresponds to the framesPerBuffer parameter passed to the + callback function. + + numberOfBuffers is the number of buffers used for multibuffered communication + with the platform specific audio routines. If you pass zero, then an optimum + value will be chosen for you internally. This parameter is provided only + as a guide - and does not imply that an implementation must use multibuffered + i/o when reliable double buffering is available (such as SndPlayDoubleBuffer() + on the Macintosh.) + + streamFlags may contain a combination of flags ORed together. + These flags modify the behaviour of the streaming process. Some flags may only + be relevant to certain buffer formats. + + callback is a pointer to a client supplied function that is responsible + for processing and filling input and output buffers (see above for details.) + + userData is a client supplied pointer which is passed to the callback + function. It could for example, contain a pointer to instance data necessary + for processing the audio buffers. + + return value: + Upon success Pa_OpenStream() returns PaNoError and places a pointer to a + valid PortAudioStream in the stream argument. The stream is inactive (stopped). + If a call to Pa_OpenStream() fails a non-zero error code is returned (see + PaError above) and the value of stream is invalid. + +*/ + +PaError Pa_OpenStream( PortAudioStream** stream, + PaDeviceID inputDevice, + int numInputChannels, + PaSampleFormat inputSampleFormat, + void *inputDriverInfo, + PaDeviceID outputDevice, + int numOutputChannels, + PaSampleFormat outputSampleFormat, + void *outputDriverInfo, + double sampleRate, + unsigned long framesPerBuffer, + unsigned long numberOfBuffers, + PaStreamFlags streamFlags, + PortAudioCallback *callback, + void *userData ); + + +/* + Pa_OpenDefaultStream() is a simplified version of Pa_OpenStream() that opens + the default input and/or output devices. Most parameters have identical meaning + to their Pa_OpenStream() counterparts, with the following exceptions: + + If either numInputChannels or numOutputChannels is 0 the respective device + is not opened. This has the same effect as passing paNoDevice in the device + arguments to Pa_OpenStream(). + + sampleFormat applies to both the input and output buffers. + +*/ + +PaError Pa_OpenDefaultStream( PortAudioStream** stream, + int numInputChannels, + int numOutputChannels, + PaSampleFormat sampleFormat, + double sampleRate, + unsigned long framesPerBuffer, + unsigned long numberOfBuffers, + PortAudioCallback *callback, + void *userData ); + +/* + Pa_CloseStream() closes an audio stream, flushing any pending buffers. + +*/ + +PaError Pa_CloseStream( PortAudioStream* ); + +/* + Pa_StartStream() and Pa_StopStream() begin and terminate audio processing. + Pa_StopStream() waits until all pending audio buffers have been played. + Pa_AbortStream() stops playing immediately without waiting for pending + buffers to complete. + +*/ + +PaError Pa_StartStream( PortAudioStream *stream ); + +PaError Pa_StopStream( PortAudioStream *stream ); + +PaError Pa_AbortStream( PortAudioStream *stream ); + +/* + Pa_StreamActive() returns one (1) when the stream is active (ie playing + or recording audio), zero (0) when not playing, or a negative error number + if the stream is invalid. + The stream is active between calls to Pa_StartStream() and Pa_StopStream(), + but may also become inactive if the callback returns a non-zero value. + In the latter case, the stream is considered inactive after the last + buffer has finished playing. + +*/ + +PaError Pa_StreamActive( PortAudioStream *stream ); + +/* + Pa_StreamTime() returns the current output time in samples for the stream. + This time may be used as a time reference (for example synchronizing audio to + MIDI). + +*/ + +PaTimestamp Pa_StreamTime( PortAudioStream *stream ); + +/* + Pa_GetCPULoad() returns the CPU Load for the stream. + The "CPU Load" is a fraction of total CPU time consumed by the stream's + audio processing routines including, but not limited to the client supplied + callback. + A value of 0.5 would imply that PortAudio and the sound generating + callback was consuming roughly 50% of the available CPU time. + This function may be called from the callback function or the application. + +*/ + +double Pa_GetCPULoad( PortAudioStream* stream ); + +/* + Pa_GetMinNumBuffers() returns the minimum number of buffers required by + the current host based on minimum latency. + On the PC, for the DirectSound implementation, latency can be optionally set + by user by setting an environment variable. + For example, to set latency to 200 msec, put: + + set PA_MIN_LATENCY_MSEC=200 + + in the AUTOEXEC.BAT file and reboot. + If the environment variable is not set, then the latency will be determined + based on the OS. Windows NT has higher latency than Win95. + +*/ + +int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate ); + +/* + Pa_Sleep() puts the caller to sleep for at least 'msec' milliseconds. + You may sleep longer than the requested time so don't rely on this for + accurate musical timing. + + Pa_Sleep() is provided as a convenience for authors of portable code (such as + the tests and examples in the PortAudio distribution.) + +*/ + +void Pa_Sleep( long msec ); + +/* + Pa_GetSampleSize() returns the size in bytes of a single sample in the + supplied PaSampleFormat, or paSampleFormatNotSupported if the format is + no supported. + +*/ + +PaError Pa_GetSampleSize( PaSampleFormat format ); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* PORT_AUDIO_H */ |