]> Repos - portaudio/commitdiff
wasapi:
authordmitrykos <dmitrykos@0f58301d-fd10-0410-b4af-bbb618454e57>
Mon, 28 Jun 2010 21:29:16 +0000 (21:29 +0000)
committerdmitrykos <dmitrykos@0f58301d-fd10-0410-b4af-bbb618454e57>
Mon, 28 Jun 2010 21:29:16 +0000 (21:29 +0000)
 - made framesPerBuffer and suggestedLatency behavior as per PA specification, e.g. framesPerBuffer set main device period, suggestedLatency is a surplus if not 0
 - fixed bug with Input in situation when WASAPI operates in native not-WOW64 process and using event mechanism would provide less frames to a user callback than expected (due to the fact as WASAPI's audio client provides only 1 packet per GetBuffer call which)

src/hostapi/wasapi/pa_win_wasapi.c

index 990a142d5e82083d269b96ca6ab8212ae20c9cee..1518424d5e8053cd3536bbe96fb749f4c2235d84 100644 (file)
@@ -701,39 +701,44 @@ static UINT32 MakeFramesFromHns(REFERENCE_TIME hnsPeriod, UINT32 nSamplesPerSec)
 }\r
 \r
 // ------------------------------------------------------------------------------------------\r
-// Aligns v backwards\r
+// Aligns 'v' backwards\r
 static UINT32 ALIGN_BWD(UINT32 v, UINT32 align)\r
 {\r
        return ((v - (align ? v % align : 0)));\r
 }\r
 \r
+// ------------------------------------------------------------------------------------------\r
+// Aligns 'v' forward\r
+static UINT32 ALIGN_FWD(UINT32 v, UINT32 align)\r
+{\r
+       UINT32 remainder = (align ? (v % align) : 0);\r
+       if (remainder == 0)\r
+               return v;\r
+       return v + (align - remainder);\r
+}\r
+\r
 // ------------------------------------------------------------------------------------------\r
 // Aligns WASAPI buffer to 128 byte packet boundary. HD Audio will fail to play if buffer\r
 // is misaligned. This problem was solved in Windows 7 were AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED\r
 // is thrown although we must align for Vista anyway.\r
 static UINT32 AlignFramesPerBuffer(UINT32 nFrames, UINT32 nSamplesPerSec, UINT32 nBlockAlign)\r
 {\r
-#define HDA_PACKET_SIZE 128\r
+#define HDA_PACKET_SIZE (128)\r
 \r
-       //long packets_total = 10000 * (nSamplesPerSec * nBlockAlign / HDA_PACKET_SIZE);\r
-       long frame_bytes   = nFrames * nBlockAlign;\r
+       long frame_bytes = nFrames * nBlockAlign;\r
        long packets;\r
 \r
        // align to packet size\r
-       frame_bytes  = ALIGN_BWD(frame_bytes, HDA_PACKET_SIZE);\r
+       frame_bytes  = ALIGN_FWD(frame_bytes, HDA_PACKET_SIZE); // use ALIGN_FWD if bigger but safer period is more desired\r
        nFrames      = frame_bytes / nBlockAlign;\r
        packets      = frame_bytes / HDA_PACKET_SIZE;\r
 \r
-       // align to packets count\r
-       /*while (packets && ((packets_total % packets) != 0))\r
-       {\r
-               --packets;\r
-       }*/\r
-\r
        frame_bytes = packets * HDA_PACKET_SIZE;\r
        nFrames     = frame_bytes / nBlockAlign;\r
-\r
+       \r
        return nFrames;\r
+\r
+#undef HDA_PACKET_SIZE\r
 }\r
 \r
 // ------------------------------------------------------------------------------------------\r
@@ -1968,11 +1973,16 @@ static HRESULT CreateAudioClient(PaWasapiSubStream *pSubStream, PaWasapiDeviceIn
        }\r
 \r
        // Correct latency to default device period (in Exclusive mode this is 10ms) if user selected 0\r
-       suggestedLatency = (params->suggestedLatency < 0.001 ? nano100ToSeconds(info->DefaultDevicePeriod) : params->suggestedLatency);\r
+       //suggestedLatency = (params->suggestedLatency < 0.001 ? nano100ToSeconds(info->DefaultDevicePeriod) : params->suggestedLatency);\r
+       suggestedLatency = params->suggestedLatency;\r
 \r
        // Add latency frames\r
        framesPerLatency += MakeFramesFromHns(SecondsTonano100(suggestedLatency), pSubStream->wavex.Format.nSamplesPerSec);\r
 \r
+       // Avoid 0 frames\r
+       if (framesPerLatency == 0)\r
+               framesPerLatency = MakeFramesFromHns(info->DefaultDevicePeriod, pSubStream->wavex.Format.nSamplesPerSec);\r
+\r
        // Align frames to HD Audio packet size of 128 bytes for Exclusive mode only.\r
        // Not aligning on Windows Vista will cause Event timeout, although Windows 7 will\r
        // return AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED error to realign buffer. Aligning is necessary\r
@@ -2270,7 +2280,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
                        stream->in.streamFlags = 0; // polling interface is implemented for full-duplex mode also\r
 \r
                // Create Audio client\r
-               hr = CreateAudioClient(&stream->in, info, inputParameters, 0/*framesPerLatency*/,\r
+               hr = CreateAudioClient(&stream->in, info, inputParameters, framesPerBuffer/*framesPerLatency*/,\r
                        sampleRate, stream->in.streamFlags, (streamCallback == NULL), FALSE, &result);\r
         if (hr != S_OK)\r
                {\r
@@ -2384,7 +2394,7 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
                        stream->out.streamFlags = 0; // polling interface is implemented for full-duplex mode also\r
 \r
                // Create Audio client\r
-               hr = CreateAudioClient(&stream->out, info, outputParameters, 0/*framesPerLatency*/,\r
+               hr = CreateAudioClient(&stream->out, info, outputParameters, framesPerBuffer/*framesPerLatency*/,\r
                        sampleRate, stream->out.streamFlags, (streamCallback == NULL), TRUE, &result);\r
         if (hr != S_OK)\r
                {\r
@@ -2522,8 +2532,8 @@ static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
        // Exclusive/Shared non paWinWasapiPolling mode: paUtilFixedHostBufferSize - always fixed\r
        // Exclusive/Shared paWinWasapiPolling mode: paUtilBoundedHostBufferSize - may vary\r
        bufferMode = paUtilFixedHostBufferSize;\r
-       if (inputParameters &&\r
-               (!stream->in.streamFlags || ((stream->in.streamFlags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) == 0)))\r
+       if (inputParameters /*&& // !!! WASAPI IAudioCaptureClient::GetBuffer extracts not number of frames but 1 packet, thus we always must adapt\r
+               (!stream->in.streamFlags || ((stream->in.streamFlags & AUDCLNT_STREAMFLAGS_EVENTCALLBACK) == 0))*/)\r
                bufferMode = paUtilBoundedHostBufferSize;\r
        else\r
        if (outputParameters &&\r