#define PAWIN_INDEXOF_DWCHANNELMASK (PAWIN_SIZEOF_WAVEFORMATEX+2)\r
#define PAWIN_INDEXOF_SUBFORMAT (PAWIN_SIZEOF_WAVEFORMATEX+6)\r
\r
+\r
+/*\r
+ Valid values to pass for the waveFormatTag PaWin_InitializeWaveFormatEx and\r
+ PaWin_InitializeWaveFormatExtensible functions below. These must match\r
+ the standard Windows WAVE_FORMAT_* values.\r
+*/\r
+#define PAWIN_WAVE_FORMAT_PCM (1)\r
+#define PAWIN_WAVE_FORMAT_IEEE_FLOAT (3)\r
+#define PAWIN_WAVE_FORMAT_DOLBY_AC3_SPDIF (0x0092)\r
+#define PAWIN_WAVE_FORMAT_WMA_SPDIF (0x0164)\r
+\r
+\r
+/*\r
+ returns PAWIN_WAVE_FORMAT_PCM or PAWIN_WAVE_FORMAT_IEEE_FLOAT\r
+ depending on the sampleFormat parameter.\r
+*/\r
+int PaWin_SampleFormatToLinearWaveFormatTag( PaSampleFormat sampleFormat );\r
+\r
/*\r
Use the following two functions to initialize the waveformat structure.\r
*/\r
\r
void PaWin_InitializeWaveFormatEx( PaWinWaveFormat *waveFormat, \r
- int numChannels, PaSampleFormat sampleFormat, double sampleRate );\r
+ int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double sampleRate );\r
\r
\r
void PaWin_InitializeWaveFormatExtensible( PaWinWaveFormat *waveFormat, \r
- int numChannels, PaSampleFormat sampleFormat, double sampleRate,\r
+ int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double sampleRate,\r
PaWinWaveFormatChannelMask channelMask );\r
\r
\r
*/
#define paWinMmeDontThrottleOverloadedProcessingThread (0x08)
+/* flags for non-PCM spdif passthrough */
+#define paWinMmeWaveFormatDolbyAc3Spdif (0x10)
+#define paWinMmeWaveFormatWmaSpdif (0x20)
+
typedef struct PaWinMmeDeviceAndChannelCount{
PaDeviceIndex device;
// first try WAVEFORMATEXTENSIBLE. if this fails, fall back to WAVEFORMATEX
PaWin_InitializeWaveFormatExtensible( &waveFormat, nChannels,
- sampleFormat, nFrameRate, channelMask );
+ sampleFormat, PaWin_SampleFormatToLinearWaveFormatTag( sampleFormat ),
+ nFrameRate, channelMask );
if( IDirectSoundCapture_CreateCaptureBuffer( stream->pDirectSoundCapture,
&captureDesc, &stream->pDirectSoundInputBuffer, NULL) != DS_OK )
{
- PaWin_InitializeWaveFormatEx( &waveFormat, nChannels, sampleFormat, nFrameRate );
+ PaWin_InitializeWaveFormatEx( &waveFormat, nChannels, sampleFormat,
+ PaWin_SampleFormatToLinearWaveFormatTag( sampleFormat ), nFrameRate );
if ((result = IDirectSoundCapture_CreateCaptureBuffer( stream->pDirectSoundCapture,
&captureDesc, &stream->pDirectSoundInputBuffer, NULL)) != DS_OK) return result;
// first try WAVEFORMATEXTENSIBLE. if this fails, fall back to WAVEFORMATEX
PaWin_InitializeWaveFormatExtensible( &waveFormat, nChannels,
- sampleFormat, nFrameRate, channelMask );
+ sampleFormat, PaWin_SampleFormatToLinearWaveFormatTag( sampleFormat ),
+ nFrameRate, channelMask );
if( IDirectSoundBuffer_SetFormat( pPrimaryBuffer, (WAVEFORMATEX*)&waveFormat) != DS_OK )
{
- PaWin_InitializeWaveFormatEx( &waveFormat, nChannels, sampleFormat, nFrameRate );
+ PaWin_InitializeWaveFormatEx( &waveFormat, nChannels, sampleFormat,
+ PaWin_SampleFormatToLinearWaveFormatTag( sampleFormat ), nFrameRate );
if((result = IDirectSoundBuffer_SetFormat( pPrimaryBuffer, (WAVEFORMATEX*)&waveFormat)) != DS_OK) return result;
}
/* @todo at the moment we only query with 16 bit sample format and directout speaker config*/
PaWin_InitializeWaveFormatExtensible( &waveFormat, channels,
- paInt16, sampleRate, PAWIN_SPEAKER_DIRECTOUT );
+ paInt16, PaWin_SampleFormatToLinearWaveFormatTag( paInt16 ),
+ sampleRate, PAWIN_SPEAKER_DIRECTOUT );
if( waveFormatExQueryFunction( winMmeDeviceId, (WAVEFORMATEX*)&waveFormat ) == paNoError )
return paNoError;
- PaWin_InitializeWaveFormatEx( &waveFormat, channels, paInt16, sampleRate );
+ PaWin_InitializeWaveFormatEx( &waveFormat, channels, paInt16,
+ PaWin_SampleFormatToLinearWaveFormatTag( paInt16 ), sampleRate );
return waveFormatExQueryFunction( winMmeDeviceId, (WAVEFORMATEX*)&waveFormat );
}
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, PaWinWaveFormatChannelMask channelMask, int isInput );
static PaError InitializeWaveHandles( PaWinMmeHostApiRepresentation *winMmeHostApi,
PaWinMmeSingleDirectionHandlesAndBuffers *handlesAndBuffers,
+ unsigned long winMmeSpecificFlags,
unsigned long bytesPerHostSample,
double sampleRate, PaWinMmeDeviceAndChannelCount *devices,
unsigned int deviceCount, PaWinWaveFormatChannelMask channelMask, int isInput )
PaError result;
MMRESULT mmresult;
signed int i, j;
+ PaSampleFormat sampleFormat;
+ int waveFormatTag;
/* for error cleanup we expect that InitializeSingleDirectionHandlesAndBuffers()
has already been called to zero some fields */
((HWAVEOUT*)handlesAndBuffers->waveHandles)[i] = 0;
}
+ /* @todo at the moment we only use 16 bit sample format */
+ sampleFormat = paInt16;
+ waveFormatTag = PaWin_SampleFormatToLinearWaveFormatTag( sampleFormat );
+
+ if( winMmeSpecificFlags & paWinMmeWaveFormatDolbyAc3Spdif )
+ waveFormatTag = PAWIN_WAVE_FORMAT_DOLBY_AC3_SPDIF;
+ else if( winMmeSpecificFlags & paWinMmeWaveFormatWmaSpdif )
+ waveFormatTag = PAWIN_WAVE_FORMAT_WMA_SPDIF;
+
for( i = 0; i < (signed int)deviceCount; ++i )
{
PaWinWaveFormat waveFormat;
/* first, attempt to open the device using WAVEFORMATEXTENSIBLE,
if this fails we fall back to WAVEFORMATEX */
- /* @todo at the moment we only use 16 bit sample format */
PaWin_InitializeWaveFormatExtensible( &waveFormat, devices[i].channelCount,
- paInt16, sampleRate, channelMask );
+ sampleFormat, waveFormatTag, sampleRate, channelMask );
}
else
{
/* retry with WAVEFORMATEX */
- PaWin_InitializeWaveFormatEx( &waveFormat, devices[i].channelCount, paInt16, sampleRate );
+ PaWin_InitializeWaveFormatEx( &waveFormat, devices[i].channelCount,
+ sampleFormat, waveFormatTag, sampleRate );
}
/* REVIEW: consider not firing an event for input when a full duplex
static PaError ValidateWinMmeSpecificStreamInfo(
const PaStreamParameters *streamParameters,
const PaWinMmeStreamInfo *streamInfo,
+ unsigned long *winMmeSpecificFlags,
char *throttleProcessingThreadOnOverload,
unsigned long *deviceCount )
{
return paIncompatibleHostApiSpecificStreamInfo;
}
+ *winMmeSpecificFlags = streamInfo->flags;
+
if( streamInfo->flags & paWinMmeDontThrottleOverloadedProcessingThread )
*throttleProcessingThreadOnOverload = 0;
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;
/* validate input hostApiSpecificStreamInfo */
inputStreamInfo = (PaWinMmeStreamInfo*)inputParameters->hostApiSpecificStreamInfo;
result = ValidateWinMmeSpecificStreamInfo( inputParameters, inputStreamInfo,
+ &winMmeSpecificInputFlags,
&throttleProcessingThreadOnOverload,
&inputDeviceCount );
if( result != paNoError ) return result;
/* validate output hostApiSpecificStreamInfo */
outputStreamInfo = (PaWinMmeStreamInfo*)outputParameters->hostApiSpecificStreamInfo;
result = ValidateWinMmeSpecificStreamInfo( outputParameters, outputStreamInfo,
+ &winMmeSpecificOutputFlags,
&throttleProcessingThreadOnOverload,
&outputDeviceCount );
if( result != paNoError ) return result;
if( inputParameters )
{
result = InitializeWaveHandles( winMmeHostApi, &stream->input,
+ winMmeSpecificInputFlags,
stream->bufferProcessor.bytesPerHostInputSample, sampleRate,
inputDevices, inputDeviceCount, inputChannelMask, 1 /* isInput */ );
if( result != paNoError ) goto error;
if( outputParameters )
{
result = InitializeWaveHandles( winMmeHostApi, &stream->output,
+ winMmeSpecificOutputFlags,
stream->bufferProcessor.bytesPerHostOutputSample, sampleRate,
outputDevices, outputDeviceCount, outputChannelMask, 0 /* isInput */ );
if( result != paNoError ) goto error;
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE\r
#endif\r
\r
-#if !defined(WAVE_FORMAT_IEEE_FLOAT)\r
-#define WAVE_FORMAT_IEEE_FLOAT 0x0003\r
-#endif\r
-\r
-static GUID pawin_ksDataFormatSubtypePcm = \r
+static GUID pawin_ksDataFormatSubtypeGuidBase = \r
{ (USHORT)(WAVE_FORMAT_PCM), 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 };\r
\r
-static GUID pawin_ksDataFormatSubtypeIeeeFloat = \r
- { (USHORT)(WAVE_FORMAT_IEEE_FLOAT), 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 };\r
\r
+int PaWin_SampleFormatToLinearWaveFormatTag( PaSampleFormat sampleFormat )\r
+{\r
+ if( sampleFormat == paFloat32 )\r
+ return PAWIN_WAVE_FORMAT_IEEE_FLOAT;\r
+ \r
+ return PAWIN_WAVE_FORMAT_PCM;\r
+}\r
\r
\r
void PaWin_InitializeWaveFormatEx( PaWinWaveFormat *waveFormat, \r
- int numChannels, PaSampleFormat sampleFormat, double sampleRate )\r
+ int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double sampleRate )\r
{\r
WAVEFORMATEX *waveFormatEx = (WAVEFORMATEX*)waveFormat;\r
int bytesPerSample = Pa_GetSampleSize(sampleFormat);\r
unsigned long bytesPerFrame = numChannels * bytesPerSample;\r
-\r
- if( sampleFormat == paFloat32 )\r
- waveFormatEx->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;\r
- else\r
- waveFormatEx->wFormatTag = WAVE_FORMAT_PCM;\r
\r
+ waveFormatEx->wFormatTag = waveFormatTag;\r
waveFormatEx->nChannels = (WORD)numChannels;\r
waveFormatEx->nSamplesPerSec = (DWORD)sampleRate;\r
waveFormatEx->nAvgBytesPerSec = waveFormatEx->nSamplesPerSec * bytesPerFrame;\r
\r
\r
void PaWin_InitializeWaveFormatExtensible( PaWinWaveFormat *waveFormat, \r
- int numChannels, PaSampleFormat sampleFormat, double sampleRate,\r
+ int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double sampleRate,\r
PaWinWaveFormatChannelMask channelMask )\r
{\r
WAVEFORMATEX *waveFormatEx = (WAVEFORMATEX*)waveFormat;\r
int bytesPerSample = Pa_GetSampleSize(sampleFormat);\r
unsigned long bytesPerFrame = numChannels * bytesPerSample;\r
+ GUID guid;\r
\r
waveFormatEx->wFormatTag = WAVE_FORMAT_EXTENSIBLE;\r
waveFormatEx->nChannels = (WORD)numChannels;\r
waveFormatEx->wBitsPerSample;\r
\r
*((DWORD*)&waveFormat->fields[PAWIN_INDEXOF_DWCHANNELMASK]) = channelMask;\r
- \r
- if( sampleFormat == paFloat32 )\r
- *((GUID*)&waveFormat->fields[PAWIN_INDEXOF_SUBFORMAT]) =\r
- pawin_ksDataFormatSubtypeIeeeFloat;\r
- else\r
- *((GUID*)&waveFormat->fields[PAWIN_INDEXOF_SUBFORMAT]) =\r
- pawin_ksDataFormatSubtypePcm;\r
+ \r
+ guid = pawin_ksDataFormatSubtypeGuidBase;\r
+ guid.Data1 = (USHORT)waveFormatTag;\r
+ *((GUID*)&waveFormat->fields[PAWIN_INDEXOF_SUBFORMAT]) = guid;\r
}\r
\r
\r