-
-
Notifications
You must be signed in to change notification settings - Fork 735
oneCore synth: Fix lag between utterances introduced in NVDA 2019.3. #11023
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
When pushing the last chunk of audio for an utterance, use WavePlayer.sync() instead of WavePlayer.idle(). We do this because idle closes the audio device. If there's something in the queue after playing the final chunk, that will result in WaveOutOpen being called in the callback when we push the next chunk of audio. We *really* don't want this because calling WaveOutOpen blocks for ~100 ms if called from the callback when the SSML includes marks, resulting in lag between utterances. If the queue is empty after sync returns, only then do we call idle and allow the device to close.
feerrenrut
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @jcsteh, I have tested this build and can confirm.
I made recordings of alpha vs this PR using One Core - David at rate 40 with rate boost enabled.
With "speak key presses" enabled, on the desktop I pressed a key and waited for the file name to be announced.
I measured the time between the key press announcement and the icon name on the desktop. On average this PR is was about 150ms faster on my machine.
|
This might solve also #10971. |
…io played for 10 seconds. (PR #11024) Fixes #5172 Fixes #10721 ## Summary of the issue: - As described in #5172, some audio drivers/hardware take a long time to open the device and/or truncate the start/end of the audio. - As described in #10721 (comment), calling WaveOutOpen in the OneCore synth callback mysteriously blocks (and thus lags) for ~100 ms. Because we close the audio device on idle, we can trigger this problem. Although #11023 mostly fixes this, it's impossible (or at least very difficult) to resolve this completely from within the OneCore driver. - Aside from all of this, closing and opening the audio device for rapid short utterances (e.g. rapid movement with the cursor keys or typing) doesn't seem particularly optimal. It's difficult to measure this, but I'd say mitigating this is likely to make audio performance faster/smoother. ## Description of how this pull request fixes the issue: When WavePlayer.idle() is called and closeWhenIdle is set, instead of closing the device immediately after the audio finishes, set a timer. If audio is played before the timer elapses, stop the timer. Close the device when the timer expires.
Fixes #5172 Fixes #10721 Fixes #11482 Fixes #11490 ### History #5172 Some audio drivers/hardware take a long time to open the device and/or truncate the start/end of the audio. #10721 Calling WaveOutOpen in the OneCore synth callback mysteriously blocks (and thus lags) for ~100 ms. Because we close the audio device on idle, we can trigger this problem. Although PR #11023 mostly fixed this, it's impossible (or at least very difficult) to resolve this completely from within the OneCore driver. PR #11024 attempted to fix these issues by waiting 10 seconds before closing the audio device" ### Problem to solve Subsequent to #11024, there are occasional exceptions from nvwave, particularly when switching synthesisers. In particular the following cases need to be handled smoothly: - When using Microsoft Sound Mapper, NVDA should use the Windows default device (even if it changes) - When the NVDA configured devices becomes invalid, nvWave should fall back to Microsoft Sound Mapper - When the NVDA configured device becomes available again, NVDA should switch back to using it. - Handle no audio device at all. Since these issues needed to be fixed, and also: - Closing and opening the audio device was originally introduced to support Remote Desktop audio, this is now better served by other solutions. - Performance is improved by keeping it open, using a timeout means that the lag is more rare, but will still occur. ### How it is solved Instead, now don't close the device at all. As per the discussion: #11505 (comment) To fix issues with current / preferred device: - nvWave now saves the preferred device when it is constructed. - If using a device fails, it is considered unavailable, nvWave attempts to fall back to "Microsoft Sound Mapper". - From my testing, using "Microsoft Sound Mapper" correctly handled changing the default device (Win 10 2004). It would be helpful if others could confirm, especially on different OS versions. - During `_idleUnbuffered` - The current device is checked to see if it matches the preferred device. - The available devices are polled to see if the preferred device is available, if so it switches.
Link to issue number:
Fixes #10721. Mostly.
Summary of the issue:
When using Windows OneCore speech, there is a significant lag between utterances which was not present in NVDA <= 2019.2.1.
Description of how this pull request fixes the issue:
See #10721 (comment) for additional background.
When pushing the last chunk of audio for an utterance, use WavePlayer.sync() instead of WavePlayer.idle().
We do this because idle closes the audio device.
If there's something in the queue after playing the final chunk, that will result in WaveOutOpen being called in the callback when we push the next chunk of audio.
We really don't want this because calling WaveOutOpen blocks for ~100 ms if called from the callback when the SSML includes marks, resulting in lag between utterances.
If the queue is empty after sync returns, only then do we call idle and allow the device to close.
Testing performed:
Tested as per STR in #10721 (comment).
Known issues with pull request:
Unfortunately, there's still a rare race condition where as we're closing the device, something can arrive in the queue, so we hit the same issue again. I think a much broader solution is needed to fix this. See #10721 (comment).
Change log entry:
Bug fixes:
- The Windows OneCore speech synthesizer no longer lags between utterances. (#10721)