Skip to content
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 SAPI 5 initialisation #17513

Merged
merged 1 commit into from
Dec 15, 2024
Merged

Fix SAPI 5 initialisation #17513

merged 1 commit into from
Dec 15, 2024

Conversation

SaschaCowley
Copy link
Member

Link to issue number:

Closes #17512
Fix-up of #17496

Summary of the issue:

After the removal of winmm support, SAPI5 synthesisers failed to initialise.
This is because we switched from integer-based IDs as used by winmm, to ID strings as used by Windows Core Audio.

Description of user facing changes

SAPI5 synthesisers now initialise correctly.

Description of development approach

Rather than calling outputDeviceNameToID to index into the audio outputs returned by SAPI, iterate over them and look for one whose Description matches the friendly name of the output device to use as stored in the user's config.

Testing strategy:

Tested loading SAPI5 with a number of output devices selected, and changing output devices with SAPI5 loaded.

Known issues with pull request:

None.

Code Review Checklist:

  • Documentation:
    • Change log entry
    • User Documentation
    • Developer / Technical Documentation
    • Context sensitive help for GUI changes
  • Testing:
    • Unit tests
    • System (end to end) tests
    • Manual testing
  • UX of all users considered:
    • Speech
    • Braille
    • Low Vision
    • Different web browsers
    • Localization in other languages / culture than English
  • API is compatible with existing add-ons.
  • Security precautions taken.

@coderabbitai summary

@SaschaCowley SaschaCowley marked this pull request as ready for review December 13, 2024 08:46
@SaschaCowley SaschaCowley requested a review from a team as a code owner December 13, 2024 08:46
@AppVeyorBot
Copy link

See test results for failed build of commit 1c6a4fbd0c

@burmancomp
Copy link
Contributor

Works for me. This should be merged as soon as possible.

@Adriani90
Copy link
Collaborator

This might impact SAPI 4 as well I guess. Right?
See #17516.

@zstanecic
Copy link
Contributor

No @Adriani90,
Sapi4 has different error and the log output. It is separate problem.

@SaschaCowley SaschaCowley merged commit 782c3d8 into master Dec 15, 2024
4 of 5 checks passed
@SaschaCowley SaschaCowley deleted the fixSapi5 branch December 15, 2024 23:18
@github-actions github-actions bot added this to the 2025.1 milestone Dec 15, 2024
@gexgd0419
Copy link
Contributor

This is my SAPI4 error log, with code:

setSynth failed for sapi4
Traceback (most recent call last):
  File "synthDriverHandler.py", line 483, in setSynth
    _curSynth = getSynthInstance(name, asDefault)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "synthDriverHandler.py", line 446, in getSynthInstance
    newSynth: SynthDriver = _getSynthDriver(name)()
                            ^^^^^^^^^^^^^^^^^^^^^^^
  File "synthDrivers\sapi4.py", line 152, in __init__
    self.voice = str(self._enginesList[0].gModeID)
    ^^^^^^^^^^
  File "synthDrivers\sapi4.py", line 263, in _set_voice
    self._ttsAudio.DeviceNumSet(nvwave.outputDeviceNameToID(config.conf["speech"]["outputDevice"], True))
ctypes.ArgumentError: argument 1: TypeError: wrong type

It's also nvwave.outputDeviceNameToID that caused the issue (type mismatch), so I guess that they are the same issue.

@gexgd0419
Copy link
Contributor

The problem is that unlike SAPI5 which allows you to enumerate audio devices and compare the names, SAPI4 only accepts a device number, so you will have to get the device number elsewhere. The fix for SAPI5 cannot be easily applied to SAPI4.

@SaschaCowley
Copy link
Member Author

@gexgd0419, thanks for the info. We are already aware of the cause and are working to implement a fix.

@gexgd0419
Copy link
Contributor

gexgd0419 commented Dec 18, 2024

I just thought of a question: what if two audio endpoints use the same description string (friendly name)? For example, a user connects two speakers/headphones with the exact same model. Will only one of them be able to be selected?

This problem is mentioned in Endpoint ID Strings.

If a system contains two or more identical audio adapter devices, the corresponding audio endpoint devices will have identical friendly names, but each endpoint device will have a unique endpoint ID string. For more information about obtaining the friendly name of an endpoint device, see Device Properties.

If you are using MME, then waveOutMessage can be used to get the endpoint ID, using DRV_QUERYFUNCTIONINSTANCEID message:

To obtain the endpoint ID string for a legacy waveform device, use the waveOutMessage or waveInMessage function to send a DRV_QUERYFUNCTIONINSTANCEID message to the waveform device driver. For a code example that shows the use of this message, see Device Roles for Legacy Windows Multimedia Applications.

So maybe we still need to keep some WinMM related code to perform conversion from WASAPI device IDs to WinMM device indexes.

@gexgd0419
Copy link
Contributor

Or maybe we can make a unified audio processing system in NVDA, so that instead of allowing each synthesizers to send their audio to the speaker on its own, make the synthesizers send the audio to NVDA. Then it will be possible to perform some audio processing, for example, silence removing, before sending the audio to the speaker. Also, you will be able to get rid of WinMM entirely.

@SaschaCowley
Copy link
Member Author

@gexgd0419 the issue with duplicate friendly names is one of the reasons we're switching to using endpoint IDs. This fix was implemented as that work was not ready to merge, so that SAPI5 would not be broken over the Christmas/New Years break.
We will be keeping the bare minimum of winmm code to support SAPI4 while we still support that API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cannot load sapi 5 synthesizer
7 participants