* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
+
+#include "portaudio.h"
#ifdef __cplusplus
extern "C"
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)
/************************************************************************************/
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;
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;
/************************************************************************************/
-/****************** Prototypes ******************************************************/
+/******** These functions must be provided by a platform implementation. ************/
/************************************************************************************/
PaError PaHost_Init( void );
PaError PaHost_StopEngine( internalPortAudioStream *past, int abort );
PaError PaHost_StreamActive( internalPortAudioStream *past );
-long Pa_CallConvertInt16( internalPortAudioStream *past,
- short *nativeInputBuffer,
- short *nativeOutputBuffer );
-
-long Pa_CallConvertFloat32( internalPortAudioStream *past,
- float *nativeInputBuffer,
- float *nativeOutputBuffer );
-
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 ******************/
+/**********************************************************************/
+
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 */
past->past_Magic = PA_MAGIC; /* Set ID to catch bugs. */
past->past_FramesPerUserBuffer = framesPerBuffer;
- past->past_NumUserBuffers = numberOfBuffers; /* NOTE - PaHost_OpenStream() NMUST CHECK FOR ZERO! */
+ past->past_NumUserBuffers = numberOfBuffers; /* NOTE - PaHost_OpenStream() MUST CHECK FOR ZERO! */
past->past_Callback = callback;
past->past_UserData = userData;
past->past_OutputSampleFormat = outputSampleFormat;
#else
past->past_SampleRate = sampleRate;
#endif
- /* Allocate single Input buffer. */
+ /* 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 )
/*************************************************************
** 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 DITHER_BITS (15)
-#define DITHER_SCALE (1.0f / ((1<<DITHER_BITS)-1))
-static long Pa_TriangularDither( void )
+#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;
/* Generate two random numbers. */
randSeed1 = (randSeed1 * 196314165) + 907633515;
randSeed2 = (randSeed2 * 196314165) + 907633515;
- /* Generate triangular distribution about 0. */
- current = (((long)randSeed1)>>(32-DITHER_BITS)) + (((long)randSeed2)>>(32-DITHER_BITS));
+ /* 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;
short *nativeOutputBuffer )
{
long temp;
- long bytesEmpty = 0;
- long bytesFilled = 0;
int userResult;
unsigned int i;
void *inputBuffer = NULL;
for( i=0; i<samplesPerBuffer; i++ )
{
temp = nativeInputBuffer[i];
- temp += Pa_TriangularDither() >> 8; /* PLB20010820 */
+ temp += PaConvert_TriangularDither() >> 8; /* PLB20010820 */
temp = ((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp));
inBufPtr[i] = (char)(temp >> 8);
}
for( i=0; i<samplesPerBuffer; i++ )
{
temp = nativeInputBuffer[i];
- temp += Pa_TriangularDither() >> 8; /* PLB20010820 */
+ temp += PaConvert_TriangularDither() >> 8; /* PLB20010820 */
temp = ((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp));
inBufPtr[i] = (unsigned char)((temp>>8) + 0x80); /* PLB20010820 */
}
/* 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 = Pa_TriangularDither()*DITHER_SCALE;
+ 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));
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) + Pa_TriangularDither();
+ temp = (outBufPtr[i] >> 1) + PaConvert_TriangularDither();
temp = temp >> 15;
*nativeOutputBuffer++ = (short)((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp));
}
return userResult;
}
-/*************************************************************************
-** Called by host code.
-** Convert input from Float32, call user code, then convert output
-** to Float32 format for native use.
-** Assumes host native format is Float32.
-** Returns result from user callback.
-** FIXME - Unimplemented for formats other than paFloat32!!!!
-*/
-long Pa_CallConvertFloat32( internalPortAudioStream *past,
- float *nativeInputBuffer,
- float *nativeOutputBuffer )
-{
- long bytesEmpty = 0;
- long bytesFilled = 0;
- int userResult;
- void *inputBuffer = NULL;
- void *outputBuffer = NULL;
-
- /* Get native data from DirectSound. */
- if( (past->past_NumInputChannels > 0) && (nativeInputBuffer != NULL) )
- {
- inputBuffer = nativeInputBuffer; /* FIXME */
- }
-
- /* 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 == paFloat32) ?
- 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. */ /* FIXME */
- return userResult;
-}
-
/*************************************************************************/
PaError Pa_Initialize( void )
{