]> Repos - portaudio/commitdiff
Added support for conversion nroutines in pa_convert.c.
authorphilburk <philburk@0f58301d-fd10-0410-b4af-bbb618454e57>
Thu, 21 Mar 2002 00:32:50 +0000 (00:32 +0000)
committerphilburk <philburk@0f58301d-fd10-0410-b4af-bbb618454e57>
Thu, 21 Mar 2002 00:32:50 +0000 (00:32 +0000)
SHifted Dither value right by one to account for high pass filter.

pa_common/pa_host.h
pa_common/pa_lib.c

index 9a3526129736de3d86792dfbf2a21f9fba690591..b077f8391e9eb4eef00301d3d909041a3fa512c5 100644 (file)
@@ -36,6 +36,8 @@
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
+#include "portaudio.h"
 
 #ifdef __cplusplus
 extern "C"
@@ -59,6 +61,12 @@ 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)
 
 /************************************************************************************/
@@ -76,7 +84,9 @@ typedef struct internalPortAudioStream
     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;
@@ -99,11 +109,19 @@ typedef struct internalPortAudioStream
     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 );
@@ -120,22 +138,42 @@ PaError PaHost_StartEngine( internalPortAudioStream   *past );
 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 */
index f32c635227e59047658b587fb988553f0deff9b7..2c7c41c4466a352317b281c1f316b02610bd8293 100644 (file)
@@ -217,7 +217,7 @@ PaError Pa_OpenStream(
 
     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;
@@ -248,7 +248,7 @@ PaError Pa_OpenStream(
 #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 )
@@ -481,10 +481,11 @@ double Pa_GetCPULoad(  PortAudioStream* stream)
 /*************************************************************
 ** 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;
@@ -493,8 +494,12 @@ static long Pa_TriangularDither( void )
     /* 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;
@@ -513,8 +518,6 @@ long Pa_CallConvertInt16( internalPortAudioStream   *past,
                           short *nativeOutputBuffer )
 {
     long              temp;
-    long              bytesEmpty = 0;
-    long              bytesFilled = 0;
     int               userResult;
     unsigned int      i;
     void             *inputBuffer = NULL;
@@ -576,7 +579,7 @@ long Pa_CallConvertInt16( internalPortAudioStream   *past,
                     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);
                     }
@@ -602,7 +605,7 @@ long Pa_CallConvertInt16( internalPortAudioStream   *past,
                     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 */
                     }
@@ -669,7 +672,7 @@ long Pa_CallConvertInt16( internalPortAudioStream   *past,
                     /* 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));
@@ -693,7 +696,7 @@ long Pa_CallConvertInt16( internalPortAudioStream   *past,
                     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));
                     }
@@ -730,55 +733,6 @@ long Pa_CallConvertInt16( internalPortAudioStream   *past,
     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 )
 {