我们为语音识别编写软件(C#),直到特定的 W10 更新为止,我们的语音识别没有任何问题(通过 USB 麦克风/耳机)。我们现在面临识别问题,发现这是由(音频)输入设备设置“信号增强”和“启用音频增强”引起的。我们发现,当禁用此设置时,识别结果要好得多,并且我们不会丢失单词或句子。
目前,我们能够禁用此功能的唯一方法是手动取消选中该框,但每次连接设备时都必须执行此操作,有时在 Win Update 后也必须执行此操作。
有什么方法可以通过编程方式改变此设置吗?
任何指示或建议将非常感激:)
我们的软件电话也面临着类似的问题。 信号增强显然会产生音频设备的延迟启动(带有 CALLBACK_THREAD 的 WaveInOpen 方法),但这种效果仅出现在少数 PC 上。我们不能肯定地说信号增强是问题所在,但关键是禁用“信号增强”改善了这些电脑的情况,没有这么大的延迟,从 1.5 秒到 200 毫秒。
无论如何,我想以编程方式停用并为每个电话再次激活它。
我可以在我的 Windows 注册表 (Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Capture) 中跟踪该条目
{1da5d803-d492-4edd-8c23-e0c0ffee7f0e},5(PKEY_AudioEndpoint_Disable_SysFx)
当我在音频设置中激活和停用信号增强选项时,会被设置和取消设置。
问题是该注册表项位于 FxProperties 文件夹内。有两个文件夹用于提供音频效果的设备:
...MMDevices\Audio\Capture\{guid}\属性
...MMDevices\Audio\Capture\{guid}\FxProperties
当我使用 IMMDevice 接口读取属性时,我只获得 Properties 文件夹内的条目列表,但不知道如何访问 FxProperties 文件夹。我使用以下代码:(删除了一些部分和检查,只写了必要的)
pEnumerator->EnumAudioEndpoints(eAll, DEVICE_STATEMASK_ALL, &pMMDeviceCollection);
pMMDeviceCollection->GetCount(&nDevices);
for (UINT i = 0; i < nDevices; i++) {
pMMDeviceCollection->Item(i, &pMMDevice);
pMMDevice->OpenPropertyStore(STGM_READ, &store);
}
OpenPropertyStore 仅允许您访问 Properties 文件夹。
我继续研究如何访问 FxProperties 商店。在这种情况下,我会实现类似的东西:
fxStore->SetValue(PKEY_AudioEndpoint_Disable_SysFx, ENDPOINT_SYSFX_DISABLED);
这有望停用相应设备的信号增强功能。
使用 SHGetPropertyStoreFromParsingName 或 RegGetValue 的另一次尝试均未成功。 错误代码为 0x80070002 和 ERROR_FILE_NOT_FOUND。
我也尝试以管理权限启动我的应用程序,但没有区别。没有 FxProperties 条目的迹象。
编辑: 我找到了这个链接: https://learn.microsoft.com/en-us/answers/questions/669471/how-to-control-enable-audio-enhancements-with-code
IPolicyConfig 可以解决这个问题,但它是一个未记录的 Windows 接口。我不会依赖它。
基于 Sergio 的答案和此问答https://learn.microsoft.com/en-us/answers/questions/669471/how-to-control-enable-audio-enhancements-with-code,我发现禁用音频增强的方法:
std::wstring key_path = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\MMDevices\\Audio\\Capture\\{guid}\\FxProperties";
std::wstring key_item = L"{1da5d803-d492-4edd-8c23-e0c0ffee7f0e},5";
unsigned long val = 0;
bool res = Get_DWORDRegistryValue(HKEY_LOCAL_MACHINE, (LPCTSTR)key_path.c_str(), (LPCTSTR)key_item.c_str(), val);
if (!res)
{
std::cout << "Get key item failed, not exist!\n";
val = 1;
// Must use Admin right to run this code
if (!Set_DWORDRegistryValue(HKEY_LOCAL_MACHINE, (LPCTSTR)key_path.c_str(), (LPCTSTR)key_item.c_str(), val))
{
std::cout << "Set Registry failed\n";
}
}
// Writes a DWORD value to the registry
bool Set_DWORDRegistryValue(HKEY hKeyRoot, LPCTSTR pszSubKey, LPCTSTR pszValue, unsigned long ulValue)
{
HKEY hKey;
LONG lRes;
lRes = RegOpenKeyEx(hKeyRoot, pszSubKey, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, &hKey);
if (lRes != ERROR_SUCCESS)
{
SetLastError(lRes);
return false;
}
lRes = RegSetValueEx(hKey, pszValue, 0, REG_DWORD, (unsigned char *)&ulValue, sizeof(ulValue));
RegCloseKey(hKey);
if (lRes != ERROR_SUCCESS)
{
SetLastError(lRes);
return false;
}
return true;
}