-
-
Notifications
You must be signed in to change notification settings - Fork 715
Fix SAPI5 #18675
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
Fix SAPI5 #18675
Conversation
I moved Then there's a racing problem: if the main thread calls As the speech thread itself can do nothing when calling feed or idle, calling stop in another thread is needed. But how should I prevent stop from missing the feed call that I want to cancel, aside from just calling stop again and again in a loop until cancellation completes? Maybe I can use some kind of synchronization, but inside @jcsteh I wonder if you have better idea about how to handle this. Also I wonder if it's a general problem that stop may be called before the next feed during cancellation, resulting in one more audio chunk being fed and played after stopping. In this case, SAPI5 will send the final audio chunk flushed out of the SonicStream before the speech stream completes, and the final chunk might be big enough to become a noticeable delay. |
Can you explain your threading model now? How many threads are they and what do they do at various points?
I can't stress this enough: you must not have the main thread wait for anything. The main thread should call WavePlayer.stop and return, no waiting. Any waiting in the main thread is going to cause problems in some way or another.
Ideally, you would set the cancellation flag in the main thread just before you call WavePlayer.stop. When the feeding thread picks up the cancellation, it should do whatever it needs to do to prevent any more chunks being fed, then clear the flag.
It isn't. When the feed call returns, synth drivers check whether cancellation has occurred and abandon any remaining chunks if so. |
@gexgd0419 - do you think we can get this to a mergable state for monday next week (or sooner)? it seems we've got positive feedback from testers of the earlier commit |
I think that the real problem here is that I got the duration calculation wrong, which was fixed in 0ec85e4, and I'm waiting for feedback from #18674. This caused the waiting time for the first chunk to be too long, so there's a delay when speaking longer text. But yes, the previous commit should fix the NVDA frozen problem. I'll mark this ready when the rest of the work is done. Should I mark this PR to "fix 18674" before there's feedback from the user? |
Should |
No we use |
If multiple utterances are queued, should |
I think we do it once everything is done |
@seanbudd Does this need a changelog entry? |
Unless this fixes anything for 2025.2, no. If it's just fixing issues introduced in the 2025.3 release cycle there's no need for a change log |
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.
Pull Request Overview
This PR fixes NVDA unresponsiveness issues with SAPI5 voices by addressing synchronization problems in the EndStream handler. The changes move audio processing logic to a dedicated thread to prevent blocking and improve the handling of WASAPI thread lifecycle.
- Moves EndStream audio processing logic to the dedicated speak thread to prevent blocking
- Removes main thread waiting for cancellation completion to prevent freezing
- Improves WASAPI thread lifecycle management with proper start/stop handling
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
Co-authored-by: Copilot <[email protected]>
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 @gexgd0419
Link to issue number:
Fixes #18674. Fixes #18676. Fixes #18760.
Summary of the issue:
NVDA becomes unresponsive for a small period of time when speaking some text in SAPI5 voices.
#18658 leaves more audio data for the EndStream handler to be played, which causes NVDA to be frozen when the EndStream handler is feeding the remaining audio chunks.
Description of user facing changes:
The above issue should be fixed.
Description of developer facing changes:
None
Description of development approach:
Moves the feeding logic in EndStream to the dedicated speak thread, avoiding blocking the SAPI5 thread that EndStream runs on.
The main thread no longer waits for cancellation to complete in order to prevent freezing.
The dedicated speak thread for WASAPI will be stopped and restarted when WASAPI is turned on or off, in order to prevent errors accessing the player when WASAPI is turned off and the player no longer exists.
Testing strategy:
Known issues with pull request:
Code Review Checklist:
@coderabbitai summary