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:
parent
6cff10c3f4
commit
1de1b421f9
5 changed files with 77 additions and 32 deletions
|
|
@ -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 );
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue