Update portaudio to the latest snapshot. It seems to have some improvements on sample conversion, WASAPI and ASIO.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3050 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
gigaherz 2010-05-20 16:56:53 +00:00
parent 09e168b5ac
commit 1884c409e1
7 changed files with 648 additions and 209 deletions

View File

@ -45,3 +45,4 @@ PaWasapi_GetDeviceDefaultFormat @56
PaWasapi_GetDeviceRole @57
PaWasapi_ThreadPriorityBoost @58
PaWasapi_ThreadPriorityRevert @59
PaWasapi_GetFramesPerHostBuffer @60

View File

@ -41,3 +41,4 @@ PaWasapi_GetDeviceDefaultFormat @56
PaWasapi_GetDeviceRole @57
PaWasapi_ThreadPriorityBoost @58
PaWasapi_ThreadPriorityRevert @59
PaWasapi_GetFramesPerHostBuffer @60

View File

@ -84,8 +84,8 @@ PaWasapiFlags;
/* Host processor. Allows to skip internal PA processing completely.
You must set paWinWasapiRedirectHostProcessor flag to PaWasapiStreamInfo::flags member
in order to have host processor redirected to your callback.
Use with caution! inputFrames and outputFrames depend solely on final device setup (buffer
size is just recommendation) but are not changing during run-time once stream is started.
Use with caution! inputFrames and outputFrames depend solely on final device setup.
To query maximal values of inputFrames/outputFrames use PaWasapi_GetFramesPerHostBuffer.
*/
typedef void (*PaWasapiHostProcessorCallback) (void *inputBuffer, long inputFrames,
void *outputBuffer, long outputFrames,
@ -164,11 +164,11 @@ PaWasapiStreamInfo;
/** Returns default sound format for device. Format is represented by PaWinWaveFormat or
WAVEFORMATEXTENSIBLE structure.
@param pFormat pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure.
@param nFormatSize pize of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes.
@param nDevice device index.
@param pFormat Pointer to PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure.
@param nFormatSize Size of PaWinWaveFormat or WAVEFORMATEXTENSIBLE structure in bytes.
@param nDevice Device index.
@return A non-negative value indicating the number of bytes copied into format decriptor
@return Non-negative value indicating the number of bytes copied into format decriptor
or, a PaErrorCode (which are always negative) if PortAudio is not initialized
or an error is encountered.
*/
@ -179,7 +179,7 @@ int PaWasapi_GetDeviceDefaultFormat( void *pFormat, unsigned int nFormatSize, Pa
@param nDevice device index.
@return A non-negative value indicating device role or, a PaErrorCode (which are always negative)
@return Non-negative value indicating device role or, a PaErrorCode (which are always negative)
if PortAudio is not initialized or an error is encountered.
*/
int/*PaWasapiDeviceRole*/ PaWasapi_GetDeviceRole( PaDeviceIndex nDevice );
@ -188,14 +188,14 @@ int/*PaWasapiDeviceRole*/ PaWasapi_GetDeviceRole( PaDeviceIndex nDevice );
/** Boost thread priority of calling thread (MMCSS). Use it for Blocking Interface only for thread
which makes calls to Pa_WriteStream/Pa_ReadStream.
@param hTask a handle to pointer to priority task. Must be used with PaWasapi_RevertThreadPriority
@param hTask Handle to pointer to priority task. Must be used with PaWasapi_RevertThreadPriority
method to revert thread priority to initial state.
@param nPriorityClass an Id of thread priority of PaWasapiThreadPriority type. Specifying
@param nPriorityClass Id of thread priority of PaWasapiThreadPriority type. Specifying
eThreadPriorityNone does nothing.
@return Error code indicating success or failure.
@see PaWasapi_RevertThreadPriority
@see PaWasapi_RevertThreadPriority
*/
PaError PaWasapi_ThreadPriorityBoost( void **hTask, PaWasapiThreadPriority nPriorityClass );
@ -203,13 +203,26 @@ PaError PaWasapi_ThreadPriorityBoost( void **hTask, PaWasapiThreadPriority nPrio
/** Boost thread priority of calling thread (MMCSS). Use it for Blocking Interface only for thread
which makes calls to Pa_WriteStream/Pa_ReadStream.
@param hTask Task handle obtained by PaWasapi_BoostThreadPriority method.
@param hTask Task handle obtained by PaWasapi_BoostThreadPriority method.
@return Error code indicating success or failure.
@see PaWasapi_BoostThreadPriority
@see PaWasapi_BoostThreadPriority
*/
PaError PaWasapi_ThreadPriorityRevert( void *hTask );
/** Get number of frames per host buffer. This is maximal value of frames of WASAPI buffer which
can be locked for operations. Use this method as helper to findout maximal values of
inputFrames/outputFrames of PaWasapiHostProcessorCallback.
@param pStream Pointer to PaStream to query.
@param nInput Pointer to variable to receive number of input frames. Can be NULL.
@param nOutput Pointer to variable to receive number of output frames. Can be NULL.
@return Error code indicating success or failure.
@see PaWasapiHostProcessorCallback
*/
PaError PaWasapi_GetFramesPerHostBuffer( PaStream *pStream, unsigned int *nInput, unsigned int *nOutput );
/*
IMPORTANT:
@ -228,24 +241,31 @@ PaError PaWasapi_ThreadPriorityRevert( void *hTask );
two versions:
1) Event-Driven:
This is the most powerful WASAPI implementation which is capable to provides glitch-free
audio at 2ms latency in Exclusive mode. Lowest possible latency for this mode is
usually - 2ms for HD Audio class audio chips (including on-board audio, 2ms was achieved
on Realtek ALC888/S/T). For Shared mode latency can not go lower than 20ms.
This is the most powerful WASAPI implementation which provides glitch-free
audio at around 3ms latency in Exclusive mode. Lowest possible latency for this mode is
usually - 1.4(Vista only)-3ms(Windows 7+) for HD Audio class audio chips. For the
Shared mode latency can not be lower than 20ms.
2) Poll-Driven:
Polling is another 2-nd method to operate with WASAPI. It is less efficient than Event-Driven
and provides latency at around 12-13ms. Polling must be used to overcome a system bug
under Windows Vista x64 when application is WOW64(32-bit) and Event-Driven method simply times
out (event handle is never signalled on buffer completion). Please note, such Vista bug
does not exist in Windows 7 x64.
Polling is setup by speciying 'paWinWasapiPolling' flag.
Thread priority can be boosted by specifying 'paWinWasapiBlockingThreadPriorityPro' flag.
and provides latency at around 10-13ms. Polling must be used to overcome a system bug
under Windows Vista x64 when application is WOW64(32-bit) and Event-Driven method simply
times out (event handle is never signalled on buffer completion). Please note, such WOW64 bug
does not exist in Vista x86 or Windows 7.
Polling can be setup by speciying 'paWinWasapiPolling' flag. Our WASAPI implementation detects
WOW64 bug and sets 'paWinWasapiPolling' automatically.
Thread priority:
Normally thread priority is set automatically and does not require modification. Although
if user wants some tweaking thread priority can be modified by setting 'paWinWasapiThreadPriority'
flag and specifying 'PaWasapiStreamInfo::threadPriority' with value from PaWasapiThreadPriority
enum.
Blocking Interface:
Blocking interface is implemented but due to above described Poll-Driven method can not
deliver low latency audio. Specifying too low latency in Shared mode will result in
deliver lowest possible latency. Specifying too low latency in Shared mode will result in
distorted audio although Exclusive mode adds stability.
Pa_IsFormatSupported:

View File

@ -1,5 +1,5 @@
/*
* $Id: pa_converters.c 1339 2008-02-15 07:50:33Z rossb $
* $Id: pa_converters.c 1495 2010-04-17 07:43:00Z dmitrykos $
* Portable Audio I/O Library sample conversion mechanism
*
* Based on the Open Source API proposed by Ross Bencina
@ -1073,13 +1073,13 @@ static void Int24_To_Float32(
{
#if defined(PA_LITTLE_ENDIAN)
temp = (((long)src[0]) << 8);
temp = temp | (((long)src[1]) << 16);
temp = temp | (((long)src[2]) << 24);
temp = (((PaInt32)src[0]) << 8);
temp = temp | (((PaInt32)src[1]) << 16);
temp = temp | (((PaInt32)src[2]) << 24);
#elif defined(PA_BIG_ENDIAN)
temp = (((long)src[0]) << 24);
temp = temp | (((long)src[1]) << 16);
temp = temp | (((long)src[2]) << 8);
temp = (((PaInt32)src[0]) << 24);
temp = temp | (((PaInt32)src[1]) << 16);
temp = temp | (((PaInt32)src[2]) << 8);
#endif
*dest = (float) ((double)temp * const_1_div_2147483648_);
@ -1106,13 +1106,13 @@ static void Int24_To_Int32(
{
#if defined(PA_LITTLE_ENDIAN)
temp = (((long)src[0]) << 8);
temp = temp | (((long)src[1]) << 16);
temp = temp | (((long)src[2]) << 24);
temp = (((PaInt32)src[0]) << 8);
temp = temp | (((PaInt32)src[1]) << 16);
temp = temp | (((PaInt32)src[2]) << 24);
#elif defined(PA_BIG_ENDIAN)
temp = (((long)src[0]) << 24);
temp = temp | (((long)src[1]) << 16);
temp = temp | (((long)src[2]) << 8);
temp = (((PaInt32)src[0]) << 24);
temp = temp | (((PaInt32)src[1]) << 16);
temp = temp | (((PaInt32)src[2]) << 8);
#endif
*dest = temp;
@ -1163,15 +1163,39 @@ static void Int24_To_Int16_Dither(
void *sourceBuffer, signed int sourceStride,
unsigned int count, struct PaUtilTriangularDitherGenerator *ditherGenerator )
{
(void) destinationBuffer; /* unused parameters */
(void) destinationStride; /* unused parameters */
(void) sourceBuffer; /* unused parameters */
(void) sourceStride; /* unused parameters */
(void) count; /* unused parameters */
(void) ditherGenerator; /* unused parameters */
/* IMPLEMENT ME */
#define _PA_CNV_RESCALE(__max_from,__max_to,g) ((1.0f/(float)(__max_from/2+1))*((float)((__max_to/2+1)+g)))
#ifndef PA_BIG_ENDIAN
#define _PA_INT24_TO_INT32(v) ((int)(((int)v[2] << 24)|((int)v[1] << 16)|((int)v[0] << 8)) >> 8)
#else
#define _PA_INT24_TO_INT32(v) ((int)(((int)v[0] << 24)|((int)v[1] << 16)|((int)v[2] << 8)) >> 8)
#endif
#define _PA_INT24_TO_FLOAT(v,g) ((float)(_PA_INT24_TO_INT32(v)) * _PA_CNV_RESCALE(0xffffff,0xffff,g))
unsigned char *src = (unsigned char *)sourceBuffer;
PaInt16 *dest = (PaInt16 *)destinationBuffer;
float dither, dithered;
while( count-- )
{
dither = PaUtil_GenerateFloatTriangularDither( ditherGenerator );
/* downscale 24-bit int to 16-bit int placed into 32-bit float container,
16-bit scaler is decreased by 2 to leave space for dither in order not to overflow
*/
dithered = _PA_INT24_TO_FLOAT(src, -2.0f) + dither;
#ifdef PA_USE_C99_LRINTF
*dest = lrintf(dithered-0.5f);
#else
*dest = (PaInt16) dithered;
#endif
src += sourceStride * 3;
dest += destinationStride;
}
}
/* -------------------------------------------------------------------------- */
static void Int24_To_Int8(

View File

@ -156,7 +156,7 @@
// We only need IASIOThiscallResolver at all if we are on Win32. For other
// platforms we simply bypass the IASIOThiscallResolver definition to allow us
// to be safely #include'd whatever the platform to keep client code portable
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(_WIN64)
// If microsoft compiler we can call IASIO directly so IASIOThiscallResolver
@ -276,6 +276,7 @@ extern IASIO* theAsioDriver;
"call *"#funcOffset"(%%edx)\n\t" \
:"=a"(resultName) /* Output Operands */ \
:"c"(thisPtr) /* Input Operands */ \
: "%edx" /* Clobbered Registers */ \
); \
@ -286,6 +287,7 @@ extern IASIO* theAsioDriver;
: /* Output Operands */ \
:"r"(param1), /* Input Operands */ \
"c"(thisPtr) \
: "%edx" /* Clobbered Registers */ \
); \
@ -296,20 +298,25 @@ extern IASIO* theAsioDriver;
:"=a"(resultName) /* Output Operands */ \
:"r"(param1), /* Input Operands */ \
"c"(thisPtr) \
: "%edx" /* Clobbered Registers */ \
); \
#define CALL_THISCALL_1_DOUBLE( resultName, thisPtr, funcOffset, param1 ) \
__asm__ __volatile__ ("pushl 4(%1)\n\t" \
"pushl (%1)\n\t" \
"movl (%2), %%edx\n\t" \
"call *"#funcOffset"(%%edx);\n\t" \
:"=a"(resultName) /* Output Operands */ \
:"a"(&param1), /* Input Operands */ \
/* Note: Using "r" above instead of "a" fails */ \
/* when using GCC 3.3.3, and maybe later versions*/\
"c"(thisPtr) \
); \
do { \
double param1f64 = param1; /* Cast explicitly to double */ \
double *param1f64Ptr = &param1f64; /* Make pointer to address */ \
__asm__ __volatile__ ("pushl 4(%1)\n\t" \
"pushl (%1)\n\t" \
"movl (%2), %%edx\n\t" \
"call *"#funcOffset"(%%edx);\n\t" \
: "=a"(resultName) /* Output Operands */ \
: "r"(param1f64Ptr), /* Input Operands */ \
"c"(thisPtr), \
"m"(*param1f64Ptr) /* Using address */ \
: "%edx" /* Clobbered Registers */ \
); \
} while (0); \
#define CALL_THISCALL_2( resultName, thisPtr, funcOffset, param1, param2 ) \
@ -321,6 +328,7 @@ extern IASIO* theAsioDriver;
:"r"(param2), /* Input Operands */ \
"r"(param1), \
"c"(thisPtr) \
: "%edx" /* Clobbered Registers */ \
); \
@ -337,6 +345,7 @@ extern IASIO* theAsioDriver;
"r"(param2), \
"r"(param1), \
"c"(thisPtr) \
: "%edx" /* Clobbered Registers */ \
); \
#endif

View File

@ -111,7 +111,7 @@
// We only need IASIOThiscallResolver at all if we are on Win32. For other
// platforms we simply bypass the IASIOThiscallResolver definition to allow us
// to be safely #include'd whatever the platform to keep client code portable
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) && !defined(_WIN64)
// If microsoft compiler we can call IASIO directly so IASIOThiscallResolver

File diff suppressed because it is too large Load Diff