aboutsummaryrefslogtreecommitdiff
path: root/pd/portaudio/src/hostapi/wmme
diff options
context:
space:
mode:
Diffstat (limited to 'pd/portaudio/src/hostapi/wmme')
-rw-r--r--pd/portaudio/src/hostapi/wmme/pa_win_wmme.c565
1 files changed, 444 insertions, 121 deletions
diff --git a/pd/portaudio/src/hostapi/wmme/pa_win_wmme.c b/pd/portaudio/src/hostapi/wmme/pa_win_wmme.c
index 3264ebf8..d2c13f99 100644
--- a/pd/portaudio/src/hostapi/wmme/pa_win_wmme.c
+++ b/pd/portaudio/src/hostapi/wmme/pa_win_wmme.c
@@ -1,5 +1,5 @@
/*
- * $Id: pa_win_wmme.c 1229 2007-06-15 16:11:11Z rossb $
+ * $Id: pa_win_wmme.c 1405 2009-03-08 08:10:55Z rossb $
* pa_win_wmme.c
* Implementation of PortAudio for Windows MultiMedia Extensions (WMME)
*
@@ -62,7 +62,9 @@
*/
/** @file
- @ingroup hostaip_src
+ @ingroup hostapi_src
+
+ @brief Win32 host API implementation for the Windows MultiMedia Extensions (WMME) audio API.
@todo Fix buffer catch up code, can sometimes get stuck (perhaps fixed now,
needs to be reviewed and tested.)
@@ -88,6 +90,10 @@ Non-critical stuff for the future:
@todo define UNICODE and _UNICODE in the project settings and see what breaks
+ @todo refactor conversion of MMSYSTEM errors into PA arrors into a single function.
+
+ @todo cleanup WAVEFORMATEXTENSIBLE retry in InitializeWaveHandles to not use a for loop
+
*/
/*
@@ -133,6 +139,24 @@ Non-critical stuff for the future:
#include "pa_debugprint.h"
#include "pa_win_wmme.h"
+#include "pa_win_waveformat.h"
+
+#ifdef PAWIN_USE_WDMKS_DEVICE_INFO
+#include "pa_win_wdmks_utils.h"
+#ifndef DRV_QUERYDEVICEINTERFACE
+#define DRV_QUERYDEVICEINTERFACE (DRV_RESERVED + 12)
+#endif
+#ifndef DRV_QUERYDEVICEINTERFACESIZE
+#define DRV_QUERYDEVICEINTERFACESIZE (DRV_RESERVED + 13)
+#endif
+#endif /* PAWIN_USE_WDMKS_DEVICE_INFO */
+
+/* use CreateThread for CYGWIN, _beginthreadex for all others */
+#ifndef __CYGWIN__
+#define CREATE_THREAD (HANDLE)_beginthreadex( 0, 0, ProcessingThreadProc, stream, 0, &stream->processingThreadId )
+#else
+#define CREATE_THREAD CreateThread( 0, 0, ProcessingThreadProc, stream, 0, &stream->processingThreadId )
+#endif
#if (defined(UNDER_CE))
#pragma comment(lib, "Coredll.lib")
@@ -374,6 +398,8 @@ typedef struct
{
PaDeviceInfo inheritedDeviceInfo;
DWORD dwFormats; /**<< standard formats bitmask from the WAVEINCAPS and WAVEOUTCAPS structures */
+ char deviceInputChannelCountIsKnown; /**<< if the system returns 0xFFFF then we don't really know the number of supported channels (1=>known, 0=>unknown)*/
+ char deviceOutputChannelCountIsKnown; /**<< if the system returns 0xFFFF then we don't really know the number of supported channels (1=>known, 0=>unknown)*/
}
PaWinMmeDeviceInfo;
@@ -445,6 +471,21 @@ static UINT LocalDeviceIndexToWinMmeDeviceId( PaWinMmeHostApiRepresentation *hos
}
+static int SampleFormatAndWinWmmeSpecificFlagsToLinearWaveFormatTag( PaSampleFormat sampleFormat, unsigned long winMmeSpecificFlags )
+{
+ int waveFormatTag = 0;
+
+ if( winMmeSpecificFlags & paWinMmeWaveFormatDolbyAc3Spdif )
+ waveFormatTag = PAWIN_WAVE_FORMAT_DOLBY_AC3_SPDIF;
+ else if( winMmeSpecificFlags & paWinMmeWaveFormatWmaSpdif )
+ waveFormatTag = PAWIN_WAVE_FORMAT_WMA_SPDIF;
+ else
+ waveFormatTag = PaWin_SampleFormatToLinearWaveFormatTag( sampleFormat );
+
+ return waveFormatTag;
+}
+
+
static PaError QueryInputWaveFormatEx( int deviceId, WAVEFORMATEX *waveFormatEx )
{
MMRESULT mmresult;
@@ -499,41 +540,57 @@ static PaError QueryOutputWaveFormatEx( int deviceId, WAVEFORMATEX *waveFormatEx
static PaError QueryFormatSupported( PaDeviceInfo *deviceInfo,
PaError (*waveFormatExQueryFunction)(int, WAVEFORMATEX*),
- int winMmeDeviceId, int channels, double sampleRate )
+ int winMmeDeviceId, int channels, double sampleRate, unsigned long winMmeSpecificFlags )
{
PaWinMmeDeviceInfo *winMmeDeviceInfo = (PaWinMmeDeviceInfo*)deviceInfo;
- WAVEFORMATEX waveFormatEx;
+ PaWinWaveFormat waveFormat;
+ PaSampleFormat sampleFormat;
+ int waveFormatTag;
- if( sampleRate == 11025.0
- && ( (channels == 1 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_1M16))
- || (channels == 2 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_1S16)) ) ){
+ /* @todo at the moment we only query with 16 bit sample format and directout speaker config*/
- return paNoError;
- }
+ sampleFormat = paInt16;
+ waveFormatTag = SampleFormatAndWinWmmeSpecificFlagsToLinearWaveFormatTag( sampleFormat, winMmeSpecificFlags );
- if( sampleRate == 22050.0
- && ( (channels == 1 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_2M16))
- || (channels == 2 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_2S16)) ) ){
+ if( waveFormatTag == PaWin_SampleFormatToLinearWaveFormatTag( paInt16 ) ){
+
+ /* attempt bypass querying the device for linear formats */
- return paNoError;
+ if( sampleRate == 11025.0
+ && ( (channels == 1 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_1M16))
+ || (channels == 2 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_1S16)) ) ){
+
+ return paNoError;
+ }
+
+ if( sampleRate == 22050.0
+ && ( (channels == 1 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_2M16))
+ || (channels == 2 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_2S16)) ) ){
+
+ return paNoError;
+ }
+
+ if( sampleRate == 44100.0
+ && ( (channels == 1 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_4M16))
+ || (channels == 2 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_4S16)) ) ){
+
+ return paNoError;
+ }
}
- if( sampleRate == 44100.0
- && ( (channels == 1 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_4M16))
- || (channels == 2 && (winMmeDeviceInfo->dwFormats & WAVE_FORMAT_4S16)) ) ){
+ /* first, attempt to query the device using WAVEFORMATEXTENSIBLE,
+ if this fails we fall back to WAVEFORMATEX */
+
+ PaWin_InitializeWaveFormatExtensible( &waveFormat, channels, sampleFormat, waveFormatTag,
+ sampleRate, PAWIN_SPEAKER_DIRECTOUT );
+
+ if( waveFormatExQueryFunction( winMmeDeviceId, (WAVEFORMATEX*)&waveFormat ) == paNoError )
return paNoError;
- }
- waveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
- waveFormatEx.nChannels = (WORD)channels;
- waveFormatEx.nSamplesPerSec = (DWORD)sampleRate;
- waveFormatEx.nAvgBytesPerSec = waveFormatEx.nSamplesPerSec * channels * sizeof(short);
- waveFormatEx.nBlockAlign = (WORD)(channels * sizeof(short));
- waveFormatEx.wBitsPerSample = 16;
- waveFormatEx.cbSize = 0;
+ PaWin_InitializeWaveFormatEx( &waveFormat, channels, sampleFormat, waveFormatTag, sampleRate );
- return waveFormatExQueryFunction( winMmeDeviceId, &waveFormatEx );
+ return waveFormatExQueryFunction( winMmeDeviceId, (WAVEFORMATEX*)&waveFormat );
}
@@ -553,7 +610,7 @@ static void DetectDefaultSampleRate( PaWinMmeDeviceInfo *winMmeDeviceInfo, int w
for( i=0; i < PA_DEFAULTSAMPLERATESEARCHORDER_COUNT_; ++i )
{
double sampleRate = defaultSampleRateSearchOrder_[ i ];
- PaError paerror = QueryFormatSupported( deviceInfo, waveFormatExQueryFunction, winMmeDeviceId, maxChannels, sampleRate );
+ PaError paerror = QueryFormatSupported( deviceInfo, waveFormatExQueryFunction, winMmeDeviceId, maxChannels, sampleRate, 0 );
if( paerror == paNoError )
{
deviceInfo->defaultSampleRate = sampleRate;
@@ -563,6 +620,40 @@ static void DetectDefaultSampleRate( PaWinMmeDeviceInfo *winMmeDeviceInfo, int w
}
+#ifdef PAWIN_USE_WDMKS_DEVICE_INFO
+static int QueryWaveInKSFilterMaxChannels( int waveInDeviceId, int *maxChannels )
+{
+ void *devicePath;
+ DWORD devicePathSize;
+ int result = 0;
+
+ if( waveInMessage((HWAVEIN)waveInDeviceId, DRV_QUERYDEVICEINTERFACESIZE,
+ (DWORD_PTR)&devicePathSize, 0 ) != MMSYSERR_NOERROR )
+ return 0;
+
+ devicePath = PaUtil_AllocateMemory( devicePathSize );
+ if( !devicePath )
+ return 0;
+
+ /* apparently DRV_QUERYDEVICEINTERFACE returns a unicode interface path, although this is undocumented */
+ if( waveInMessage((HWAVEIN)waveInDeviceId, DRV_QUERYDEVICEINTERFACE,
+ (DWORD_PTR)devicePath, devicePathSize ) == MMSYSERR_NOERROR )
+ {
+ int count = PaWin_WDMKS_QueryFilterMaximumChannelCount( devicePath, /* isInput= */ 1 );
+ if( count > 0 )
+ {
+ *maxChannels = count;
+ result = 1;
+ }
+ }
+
+ PaUtil_FreeMemory( devicePath );
+
+ return result;
+}
+#endif /* PAWIN_USE_WDMKS_DEVICE_INFO */
+
+
static PaError InitializeInputDeviceInfo( PaWinMmeHostApiRepresentation *winMmeHostApi,
PaWinMmeDeviceInfo *winMmeDeviceInfo, UINT winMmeInputDeviceId, int *success )
{
@@ -616,17 +707,30 @@ static PaError InitializeInputDeviceInfo( PaWinMmeHostApiRepresentation *winMmeH
}
deviceInfo->name = deviceName;
- deviceInfo->maxInputChannels = wic.wChannels;
- /* Sometimes a device can return a rediculously large number of channels.
- * This happened with an SBLive card on a Windows ME box.
- * If that happens, then force it to 2 channels. PLB20010413
+ if( wic.wChannels == 0xFFFF || wic.wChannels < 1 || wic.wChannels > 255 ){
+ /* For Windows versions using WDM (possibly Windows 98 ME and later)
+ * the kernel mixer sits between the application and the driver. As a result,
+ * wave*GetDevCaps often kernel mixer channel counts, which are unlimited.
+ * When this happens we assume the device is stereo and set a flag
+ * so that other channel counts can be tried with OpenStream -- i.e. when
+ * device*ChannelCountIsKnown is false, OpenStream will try whatever
+ * channel count you supply.
+ * see also InitializeOutputDeviceInfo() below.
*/
- if( (deviceInfo->maxInputChannels < 1) || (deviceInfo->maxInputChannels > 256) )
- {
- PA_DEBUG(("Pa_GetDeviceInfo: Num input channels reported as %d! Changed to 2.\n", deviceInfo->maxInputChannels ));
+
+ PA_DEBUG(("Pa_GetDeviceInfo: Num input channels reported as %d! Changed to 2.\n", wic.wChannels ));
deviceInfo->maxInputChannels = 2;
+ winMmeDeviceInfo->deviceInputChannelCountIsKnown = 0;
+ }else{
+ deviceInfo->maxInputChannels = wic.wChannels;
+ winMmeDeviceInfo->deviceInputChannelCountIsKnown = 1;
}
+#ifdef PAWIN_USE_WDMKS_DEVICE_INFO
+ winMmeDeviceInfo->deviceInputChannelCountIsKnown =
+ QueryWaveInKSFilterMaxChannels( winMmeInputDeviceId, &deviceInfo->maxInputChannels );
+#endif /* PAWIN_USE_WDMKS_DEVICE_INFO */
+
winMmeDeviceInfo->dwFormats = wic.dwFormats;
DetectDefaultSampleRate( winMmeDeviceInfo, winMmeInputDeviceId,
@@ -639,6 +743,40 @@ error:
}
+#ifdef PAWIN_USE_WDMKS_DEVICE_INFO
+static int QueryWaveOutKSFilterMaxChannels( int waveOutDeviceId, int *maxChannels )
+{
+ void *devicePath;
+ DWORD devicePathSize;
+ int result = 0;
+
+ if( waveOutMessage((HWAVEOUT)waveOutDeviceId, DRV_QUERYDEVICEINTERFACESIZE,
+ (DWORD_PTR)&devicePathSize, 0 ) != MMSYSERR_NOERROR )
+ return 0;
+
+ devicePath = PaUtil_AllocateMemory( devicePathSize );
+ if( !devicePath )
+ return 0;
+
+ /* apparently DRV_QUERYDEVICEINTERFACE returns a unicode interface path, although this is undocumented */
+ if( waveOutMessage((HWAVEOUT)waveOutDeviceId, DRV_QUERYDEVICEINTERFACE,
+ (DWORD_PTR)devicePath, devicePathSize ) == MMSYSERR_NOERROR )
+ {
+ int count = PaWin_WDMKS_QueryFilterMaximumChannelCount( devicePath, /* isInput= */ 0 );
+ if( count > 0 )
+ {
+ *maxChannels = count;
+ result = 1;
+ }
+ }
+
+ PaUtil_FreeMemory( devicePath );
+
+ return result;
+}
+#endif /* PAWIN_USE_WDMKS_DEVICE_INFO */
+
+
static PaError InitializeOutputDeviceInfo( PaWinMmeHostApiRepresentation *winMmeHostApi,
PaWinMmeDeviceInfo *winMmeDeviceInfo, UINT winMmeOutputDeviceId, int *success )
{
@@ -647,7 +785,7 @@ static PaError InitializeOutputDeviceInfo( PaWinMmeHostApiRepresentation *winMme
MMRESULT mmresult;
WAVEOUTCAPS woc;
PaDeviceInfo *deviceInfo = &winMmeDeviceInfo->inheritedDeviceInfo;
-
+
*success = 0;
mmresult = waveOutGetDevCaps( winMmeOutputDeviceId, &woc, sizeof( WAVEOUTCAPS ) );
@@ -692,17 +830,30 @@ static PaError InitializeOutputDeviceInfo( PaWinMmeHostApiRepresentation *winMme
}
deviceInfo->name = deviceName;
- deviceInfo->maxOutputChannels = woc.wChannels;
- /* Sometimes a device can return a rediculously large number of channels.
- * This happened with an SBLive card on a Windows ME box.
- * It also happens on Win XP!
+ if( woc.wChannels == 0xFFFF || woc.wChannels < 1 || woc.wChannels > 255 ){
+ /* For Windows versions using WDM (possibly Windows 98 ME and later)
+ * the kernel mixer sits between the application and the driver. As a result,
+ * wave*GetDevCaps often kernel mixer channel counts, which are unlimited.
+ * When this happens we assume the device is stereo and set a flag
+ * so that other channel counts can be tried with OpenStream -- i.e. when
+ * device*ChannelCountIsKnown is false, OpenStream will try whatever
+ * channel count you supply.
+ * see also InitializeInputDeviceInfo() above.
*/
- if( (deviceInfo->maxOutputChannels < 1) || (deviceInfo->maxOutputChannels > 256) )
- {
- PA_DEBUG(("Pa_GetDeviceInfo: Num output channels reported as %d! Changed to 2.\n", deviceInfo->maxOutputChannels ));
+
+ PA_DEBUG(("Pa_GetDeviceInfo: Num output channels reported as %d! Changed to 2.\n", woc.wChannels ));
deviceInfo->maxOutputChannels = 2;
+ winMmeDeviceInfo->deviceOutputChannelCountIsKnown = 0;
+ }else{
+ deviceInfo->maxOutputChannels = woc.wChannels;
+ winMmeDeviceInfo->deviceOutputChannelCountIsKnown = 1;
}
+#ifdef PAWIN_USE_WDMKS_DEVICE_INFO
+ winMmeDeviceInfo->deviceOutputChannelCountIsKnown =
+ QueryWaveOutKSFilterMaxChannels( winMmeOutputDeviceId, &deviceInfo->maxOutputChannels );
+#endif /* PAWIN_USE_WDMKS_DEVICE_INFO */
+
winMmeDeviceInfo->dwFormats = woc.dwFormats;
DetectDefaultSampleRate( winMmeDeviceInfo, winMmeOutputDeviceId,
@@ -748,6 +899,8 @@ PaError PaWinMme_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
PaWinMmeDeviceInfo *deviceInfoArray;
int deviceInfoInitializationSucceeded;
PaTime defaultLowLatency, defaultHighLatency;
+ DWORD waveInPreferredDevice, waveOutPreferredDevice;
+ DWORD preferredDeviceStatusFlags;
winMmeHostApi = (PaWinMmeHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaWinMmeHostApiRepresentation) );
if( !winMmeHostApi )
@@ -779,6 +932,19 @@ PaError PaWinMme_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
winMmeHostApi->inputDeviceCount = 0;
winMmeHostApi->outputDeviceCount = 0;
+#if !defined(DRVM_MAPPER_PREFERRED_GET)
+/* DRVM_MAPPER_PREFERRED_GET is defined in mmddk.h but we avoid a dependency on the DDK by defining it here */
+#define DRVM_MAPPER_PREFERRED_GET (0x2000+21)
+#endif
+
+ /* the following calls assume that if wave*Message fails the preferred device parameter won't be modified */
+ preferredDeviceStatusFlags = 0;
+ waveInPreferredDevice = -1;
+ waveInMessage( (HWAVEIN)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD)&waveInPreferredDevice, (DWORD)&preferredDeviceStatusFlags );
+
+ preferredDeviceStatusFlags = 0;
+ waveOutPreferredDevice = -1;
+ waveOutMessage( (HWAVEOUT)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD)&waveOutPreferredDevice, (DWORD)&preferredDeviceStatusFlags );
maximumPossibleDeviceCount = 0;
@@ -830,7 +996,9 @@ PaError PaWinMme_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
deviceInfo->hostApi = hostApiIndex;
deviceInfo->maxInputChannels = 0;
+ wmmeDeviceInfo->deviceInputChannelCountIsKnown = 1;
deviceInfo->maxOutputChannels = 0;
+ wmmeDeviceInfo->deviceOutputChannelCountIsKnown = 1;
deviceInfo->defaultLowInputLatency = defaultLowLatency;
deviceInfo->defaultLowOutputLatency = defaultLowLatency;
@@ -843,8 +1011,14 @@ PaError PaWinMme_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
goto error;
if( deviceInfoInitializationSucceeded ){
- if( (*hostApi)->info.defaultInputDevice == paNoDevice )
+ if( (*hostApi)->info.defaultInputDevice == paNoDevice ){
+ /* if there is currently no default device, use the first one available */
+ (*hostApi)->info.defaultInputDevice = (*hostApi)->info.deviceCount;
+
+ }else if( winMmeDeviceId == waveInPreferredDevice ){
+ /* set the default device to the system preferred device */
(*hostApi)->info.defaultInputDevice = (*hostApi)->info.deviceCount;
+ }
winMmeHostApi->winMmeDeviceIds[ (*hostApi)->info.deviceCount ] = winMmeDeviceId;
(*hostApi)->deviceInfos[ (*hostApi)->info.deviceCount ] = deviceInfo;
@@ -865,7 +1039,9 @@ PaError PaWinMme_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
deviceInfo->hostApi = hostApiIndex;
deviceInfo->maxInputChannels = 0;
+ wmmeDeviceInfo->deviceInputChannelCountIsKnown = 1;
deviceInfo->maxOutputChannels = 0;
+ wmmeDeviceInfo->deviceOutputChannelCountIsKnown = 1;
deviceInfo->defaultLowInputLatency = defaultLowLatency;
deviceInfo->defaultLowOutputLatency = defaultLowLatency;
@@ -878,8 +1054,14 @@ PaError PaWinMme_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
goto error;
if( deviceInfoInitializationSucceeded ){
- if( (*hostApi)->info.defaultOutputDevice == paNoDevice )
+ if( (*hostApi)->info.defaultOutputDevice == paNoDevice ){
+ /* if there is currently no default device, use the first one available */
+ (*hostApi)->info.defaultOutputDevice = (*hostApi)->info.deviceCount;
+
+ }else if( winMmeDeviceId == waveOutPreferredDevice ){
+ /* set the default device to the system preferred device */
(*hostApi)->info.defaultOutputDevice = (*hostApi)->info.deviceCount;
+ }
winMmeHostApi->winMmeDeviceIds[ (*hostApi)->info.deviceCount ] = winMmeDeviceId;
(*hostApi)->deviceInfos[ (*hostApi)->info.deviceCount ] = deviceInfo;
@@ -891,7 +1073,6 @@ PaError PaWinMme_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiInd
}
}
-
InitializeDefaultDeviceIdsFromEnv( winMmeHostApi );
(*hostApi)->Terminate = Terminate;
@@ -941,6 +1122,34 @@ static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
}
+static PaError IsInputChannelCountSupported( PaWinMmeDeviceInfo* deviceInfo, int channelCount )
+{
+ PaError result = paNoError;
+
+ if( channelCount > 0
+ && deviceInfo->deviceInputChannelCountIsKnown
+ && channelCount > deviceInfo->inheritedDeviceInfo.maxInputChannels ){
+
+ result = paInvalidChannelCount;
+ }
+
+ return result;
+}
+
+static PaError IsOutputChannelCountSupported( PaWinMmeDeviceInfo* deviceInfo, int channelCount )
+{
+ PaError result = paNoError;
+
+ if( channelCount > 0
+ && deviceInfo->deviceOutputChannelCountIsKnown
+ && channelCount > deviceInfo->inheritedDeviceInfo.maxOutputChannels ){
+
+ result = paInvalidChannelCount;
+ }
+
+ return result;
+}
+
static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
const PaStreamParameters *inputParameters,
const PaStreamParameters *outputParameters,
@@ -985,13 +1194,19 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
inputDeviceInfo = hostApi->deviceInfos[ inputStreamInfo->devices[i].device ];
/* check that input device can support inputChannelCount */
- if( inputStreamInfo->devices[i].channelCount <= 0
- || inputStreamInfo->devices[i].channelCount > inputDeviceInfo->maxInputChannels )
+ if( inputStreamInfo->devices[i].channelCount < 1 )
return paInvalidChannelCount;
+ paerror = IsInputChannelCountSupported( (PaWinMmeDeviceInfo*)inputDeviceInfo,
+ inputStreamInfo->devices[i].channelCount );
+ if( paerror != paNoError )
+ return paerror;
+
/* test for valid sample rate, see comment above */
winMmeInputDeviceId = LocalDeviceIndexToWinMmeDeviceId( winMmeHostApi, inputStreamInfo->devices[i].device );
- paerror = QueryFormatSupported( inputDeviceInfo, QueryInputWaveFormatEx, winMmeInputDeviceId, inputStreamInfo->devices[i].channelCount, sampleRate );
+ paerror = QueryFormatSupported( inputDeviceInfo, QueryInputWaveFormatEx,
+ winMmeInputDeviceId, inputStreamInfo->devices[i].channelCount, sampleRate,
+ ((inputStreamInfo) ? inputStreamInfo->flags : 0) );
if( paerror != paNoError )
return paInvalidSampleRate;
}
@@ -1007,12 +1222,15 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
inputDeviceInfo = hostApi->deviceInfos[ inputParameters->device ];
/* check that input device can support inputChannelCount */
- if( inputChannelCount > inputDeviceInfo->maxInputChannels )
- return paInvalidChannelCount;
+ paerror = IsInputChannelCountSupported( (PaWinMmeDeviceInfo*)inputDeviceInfo, inputChannelCount );
+ if( paerror != paNoError )
+ return paerror;
/* test for valid sample rate, see comment above */
winMmeInputDeviceId = LocalDeviceIndexToWinMmeDeviceId( winMmeHostApi, inputParameters->device );
- paerror = QueryFormatSupported( inputDeviceInfo, QueryInputWaveFormatEx, winMmeInputDeviceId, inputChannelCount, sampleRate );
+ paerror = QueryFormatSupported( inputDeviceInfo, QueryInputWaveFormatEx,
+ winMmeInputDeviceId, inputChannelCount, sampleRate,
+ ((inputStreamInfo) ? inputStreamInfo->flags : 0) );
if( paerror != paNoError )
return paInvalidSampleRate;
}
@@ -1040,13 +1258,19 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
outputDeviceInfo = hostApi->deviceInfos[ outputStreamInfo->devices[i].device ];
/* check that output device can support outputChannelCount */
- if( outputStreamInfo->devices[i].channelCount <= 0
- || outputStreamInfo->devices[i].channelCount > outputDeviceInfo->maxOutputChannels )
+ if( outputStreamInfo->devices[i].channelCount < 1 )
return paInvalidChannelCount;
+ paerror = IsOutputChannelCountSupported( (PaWinMmeDeviceInfo*)outputDeviceInfo,
+ outputStreamInfo->devices[i].channelCount );
+ if( paerror != paNoError )
+ return paerror;
+
/* test for valid sample rate, see comment above */
winMmeOutputDeviceId = LocalDeviceIndexToWinMmeDeviceId( winMmeHostApi, outputStreamInfo->devices[i].device );
- paerror = QueryFormatSupported( outputDeviceInfo, QueryOutputWaveFormatEx, winMmeOutputDeviceId, outputStreamInfo->devices[i].channelCount, sampleRate );
+ paerror = QueryFormatSupported( outputDeviceInfo, QueryOutputWaveFormatEx,
+ winMmeOutputDeviceId, outputStreamInfo->devices[i].channelCount, sampleRate,
+ ((outputStreamInfo) ? outputStreamInfo->flags : 0) );
if( paerror != paNoError )
return paInvalidSampleRate;
}
@@ -1062,12 +1286,15 @@ static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
outputDeviceInfo = hostApi->deviceInfos[ outputParameters->device ];
/* check that output device can support outputChannelCount */
- if( outputChannelCount > outputDeviceInfo->maxOutputChannels )
- return paInvalidChannelCount;
+ paerror = IsOutputChannelCountSupported( (PaWinMmeDeviceInfo*)outputDeviceInfo, outputChannelCount );
+ if( paerror != paNoError )
+ return paerror;
/* test for valid sample rate, see comment above */
winMmeOutputDeviceId = LocalDeviceIndexToWinMmeDeviceId( winMmeHostApi, outputParameters->device );
- paerror = QueryFormatSupported( outputDeviceInfo, QueryOutputWaveFormatEx, winMmeOutputDeviceId, outputChannelCount, sampleRate );
+ paerror = QueryFormatSupported( outputDeviceInfo, QueryOutputWaveFormatEx,
+ winMmeOutputDeviceId, outputChannelCount, sampleRate,
+ ((outputStreamInfo) ? outputStreamInfo->flags : 0) );
if( paerror != paNoError )
return paInvalidSampleRate;
}
@@ -1491,9 +1718,10 @@ typedef struct
static void InitializeSingleDirectionHandlesAndBuffers( PaWinMmeSingleDirectionHandlesAndBuffers *handlesAndBuffers );
static PaError InitializeWaveHandles( PaWinMmeHostApiRepresentation *winMmeHostApi,
PaWinMmeSingleDirectionHandlesAndBuffers *handlesAndBuffers,
+ unsigned long winMmeSpecificFlags,
unsigned long bytesPerHostSample,
double sampleRate, PaWinMmeDeviceAndChannelCount *devices,
- unsigned int deviceCount, int isInput );
+ unsigned int deviceCount, PaWinWaveFormatChannelMask channelMask, int isInput );
static PaError TerminateWaveHandles( PaWinMmeSingleDirectionHandlesAndBuffers *handlesAndBuffers, int isInput, int currentlyProcessingAnError );
static PaError InitializeWaveHeaders( PaWinMmeSingleDirectionHandlesAndBuffers *handlesAndBuffers,
unsigned long hostBufferCount,
@@ -1515,15 +1743,16 @@ static void InitializeSingleDirectionHandlesAndBuffers( PaWinMmeSingleDirectionH
static PaError InitializeWaveHandles( PaWinMmeHostApiRepresentation *winMmeHostApi,
PaWinMmeSingleDirectionHandlesAndBuffers *handlesAndBuffers,
+ unsigned long winMmeSpecificFlags,
unsigned long bytesPerHostSample,
double sampleRate, PaWinMmeDeviceAndChannelCount *devices,
- unsigned int deviceCount, int isInput )
+ unsigned int deviceCount, PaWinWaveFormatChannelMask channelMask, int isInput )
{
PaError result;
MMRESULT mmresult;
- unsigned long bytesPerFrame;
- WAVEFORMATEX wfx;
- signed int i;
+ signed int i, j;
+ PaSampleFormat sampleFormat;
+ int waveFormatTag;
/* for error cleanup we expect that InitializeSingleDirectionHandlesAndBuffers()
has already been called to zero some fields */
@@ -1551,64 +1780,98 @@ static PaError InitializeWaveHandles( PaWinMmeHostApiRepresentation *winMmeHostA
((HWAVEOUT*)handlesAndBuffers->waveHandles)[i] = 0;
}
- wfx.wFormatTag = WAVE_FORMAT_PCM;
- wfx.nSamplesPerSec = (DWORD) sampleRate;
- wfx.cbSize = 0;
-
+ /* @todo at the moment we only use 16 bit sample format */
+ sampleFormat = paInt16;
+ waveFormatTag = SampleFormatAndWinWmmeSpecificFlagsToLinearWaveFormatTag( sampleFormat, winMmeSpecificFlags );
+
for( i = 0; i < (signed int)deviceCount; ++i )
{
- UINT winMmeDeviceId;
+ PaWinWaveFormat waveFormat;
+ UINT winMmeDeviceId = LocalDeviceIndexToWinMmeDeviceId( winMmeHostApi, devices[i].device );
+
+ /* @todo: consider providing a flag or #define to not try waveformat extensible
+ this could just initialize j to 1 the first time round. */
- winMmeDeviceId = LocalDeviceIndexToWinMmeDeviceId( winMmeHostApi, devices[i].device );
- wfx.nChannels = (WORD)devices[i].channelCount;
+ for( j = 0; j < 2; ++j )
+ {
+ if( j == 0 )
+ {
+ /* first, attempt to open the device using WAVEFORMATEXTENSIBLE,
+ if this fails we fall back to WAVEFORMATEX */
- bytesPerFrame = wfx.nChannels * bytesPerHostSample;
+ PaWin_InitializeWaveFormatExtensible( &waveFormat, devices[i].channelCount,
+ sampleFormat, waveFormatTag, sampleRate, channelMask );
- wfx.nAvgBytesPerSec = (DWORD)(bytesPerFrame * sampleRate);
- wfx.nBlockAlign = (WORD)bytesPerFrame;
- wfx.wBitsPerSample = (WORD)((bytesPerFrame/wfx.nChannels) * 8);
+ }
+ else
+ {
+ /* retry with WAVEFORMATEX */
- /* REVIEW: consider not firing an event for input when a full duplex
- stream is being used. this would probably depend on the
- neverDropInput flag. */
+ PaWin_InitializeWaveFormatEx( &waveFormat, devices[i].channelCount,
+ sampleFormat, waveFormatTag, sampleRate );
+ }
- if( isInput )
- mmresult = waveInOpen( &((HWAVEIN*)handlesAndBuffers->waveHandles)[i], winMmeDeviceId, &wfx,
+ /* REVIEW: consider not firing an event for input when a full duplex
+ stream is being used. this would probably depend on the
+ neverDropInput flag. */
+
+ if( isInput )
+ {
+ mmresult = waveInOpen( &((HWAVEIN*)handlesAndBuffers->waveHandles)[i], winMmeDeviceId,
+ (WAVEFORMATEX*)&waveFormat,
(DWORD_PTR)handlesAndBuffers->bufferEvent, (DWORD_PTR)0, CALLBACK_EVENT );
- else
- mmresult = waveOutOpen( &((HWAVEOUT*)handlesAndBuffers->waveHandles)[i], winMmeDeviceId, &wfx,
+ }
+ else
+ {
+ mmresult = waveOutOpen( &((HWAVEOUT*)handlesAndBuffers->waveHandles)[i], winMmeDeviceId,
+ (WAVEFORMATEX*)&waveFormat,
(DWORD_PTR)handlesAndBuffers->bufferEvent, (DWORD_PTR)0, CALLBACK_EVENT );
+ }
- if( mmresult != MMSYSERR_NOERROR )
- {
- switch( mmresult )
+ if( mmresult == MMSYSERR_NOERROR )
{
- case MMSYSERR_ALLOCATED: /* Specified resource is already allocated. */
- result = paDeviceUnavailable;
- break;
- case MMSYSERR_NODRIVER: /* No device driver is present. */
- result = paDeviceUnavailable;
- break;
- case MMSYSERR_NOMEM: /* Unable to allocate or lock memory. */
- result = paInsufficientMemory;
- break;
+ break; /* success */
+ }
+ else if( j == 0 )
+ {
+ continue; /* try again with WAVEFORMATEX */
+ }
+ else
+ {
+ switch( mmresult )
+ {
+ case MMSYSERR_ALLOCATED: /* Specified resource is already allocated. */
+ result = paDeviceUnavailable;
+ break;
+ case MMSYSERR_NODRIVER: /* No device driver is present. */
+ result = paDeviceUnavailable;
+ break;
+ case MMSYSERR_NOMEM: /* Unable to allocate or lock memory. */
+ result = paInsufficientMemory;
+ break;
- case MMSYSERR_BADDEVICEID: /* Specified device identifier is out of range. */
- /* falls through */
- case WAVERR_BADFORMAT: /* Attempted to open with an unsupported waveform-audio format. */
- /* falls through */
- default:
- result = paUnanticipatedHostError;
- if( isInput )
- {
- PA_MME_SET_LAST_WAVEIN_ERROR( mmresult );
- }
- else
- {
- PA_MME_SET_LAST_WAVEOUT_ERROR( mmresult );
- }
+ case MMSYSERR_BADDEVICEID: /* Specified device identifier is out of range. */
+ /* falls through */
+
+ case WAVERR_BADFORMAT: /* Attempted to open with an unsupported waveform-audio format. */
+ /* This can also occur if we try to open the device with an unsupported
+ * number of channels. This is attempted when device*ChannelCountIsKnown is
+ * set to 0.
+ */
+ /* falls through */
+ default:
+ result = paUnanticipatedHostError;
+ if( isInput )
+ {
+ PA_MME_SET_LAST_WAVEIN_ERROR( mmresult );
+ }
+ else
+ {
+ PA_MME_SET_LAST_WAVEOUT_ERROR( mmresult );
+ }
+ }
+ goto error;
}
- goto error;
}
}
@@ -1850,6 +2113,7 @@ struct PaWinMmeStream
static PaError ValidateWinMmeSpecificStreamInfo(
const PaStreamParameters *streamParameters,
const PaWinMmeStreamInfo *streamInfo,
+ unsigned long *winMmeSpecificFlags,
char *throttleProcessingThreadOnOverload,
unsigned long *deviceCount )
{
@@ -1861,6 +2125,8 @@ static PaError ValidateWinMmeSpecificStreamInfo(
return paIncompatibleHostApiSpecificStreamInfo;
}
+ *winMmeSpecificFlags = streamInfo->flags;
+
if( streamInfo->flags & paWinMmeDontThrottleOverloadedProcessingThread )
*throttleProcessingThreadOnOverload = 0;
@@ -1926,12 +2192,20 @@ static PaError ValidateInputChannelCounts(
unsigned long deviceCount )
{
unsigned int i;
+ PaWinMmeDeviceInfo *inputDeviceInfo;
+ PaError paerror;
for( i=0; i < deviceCount; ++i )
{
- if( devices[i].channelCount < 1 || devices[i].channelCount
- > hostApi->deviceInfos[ devices[i].device ]->maxInputChannels )
+ if( devices[i].channelCount < 1 )
return paInvalidChannelCount;
+
+ inputDeviceInfo =
+ (PaWinMmeDeviceInfo*)hostApi->deviceInfos[ devices[i].device ];
+
+ paerror = IsInputChannelCountSupported( inputDeviceInfo, devices[i].channelCount );
+ if( paerror != paNoError )
+ return paerror;
}
return paNoError;
@@ -1943,12 +2217,20 @@ static PaError ValidateOutputChannelCounts(
unsigned long deviceCount )
{
unsigned int i;
+ PaWinMmeDeviceInfo *outputDeviceInfo;
+ PaError paerror;
for( i=0; i < deviceCount; ++i )
{
- if( devices[i].channelCount < 1 || devices[i].channelCount
- > hostApi->deviceInfos[ devices[i].device ]->maxOutputChannels )
+ if( devices[i].channelCount < 1 )
return paInvalidChannelCount;
+
+ outputDeviceInfo =
+ (PaWinMmeDeviceInfo*)hostApi->deviceInfos[ devices[i].device ];
+
+ paerror = IsOutputChannelCountSupported( outputDeviceInfo, devices[i].channelCount );
+ if( paerror != paNoError )
+ return paerror;
}
return paNoError;
@@ -1981,14 +2263,17 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
PaSampleFormat inputSampleFormat, outputSampleFormat;
double suggestedInputLatency, suggestedOutputLatency;
PaWinMmeStreamInfo *inputStreamInfo, *outputStreamInfo;
+ PaWinWaveFormatChannelMask inputChannelMask, outputChannelMask;
unsigned long framesPerHostInputBuffer;
unsigned long hostInputBufferCount;
unsigned long framesPerHostOutputBuffer;
unsigned long hostOutputBufferCount;
unsigned long framesPerBufferProcessorCall;
PaWinMmeDeviceAndChannelCount *inputDevices = 0; /* contains all devices and channel counts as local host api ids, even when PaWinMmeUseMultipleDevices is not used */
+ unsigned long winMmeSpecificInputFlags = 0;
unsigned long inputDeviceCount = 0;
PaWinMmeDeviceAndChannelCount *outputDevices = 0;
+ unsigned long winMmeSpecificOutputFlags = 0;
unsigned long outputDeviceCount = 0; /* contains all devices and channel counts as local host api ids, even when PaWinMmeUseMultipleDevices is not used */
char throttleProcessingThreadOnOverload = 1;
@@ -2004,6 +2289,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
/* validate input hostApiSpecificStreamInfo */
inputStreamInfo = (PaWinMmeStreamInfo*)inputParameters->hostApiSpecificStreamInfo;
result = ValidateWinMmeSpecificStreamInfo( inputParameters, inputStreamInfo,
+ &winMmeSpecificInputFlags,
&throttleProcessingThreadOnOverload,
&inputDeviceCount );
if( result != paNoError ) return result;
@@ -2019,6 +2305,18 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
hostInputSampleFormat =
PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, inputSampleFormat );
+
+ if( inputDeviceCount != 1 ){
+ /* always use direct speakers when using multi-device multichannel mode */
+ inputChannelMask = PAWIN_SPEAKER_DIRECTOUT;
+ }
+ else
+ {
+ if( inputStreamInfo && inputStreamInfo->flags & paWinMmeUseChannelMask )
+ inputChannelMask = inputStreamInfo->channelMask;
+ else
+ inputChannelMask = PaWin_DefaultChannelMask( inputDevices[0].channelCount );
+ }
}
else
{
@@ -2041,6 +2339,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
/* validate output hostApiSpecificStreamInfo */
outputStreamInfo = (PaWinMmeStreamInfo*)outputParameters->hostApiSpecificStreamInfo;
result = ValidateWinMmeSpecificStreamInfo( outputParameters, outputStreamInfo,
+ &winMmeSpecificOutputFlags,
&throttleProcessingThreadOnOverload,
&outputDeviceCount );
if( result != paNoError ) return result;
@@ -2056,6 +2355,18 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
hostOutputSampleFormat =
PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, outputSampleFormat );
+
+ if( outputDeviceCount != 1 ){
+ /* always use direct speakers when using multi-device multichannel mode */
+ outputChannelMask = PAWIN_SPEAKER_DIRECTOUT;
+ }
+ else
+ {
+ if( outputStreamInfo && outputStreamInfo->flags & paWinMmeUseChannelMask )
+ outputChannelMask = outputStreamInfo->channelMask;
+ else
+ outputChannelMask = PaWin_DefaultChannelMask( outputDevices[0].channelCount );
+ }
}
else
{
@@ -2078,6 +2389,14 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
return paInvalidFlag; /* unexpected platform specific flag */
+ /* always disable clipping and dithering if we are outputting a raw spdif stream */
+ if( (winMmeSpecificOutputFlags & paWinMmeWaveFormatDolbyAc3Spdif)
+ || (winMmeSpecificOutputFlags & paWinMmeWaveFormatWmaSpdif) ){
+
+ streamFlags = streamFlags | paClipOff | paDitherOff;
+ }
+
+
result = CalculateBufferSettings( &framesPerHostInputBuffer, &hostInputBufferCount,
&framesPerHostOutputBuffer, &hostOutputBufferCount,
inputChannelCount, hostInputSampleFormat, suggestedInputLatency, inputStreamInfo,
@@ -2176,16 +2495,18 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
if( inputParameters )
{
result = InitializeWaveHandles( winMmeHostApi, &stream->input,
+ winMmeSpecificInputFlags,
stream->bufferProcessor.bytesPerHostInputSample, sampleRate,
- inputDevices, inputDeviceCount, 1 /* isInput */ );
+ inputDevices, inputDeviceCount, inputChannelMask, 1 /* isInput */ );
if( result != paNoError ) goto error;
}
if( outputParameters )
{
result = InitializeWaveHandles( winMmeHostApi, &stream->output,
+ winMmeSpecificOutputFlags,
stream->bufferProcessor.bytesPerHostOutputSample, sampleRate,
- outputDevices, outputDeviceCount, 0 /* isInput */ );
+ outputDevices, outputDeviceCount, outputChannelMask, 0 /* isInput */ );
if( result != paNoError ) goto error;
}
@@ -2340,6 +2661,7 @@ static PaError AdvanceToNextInputBuffer( PaWinMmeStream *stream )
for( i=0; i < stream->input.deviceCount; ++i )
{
+ stream->input.waveHeaders[i][ stream->input.currentBufferIndex ].dwFlags &= ~WHDR_DONE;
mmresult = waveInAddBuffer( ((HWAVEIN*)stream->input.waveHandles)[i],
&stream->input.waveHeaders[i][ stream->input.currentBufferIndex ],
sizeof(WAVEHDR) );
@@ -2642,7 +2964,7 @@ static DWORD WINAPI ProcessingThreadProc( void *pArg )
for( i=0; i<stream->input.deviceCount; ++i )
{
/* we have stored the number of channels in the buffer in dwUser */
- int channelCount = stream->input.waveHeaders[i][ hostInputBufferIndex ].dwUser;
+ int channelCount = (int)stream->input.waveHeaders[i][ hostInputBufferIndex ].dwUser;
PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor, channel,
stream->input.waveHeaders[i][ hostInputBufferIndex ].lpData +
@@ -2663,7 +2985,7 @@ static DWORD WINAPI ProcessingThreadProc( void *pArg )
for( i=0; i<stream->output.deviceCount; ++i )
{
/* we have stored the number of channels in the buffer in dwUser */
- int channelCount = stream->output.waveHeaders[i][ hostOutputBufferIndex ].dwUser;
+ int channelCount = (int)stream->output.waveHeaders[i][ hostOutputBufferIndex ].dwUser;
PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor, channel,
stream->output.waveHeaders[i][ hostOutputBufferIndex ].lpData +
@@ -2866,6 +3188,7 @@ static PaError StartStream( PaStream *s )
{
for( j=0; j<stream->input.deviceCount; ++j )
{
+ stream->input.waveHeaders[j][i].dwFlags &= ~WHDR_DONE;
mmresult = waveInAddBuffer( ((HWAVEIN*)stream->input.waveHandles)[j], &stream->input.waveHeaders[j][i], sizeof(WAVEHDR) );
if( mmresult != MMSYSERR_NOERROR )
{
@@ -2912,7 +3235,7 @@ static PaError StartStream( PaStream *s )
for( j=0; j<stream->output.deviceCount; ++j )
{
/* we have stored the number of channels in the buffer in dwUser */
- int channelCount = stream->output.waveHeaders[j][i].dwUser;
+ int channelCount = (int)stream->output.waveHeaders[j][i].dwUser;
PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor, channel,
stream->output.waveHeaders[j][i].lpData +
@@ -2988,7 +3311,7 @@ static PaError StartStream( PaStream *s )
if( result != paNoError ) goto error;
/* Create thread that waits for audio buffers to be ready for processing. */
- stream->processingThread = CreateThread( 0, 0, ProcessingThreadProc, stream, 0, &stream->processingThreadId );
+ stream->processingThread = CREATE_THREAD;
if( !stream->processingThread )
{
result = paUnanticipatedHostError;
@@ -3120,7 +3443,7 @@ static PaError StopStream( PaStream *s )
for( i=0; i<stream->output.deviceCount; ++i )
{
/* we have stored the number of channels in the buffer in dwUser */
- int channelCount = stream->output.waveHeaders[i][ hostOutputBufferIndex ].dwUser;
+ int channelCount = (int)stream->output.waveHeaders[i][ hostOutputBufferIndex ].dwUser;
PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor, channel,
stream->output.waveHeaders[i][ hostOutputBufferIndex ].lpData +
@@ -3344,7 +3667,7 @@ static PaError ReadStream( PaStream* s,
}
else
{
- userBuffer = alloca( sizeof(void*) * stream->bufferProcessor.inputChannelCount );
+ userBuffer = (void*)alloca( sizeof(void*) * stream->bufferProcessor.inputChannelCount );
if( !userBuffer )
return paInsufficientMemory;
for( i = 0; i<stream->bufferProcessor.inputChannelCount; ++i )
@@ -3372,7 +3695,7 @@ static PaError ReadStream( PaStream* s,
for( i=0; i<stream->input.deviceCount; ++i )
{
/* we have stored the number of channels in the buffer in dwUser */
- int channelCount = stream->input.waveHeaders[i][ hostInputBufferIndex ].dwUser;
+ int channelCount = (int)stream->input.waveHeaders[i][ hostInputBufferIndex ].dwUser;
PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor, channel,
stream->input.waveHeaders[i][ hostInputBufferIndex ].lpData +
@@ -3448,7 +3771,7 @@ static PaError WriteStream( PaStream* s,
}
else
{
- userBuffer = alloca( sizeof(void*) * stream->bufferProcessor.outputChannelCount );
+ userBuffer = (const void*)alloca( sizeof(void*) * stream->bufferProcessor.outputChannelCount );
if( !userBuffer )
return paInsufficientMemory;
for( i = 0; i<stream->bufferProcessor.outputChannelCount; ++i )
@@ -3477,7 +3800,7 @@ static PaError WriteStream( PaStream* s,
for( i=0; i<stream->output.deviceCount; ++i )
{
/* we have stored the number of channels in the buffer in dwUser */
- int channelCount = stream->output.waveHeaders[i][ hostOutputBufferIndex ].dwUser;
+ int channelCount = (int)stream->output.waveHeaders[i][ hostOutputBufferIndex ].dwUser;
PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor, channel,
stream->output.waveHeaders[i][ hostOutputBufferIndex ].lpData +