156 lines
5.1 KiB
C++
Raw Normal View History

2024-01-08 23:37:00 +08:00

2024-04-02 15:36:52 +08:00
bool _Speak(std::wstring &Content, const wchar_t *token, int voiceid, int rate, int volume, std::wstring &FileName)
{
ISpVoice *pVoice = NULL;
2024-01-08 23:37:00 +08:00
if (FAILED(::CoInitialize(NULL)))
return false;
bool ret = true;
do
{
2024-04-02 15:36:52 +08:00
HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
if (FAILED(hr) || (NULL == pVoice))
{
2024-01-08 23:37:00 +08:00
ret = false;
break;
}
2024-04-02 15:36:52 +08:00
IEnumSpObjectTokens *pSpEnumTokens = NULL;
if (SUCCEEDED(SpEnumTokens(token, NULL, NULL, &pSpEnumTokens)))
{
2024-01-08 23:37:00 +08:00
ULONG ulTokensNumber = 0;
pSpEnumTokens->GetCount(&ulTokensNumber);
2024-04-02 15:36:52 +08:00
ISpObjectToken *m_pISpObjectToken;
2024-01-08 23:37:00 +08:00
pSpEnumTokens->Item(voiceid, &m_pISpObjectToken);
pVoice->SetVoice(m_pISpObjectToken);
pVoice->SetRate(rate);
pVoice->SetVolume(volume);
2024-04-02 15:36:52 +08:00
CComPtr<ISpStream> cpWavStream;
CComPtr<ISpStreamFormat> cpOldStream;
2024-01-08 23:37:00 +08:00
CSpStreamFormat originalFmt;
hr = pVoice->GetOutputStream(&cpOldStream);
2024-04-02 15:36:52 +08:00
if (FAILED(hr) || (NULL == cpOldStream))
{
2024-01-08 23:37:00 +08:00
ret = false;
break;
}
originalFmt.AssignFormat(cpOldStream);
hr = SPBindToFile(FileName.c_str(), SPFM_CREATE_ALWAYS, &cpWavStream, &originalFmt.FormatId(), originalFmt.WaveFormatExPtr());
2024-04-02 15:36:52 +08:00
if (FAILED(hr))
{
2024-01-08 23:37:00 +08:00
ret = false;
break;
}
pVoice->SetOutput(cpWavStream, TRUE);
pVoice->Speak(Content.c_str(), SPF_IS_XML, NULL);
pVoice->Release();
pSpEnumTokens->Release();
pVoice = NULL;
}
} while (0);
::CoUninitialize();
return ret;
}
2024-04-02 15:36:52 +08:00
std::vector<std::wstring> _List(const wchar_t *token)
{
2024-01-08 23:37:00 +08:00
if (FAILED(::CoInitialize(NULL)))
return {};
2024-04-02 15:36:52 +08:00
ISpVoice *pSpVoice = NULL;
2024-01-08 23:37:00 +08:00
std::vector<std::wstring> ret;
2024-04-02 15:36:52 +08:00
IEnumSpObjectTokens *pSpEnumTokens = NULL;
if (FAILED(CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pSpVoice)))
{
2024-01-08 23:37:00 +08:00
return {};
}
2024-04-02 15:36:52 +08:00
if (SUCCEEDED(SpEnumTokens(token, NULL, NULL, &pSpEnumTokens)))
{
2024-01-08 23:37:00 +08:00
ULONG ulTokensNumber = 0;
pSpEnumTokens->GetCount(&ulTokensNumber);
2024-04-02 15:36:52 +08:00
ISpObjectToken *m_pISpObjectToken;
2024-01-08 23:37:00 +08:00
for (ULONG i = 0; i < ulTokensNumber; i++)
{
pSpEnumTokens->Item(i, &m_pISpObjectToken);
2024-04-02 15:36:52 +08:00
WCHAR *pszVoiceId = NULL;
2024-01-08 23:37:00 +08:00
LPWSTR pszVoiceName;
if (SUCCEEDED(m_pISpObjectToken->GetId(&pszVoiceId)))
2024-04-02 15:36:52 +08:00
{
2024-01-08 23:37:00 +08:00
if (SUCCEEDED(m_pISpObjectToken->GetStringValue(NULL, &pszVoiceName)))
{
ret.emplace_back(pszVoiceName);
CoTaskMemFree(pszVoiceName);
}
CoTaskMemFree(pszVoiceId);
}
}
m_pISpObjectToken->Release();
pSpEnumTokens->Release();
}
pSpVoice->Release();
::CoUninitialize();
return ret;
}
2024-04-02 15:36:52 +08:00
int neospeechlist(int argc, wchar_t *argv[])
{
FILE *f = _wfopen(argv[1], L"wb");
for (auto key : {L"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech\\Voices", L"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech_OneCore\\Voices"})
2024-03-23 18:33:58 +08:00
{
2024-04-02 15:36:52 +08:00
auto speechs = _List(key);
for (int i = 0; i < speechs.size(); i++)
{
if (speechs[i].substr(0, 2) == L"VW")
{
fwrite(speechs[i].c_str(), 1, speechs[i].size() * 2, f);
fwrite(L"\n", 1, 2, f);
fwrite(key, 1, wcslen(key) * 2, f);
fwrite(L"\n", 1, 2, f);
auto idx = std::to_wstring(i);
fwrite(idx.c_str(), 1, idx.size() * 2, f);
fwrite(L"\n", 1, 2, f);
2024-03-23 18:33:58 +08:00
}
2024-01-08 23:37:00 +08:00
}
}
2024-04-02 15:36:52 +08:00
fclose(f);
2024-03-23 18:33:58 +08:00
return 0;
}
2024-04-02 15:36:52 +08:00
int neospeech(int argc, wchar_t *argv[])
{
auto hkey = argv[4];
auto idx = std::stoi(argv[5]);
HANDLE hPipe = CreateNamedPipe(argv[1], PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, 65535, 65535, NMPWAIT_WAIT_FOREVER, 0);
2024-01-08 23:37:00 +08:00
2024-03-23 18:33:58 +08:00
SECURITY_DESCRIPTOR sd = {};
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
2024-04-02 15:36:52 +08:00
SECURITY_ATTRIBUTES allAccess = SECURITY_ATTRIBUTES{sizeof(SECURITY_ATTRIBUTES), &sd, FALSE};
2024-03-23 18:33:58 +08:00
SetEvent(CreateEvent(&allAccess, FALSE, FALSE, argv[2]));
2024-04-02 15:36:52 +08:00
if (ConnectNamedPipe(hPipe, NULL) != NULL)
{
2024-03-23 18:33:58 +08:00
DWORD len = 0;
2024-04-02 15:36:52 +08:00
}
2024-03-23 18:33:58 +08:00
int II = 0;
2024-04-02 15:36:52 +08:00
while (true)
{
wchar_t text[10000];
2024-03-23 18:33:58 +08:00
II += 1;
DWORD _;
int speed;
2024-04-02 15:36:52 +08:00
if (!ReadFile(hPipe, (unsigned char *)&speed, 4, &_, NULL))
break;
if (!ReadFile(hPipe, (unsigned char *)text, 10000 * 2, &_, NULL))
break;
2024-03-23 18:33:58 +08:00
std::wstring content = text;
2024-04-02 15:36:52 +08:00
wchar_t newname[1024] = {0};
2024-03-23 18:33:58 +08:00
wsprintf(newname, L"%s%d.wav", argv[3], II);
std::wstring newname_ = newname;
_Speak(content, hkey, idx, speed, 100, newname_);
2024-04-02 15:36:52 +08:00
WriteFile(hPipe, newname, wcslen(newname) * 2, &_, NULL);
}
return 0;
2024-01-08 23:37:00 +08:00
}