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