mirror of
https://github.com/cookiengineer/audacity
synced 2025-10-26 07:13:49 +01:00
Move library tree where it belongs
This commit is contained in:
470
lib-src/portaudio/pa_common/pa_convert.c
Normal file
470
lib-src/portaudio/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.0, 0.999999 );
|
||||
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;
|
||||
}
|
||||
189
lib-src/portaudio/pa_common/pa_host.h
Normal file
189
lib-src/portaudio/pa_common/pa_host.h
Normal file
@@ -0,0 +1,189 @@
|
||||
#ifndef PA_HOST_H
|
||||
#define PA_HOST_H
|
||||
|
||||
/*
|
||||
* $Id: pa_host.h,v 1.5 2003-03-02 08:01:34 dmazzoni Exp $
|
||||
* Host dependant internal API for PortAudio
|
||||
*
|
||||
* Author: Phil Burk <philburk@softsynth.com>
|
||||
*
|
||||
* PortAudio Portable Real-Time Audio Library
|
||||
* Latest Version at: http://www.softsynth.com/portaudio/
|
||||
* DirectSound and Macintosh Implementation
|
||||
* Copyright (c) 1999-2000 Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "portaudio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifndef SUPPORT_AUDIO_CAPTURE
|
||||
#define SUPPORT_AUDIO_CAPTURE (1)
|
||||
#endif
|
||||
|
||||
#ifndef int32
|
||||
typedef long int32;
|
||||
#endif
|
||||
#ifndef uint32
|
||||
typedef unsigned long uint32;
|
||||
#endif
|
||||
#ifndef int16
|
||||
typedef short int16;
|
||||
#endif
|
||||
#ifndef uint16
|
||||
typedef unsigned short uint16;
|
||||
#endif
|
||||
|
||||
/* Used to convert between various sample formats. */
|
||||
typedef void (PortAudioConverter)(
|
||||
void *inputBuffer, int inputStride,
|
||||
void *outputBuffer, int outputStride,
|
||||
int numSamples );
|
||||
|
||||
#define PA_MAGIC (0x18273645)
|
||||
|
||||
/************************************************************************************/
|
||||
/****************** Structures ******************************************************/
|
||||
/************************************************************************************/
|
||||
|
||||
typedef struct internalPortAudioStream
|
||||
{
|
||||
uint32 past_Magic; /* ID for struct to catch bugs. */
|
||||
|
||||
/* Begin user specified information. */
|
||||
uint32 past_FramesPerUserBuffer;
|
||||
uint32 past_NumUserBuffers;
|
||||
double past_SampleRate; /* Closest supported sample rate. */
|
||||
int past_NumInputChannels;
|
||||
int past_NumOutputChannels;
|
||||
PaDeviceID past_InputDeviceID;
|
||||
PaDeviceID past_OutputDeviceID;
|
||||
PaSampleFormat past_InputSampleFormat;
|
||||
PaSampleFormat past_OutputSampleFormat;
|
||||
PortAudioCallback *past_Callback;
|
||||
void *past_UserData;
|
||||
uint32 past_Flags;
|
||||
/* End user specified information. */
|
||||
|
||||
void *past_DeviceData;
|
||||
PaSampleFormat past_NativeOutputSampleFormat;
|
||||
PaSampleFormat past_NativeInputSampleFormat;
|
||||
|
||||
/* Flags for communicating between foreground and background. */
|
||||
volatile int past_IsActive; /* Background is still playing. */
|
||||
volatile int past_StopSoon; /* Background should keep playing when buffers empty. */
|
||||
volatile int past_StopNow; /* Background should stop playing now. */
|
||||
/* These buffers are used when the native format does not match the user format. */
|
||||
void *past_InputBuffer;
|
||||
uint32 past_InputBufferSize; /* Size in bytes of the input buffer. */
|
||||
void *past_OutputBuffer;
|
||||
uint32 past_OutputBufferSize;
|
||||
/* Measurements */
|
||||
uint32 past_NumCallbacks;
|
||||
PaTimestamp past_FrameCount; /* Frames output to buffer. */
|
||||
/* For measuring CPU utilization. */
|
||||
double past_AverageInsideCount;
|
||||
double past_AverageTotalCount;
|
||||
double past_Usage;
|
||||
int past_IfLastExitValid;
|
||||
/* Format Conversion */
|
||||
/* These are setup by PaConversion_Setup() */
|
||||
PortAudioConverter *past_InputConversionProc;
|
||||
int past_InputConversionSourceStride;
|
||||
int past_InputConversionTargetStride;
|
||||
PortAudioConverter *past_OutputConversionProc;
|
||||
int past_OutputConversionSourceStride;
|
||||
int past_OutputConversionTargetStride;
|
||||
}
|
||||
internalPortAudioStream;
|
||||
|
||||
/************************************************************************************/
|
||||
/******** These functions must be provided by a platform implementation. ************/
|
||||
/************************************************************************************/
|
||||
|
||||
PaError PaHost_Init( void );
|
||||
PaError PaHost_Term( void );
|
||||
|
||||
PaError PaHost_OpenStream( internalPortAudioStream *past );
|
||||
PaError PaHost_CloseStream( internalPortAudioStream *past );
|
||||
|
||||
PaError PaHost_StartOutput( internalPortAudioStream *past );
|
||||
PaError PaHost_StopOutput( internalPortAudioStream *past, int abort );
|
||||
PaError PaHost_StartInput( internalPortAudioStream *past );
|
||||
PaError PaHost_StopInput( internalPortAudioStream *past, int abort );
|
||||
PaError PaHost_StartEngine( internalPortAudioStream *past );
|
||||
PaError PaHost_StopEngine( internalPortAudioStream *past, int abort );
|
||||
PaError PaHost_StreamActive( internalPortAudioStream *past );
|
||||
|
||||
void *PaHost_AllocateFastMemory( long numBytes );
|
||||
void PaHost_FreeFastMemory( void *addr, long numBytes );
|
||||
|
||||
/* This only called if PA_VALIDATE_RATE IS CALLED. */
|
||||
PaError PaHost_ValidateSampleRate( PaDeviceID id, double requestedFrameRate,
|
||||
double *closestFrameRatePtr );
|
||||
|
||||
/**********************************************************************/
|
||||
/************ Common Utility Routines provided by PA ******************/
|
||||
/**********************************************************************/
|
||||
|
||||
/* PaHost_IsInitialized() returns non-zero if PA is initialized, 0 otherwise */
|
||||
int PaHost_IsInitialized( void );
|
||||
|
||||
internalPortAudioStream* PaHost_GetStreamRepresentation( PortAudioStream *stream );
|
||||
|
||||
int PaHost_FindClosestTableEntry( double allowableError, const double *rateTable,
|
||||
int numRates, double frameRate );
|
||||
|
||||
long Pa_CallConvertInt16( internalPortAudioStream *past,
|
||||
short *nativeInputBuffer,
|
||||
short *nativeOutputBuffer );
|
||||
|
||||
/* Calculate 2 LSB dither signal with a triangular distribution.
|
||||
** Ranged properly for adding to a 32 bit 1.31 fixed point value prior to >>15.
|
||||
** Range of output is +/- 65535
|
||||
** Multiply by PA_DITHER_SCALE to get a float between -2.0 and 2.0. */
|
||||
#define PA_DITHER_BITS (15)
|
||||
#define PA_DITHER_SCALE (1.0f / ((1<<PA_DITHER_BITS)-1))
|
||||
long PaConvert_TriangularDither( void );
|
||||
|
||||
PaError PaConvert_SetupInput( internalPortAudioStream *past,
|
||||
PaSampleFormat nativeInputSampleFormat );
|
||||
|
||||
PaError PaConvert_SetupOutput( internalPortAudioStream *past,
|
||||
PaSampleFormat nativeOutputSampleFormat );
|
||||
|
||||
long PaConvert_Process( internalPortAudioStream *past,
|
||||
void *nativeInputBuffer,
|
||||
void *nativeOutputBuffer );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* PA_HOST_H */
|
||||
806
lib-src/portaudio/pa_common/pa_lib.c
Normal file
806
lib-src/portaudio/pa_common/pa_lib.c
Normal file
@@ -0,0 +1,806 @@
|
||||
/*
|
||||
* $Id: pa_lib.c,v 1.6 2003-03-02 08:01:34 dmazzoni Exp $
|
||||
* Portable Audio I/O Library
|
||||
* Host Independant Layer
|
||||
*
|
||||
* Based on the Open Source API proposed by Ross Bencina
|
||||
* Copyright (c) 1999-2000 Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Modification History:
|
||||
PLB20010422 - apply Mike Berry's changes for CodeWarrior on PC
|
||||
PLB20010820 - fix dither and shift for recording PaUInt8 format
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
/* PLB20010422 - "memory.h" doesn't work on CodeWarrior for PC. Thanks Mike Berry for the mod. */
|
||||
#ifdef _WIN32
|
||||
#ifndef __MWERKS__
|
||||
#include <memory.h>
|
||||
#endif /* __MWERKS__ */
|
||||
#else /* !_WIN32 */
|
||||
#include <memory.h>
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#include "portaudio.h"
|
||||
#include "pa_host.h"
|
||||
#include "pa_trace.h"
|
||||
|
||||
/* The reason we might NOT want to validate the rate before opening the stream
|
||||
* is because many DirectSound drivers lie about the rates they actually support.
|
||||
*/
|
||||
#define PA_VALIDATE_RATE (0) /* If true validate sample rate against driver info. */
|
||||
|
||||
/*
|
||||
O- maybe not allocate past_InputBuffer and past_OutputBuffer if not needed for conversion
|
||||
*/
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE (0)
|
||||
#define TRUE (!FALSE)
|
||||
#endif
|
||||
|
||||
#define PRINT(x) { printf x; fflush(stdout); }
|
||||
#define ERR_RPT(x) PRINT(x)
|
||||
#define DBUG(x) /* PRINT(x) */
|
||||
#define DBUGX(x) /* PRINT(x) */
|
||||
|
||||
static int gInitCount = 0; /* Count number of times Pa_Initialize() called to allow nesting and overlapping. */
|
||||
|
||||
static PaError Pa_KillStream( PortAudioStream *stream, int abort );
|
||||
|
||||
/***********************************************************************/
|
||||
int PaHost_FindClosestTableEntry( double allowableError, const double *rateTable, int numRates, double frameRate )
|
||||
{
|
||||
double err, minErr = allowableError;
|
||||
int i, bestFit = -1;
|
||||
|
||||
for( i=0; i<numRates; i++ )
|
||||
{
|
||||
err = fabs( frameRate - rateTable[i] );
|
||||
if( err < minErr )
|
||||
{
|
||||
minErr = err;
|
||||
bestFit = i;
|
||||
}
|
||||
}
|
||||
return bestFit;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
** Make sure sample rate is legal and also convert to enumeration for driver.
|
||||
*/
|
||||
PaError PaHost_ValidateSampleRate( PaDeviceID id, double requestedFrameRate,
|
||||
double *closestFrameRatePtr )
|
||||
{
|
||||
long bestRateIndex;
|
||||
const PaDeviceInfo *pdi;
|
||||
pdi = Pa_GetDeviceInfo( id );
|
||||
if( pdi == NULL )
|
||||
{
|
||||
return paInvalidDeviceId;
|
||||
}
|
||||
|
||||
if( pdi->numSampleRates == -1 )
|
||||
{
|
||||
/* Is it out of range? */
|
||||
if( (requestedFrameRate < pdi->sampleRates[0]) ||
|
||||
(requestedFrameRate > pdi->sampleRates[1]) )
|
||||
{
|
||||
return paInvalidSampleRate;
|
||||
}
|
||||
|
||||
*closestFrameRatePtr = requestedFrameRate;
|
||||
}
|
||||
else
|
||||
{
|
||||
bestRateIndex = PaHost_FindClosestTableEntry( 1.0, pdi->sampleRates, pdi->numSampleRates, requestedFrameRate );
|
||||
if( bestRateIndex < 0 ) return paInvalidSampleRate;
|
||||
*closestFrameRatePtr = pdi->sampleRates[bestRateIndex];
|
||||
}
|
||||
return paNoError;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
PaError Pa_OpenStream(
|
||||
PortAudioStream** streamPtrPtr,
|
||||
PaDeviceID inputDeviceID,
|
||||
int numInputChannels,
|
||||
PaSampleFormat inputSampleFormat,
|
||||
void *inputDriverInfo,
|
||||
PaDeviceID outputDeviceID,
|
||||
int numOutputChannels,
|
||||
PaSampleFormat outputSampleFormat,
|
||||
void *outputDriverInfo,
|
||||
double sampleRate,
|
||||
unsigned long framesPerBuffer,
|
||||
unsigned long numberOfBuffers,
|
||||
unsigned long streamFlags,
|
||||
PortAudioCallback *callback,
|
||||
void *userData )
|
||||
{
|
||||
internalPortAudioStream *past = NULL;
|
||||
PaError result = paNoError;
|
||||
int bitsPerInputSample;
|
||||
int bitsPerOutputSample;
|
||||
/* Print passed parameters. */
|
||||
DBUG(("Pa_OpenStream( %p, %d, %d, %d, %p, /* input */ \n",
|
||||
streamPtrPtr, inputDeviceID, numInputChannels,
|
||||
inputSampleFormat, inputDriverInfo ));
|
||||
DBUG((" %d, %d, %d, %p, /* output */\n",
|
||||
outputDeviceID, numOutputChannels,
|
||||
outputSampleFormat, outputDriverInfo ));
|
||||
DBUG((" %g, %d, %d, 0x%x, , %p )\n",
|
||||
sampleRate, framesPerBuffer, numberOfBuffers,
|
||||
streamFlags, userData ));
|
||||
|
||||
/* Check for parameter errors. */
|
||||
if( (streamFlags & ~(paClipOff | paDitherOff)) != 0 ) return paInvalidFlag;
|
||||
if( streamPtrPtr == NULL ) return paBadStreamPtr;
|
||||
if( inputDriverInfo != NULL ) return paHostError; /* REVIEW */
|
||||
if( outputDriverInfo != NULL ) return paHostError; /* REVIEW */
|
||||
if( (inputDeviceID < 0) && ( outputDeviceID < 0) ) return paInvalidDeviceId;
|
||||
if( (outputDeviceID >= Pa_CountDevices()) || (inputDeviceID >= Pa_CountDevices()) )
|
||||
{
|
||||
return paInvalidDeviceId;
|
||||
}
|
||||
if( (numInputChannels <= 0) && ( numOutputChannels <= 0) ) return paInvalidChannelCount;
|
||||
|
||||
#if SUPPORT_AUDIO_CAPTURE
|
||||
if( inputDeviceID >= 0 )
|
||||
{
|
||||
PaError size = Pa_GetSampleSize( inputSampleFormat );
|
||||
if( size < 0 ) return size;
|
||||
bitsPerInputSample = 8 * size;
|
||||
if( (numInputChannels <= 0) ) return paInvalidChannelCount;
|
||||
}
|
||||
#else
|
||||
if( inputDeviceID >= 0 )
|
||||
{
|
||||
return paInvalidChannelCount;
|
||||
}
|
||||
#endif /* SUPPORT_AUDIO_CAPTURE */
|
||||
else
|
||||
{
|
||||
if( numInputChannels > 0 ) return paInvalidChannelCount;
|
||||
bitsPerInputSample = 0;
|
||||
}
|
||||
|
||||
if( outputDeviceID >= 0 )
|
||||
{
|
||||
PaError size = Pa_GetSampleSize( outputSampleFormat );
|
||||
if( size < 0 ) return size;
|
||||
bitsPerOutputSample = 8 * size;
|
||||
if( (numOutputChannels <= 0) ) return paInvalidChannelCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( numOutputChannels > 0 ) return paInvalidChannelCount;
|
||||
bitsPerOutputSample = 0;
|
||||
}
|
||||
|
||||
if( callback == NULL ) return paNullCallback;
|
||||
|
||||
/* Allocate and clear stream structure. */
|
||||
past = (internalPortAudioStream *) PaHost_AllocateFastMemory( sizeof(internalPortAudioStream) );
|
||||
if( past == NULL ) return paInsufficientMemory;
|
||||
memset( past, 0, sizeof(internalPortAudioStream) );
|
||||
AddTraceMessage("Pa_OpenStream: past", (long) past );
|
||||
|
||||
past->past_Magic = PA_MAGIC; /* Set ID to catch bugs. */
|
||||
past->past_FramesPerUserBuffer = framesPerBuffer;
|
||||
past->past_NumUserBuffers = numberOfBuffers; /* NOTE - PaHost_OpenStream() MUST CHECK FOR ZERO! */
|
||||
past->past_Callback = callback;
|
||||
past->past_UserData = userData;
|
||||
past->past_OutputSampleFormat = outputSampleFormat;
|
||||
past->past_InputSampleFormat = inputSampleFormat;
|
||||
past->past_OutputDeviceID = outputDeviceID;
|
||||
past->past_InputDeviceID = inputDeviceID;
|
||||
past->past_NumInputChannels = numInputChannels;
|
||||
past->past_NumOutputChannels = numOutputChannels;
|
||||
past->past_Flags = streamFlags;
|
||||
|
||||
/* Check for absurd sample rates. */
|
||||
if( (sampleRate < 1000.0) || (sampleRate > 200000.0) )
|
||||
{
|
||||
result = paInvalidSampleRate;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Allocate buffers that may be used for format conversion from user to native buffers. */
|
||||
if( numInputChannels > 0 )
|
||||
{
|
||||
|
||||
#if PA_VALIDATE_RATE
|
||||
result = PaHost_ValidateSampleRate( inputDeviceID, sampleRate, &past->past_SampleRate );
|
||||
if( result < 0 )
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
#else
|
||||
past->past_SampleRate = sampleRate;
|
||||
#endif
|
||||
/* Allocate single Input buffer for passing formatted samples to user callback. */
|
||||
past->past_InputBufferSize = framesPerBuffer * numInputChannels * ((bitsPerInputSample+7) / 8);
|
||||
past->past_InputBuffer = PaHost_AllocateFastMemory(past->past_InputBufferSize);
|
||||
if( past->past_InputBuffer == NULL )
|
||||
{
|
||||
result = paInsufficientMemory;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
past->past_InputBuffer = NULL;
|
||||
}
|
||||
|
||||
/* Allocate single Output buffer. */
|
||||
if( numOutputChannels > 0 )
|
||||
{
|
||||
#if PA_VALIDATE_RATE
|
||||
result = PaHost_ValidateSampleRate( outputDeviceID, sampleRate, &past->past_SampleRate );
|
||||
if( result < 0 )
|
||||
{
|
||||
goto cleanup;
|
||||
}
|
||||
#else
|
||||
past->past_SampleRate = sampleRate;
|
||||
#endif
|
||||
past->past_OutputBufferSize = framesPerBuffer * numOutputChannels * ((bitsPerOutputSample+7) / 8);
|
||||
past->past_OutputBuffer = PaHost_AllocateFastMemory(past->past_OutputBufferSize);
|
||||
if( past->past_OutputBuffer == NULL )
|
||||
{
|
||||
result = paInsufficientMemory;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
past->past_OutputBuffer = NULL;
|
||||
}
|
||||
|
||||
result = PaHost_OpenStream( past );
|
||||
if( result < 0 ) goto cleanup;
|
||||
|
||||
*streamPtrPtr = (void *) past;
|
||||
|
||||
return result;
|
||||
|
||||
cleanup:
|
||||
if( past != NULL ) Pa_CloseStream( past );
|
||||
*streamPtrPtr = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
PaError Pa_OpenDefaultStream( PortAudioStream** stream,
|
||||
int numInputChannels,
|
||||
int numOutputChannels,
|
||||
PaSampleFormat sampleFormat,
|
||||
double sampleRate,
|
||||
unsigned long framesPerBuffer,
|
||||
unsigned long numberOfBuffers,
|
||||
PortAudioCallback *callback,
|
||||
void *userData )
|
||||
{
|
||||
return Pa_OpenStream(
|
||||
stream,
|
||||
((numInputChannels > 0) ? Pa_GetDefaultInputDeviceID() : paNoDevice),
|
||||
numInputChannels, sampleFormat, NULL,
|
||||
((numOutputChannels > 0) ? Pa_GetDefaultOutputDeviceID() : paNoDevice),
|
||||
numOutputChannels, sampleFormat, NULL,
|
||||
sampleRate, framesPerBuffer, numberOfBuffers, paNoFlag, callback, userData );
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
PaError Pa_CloseStream( PortAudioStream* stream)
|
||||
{
|
||||
PaError result;
|
||||
internalPortAudioStream *past;
|
||||
|
||||
DBUG(("Pa_CloseStream()\n"));
|
||||
if( stream == NULL ) return paBadStreamPtr;
|
||||
past = (internalPortAudioStream *) stream;
|
||||
|
||||
Pa_AbortStream( past );
|
||||
result = PaHost_CloseStream( past );
|
||||
|
||||
if( past->past_InputBuffer ) PaHost_FreeFastMemory( past->past_InputBuffer, past->past_InputBufferSize );
|
||||
if( past->past_OutputBuffer ) PaHost_FreeFastMemory( past->past_OutputBuffer, past->past_OutputBufferSize );
|
||||
PaHost_FreeFastMemory( past, sizeof(internalPortAudioStream) );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
PaError Pa_StartStream( PortAudioStream *stream )
|
||||
{
|
||||
PaError result = paHostError;
|
||||
internalPortAudioStream *past;
|
||||
|
||||
if( stream == NULL ) return paBadStreamPtr;
|
||||
past = (internalPortAudioStream *) stream;
|
||||
|
||||
past->past_FrameCount = 0.0;
|
||||
|
||||
if( past->past_NumInputChannels > 0 )
|
||||
{
|
||||
result = PaHost_StartInput( past );
|
||||
DBUG(("Pa_StartStream: PaHost_StartInput returned = 0x%X.\n", result));
|
||||
if( result < 0 ) goto error;
|
||||
}
|
||||
|
||||
if( past->past_NumOutputChannels > 0 )
|
||||
{
|
||||
result = PaHost_StartOutput( past );
|
||||
DBUG(("Pa_StartStream: PaHost_StartOutput returned = 0x%X.\n", result));
|
||||
if( result < 0 ) goto error;
|
||||
}
|
||||
|
||||
result = PaHost_StartEngine( past );
|
||||
DBUG(("Pa_StartStream: PaHost_StartEngine returned = 0x%X.\n", result));
|
||||
if( result < 0 ) goto error;
|
||||
|
||||
return paNoError;
|
||||
|
||||
error:
|
||||
return result;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
PaError Pa_StopStream( PortAudioStream *stream )
|
||||
{
|
||||
return Pa_KillStream( stream, 0 );
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
PaError Pa_AbortStream( PortAudioStream *stream )
|
||||
{
|
||||
return Pa_KillStream( stream, 1 );
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
static PaError Pa_KillStream( PortAudioStream *stream, int abort )
|
||||
{
|
||||
PaError result = paNoError;
|
||||
internalPortAudioStream *past;
|
||||
|
||||
DBUG(("Pa_StopStream().\n"));
|
||||
if( stream == NULL ) return paBadStreamPtr;
|
||||
past = (internalPortAudioStream *) stream;
|
||||
|
||||
if( (past->past_NumInputChannels > 0) || (past->past_NumOutputChannels > 0) )
|
||||
{
|
||||
result = PaHost_StopEngine( past, abort );
|
||||
DBUG(("Pa_StopStream: PaHost_StopEngine returned = 0x%X.\n", result));
|
||||
if( result < 0 ) goto error;
|
||||
}
|
||||
|
||||
if( past->past_NumInputChannels > 0 )
|
||||
{
|
||||
result = PaHost_StopInput( past, abort );
|
||||
DBUG(("Pa_StopStream: PaHost_StopInput returned = 0x%X.\n", result));
|
||||
if( result != paNoError ) goto error;
|
||||
}
|
||||
|
||||
if( past->past_NumOutputChannels > 0 )
|
||||
{
|
||||
result = PaHost_StopOutput( past, abort );
|
||||
DBUG(("Pa_StopStream: PaHost_StopOutput returned = 0x%X.\n", result));
|
||||
if( result != paNoError ) goto error;
|
||||
}
|
||||
|
||||
error:
|
||||
past->past_Usage = 0;
|
||||
past->past_IfLastExitValid = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
PaError Pa_StreamActive( PortAudioStream *stream )
|
||||
{
|
||||
internalPortAudioStream *past;
|
||||
if( stream == NULL ) return paBadStreamPtr;
|
||||
past = (internalPortAudioStream *) stream;
|
||||
return PaHost_StreamActive( past );
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
const char *Pa_GetErrorText( PaError errnum )
|
||||
{
|
||||
const char *msg;
|
||||
|
||||
switch(errnum)
|
||||
{
|
||||
case paNoError: msg = "Success"; break;
|
||||
case paHostError: msg = "Host error."; break;
|
||||
case paInvalidChannelCount: msg = "Invalid number of channels."; break;
|
||||
case paInvalidSampleRate: msg = "Invalid sample rate."; break;
|
||||
case paInvalidDeviceId: msg = "Invalid device ID."; break;
|
||||
case paInvalidFlag: msg = "Invalid flag."; break;
|
||||
case paSampleFormatNotSupported: msg = "Sample format not supported"; break;
|
||||
case paBadIODeviceCombination: msg = "Illegal combination of I/O devices."; break;
|
||||
case paInsufficientMemory: msg = "Insufficient memory."; break;
|
||||
case paBufferTooBig: msg = "Buffer too big."; break;
|
||||
case paBufferTooSmall: msg = "Buffer too small."; break;
|
||||
case paNullCallback: msg = "No callback routine specified."; break;
|
||||
case paBadStreamPtr: msg = "Invalid stream pointer."; break;
|
||||
case paTimedOut : msg = "Wait Timed Out."; break;
|
||||
case paInternalError: msg = "Internal PortAudio Error."; break;
|
||||
case paDeviceUnavailable: msg = "Device Unavailable."; break;
|
||||
default: msg = "Illegal error number."; break;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
/*
|
||||
Get CPU Load as a fraction of total CPU time.
|
||||
A value of 0.5 would imply that PortAudio and the sound generating
|
||||
callback was consuming roughly 50% of the available CPU time.
|
||||
The amount may vary depending on CPU load.
|
||||
This function may be called from the callback function.
|
||||
*/
|
||||
double Pa_GetCPULoad( PortAudioStream* stream)
|
||||
{
|
||||
internalPortAudioStream *past;
|
||||
if( stream == NULL ) return (double) paBadStreamPtr;
|
||||
past = (internalPortAudioStream *) stream;
|
||||
return past->past_Usage;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
internalPortAudioStream* PaHost_GetStreamRepresentation( PortAudioStream *stream )
|
||||
{
|
||||
internalPortAudioStream* result = (internalPortAudioStream*) stream;
|
||||
|
||||
if( result == NULL || result->past_Magic != PA_MAGIC )
|
||||
return NULL;
|
||||
else
|
||||
return result;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
** Calculate 2 LSB dither signal with a triangular distribution.
|
||||
** Ranged properly for adding to a 32 bit integer prior to >>15.
|
||||
** Range of output is +/- 32767
|
||||
*/
|
||||
#define PA_DITHER_BITS (15)
|
||||
#define PA_DITHER_SCALE (1.0f / ((1<<PA_DITHER_BITS)-1))
|
||||
long PaConvert_TriangularDither( void )
|
||||
{
|
||||
static unsigned long previous = 0;
|
||||
static unsigned long randSeed1 = 22222;
|
||||
static unsigned long randSeed2 = 5555555;
|
||||
long current, highPass;
|
||||
/* Generate two random numbers. */
|
||||
randSeed1 = (randSeed1 * 196314165) + 907633515;
|
||||
randSeed2 = (randSeed2 * 196314165) + 907633515;
|
||||
/* Generate triangular distribution about 0.
|
||||
* Shift before adding to prevent overflow which would skew the distribution.
|
||||
* Also shift an extra bit for the high pass filter.
|
||||
*/
|
||||
#define DITHER_SHIFT ((32 - PA_DITHER_BITS) + 1)
|
||||
current = (((long)randSeed1)>>DITHER_SHIFT) + (((long)randSeed2)>>DITHER_SHIFT);
|
||||
/* High pass filter to reduce audibility. */
|
||||
highPass = current - previous;
|
||||
previous = current;
|
||||
return highPass;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
** Called by host code.
|
||||
** Convert input from Int16, call user code, then convert output
|
||||
** to Int16 format for native use.
|
||||
** Assumes host native format is paInt16.
|
||||
** Returns result from user callback.
|
||||
*/
|
||||
long Pa_CallConvertInt16( internalPortAudioStream *past,
|
||||
short *nativeInputBuffer,
|
||||
short *nativeOutputBuffer )
|
||||
{
|
||||
long temp;
|
||||
int userResult;
|
||||
unsigned int i;
|
||||
void *inputBuffer = NULL;
|
||||
void *outputBuffer = NULL;
|
||||
|
||||
#if SUPPORT_AUDIO_CAPTURE
|
||||
/* Get native data from DirectSound. */
|
||||
if( (past->past_NumInputChannels > 0) && (nativeInputBuffer != NULL) )
|
||||
{
|
||||
/* Convert from native format to PA format. */
|
||||
unsigned int samplesPerBuffer = past->past_FramesPerUserBuffer * past->past_NumInputChannels;
|
||||
switch(past->past_InputSampleFormat)
|
||||
{
|
||||
|
||||
case paFloat32:
|
||||
{
|
||||
float *inBufPtr = (float *) past->past_InputBuffer;
|
||||
inputBuffer = past->past_InputBuffer;
|
||||
for( i=0; i<samplesPerBuffer; i++ )
|
||||
{
|
||||
inBufPtr[i] = nativeInputBuffer[i] * (1.0f / 32767.0f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case paInt32:
|
||||
{
|
||||
/* Convert 16 bit data to 32 bit integers */
|
||||
int *inBufPtr = (int *) past->past_InputBuffer;
|
||||
inputBuffer = past->past_InputBuffer;
|
||||
for( i=0; i<samplesPerBuffer; i++ )
|
||||
{
|
||||
inBufPtr[i] = nativeInputBuffer[i] << 16;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case paInt16:
|
||||
{
|
||||
/* Already in correct format so don't copy. */
|
||||
inputBuffer = nativeInputBuffer;
|
||||
break;
|
||||
}
|
||||
|
||||
case paInt8:
|
||||
{
|
||||
/* Convert 16 bit data to 8 bit chars */
|
||||
char *inBufPtr = (char *) past->past_InputBuffer;
|
||||
inputBuffer = past->past_InputBuffer;
|
||||
if( past->past_Flags & paDitherOff )
|
||||
{
|
||||
for( i=0; i<samplesPerBuffer; i++ )
|
||||
{
|
||||
inBufPtr[i] = (char)(nativeInputBuffer[i] >> 8);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i=0; i<samplesPerBuffer; i++ )
|
||||
{
|
||||
temp = nativeInputBuffer[i];
|
||||
temp += PaConvert_TriangularDither() >> 8; /* PLB20010820 */
|
||||
temp = ((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp));
|
||||
inBufPtr[i] = (char)(temp >> 8);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case paUInt8:
|
||||
{
|
||||
/* Convert 16 bit data to 8 bit unsigned chars */
|
||||
unsigned char *inBufPtr = (unsigned char *) past->past_InputBuffer;
|
||||
inputBuffer = past->past_InputBuffer;
|
||||
if( past->past_Flags & paDitherOff )
|
||||
{
|
||||
for( i=0; i<samplesPerBuffer; i++ )
|
||||
{
|
||||
inBufPtr[i] = (unsigned char)((nativeInputBuffer[i] >> 8) + 0x80);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If you dither then you have to clip because dithering could push the signal out of range! */
|
||||
for( i=0; i<samplesPerBuffer; i++ )
|
||||
{
|
||||
temp = nativeInputBuffer[i];
|
||||
temp += PaConvert_TriangularDither() >> 8; /* PLB20010820 */
|
||||
temp = ((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp));
|
||||
inBufPtr[i] = (unsigned char)((temp>>8) + 0x80); /* PLB20010820 */
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif /* SUPPORT_AUDIO_CAPTURE */
|
||||
|
||||
/* Are we doing output time? */
|
||||
if( (past->past_NumOutputChannels > 0) && (nativeOutputBuffer != NULL) )
|
||||
{
|
||||
/* May already be in native format so just write directly to native buffer. */
|
||||
outputBuffer = (past->past_OutputSampleFormat == paInt16) ?
|
||||
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 );
|
||||
|
||||
past->past_FrameCount += (PaTimestamp) past->past_FramesPerUserBuffer;
|
||||
|
||||
/* Convert to native format if necessary. */
|
||||
if( outputBuffer != NULL )
|
||||
{
|
||||
unsigned int samplesPerBuffer = past->past_FramesPerUserBuffer * past->past_NumOutputChannels;
|
||||
switch(past->past_OutputSampleFormat)
|
||||
{
|
||||
case paFloat32:
|
||||
{
|
||||
float *outBufPtr = (float *) past->past_OutputBuffer;
|
||||
if( past->past_Flags & paDitherOff )
|
||||
{
|
||||
if( past->past_Flags & paClipOff ) /* NOTHING */
|
||||
{
|
||||
for( i=0; i<samplesPerBuffer; i++ )
|
||||
{
|
||||
*nativeOutputBuffer++ = (short) (outBufPtr[i] * (32767.0f));
|
||||
}
|
||||
}
|
||||
else /* CLIP */
|
||||
{
|
||||
for( i=0; i<samplesPerBuffer; i++ )
|
||||
{
|
||||
temp = (long)(outBufPtr[i] * 32767.0f);
|
||||
*nativeOutputBuffer++ = (short)((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If you dither then you have to clip because dithering could push the signal out of range! */
|
||||
for( i=0; i<samplesPerBuffer; i++ )
|
||||
{
|
||||
float dither = PaConvert_TriangularDither()*PA_DITHER_SCALE;
|
||||
float dithered = (outBufPtr[i] * (32767.0f)) + dither;
|
||||
temp = (long) (dithered);
|
||||
*nativeOutputBuffer++ = (short)((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case paInt32:
|
||||
{
|
||||
int *outBufPtr = (int *) past->past_OutputBuffer;
|
||||
if( past->past_Flags & paDitherOff )
|
||||
{
|
||||
for( i=0; i<samplesPerBuffer; i++ )
|
||||
{
|
||||
*nativeOutputBuffer++ = (short) (outBufPtr[i] >> 16 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i=0; i<samplesPerBuffer; i++ )
|
||||
{
|
||||
/* Shift one bit down before dithering so that we have room for overflow from add. */
|
||||
temp = (outBufPtr[i] >> 1) + PaConvert_TriangularDither();
|
||||
temp = temp >> 15;
|
||||
*nativeOutputBuffer++ = (short)((temp < -0x8000) ? -0x8000 : ((temp > 0x7FFF) ? 0x7FFF : temp));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case paInt8:
|
||||
{
|
||||
char *outBufPtr = (char *) past->past_OutputBuffer;
|
||||
for( i=0; i<samplesPerBuffer; i++ )
|
||||
{
|
||||
*nativeOutputBuffer++ = (short) (((int)outBufPtr[i]) << 8);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case paUInt8:
|
||||
{
|
||||
unsigned char *outBufPtr = (unsigned char *) past->past_OutputBuffer;
|
||||
for( i=0; i<samplesPerBuffer; i++ )
|
||||
{
|
||||
*nativeOutputBuffer++ = (short) (((int)(outBufPtr[i] - 0x80)) << 8);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return userResult;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
PaError Pa_Initialize( void )
|
||||
{
|
||||
if( gInitCount++ > 0 ) return paNoError;
|
||||
ResetTraceMessages();
|
||||
return PaHost_Init();
|
||||
}
|
||||
|
||||
PaError Pa_Terminate( void )
|
||||
{
|
||||
PaError result = paNoError;
|
||||
|
||||
if( gInitCount == 0 ) return paNoError;
|
||||
else if( --gInitCount == 0 )
|
||||
{
|
||||
result = PaHost_Term();
|
||||
DumpTraceMessages();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int PaHost_IsInitialized()
|
||||
{
|
||||
return gInitCount;
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
PaError Pa_GetSampleSize( PaSampleFormat format )
|
||||
{
|
||||
int size;
|
||||
switch(format )
|
||||
{
|
||||
|
||||
case paUInt8:
|
||||
case paInt8:
|
||||
size = 1;
|
||||
break;
|
||||
|
||||
case paInt16:
|
||||
size = 2;
|
||||
break;
|
||||
|
||||
case paPackedInt24:
|
||||
size = 3;
|
||||
break;
|
||||
|
||||
case paFloat32:
|
||||
case paInt32:
|
||||
case paInt24:
|
||||
size = 4;
|
||||
break;
|
||||
|
||||
default:
|
||||
size = paSampleFormatNotSupported;
|
||||
break;
|
||||
}
|
||||
return (PaError) size;
|
||||
}
|
||||
|
||||
|
||||
83
lib-src/portaudio/pa_common/pa_trace.c
Normal file
83
lib-src/portaudio/pa_common/pa_trace.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* $Id: pa_trace.c,v 1.5 2003-03-02 08:01:34 dmazzoni Exp $
|
||||
* Portable Audio I/O Library Trace Facility
|
||||
* Store trace information in real-time for later printing.
|
||||
*
|
||||
* Based on the Open Source API proposed by Ross Bencina
|
||||
* Copyright (c) 1999-2000 Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "pa_trace.h"
|
||||
|
||||
#if TRACE_REALTIME_EVENTS
|
||||
|
||||
static char *traceTextArray[MAX_TRACE_RECORDS];
|
||||
static int traceIntArray[MAX_TRACE_RECORDS];
|
||||
static int traceIndex = 0;
|
||||
static int traceBlock = 0;
|
||||
|
||||
/*********************************************************************/
|
||||
void ResetTraceMessages()
|
||||
{
|
||||
traceIndex = 0;
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
void DumpTraceMessages()
|
||||
{
|
||||
int i;
|
||||
int numDump = (traceIndex < MAX_TRACE_RECORDS) ? traceIndex : MAX_TRACE_RECORDS;
|
||||
|
||||
printf("DumpTraceMessages: traceIndex = %d\n", traceIndex );
|
||||
for( i=0; i<numDump; i++ )
|
||||
{
|
||||
printf("%3d: %s = 0x%08X\n",
|
||||
i, traceTextArray[i], traceIntArray[i] );
|
||||
}
|
||||
ResetTraceMessages();
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
void AddTraceMessage( char *msg, int data )
|
||||
{
|
||||
if( (traceIndex == MAX_TRACE_RECORDS) && (traceBlock == 0) )
|
||||
{
|
||||
traceBlock = 1;
|
||||
/* DumpTraceMessages(); */
|
||||
}
|
||||
else if( traceIndex < MAX_TRACE_RECORDS )
|
||||
{
|
||||
traceTextArray[traceIndex] = msg;
|
||||
traceIntArray[traceIndex] = data;
|
||||
traceIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
67
lib-src/portaudio/pa_common/pa_trace.h
Normal file
67
lib-src/portaudio/pa_common/pa_trace.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#ifndef PA_TRACE_H
|
||||
#define PA_TRACE_H
|
||||
/*
|
||||
* $Id: pa_trace.h,v 1.5 2003-03-02 08:01:35 dmazzoni Exp $
|
||||
* Portable Audio I/O Library Trace Facility
|
||||
* Store trace information in real-time for later printing.
|
||||
*
|
||||
* Based on the Open Source API proposed by Ross Bencina
|
||||
* Copyright (c) 1999-2000 Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#define TRACE_REALTIME_EVENTS (0) /* Keep log of various real-time events. */
|
||||
#define MAX_TRACE_RECORDS (2048)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
/************************************************************************************/
|
||||
/****************** Prototypes ******************************************************/
|
||||
/************************************************************************************/
|
||||
|
||||
#if TRACE_REALTIME_EVENTS
|
||||
|
||||
void DumpTraceMessages();
|
||||
void ResetTraceMessages();
|
||||
void AddTraceMessage( char *msg, int data );
|
||||
|
||||
#else
|
||||
|
||||
#define AddTraceMessage(msg,data) /* noop */
|
||||
#define ResetTraceMessages() /* noop */
|
||||
#define DumpTraceMessages() /* noop */
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* PA_TRACE_H */
|
||||
463
lib-src/portaudio/pa_common/portaudio.h
Normal file
463
lib-src/portaudio/pa_common/portaudio.h
Normal file
@@ -0,0 +1,463 @@
|
||||
#ifndef PORT_AUDIO_H
|
||||
#define PORT_AUDIO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/*
|
||||
* $Id: portaudio.h,v 1.6 2003-03-02 08:01:35 dmazzoni Exp $
|
||||
* PortAudio Portable Real-Time Audio Library
|
||||
* PortAudio API Header File
|
||||
* Latest version available at: http://www.audiomulch.com/portaudio/
|
||||
*
|
||||
* Copyright (c) 1999-2000 Ross Bencina and Phil Burk
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* Any person wishing to distribute modifications to the Software is
|
||||
* requested to send the modifications to the original developer so that
|
||||
* they can be incorporated into the canonical version.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef int PaError;
|
||||
typedef enum {
|
||||
paNoError = 0,
|
||||
|
||||
paHostError = -10000,
|
||||
paInvalidChannelCount,
|
||||
paInvalidSampleRate,
|
||||
paInvalidDeviceId,
|
||||
paInvalidFlag,
|
||||
paSampleFormatNotSupported,
|
||||
paBadIODeviceCombination,
|
||||
paInsufficientMemory,
|
||||
paBufferTooBig,
|
||||
paBufferTooSmall,
|
||||
paNullCallback,
|
||||
paBadStreamPtr,
|
||||
paTimedOut,
|
||||
paInternalError,
|
||||
paDeviceUnavailable
|
||||
} PaErrorNum;
|
||||
|
||||
/*
|
||||
Pa_Initialize() is the library initialisation function - call this before
|
||||
using the library.
|
||||
|
||||
*/
|
||||
|
||||
PaError Pa_Initialize( void );
|
||||
|
||||
/*
|
||||
Pa_Terminate() is the library termination function - call this after
|
||||
using the library.
|
||||
|
||||
*/
|
||||
|
||||
PaError Pa_Terminate( void );
|
||||
|
||||
/*
|
||||
Pa_GetHostError() returns a host specific error code.
|
||||
This can be called after receiving a PortAudio error code of paHostError.
|
||||
|
||||
*/
|
||||
|
||||
long Pa_GetHostError( void );
|
||||
|
||||
/*
|
||||
Pa_GetErrorText() translates the supplied PortAudio error number
|
||||
into a human readable message.
|
||||
|
||||
*/
|
||||
|
||||
const char *Pa_GetErrorText( PaError errnum );
|
||||
|
||||
/*
|
||||
Sample formats
|
||||
|
||||
These are formats used to pass sound data between the callback and the
|
||||
stream. Each device has a "native" format which may be used when optimum
|
||||
efficiency or control over conversion is required.
|
||||
|
||||
Formats marked "always available" are supported (emulated) by all
|
||||
PortAudio implementations.
|
||||
|
||||
The floating point representation (paFloat32) uses +1.0 and -1.0 as the
|
||||
maximum and minimum respectively.
|
||||
|
||||
paUInt8 is an unsigned 8 bit format where 128 is considered "ground"
|
||||
|
||||
*/
|
||||
|
||||
typedef unsigned long PaSampleFormat;
|
||||
#define paFloat32 ((PaSampleFormat) (1<<0)) /*always available*/
|
||||
#define paInt16 ((PaSampleFormat) (1<<1)) /*always available*/
|
||||
#define paInt32 ((PaSampleFormat) (1<<2)) /*always available*/
|
||||
#define paInt24 ((PaSampleFormat) (1<<3))
|
||||
#define paPackedInt24 ((PaSampleFormat) (1<<4))
|
||||
#define paInt8 ((PaSampleFormat) (1<<5))
|
||||
#define paUInt8 ((PaSampleFormat) (1<<6))
|
||||
#define paCustomFormat ((PaSampleFormat) (1<<16))
|
||||
|
||||
/*
|
||||
Device enumeration mechanism.
|
||||
|
||||
Device ids range from 0 to Pa_CountDevices()-1.
|
||||
|
||||
Devices may support input, output or both.
|
||||
|
||||
*/
|
||||
|
||||
typedef int PaDeviceID;
|
||||
#define paNoDevice -1
|
||||
|
||||
int Pa_CountDevices( void );
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int structVersion;
|
||||
const char *name;
|
||||
int maxInputChannels;
|
||||
int maxOutputChannels;
|
||||
/* Number of discrete rates, or -1 if range supported. */
|
||||
int numSampleRates;
|
||||
/* Array of supported sample rates, or {min,max} if range supported. */
|
||||
const double *sampleRates;
|
||||
PaSampleFormat nativeSampleFormats;
|
||||
}
|
||||
PaDeviceInfo;
|
||||
|
||||
/*
|
||||
Pa_GetDefaultInputDeviceID(), Pa_GetDefaultOutputDeviceID() return the
|
||||
default device ids for input and output respectively, or paNoDevice if
|
||||
no device is available.
|
||||
The result can be passed to Pa_OpenStream().
|
||||
|
||||
On the PC, the user can specify a default device by
|
||||
setting an environment variable. For example, to use device #1.
|
||||
|
||||
set PA_RECOMMENDED_OUTPUT_DEVICE=1
|
||||
|
||||
The user should first determine the available device ids by using
|
||||
the supplied application "pa_devs".
|
||||
|
||||
*/
|
||||
|
||||
PaDeviceID Pa_GetDefaultInputDeviceID( void );
|
||||
PaDeviceID Pa_GetDefaultOutputDeviceID( void );
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Pa_GetDeviceInfo() returns a pointer to an immutable PaDeviceInfo structure
|
||||
for the device specified.
|
||||
If the device parameter is out of range the function returns NULL.
|
||||
|
||||
PortAudio manages the memory referenced by the returned pointer, the client
|
||||
must not manipulate or free the memory. The pointer is only guaranteed to be
|
||||
valid between calls to Pa_Initialize() and Pa_Terminate().
|
||||
|
||||
*/
|
||||
|
||||
const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID device );
|
||||
|
||||
/*
|
||||
PaTimestamp is used to represent a continuous sample clock with arbitrary
|
||||
start time that can be used for syncronization. The type is used for the
|
||||
outTime argument to the PortAudioCallback and as the result of Pa_StreamTime()
|
||||
|
||||
*/
|
||||
|
||||
typedef double PaTimestamp;
|
||||
|
||||
/*
|
||||
PortAudioCallback is implemented by PortAudio clients.
|
||||
|
||||
inputBuffer and outputBuffer are arrays of interleaved samples,
|
||||
the format, packing and number of channels used by the buffers are
|
||||
determined by parameters to Pa_OpenStream() (see below).
|
||||
|
||||
framesPerBuffer is the number of sample frames to be processed by the callback.
|
||||
|
||||
outTime is the time in samples when the buffer(s) processed by
|
||||
this callback will begin being played at the audio output.
|
||||
See also Pa_StreamTime()
|
||||
|
||||
userData is the value of a user supplied pointer passed to Pa_OpenStream()
|
||||
intended for storing synthesis data etc.
|
||||
|
||||
return value:
|
||||
The callback can return a non-zero value to stop the stream. This may be
|
||||
useful in applications such as soundfile players where a specific duration
|
||||
of output is required. However, it is not necessary to utilise this mechanism
|
||||
as StopStream() will also terminate the stream. A callback returning a
|
||||
non-zero value must fill the entire outputBuffer.
|
||||
|
||||
NOTE: None of the other stream functions may be called from within the
|
||||
callback function except for Pa_GetCPULoad().
|
||||
|
||||
*/
|
||||
|
||||
typedef int (PortAudioCallback)(
|
||||
void *inputBuffer, void *outputBuffer,
|
||||
unsigned long framesPerBuffer,
|
||||
PaTimestamp outTime, void *userData );
|
||||
|
||||
|
||||
/*
|
||||
Stream flags
|
||||
|
||||
These flags may be supplied (ored together) in the streamFlags argument to
|
||||
the Pa_OpenStream() function.
|
||||
|
||||
*/
|
||||
|
||||
#define paNoFlag (0)
|
||||
#define paClipOff (1<<0) /* disable default clipping of out of range samples */
|
||||
#define paDitherOff (1<<1) /* disable default dithering */
|
||||
#define paPlatformSpecificFlags (0x00010000)
|
||||
typedef unsigned long PaStreamFlags;
|
||||
|
||||
/*
|
||||
A single PortAudioStream provides multiple channels of real-time
|
||||
input and output audio streaming to a client application.
|
||||
Pointers to PortAudioStream objects are passed between PortAudio functions.
|
||||
*/
|
||||
|
||||
typedef void PortAudioStream;
|
||||
#define PaStream PortAudioStream
|
||||
|
||||
/*
|
||||
Pa_OpenStream() opens a stream for either input, output or both.
|
||||
|
||||
stream is the address of a PortAudioStream pointer which will receive
|
||||
a pointer to the newly opened stream.
|
||||
|
||||
inputDevice is the id of the device used for input (see PaDeviceID above.)
|
||||
inputDevice may be paNoDevice to indicate that an input device is not required.
|
||||
|
||||
numInputChannels is the number of channels of sound to be delivered to the
|
||||
callback. It can range from 1 to the value of maxInputChannels in the
|
||||
PaDeviceInfo record for the device specified by the inputDevice parameter.
|
||||
If inputDevice is paNoDevice numInputChannels is ignored.
|
||||
|
||||
inputSampleFormat is the sample format of inputBuffer provided to the callback
|
||||
function. inputSampleFormat may be any of the formats described by the
|
||||
PaSampleFormat enumeration (see above). PortAudio guarantees support for
|
||||
the device's native formats (nativeSampleFormats in the device info record)
|
||||
and additionally 16 and 32 bit integer and 32 bit floating point formats.
|
||||
Support for other formats is implementation defined.
|
||||
|
||||
inputDriverInfo is a pointer to an optional driver specific data structure
|
||||
containing additional information for device setup or stream processing.
|
||||
inputDriverInfo is never required for correct operation. If not used
|
||||
inputDriverInfo should be NULL.
|
||||
|
||||
outputDevice is the id of the device used for output (see PaDeviceID above.)
|
||||
outputDevice may be paNoDevice to indicate that an output device is not required.
|
||||
|
||||
numOutputChannels is the number of channels of sound to be supplied by the
|
||||
callback. See the definition of numInputChannels above for more details.
|
||||
|
||||
outputSampleFormat is the sample format of the outputBuffer filled by the
|
||||
callback function. See the definition of inputSampleFormat above for more
|
||||
details.
|
||||
|
||||
outputDriverInfo is a pointer to an optional driver specific data structure
|
||||
containing additional information for device setup or stream processing.
|
||||
outputDriverInfo is never required for correct operation. If not used
|
||||
outputDriverInfo should be NULL.
|
||||
|
||||
sampleRate is the desired sampleRate. For full-duplex streams it is the
|
||||
sample rate for both input and output
|
||||
|
||||
framesPerBuffer is the length in sample frames of all internal sample buffers
|
||||
used for communication with platform specific audio routines. Wherever
|
||||
possible this corresponds to the framesPerBuffer parameter passed to the
|
||||
callback function.
|
||||
|
||||
numberOfBuffers is the number of buffers used for multibuffered communication
|
||||
with the platform specific audio routines. If you pass zero, then an optimum
|
||||
value will be chosen for you internally. This parameter is provided only
|
||||
as a guide - and does not imply that an implementation must use multibuffered
|
||||
i/o when reliable double buffering is available (such as SndPlayDoubleBuffer()
|
||||
on the Macintosh.)
|
||||
|
||||
streamFlags may contain a combination of flags ORed together.
|
||||
These flags modify the behaviour of the streaming process. Some flags may only
|
||||
be relevant to certain buffer formats.
|
||||
|
||||
callback is a pointer to a client supplied function that is responsible
|
||||
for processing and filling input and output buffers (see above for details.)
|
||||
|
||||
userData is a client supplied pointer which is passed to the callback
|
||||
function. It could for example, contain a pointer to instance data necessary
|
||||
for processing the audio buffers.
|
||||
|
||||
return value:
|
||||
Upon success Pa_OpenStream() returns PaNoError and places a pointer to a
|
||||
valid PortAudioStream in the stream argument. The stream is inactive (stopped).
|
||||
If a call to Pa_OpenStream() fails a non-zero error code is returned (see
|
||||
PaError above) and the value of stream is invalid.
|
||||
|
||||
*/
|
||||
|
||||
PaError Pa_OpenStream( PortAudioStream** stream,
|
||||
PaDeviceID inputDevice,
|
||||
int numInputChannels,
|
||||
PaSampleFormat inputSampleFormat,
|
||||
void *inputDriverInfo,
|
||||
PaDeviceID outputDevice,
|
||||
int numOutputChannels,
|
||||
PaSampleFormat outputSampleFormat,
|
||||
void *outputDriverInfo,
|
||||
double sampleRate,
|
||||
unsigned long framesPerBuffer,
|
||||
unsigned long numberOfBuffers,
|
||||
PaStreamFlags streamFlags,
|
||||
PortAudioCallback *callback,
|
||||
void *userData );
|
||||
|
||||
|
||||
/*
|
||||
Pa_OpenDefaultStream() is a simplified version of Pa_OpenStream() that opens
|
||||
the default input and/or output devices. Most parameters have identical meaning
|
||||
to their Pa_OpenStream() counterparts, with the following exceptions:
|
||||
|
||||
If either numInputChannels or numOutputChannels is 0 the respective device
|
||||
is not opened. This has the same effect as passing paNoDevice in the device
|
||||
arguments to Pa_OpenStream().
|
||||
|
||||
sampleFormat applies to both the input and output buffers.
|
||||
|
||||
*/
|
||||
|
||||
PaError Pa_OpenDefaultStream( PortAudioStream** stream,
|
||||
int numInputChannels,
|
||||
int numOutputChannels,
|
||||
PaSampleFormat sampleFormat,
|
||||
double sampleRate,
|
||||
unsigned long framesPerBuffer,
|
||||
unsigned long numberOfBuffers,
|
||||
PortAudioCallback *callback,
|
||||
void *userData );
|
||||
|
||||
/*
|
||||
Pa_CloseStream() closes an audio stream, flushing any pending buffers.
|
||||
|
||||
*/
|
||||
|
||||
PaError Pa_CloseStream( PortAudioStream* );
|
||||
|
||||
/*
|
||||
Pa_StartStream() and Pa_StopStream() begin and terminate audio processing.
|
||||
Pa_StopStream() waits until all pending audio buffers have been played.
|
||||
Pa_AbortStream() stops playing immediately without waiting for pending
|
||||
buffers to complete.
|
||||
|
||||
*/
|
||||
|
||||
PaError Pa_StartStream( PortAudioStream *stream );
|
||||
|
||||
PaError Pa_StopStream( PortAudioStream *stream );
|
||||
|
||||
PaError Pa_AbortStream( PortAudioStream *stream );
|
||||
|
||||
/*
|
||||
Pa_StreamActive() returns one (1) when the stream is active (ie playing
|
||||
or recording audio), zero (0) when not playing, or a negative error number
|
||||
if the stream is invalid.
|
||||
The stream is active between calls to Pa_StartStream() and Pa_StopStream(),
|
||||
but may also become inactive if the callback returns a non-zero value.
|
||||
In the latter case, the stream is considered inactive after the last
|
||||
buffer has finished playing.
|
||||
|
||||
*/
|
||||
|
||||
PaError Pa_StreamActive( PortAudioStream *stream );
|
||||
|
||||
/*
|
||||
Pa_StreamTime() returns the current output time in samples for the stream.
|
||||
This time may be used as a time reference (for example synchronizing audio to
|
||||
MIDI).
|
||||
|
||||
*/
|
||||
|
||||
PaTimestamp Pa_StreamTime( PortAudioStream *stream );
|
||||
|
||||
/*
|
||||
Pa_GetCPULoad() returns the CPU Load for the stream.
|
||||
The "CPU Load" is a fraction of total CPU time consumed by the stream's
|
||||
audio processing routines including, but not limited to the client supplied
|
||||
callback.
|
||||
A value of 0.5 would imply that PortAudio and the sound generating
|
||||
callback was consuming roughly 50% of the available CPU time.
|
||||
This function may be called from the callback function or the application.
|
||||
|
||||
*/
|
||||
|
||||
double Pa_GetCPULoad( PortAudioStream* stream );
|
||||
|
||||
/*
|
||||
Pa_GetMinNumBuffers() returns the minimum number of buffers required by
|
||||
the current host based on minimum latency.
|
||||
On the PC, for the DirectSound implementation, latency can be optionally set
|
||||
by user by setting an environment variable.
|
||||
For example, to set latency to 200 msec, put:
|
||||
|
||||
set PA_MIN_LATENCY_MSEC=200
|
||||
|
||||
in the AUTOEXEC.BAT file and reboot.
|
||||
If the environment variable is not set, then the latency will be determined
|
||||
based on the OS. Windows NT has higher latency than Win95.
|
||||
|
||||
*/
|
||||
|
||||
int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate );
|
||||
|
||||
/*
|
||||
Pa_Sleep() puts the caller to sleep for at least 'msec' milliseconds.
|
||||
You may sleep longer than the requested time so don't rely on this for
|
||||
accurate musical timing.
|
||||
|
||||
Pa_Sleep() is provided as a convenience for authors of portable code (such as
|
||||
the tests and examples in the PortAudio distribution.)
|
||||
|
||||
*/
|
||||
|
||||
void Pa_Sleep( long msec );
|
||||
|
||||
/*
|
||||
Pa_GetSampleSize() returns the size in bytes of a single sample in the
|
||||
supplied PaSampleFormat, or paSampleFormatNotSupported if the format is
|
||||
no supported.
|
||||
|
||||
*/
|
||||
|
||||
PaError Pa_GetSampleSize( PaSampleFormat format );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* PORT_AUDIO_H */
|
||||
Reference in New Issue
Block a user