Как я могу изменить аудиоформат голоса?

Я возиться с SAPI на Windows, и я заметил, что качество звука голоса довольно не впечатляет. Сравнивая качество звука простой тестовой программы и различные качества, которые озвучки обеспечивает, я пришел к выводу, что качество по умолчанию где-то рядом 16kHz 16 Bit Mono,

Простая тестовая программа SAPI

#include <string>
#include <iostream>

#include <Windows.h>
#include <sapi.h>#define _CHECK_HR(hr, debug_str)   \
if(FAILED(hr)) {    \
std::cout << debug_str << ": " << std::hex << "0x" << hr << std::dec << std::endl;   \
goto check_failure;   \
}

#define CHECK_HR(expr, debug_str)  \
_CHECK_HR(expr, debug_str);

#define SAFE_RELEASE(obj)   \
if(obj != NULL) {   \
obj->Release(); \
obj = NULL; \
}int main()
{
ISpVoice* voice = NULL;

CHECK_HR(CoInitialize(NULL), "CoInitialize");

CHECK_HR(CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (LPVOID*)&voice), "voice = CoCreateInstance");
CHECK_HR(voice->Speak(TEXT("This is a simple test."), 0, NULL), "voice->Speak");

std::cout << "No errors!" << std::endl;

check_failure:
SAFE_RELEASE(voice);
CoUninitialize();
}

Естественно, я пытался проконсультироваться с SAPI документация, но не узнал, как изменить формат. ISpVoice не имеет метод, который устанавливает формат, но он имеет SetOuput метод, который принимает:

поток, аудиоустройство или токен объекта для выходного аудиоустройства

Моим следующим шагом было создание IAudioClient, в формате, предоставленном SpConvertStreamFormatEnum, и установив его IAudioRenderClient как вывод голоса. Попытка не удалась, потому что я не смог инициализировать IAudioClient.

Попытка установить аудиопоток как вывод голоса

#include <string>
#include <iostream>

#include <Windows.h>
#include <Mmdeviceapi.h>
#include <Audioclient.h>
#include <audiopolicy.h>
#include <sapi.h>
#include <sphelper.h>#define _CHECK_HR(hr, debug_str)   \
if(FAILED(hr)) {    \
std::cout << debug_str << ": " << std::hex << "0x" << hr << std::dec << std::endl;   \
goto check_failure;   \
}

#define CHECK_HR(expr, debug_str)  \
_CHECK_HR(expr, debug_str);

#define SAFE_RELEASE(obj)   \
if(obj != NULL) {   \
obj->Release(); \
obj = NULL; \
}

#define SAFE_FREE(obj)   \
if(obj != NULL) {   \
CoTaskMemFree(obj); \
obj = NULL; \
}int main()
{
ISpVoice* voice = NULL;
IMMDeviceEnumerator* device_enumerator = NULL;
IMMDevice* audio_device = NULL;
WAVEFORMATEX *audio_format = NULL;
GUID format_guid;
IAudioClient* audio_client = NULL;
IAudioRenderClient* audio_render_client = NULL;

CHECK_HR(CoInitialize(NULL), "CoInitialize");

CHECK_HR(CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (LPVOID*)&voice), "CoCreateInstance");

CHECK_HR(CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), reinterpret_cast<void**>(&device_enumerator)), "CoCreateInstance");
CHECK_HR(device_enumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &audio_device), "device_enumerator->GetDefaultAudioEndpoint");

CHECK_HR(audio_device->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, reinterpret_cast<void**>(&audio_client)), "audio_device->Activate");
CHECK_HR(SpConvertStreamFormatEnum(SPSF_48kHz16BitStereo, &format_guid, &audio_format), "SpConvertStreamFormatEnum");
CHECK_HR(audio_client->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_NOPERSIST | AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE, 0, 0, audio_format, NULL), "audio_client->Initialize");
CHECK_HR(audio_client->Start(), "audio_client->Start");
CHECK_HR(audio_client->GetService(__uuidof(IAudioRenderClient), reinterpret_cast<void**>(&audio_render_client)), "audio_client->GetService");

CHECK_HR(voice->SetOutput(audio_render_client, FALSE), "voice->SetOutput");
CHECK_HR(voice->Speak(TEXT("This is a test."), 0, NULL), "voice->Speak");

std::cout << "No errors!" << std::endl;

check_failure:
SAFE_RELEASE(device_enumerator);
SAFE_RELEASE(audio_device);
SAFE_FREE(audio_format);
SAFE_RELEASE(audio_client);
SAFE_RELEASE(audio_render_client);
CoUninitialize();
}

Кроме того, я ковырялся Аудиоинтерфейсы SAPI, найти кучу других интерфейсов и реализаций, ни один из которых не кажется особенно полезным для этой задачи. Я чувствую, что я бегаю кругами здесь.

Вопрос: Как я могу изменить аудиоформат голоса, как это делает TTSApp от eSpeak?
TTSApp

0

Решение

Пытаться:

ATL::CComPtr<ISpVoice> voice;
voice.CoCreateInstance(CLSID_SpVoice);

CSpStreamFormat format;
format.AssignFormat(SPSF_44kHz16BitMono);

ATL::CComPtr<ISpAudio> audio;
SpCreateDefaultObjectFromCategoryId(SPCAT_AUDIOOUT, &audio);
audio->SetFormat(format.FormatId(), format.WaveFormatExPtr());

voice->SetOutput(audio, FALSE);

ПРИМЕЧАНИЕ. Это не включает обработку ошибок, поэтому ваш код должен будет проверить коды возврата HRESULT и правильность объекта / указателя.

Также обратите внимание, что собственный формат вывода eSpeak — 16-битный 22050 Гц моно.

Для версии C вам нужно самостоятельно обработать время жизни COM-объекта и посмотреть, что CSpStreamFormat делает в AssignFormat, FormatId а также WaveFormatExPtr методы.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]