libs-gui/Tools/gsnd/portaudio/pa_common/pa_convert.c
fedor 81632bcf5b Initial revision
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@14212 72102866-910b-0410-8b05-ffd578937521
2002-07-30 17:01:47 +00:00

402 lines
13 KiB
C

/*
* 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;
}