Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions projectDocs/design/synthesizers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Synthesizers

## SAPI 4

SAPI 4 synthesizers are not included with NVDA, and the runtimes are no longer included with Windows.
Despite this, SAPI 4 support is still required, as many users prefer older synthesizers which rely on the SAPI 4 API.

To test SAPI 4, you must install the SAPI 4 runtimes (or the SDK containing the runtimes) from Microsoft, as well as a synthesizer.
Microsoft no longer hosts downloads for these, but archives and mirrors exist.

First, you can download and install either only the SAPI 4 runtimes from [this Microsoft archive](http://web.archive.org/web/20150910165037/http://activex.microsoft.com/activex/controls/sapi/spchapi.exe), or the SAPI 4 SDK from [this Microsoft archive](https://web.archive.org/web/20030203082745/http://download.microsoft.com/download/speechSDK/Install/4.0a/WIN98/EN-US/SAPI4SDK.exe), which contains the SAPI 4 runtimes, offline documentation, and sample source code & test applications.
If you only need the offline documentation, you can download the documentation for SAPI 4 COM interfaces from [this Microsoft archive](https://web.archive.org/web/19990418101425/http://www.microsoft.com/iit/onlineDocs/speechsdk4-com.chm).

After installing the runtimes, download and install a SAPI 4 synthesizer from [this Microsoft archive](http://web.archive.org/web/20150910005021if_/http://activex.microsoft.com/activex/controls/agent2/tv_enua.exe).

After this, you should be able to select SAPI 4 as a NVDA synthesizer.
1 change: 1 addition & 0 deletions source/config/configSpec.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
delayedCharacterDescriptions = boolean(default=false)
excludedSpeechModes = int_list(default=list())
trimLeadingSilence = boolean(default=true)
useWASAPIForSAPI4 = featureFlag(optionsEnum="BoolFlag", behaviorOfDefault="enabled")

[[__many__]]
capPitchChange = integer(default=30,min=-100,max=100)
Expand Down
16 changes: 16 additions & 0 deletions source/gui/settingsDialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4457,6 +4457,17 @@ def __init__(self, parent):
self.trimLeadingSilenceCheckBox.SetValue(config.conf["speech"]["trimLeadingSilence"])
self.trimLeadingSilenceCheckBox.defaultValue = self._getDefaultValue(["speech", "trimLeadingSilence"])

# Translators: This is the label for a combo-box control in the
# Advanced settings panel.
label = _("Use WASAPI for SAPI 4 audio output:")
self.useWASAPIForSAPI4Combo = speechGroup.addLabeledControl(
labelText=label,
wxCtrlClass=nvdaControls.FeatureFlagCombo,
keyPath=["speech", "useWASAPIForSAPI4"],
conf=config.conf,
)
self.bindHelpEvent("UseWASAPIForSAPI4", self.useWASAPIForSAPI4Combo)

# Translators: This is the label for a group of advanced options in the
# Advanced settings panel
label = _("Virtual Buffers")
Expand Down Expand Up @@ -4645,6 +4656,7 @@ def haveConfigDefaultsBeenRestored(self):
and self.cancelExpiredFocusSpeechCombo.GetSelection()
== self.cancelExpiredFocusSpeechCombo.defaultValue
and self.trimLeadingSilenceCheckBox.IsChecked() == self.trimLeadingSilenceCheckBox.defaultValue
and self.useWASAPIForSAPI4Combo.isValueConfigSpecDefault()
and self.loadChromeVBufWhenBusyCombo.isValueConfigSpecDefault()
and self.caretMoveTimeoutSpinControl.GetValue() == self.caretMoveTimeoutSpinControl.defaultValue
and self.reportTransparentColorCheckBox.GetValue()
Expand Down Expand Up @@ -4674,6 +4686,7 @@ def restoreToDefaults(self):
self.wtStrategyCombo.resetToConfigSpecDefault()
self.cancelExpiredFocusSpeechCombo.SetSelection(self.cancelExpiredFocusSpeechCombo.defaultValue)
self.trimLeadingSilenceCheckBox.SetValue(self.trimLeadingSilenceCheckBox.defaultValue)
self.useWASAPIForSAPI4Combo.resetToConfigSpecDefault()
self.loadChromeVBufWhenBusyCombo.resetToConfigSpecDefault()
self.caretMoveTimeoutSpinControl.SetValue(self.caretMoveTimeoutSpinControl.defaultValue)
self.reportTransparentColorCheckBox.SetValue(self.reportTransparentColorCheckBox.defaultValue)
Expand All @@ -4687,6 +4700,8 @@ def onSave(self):

shouldResetSynth = (
config.conf["speech"]["trimLeadingSilence"] != self.trimLeadingSilenceCheckBox.IsChecked()
or config.conf["speech"]["useWASAPIForSAPI4"]
!= self.useWASAPIForSAPI4Combo._getControlCurrentFlag()
)

config.conf["development"]["enableScratchpadDir"] = self.scratchpadCheckBox.IsChecked()
Expand All @@ -4702,6 +4717,7 @@ def onSave(self):
self.cancelExpiredFocusSpeechCombo.GetSelection()
)
config.conf["speech"]["trimLeadingSilence"] = self.trimLeadingSilenceCheckBox.IsChecked()
self.useWASAPIForSAPI4Combo.saveCurrentValueToConf()
config.conf["UIA"]["allowInChromium"] = self.UIAInChromiumCombo.GetSelection()
self.enhancedEventProcessingComboBox.saveCurrentValueToConf()
config.conf["terminals"]["speakPasswords"] = self.winConsoleSpeakPasswordsCheckBox.IsChecked()
Expand Down
Loading
Loading