]> Repos - portaudio/commitdiff
Contains sample format conversion routines, eg. paInt32 to paInt16.
authorphilburk <philburk@0f58301d-fd10-0410-b4af-bbb618454e57>
Thu, 21 Mar 2002 00:30:03 +0000 (00:30 +0000)
committerphilburk <philburk@0f58301d-fd10-0410-b4af-bbb618454e57>
Thu, 21 Mar 2002 00:30:03 +0000 (00:30 +0000)
pa_common/pa_convert.c [new file with mode: 0644]

diff --git a/pa_common/pa_convert.c b/pa_common/pa_convert.c
new file mode 100644 (file)
index 0000000..377a955
--- /dev/null
@@ -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;
+}