Init
This commit is contained in:
470
DependentExtensions/portaudio_v18_1/pa_common/pa_convert.c
Normal file
470
DependentExtensions/portaudio_v18_1/pa_common/pa_convert.c
Normal file
@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user