diff options
author | Guenter Geiger <ggeiger@users.sourceforge.net> | 2003-05-09 16:04:00 +0000 |
---|---|---|
committer | Guenter Geiger <ggeiger@users.sourceforge.net> | 2003-05-09 16:04:00 +0000 |
commit | 9c0e19a3be2288db79e2502e5fa450c3e20a668d (patch) | |
tree | ca97ce615e037a533304fc4660dcf372ca3b9cd6 /pd/portaudio_v18/pa_common/pa_convert.c | |
parent | ef50dd62804d54af7da18d8bd8413c0dccd729b8 (diff) |
This commit was generated by cvs2svn to compensate for changes in r610,
which included commits to RCS files with non-trunk default branches.
svn path=/trunk/; revision=611
Diffstat (limited to 'pd/portaudio_v18/pa_common/pa_convert.c')
-rw-r--r-- | pd/portaudio_v18/pa_common/pa_convert.c | 470 |
1 files changed, 470 insertions, 0 deletions
diff --git a/pd/portaudio_v18/pa_common/pa_convert.c b/pd/portaudio_v18/pa_common/pa_convert.c new file mode 100644 index 00000000..72e021eb --- /dev/null +++ b/pd/portaudio_v18/pa_common/pa_convert.c @@ -0,0 +1,470 @@ +/* + * 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 = (long) (*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 = (unsigned char)(128 + (*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 void PaConvert_Float32_Int32( + float *sourceBuffer, int sourceStride, + long *targetBuffer, int targetStride, + int numSamples ) +{ + int i; + for( i=0; i<numSamples; i++ ) + { + int samp = (int) (*sourceBuffer * 0x7FFFFFFF); + *targetBuffer = samp; + sourceBuffer += sourceStride; + targetBuffer += targetStride; + } +} + +/*************************************************************************/ +static void PaConvert_Float32_Int32_Clip( + float *sourceBuffer, int sourceStride, + long *targetBuffer, int targetStride, + int numSamples ) +{ + int i; + for( i=0; i<numSamples; i++ ) + { + int samp; + float fs = *sourceBuffer; + CLIP( fs, -1.0f, 0.999999f ); + samp = (int) (*sourceBuffer * 0x7FFFFFFF); + *targetBuffer = samp; + sourceBuffer += sourceStride; + targetBuffer += targetStride; + } +} + +/*************************************************************************/ +static void PaConvert_Int32_Float32( + long *sourceBuffer, int sourceStride, + float *targetBuffer, int targetStride, + int numSamples ) +{ + int i; + for( i=0; i<numSamples; i++ ) + { + float samp = *sourceBuffer * (1.0f / 0x7FFFFFFF); + *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 paInt32: + switch( targetFormat ) + { + case paFloat32: + proc = (PortAudioConverter *) PaConvert_Int32_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; + case paInt32: + /* Don't bother dithering a 32 bit integer! */ + if( ifClip ) proc = (PortAudioConverter *) PaConvert_Float32_Int32_Clip; + else proc = (PortAudioConverter *) PaConvert_Float32_Int32; + 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; +} |