]> Repos - portaudio/commitdiff
initial support for ac3+wma spdif passthrough for pa_win_wmme. see flags in pa_win_wm...
authorrossb <rossb@0f58301d-fd10-0410-b4af-bbb618454e57>
Wed, 21 Jan 2009 12:07:32 +0000 (12:07 +0000)
committerrossb <rossb@0f58301d-fd10-0410-b4af-bbb618454e57>
Wed, 21 Jan 2009 12:07:32 +0000 (12:07 +0000)
include/pa_win_waveformat.h
include/pa_win_wmme.h
src/hostapi/dsound/pa_win_ds.c
src/hostapi/wmme/pa_win_wmme.c
src/os/win/pa_win_waveformat.c

index 63bf1c9587dafdd6d64358dd4e8eb33ac24d6bb5..dce18c0d9302eb65f964ada0be4a7a5a9069fa01 100644 (file)
@@ -157,16 +157,34 @@ typedef struct{
 #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
index f7176ab40f8eeac9bd7db6f0e5ca99b5a5819cbe..fa06944b293cee2d827663b95c797bfc185a3c1d 100644 (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;
index e872edebb1428d60703b2f1a1b50f3e3f14ed525..56c45ca846424a128e8b044d39f96bdda48aeee3 100644 (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;
     }
index d5ccdafd2e139d4e3042554a99aec9293ad6feca..b516c99824b25bdb586940dd8249347920409921 100644 (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;
index 6b91ebd98401c021fbc29b1b9e33db87a12f2018..bbf616c3448315d1ffcd516406f80ba277bb4713 100644 (file)
 #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
@@ -81,12 +78,13 @@ void PaWin_InitializeWaveFormatEx( PaWinWaveFormat *waveFormat,
 \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
@@ -100,13 +98,10 @@ void PaWin_InitializeWaveFormatExtensible( PaWinWaveFormat *waveFormat,
                        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