initial support for ac3+wma spdif passthrough for pa_win_wmme. see flags in pa_win_wmme.h. flags currently work for OpenStream but are ignored for IsFormatSupported

This commit is contained in:
rossb 2009-01-21 12:07:32 +00:00
commit 1de1b421f9
5 changed files with 77 additions and 32 deletions

View file

@ -157,16 +157,34 @@ typedef struct{
#define PAWIN_INDEXOF_DWCHANNELMASK (PAWIN_SIZEOF_WAVEFORMATEX+2)
#define PAWIN_INDEXOF_SUBFORMAT (PAWIN_SIZEOF_WAVEFORMATEX+6)
/*
Valid values to pass for the waveFormatTag PaWin_InitializeWaveFormatEx and
PaWin_InitializeWaveFormatExtensible functions below. These must match
the standard Windows WAVE_FORMAT_* values.
*/
#define PAWIN_WAVE_FORMAT_PCM (1)
#define PAWIN_WAVE_FORMAT_IEEE_FLOAT (3)
#define PAWIN_WAVE_FORMAT_DOLBY_AC3_SPDIF (0x0092)
#define PAWIN_WAVE_FORMAT_WMA_SPDIF (0x0164)
/*
returns PAWIN_WAVE_FORMAT_PCM or PAWIN_WAVE_FORMAT_IEEE_FLOAT
depending on the sampleFormat parameter.
*/
int PaWin_SampleFormatToLinearWaveFormatTag( PaSampleFormat sampleFormat );
/*
Use the following two functions to initialize the waveformat structure.
*/
void PaWin_InitializeWaveFormatEx( PaWinWaveFormat *waveFormat,
int numChannels, PaSampleFormat sampleFormat, double sampleRate );
int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double sampleRate );
void PaWin_InitializeWaveFormatExtensible( PaWinWaveFormat *waveFormat,
int numChannels, PaSampleFormat sampleFormat, double sampleRate,
int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double sampleRate,
PaWinWaveFormatChannelMask channelMask );

View file

