[Scopeapp-cvs]scopeapp/src/portaudio/pa_common pa_convert.c,NONE,1.1 pa_host.h,NONE,1.1 pa_lib.c,NON
Status: Alpha
Brought to you by:
narge
From: <sco...@li...> - 2002-12-05 14:46:47
|
Update of /cvsroot/scopeapp/scopeapp/src/portaudio/pa_common In directory sc8-pr-cvs1:/tmp/cvs-serv2086/pa_common Added Files: pa_convert.c pa_host.h pa_lib.c pa_trace.c pa_trace.h portaudio.h Log Message: Add common and CoreAudio-specific components of PortAudio. --- NEW FILE: pa_convert.c --- /* * 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; } --- NEW FILE: pa_host.h --- #ifndef PA_HOST_H #define PA_HOST_H /* * $Id: pa_host.h,v 1.1 2002/12/05 14:46:43 narge Exp $ * Host dependant internal API for PortAudio * * Author: Phil Burk <phi...@so...> * * 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 */ --- NEW FILE: pa_lib.c --- /* * $Id: pa_lib.c,v 1.1 2002/12/05 14:46:43 narge 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; } --- NEW FILE: pa_trace.c --- /* * $Id: pa_trace.c,v 1.1 2002/12/05 14:46:43 narge 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 --- NEW FILE: pa_trace.h --- #ifndef PA_TRACE_H #define PA_TRACE_H /* * $Id: pa_trace.h,v 1.1 2002/12/05 14:46:43 narge 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 */ --- NEW FILE: portaudio.h --- #ifndef PORT_AUDIO_H #define PORT_AUDIO_H #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* * $Id: portaudio.h,v 1.1 2002/12/05 14:46:43 narge 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 ... [truncated message content] |