diff options
author | Guenter Geiger <ggeiger@users.sourceforge.net> | 2002-07-29 17:06:19 +0000 |
---|---|---|
committer | Guenter Geiger <ggeiger@users.sourceforge.net> | 2002-07-29 17:06:19 +0000 |
commit | 57045df5fe3ec557e57dc7434ac1a07b5521bffc (patch) | |
tree | 7174058b41b73c808107c7090d9a4e93ee202341 /pd/portaudio/pa_common/pa_convert.c | |
parent | da38b3424229e59f956252c3d89895e43e84e278 (diff) |
This commit was generated by cvs2svn to compensate for changes in r58,
which included commits to RCS files with non-trunk default branches.
svn path=/trunk/; revision=59
Diffstat (limited to 'pd/portaudio/pa_common/pa_convert.c')
-rw-r--r-- | pd/portaudio/pa_common/pa_convert.c | 402 |
1 files changed, 402 insertions, 0 deletions
diff --git a/pd/portaudio/pa_common/pa_convert.c b/pd/portaudio/pa_common/pa_convert.c new file mode 100644 index 00000000..377a9554 --- /dev/null +++ b/pd/portaudio/pa_common/pa_convert.c @@ -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; +} |