@ -64,6 +64,10 @@ extern "C"
*/
#define paWinMmeDontThrottleOverloadedProcessingThread (0x08)
/* flags for non-PCM spdif passthrough */
#define paWinMmeWaveFormatDolbyAc3Spdif (0x10)
#define paWinMmeWaveFormatWmaSpdif (0x20)
typedef struct PaWinMmeDeviceAndChannelCount{
PaDeviceIndex device;

View file

@ -1401,12 +1401,14 @@ static HRESULT InitInputBuffer( PaWinDsStream *stream, PaSampleFormat sampleForm
// 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;
@ -1477,11 +1479,13 @@ static HRESULT InitOutputBuffer( PaWinDsStream *stream, PaSampleFormat sampleFor
// 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;
}

View file

@ -556,12 +556,14 @@ static PaError QueryFormatSupported( PaDeviceInfo *deviceInfo,
/* @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 );
}
@ -1683,6 +1685,7 @@ 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, PaWinWaveFormatChannelMask channelMask, int isInput );
@ -1707,6 +1710,7 @@ static void InitializeSingleDirectionHandlesAndBuffers( PaWinMmeSingleDirectionH
static PaError InitializeWaveHandles( PaWinMmeHostApiRepresentation *winMmeHostApi,
PaWinMmeSingleDirectionHandlesAndBuffers *handlesAndBuffers,
unsigned long winMmeSpecificFlags,
unsigned long bytesPerHostSample,
double sampleRate, PaWinMmeDeviceAndChannelCount *devices,
unsigned int deviceCount, PaWinWaveFormatChannelMask channelMask, int isInput )
@ -1714,6 +1718,8 @@ static PaError InitializeWaveHandles( PaWinMmeHostApiRepresentation *winMmeHostA
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 */
@ -1741,6 +1747,15 @@ static PaError InitializeWaveHandles( PaWinMmeHostApiRepresentation *winMmeHostA
((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;
@ -1756,16 +1771,16 @@ static PaError InitializeWaveHandles( PaWinMmeHostApiRepresentation *winMmeHostA
/* 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
@ -2070,6 +2085,7 @@ struct PaWinMmeStream
static PaError ValidateWinMmeSpecificStreamInfo(
const PaStreamParameters *streamParameters,
const PaWinMmeStreamInfo *streamInfo,
unsigned long *winMmeSpecificFlags,
char *throttleProcessingThreadOnOverload,
unsigned long *deviceCount )
{
@ -2081,6 +2097,8 @@ static PaError ValidateWinMmeSpecificStreamInfo(
return paIncompatibleHostApiSpecificStreamInfo;
}
*winMmeSpecificFlags = streamInfo->flags;
if( streamInfo->flags & paWinMmeDontThrottleOverloadedProcessingThread )
*throttleProcessingThreadOnOverload = 0;
@ -2224,8 +2242,10 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
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;
@ -2241,6 +2261,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;
@ -2290,6 +2311,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;
@ -2437,6 +2459,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
if( inputParameters )
{
result = InitializeWaveHandles( winMmeHostApi, &stream->input,
winMmeSpecificInputFlags,
stream->bufferProcessor.bytesPerHostInputSample, sampleRate,
inputDevices, inputDeviceCount, inputChannelMask, 1 /* isInput */ );
if( result != paNoError ) goto error;
@ -2445,6 +2468,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
if( outputParameters )
{
result = InitializeWaveHandles( winMmeHostApi, &stream->output,
winMmeSpecificOutputFlags,
stream->bufferProcessor.bytesPerHostOutputSample, sampleRate,
outputDevices, outputDeviceCount, outputChannelMask, 0 /* isInput */ );
if( result != paNoError ) goto error;

View file

@ -47,30 +47,27 @@
#define WAVE_FORMAT_EXTENSIBLE 0xFFFE
#endif
#if !defined(WAVE_FORMAT_IEEE_FLOAT)
#define WAVE_FORMAT_IEEE_FLOAT 0x0003
#endif
static GUID pawin_ksDataFormatSubtypePcm =
static GUID pawin_ksDataFormatSubtypeGuidBase =
{ (USHORT)(WAVE_FORMAT_PCM), 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 };
static GUID pawin_ksDataFormatSubtypeIeeeFloat =
{ (USHORT)(WAVE_FORMAT_IEEE_FLOAT), 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 };
int PaWin_SampleFormatToLinearWaveFormatTag( PaSampleFormat sampleFormat )
{
if( sampleFormat == paFloat32 )
return PAWIN_WAVE_FORMAT_IEEE_FLOAT;
return PAWIN_WAVE_FORMAT_PCM;
}
void PaWin_InitializeWaveFormatEx( PaWinWaveFormat *waveFormat,
int numChannels, PaSampleFormat sampleFormat, double sampleRate )
int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double sampleRate )
{
WAVEFORMATEX *waveFormatEx = (WAVEFORMATEX*)waveFormat;
int bytesPerSample = Pa_GetSampleSize(sampleFormat);
unsigned long bytesPerFrame = numChannels * bytesPerSample;
if( sampleFormat == paFloat32 )
waveFormatEx->wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
else
waveFormatEx->wFormatTag = WAVE_FORMAT_PCM;
waveFormatEx->wFormatTag = waveFormatTag;
waveFormatEx->nChannels = (WORD)numChannels;
waveFormatEx->nSamplesPerSec = (DWORD)sampleRate;
waveFormatEx->nAvgBytesPerSec = waveFormatEx->nSamplesPerSec * bytesPerFrame;
@ -81,12 +78,13 @@ void PaWin_InitializeWaveFormatEx( PaWinWaveFormat *waveFormat,
void PaWin_InitializeWaveFormatExtensible( PaWinWaveFormat *waveFormat,
int numChannels, PaSampleFormat sampleFormat, double sampleRate,
int numChannels, PaSampleFormat sampleFormat, int waveFormatTag, double sampleRate,
PaWinWaveFormatChannelMask channelMask )
{
WAVEFORMATEX *waveFormatEx = (WAVEFORMATEX*)waveFormat;
int bytesPerSample = Pa_GetSampleSize(sampleFormat);
unsigned long bytesPerFrame = numChannels * bytesPerSample;
GUID guid;
waveFormatEx->wFormatTag = WAVE_FORMAT_EXTENSIBLE;
waveFormatEx->nChannels = (WORD)numChannels;
@ -100,13 +98,10 @@ void PaWin_InitializeWaveFormatExtensible( PaWinWaveFormat *waveFormat,
waveFormatEx->wBitsPerSample;
*((DWORD*)&waveFormat->fields[PAWIN_INDEXOF_DWCHANNELMASK]) = channelMask;
if( sampleFormat == paFloat32 )
*((GUID*)&waveFormat->fields[PAWIN_INDEXOF_SUBFORMAT]) =
pawin_ksDataFormatSubtypeIeeeFloat;
else
*((GUID*)&waveFormat->fields[PAWIN_INDEXOF_SUBFORMAT]) =
pawin_ksDataFormatSubtypePcm;
guid = pawin_ksDataFormatSubtypeGuidBase;
guid.Data1 = (USHORT)waveFormatTag;
*((GUID*)&waveFormat->fields[PAWIN_INDEXOF_SUBFORMAT]) = guid;
}