This commit is contained in:
恍兮惚兮 2025-01-02 22:56:39 +08:00
parent 3a037da085
commit d4f16add89
13 changed files with 100 additions and 298 deletions

View File

@ -1,20 +1,4 @@
struct AutoHandle
{
HANDLE _handle;
AutoHandle(HANDLE handle) : _handle(handle) {};
~AutoHandle()
{
CloseHandle(_handle);
}
operator HANDLE()
{
return _handle;
}
operator bool()
{
return _handle == INVALID_HANDLE_VALUE;
}
};
inline SECURITY_ATTRIBUTES allAccess = std::invoke([] // allows non-admin processes to access kernel objects made by admin processes inline SECURITY_ATTRIBUTES allAccess = std::invoke([] // allows non-admin processes to access kernel objects made by admin processes
{ {
static SECURITY_DESCRIPTOR sd = {}; static SECURITY_DESCRIPTOR sd = {};

View File

@ -323,11 +323,11 @@ int main()
{ {
{ {
// 当更新进行时,禁止启动 // 当更新进行时,禁止启动
AutoHandle hMutex = CreateMutex(NULL, FALSE, L"LUNA_UPDATER_SINGLE"); CHandle hMutex{CreateMutex(NULL, FALSE, L"LUNA_UPDATER_SINGLE")};
if (GetLastError() == ERROR_ALREADY_EXISTS) if (GetLastError() == ERROR_ALREADY_EXISTS)
return 0; return 0;
} }
auto __handle = AutoHandle(CreateMutexA(&allAccess, FALSE, "LUNA_UPDATER_BLOCK")); CHandle __handle{CreateMutexA(&allAccess, FALSE, "LUNA_UPDATER_BLOCK")};
PyStand ps(L"files\\runtime"); PyStand ps(L"files\\runtime");
if (ps.DetectScript() != 0) if (ps.DetectScript() != 0)
{ {

View File

@ -55,10 +55,10 @@ std::optional<std::vector<byte>> _Speak(std::wstring &Content, const wchar_t *to
ULONG bytesRead; // this will tell the number of bytes that have been read ULONG bytesRead; // this will tell the number of bytes that have been read
std::vector<byte> datas; std::vector<byte> datas;
datas.resize(sSize + 0x3ea); datas.resize(sSize + 46);
auto pBuffer = datas.data(); // buffer to read the data auto pBuffer = datas.data(); // buffer to read the data
// memcpy(pBuffer,&wavHeader,sizeof(WAV_HEADER)); // memcpy(pBuffer,&wavHeader,sizeof(WAV_HEADER));
int fsize = sSize + 0x3ea; int fsize = sSize + 46;
int ptr = 0; int ptr = 0;
memcpy(pBuffer, "RIFF", 4); memcpy(pBuffer, "RIFF", 4);
ptr += 4; ptr += 4;

View File

@ -12,6 +12,7 @@
#include <mmdeviceapi.h> #include <mmdeviceapi.h>
#include <Psapi.h> #include <Psapi.h>
#include <atlbase.h> #include <atlbase.h>
#include <atlsync.h>
#include <iostream> #include <iostream>
#include <string> #include <string>

View File

@ -489,51 +489,10 @@ char *TranslateFull(char *otext, int freeText, int NeedAbort(int line, int lines
return out; return out;
} }
static wchar_t *logFile = 0;
void SetLogFile(wchar_t *file)
{
logFile = file;
}
wchar_t *TranslateFullLog(wchar_t *otext)
{
if (logFile && logFile[0])
{
HANDLE hMutex = CreateMutex(0, 0, L"TRAG Logging Super Mutext +10 from Outer Space");
DWORD res;
if (hMutex)
res = WaitForSingleObject(hMutex, 2000);
HANDLE hFile = CreateFile(logFile, GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_ALWAYS, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
DWORD junk;
if (GetLastError() == ERROR_ALREADY_EXISTS)
SetFilePointer(hFile, 0, 0, FILE_END);
else
{
wchar_t bom = 0xFEFF;
WriteFile(hFile, &bom, sizeof(wchar_t), &junk, 0);
}
WriteFile(hFile, otext, sizeof(wchar_t) * wcslen(otext), &junk, 0);
WriteFile(hFile, L"\r\n", sizeof(wchar_t) * 2, &junk, 0);
CloseHandle(hFile);
}
if (hMutex)
{
// Prolly not needed.
if (WAIT_OBJECT_0 == res)
ReleaseMutex(hMutex);
CloseHandle(hMutex);
}
}
return TranslateFull(otext);
}
struct AtlasConfig atlcfg; struct AtlasConfig atlcfg;
void writestring(const wchar_t *text, HANDLE hPipe); void writestring(const wchar_t *text, HANDLE hPipe);
wchar_t *readstring(HANDLE hPipe); wchar_t *readstring(HANDLE hPipe);
HANDLE mutex = NULL;
int atlaswmain(int argc, wchar_t *argv[]) int atlaswmain(int argc, wchar_t *argv[])
{ {
@ -548,33 +507,6 @@ int atlaswmain(int argc, wchar_t *argv[])
if (!src) if (!src)
break; break;
if (!mutex)
{
mutex = CreateMutex(NULL, FALSE, NULL);
if (!mutex)
{
return false;
}
}
bool waitingForMutex = true;
while (waitingForMutex)
{
switch (WaitForSingleObject(mutex, INFINITE))
{
case WAIT_OBJECT_0:
{
waitingForMutex = false;
break;
}
case WAIT_ABANDONED:
{
return false;
}
default:
{
}
}
}
if (!AtlasIsLoaded()) if (!AtlasIsLoaded())
{ {
// atlcfg.flags = ~BREAK_ON_SINGLE_LINE_BREAKS; // atlcfg.flags = ~BREAK_ON_SINGLE_LINE_BREAKS;
@ -583,7 +515,6 @@ int atlaswmain(int argc, wchar_t *argv[])
InitAtlas(atlcfg, ATLAS_JAP_TO_ENG); InitAtlas(atlcfg, ATLAS_JAP_TO_ENG);
if (!AtlasIsLoaded()) if (!AtlasIsLoaded())
{ {
ReleaseMutex(mutex);
writestring(0, hPipe); writestring(0, hPipe);
return false; return false;
} }
@ -592,7 +523,6 @@ int atlaswmain(int argc, wchar_t *argv[])
writestring(text, hPipe); writestring(text, hPipe);
free(src); free(src);
free(text); free(text);
ReleaseMutex(mutex);
} }
return 0; return 0;

View File

@ -39,9 +39,6 @@ char *TranslateFull(char *otext, int freeText = 0, int NeedAbort(int line, int l
int AtlasIsLoaded(); int AtlasIsLoaded();
// dirty hack
void SetLogFile(wchar_t *file);
wchar_t *TranslateFullLog(wchar_t *otext);
/* /*
wchar_t path[MAX_PATH]; wchar_t path[MAX_PATH];
GetCurrentDirectory(MAX_PATH, path); GetCurrentDirectory(MAX_PATH, path);

View File

@ -39,7 +39,7 @@ std::wstring stolower(const std::wstring &s1)
std::vector<DWORD> EnumerateProcesses(const std::wstring &exe) std::vector<DWORD> EnumerateProcesses(const std::wstring &exe)
{ {
AutoHandle hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); CHandle hSnapshot{CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)};
if (hSnapshot == INVALID_HANDLE_VALUE) if (hSnapshot == INVALID_HANDLE_VALUE)
{ {
return {}; return {};

View File

@ -5,13 +5,13 @@ int updatewmain(int argc, wchar_t *argv[])
if (argc <= 1) if (argc <= 1)
return 0; return 0;
SetProcessDPIAware(); SetProcessDPIAware();
AutoHandle hMutex = CreateMutex(NULL, FALSE, L"LUNA_UPDATER_SINGLE"); CHandle hMutex{CreateMutex(NULL, FALSE, L"LUNA_UPDATER_SINGLE")};
if (GetLastError() == ERROR_ALREADY_EXISTS) if (GetLastError() == ERROR_ALREADY_EXISTS)
return 0; return 0;
while (true) while (true)
{ {
AutoHandle semaphore = CreateMutex(NULL, FALSE, L"LUNA_UPDATER_BLOCK"); CHandle semaphore{CreateMutex(NULL, FALSE, L"LUNA_UPDATER_BLOCK")};
if (GetLastError() != ERROR_ALREADY_EXISTS) if (GetLastError() != ERROR_ALREADY_EXISTS)
break; break;
Sleep(1000); Sleep(1000);

View File

@ -26,12 +26,10 @@ namespace ebyroid
ApiAdapter *ApiAdapter::Create(const char *dllpath) ApiAdapter *ApiAdapter::Create(const char *dllpath)
{ {
printf("dllpath %s\n", dllpath);
HINSTANCE handle = LoadLibraryA(dllpath); HINSTANCE handle = LoadLibraryA(dllpath);
if (handle == nullptr) if (handle == nullptr)
{ {
char m[128]; char m[128];
printf("load error\n");
std::snprintf(m, std::snprintf(m,
128, 128,
"LoadLibrary failed with code %d (Check out the voiceroid path setting)", "LoadLibrary failed with code %d (Check out the voiceroid path setting)",
@ -52,7 +50,6 @@ namespace ebyroid
adapter->text_to_speech_ = LoadProc<ApiTextToSpeech>(handle, "_AITalkAPI_TextToSpeech@12"); adapter->text_to_speech_ = LoadProc<ApiTextToSpeech>(handle, "_AITalkAPI_TextToSpeech@12");
adapter->close_speech_ = LoadProc<ApiCloseSpeech>(handle, "_AITalkAPI_CloseSpeech@8"); adapter->close_speech_ = LoadProc<ApiCloseSpeech>(handle, "_AITalkAPI_CloseSpeech@8");
adapter->get_data_ = LoadProc<ApiGetData>(handle, "_AITalkAPI_GetData@16"); adapter->get_data_ = LoadProc<ApiGetData>(handle, "_AITalkAPI_GetData@16");
printf("load dll ok\n");
return adapter; return adapter;
} }

View File

@ -34,28 +34,17 @@ namespace ebyroid
return ebyroid; return ebyroid;
} }
int Ebyroid::Hiragana(const unsigned char *inbytes, unsigned char **outbytes, size_t *outsize) int Ebyroid::Hiragana(const char *inbytes, std::vector<char> &output)
{ {
Response *const response = new Response(api_adapter_); Response<char> response{api_adapter_};
printf("1\n");
TJobParam param; TJobParam param;
param.mode_in_out = IOMODE_PLAIN_TO_AIKANA; param.mode_in_out = IOMODE_PLAIN_TO_AIKANA;
param.user_data = response; param.user_data = &response;
char eventname[32];
std::sprintf(eventname, "TTKLOCK:%p", response);
printf("12\n");
HANDLE event = CreateEventA(NULL, TRUE, FALSE, eventname);
printf("3\n");
int32_t job_id; int32_t job_id;
ResultCode result = api_adapter_->TextToKana(&job_id, &param, (const char *)inbytes); ResultCode result = api_adapter_->TextToKana(&job_id, &param, inbytes);
printf("4\n");
if (result != ERR_SUCCESS) if (result != ERR_SUCCESS)
{ {
delete response;
printf("%d\n", result);
ResetEvent(event);
CloseHandle(event);
static const char *format = "TextToKana failed with the result code %d\n" static const char *format = "TextToKana failed with the result code %d\n"
"Given inbytes: %s"; "Given inbytes: %s";
@ -63,53 +52,33 @@ namespace ebyroid
std::snprintf(m, 0xFFFF, format, result, inbytes); std::snprintf(m, 0xFFFF, format, result, inbytes);
throw std::runtime_error(m); throw std::runtime_error(m);
} }
printf("6\n"); WaitForSingleObject(response.event, INFINITE);
WaitForSingleObject(event, INFINITE);
ResetEvent(event);
CloseHandle(event);
printf("8\n");
// finalize // finalize
result = api_adapter_->CloseKana(job_id); result = api_adapter_->CloseKana(job_id);
if (result != ERR_SUCCESS) if (result != ERR_SUCCESS)
{ {
delete response;
throw std::runtime_error("wtf"); throw std::runtime_error("wtf");
} }
// write to output memory // write to output memory
vector<unsigned char> buffer = response->End(); output = response.End();
*outsize = buffer.size();
*outbytes = (unsigned char *)malloc(buffer.size() + 1);
std::copy(buffer.begin(), buffer.end(), *outbytes);
*(*outbytes + buffer.size()) = '\0';
delete response;
return 0; return 0;
} }
int Ebyroid::Speech(const unsigned char *inbytes, int Ebyroid::Speech(const char *inbytes, std::vector<int16_t> &output, uint32_t mode)
int16_t **outbytes,
size_t *outsize,
uint32_t mode)
{ {
Response *const response = new Response(api_adapter_); Response<int16_t> response{api_adapter_};
TJobParam param; TJobParam param;
param.mode_in_out = mode == 0u ? IOMODE_AIKANA_TO_WAVE : (JobInOut)mode; param.mode_in_out = mode == 0u ? IOMODE_AIKANA_TO_WAVE : (JobInOut)mode;
param.user_data = response; param.user_data = &response;
char eventname[32];
sprintf(eventname, "TTSLOCK:%p", response);
HANDLE event = CreateEventA(NULL, TRUE, FALSE, eventname);
int32_t job_id; int32_t job_id;
ResultCode result = api_adapter_->TextToSpeech(&job_id, &param, (const char *)inbytes); ResultCode result = api_adapter_->TextToSpeech(&job_id, &param, inbytes);
if (result != ERR_SUCCESS) if (result != ERR_SUCCESS)
{ {
delete response;
ResetEvent(event);
CloseHandle(event);
static const char *format = "TextToSpeech failed with the result code %d\n" static const char *format = "TextToSpeech failed with the result code %d\n"
"Given inbytes: %s"; "Given inbytes: %s";
char m[0xFFFF]; char m[0xFFFF];
@ -117,49 +86,21 @@ namespace ebyroid
throw std::runtime_error(m); throw std::runtime_error(m);
} }
WaitForSingleObject(event, INFINITE); WaitForSingleObject(response.event, INFINITE);
ResetEvent(event);
CloseHandle(event);
// finalize // finalize
result = api_adapter_->CloseSpeech(job_id); result = api_adapter_->CloseSpeech(job_id);
if (result != ERR_SUCCESS) if (result != ERR_SUCCESS)
{ {
delete response;
throw std::runtime_error("wtf"); throw std::runtime_error("wtf");
} }
// write to output memory // write to output memory
vector<int16_t> buffer = response->End16(); output = response.End();
*outsize = buffer.size() * 2; // sizeof(int16_t) == 2
*outbytes = (int16_t *)malloc(buffer.size() * 2 + 1);
std::copy(buffer.begin(), buffer.end(), *outbytes);
*((char *)*outbytes + (buffer.size() * 2)) = '\0';
delete response;
return 0; return 0;
} }
void Response::Write(char *bytes, uint32_t size)
{
buffer_.insert(std::end(buffer_), bytes, bytes + size);
}
void Response::Write16(int16_t *shorts, uint32_t size)
{
buffer_16_.insert(std::end(buffer_16_), shorts, shorts + size);
}
vector<unsigned char> Response::End()
{
return std::move(buffer_);
}
vector<int16_t> Response::End16()
{
return std::move(buffer_16_);
}
namespace namespace
{ {
@ -167,8 +108,7 @@ namespace ebyroid
{ {
SettingsBuilder builder(base_dir, voice); SettingsBuilder builder(base_dir, voice);
Settings settings = builder.Build(); Settings settings = builder.Build();
std::unique_ptr<ApiAdapter> adapter{ApiAdapter::Create(dllpath.c_str())};
ApiAdapter *adapter = ApiAdapter::Create(dllpath.c_str());
TConfig config; TConfig config;
config.hz_voice_db = settings.frequency; config.hz_voice_db = settings.frequency;
@ -184,39 +124,17 @@ namespace ebyroid
config.code_auth_seed = "PROJECT-VOICeVIO-SFE"; config.code_auth_seed = "PROJECT-VOICeVIO-SFE";
result = adapter->Init(&config); result = adapter->Init(&config);
} }
printf("init %d\n", result);
if (result != ERR_SUCCESS) if (result != ERR_SUCCESS)
{ {
delete adapter;
string message = "API initialization failed with code "; string message = "API initialization failed with code ";
message += std::to_string(result); message += std::to_string(result);
throw std::runtime_error(message); throw std::runtime_error(message);
} }
/*pair<bool, string>xx = WithDirecory(settings.base_dir, [adapter, settings]() {
ResultCode result = adapter->LangLoad(settings.language_dir);
printf("laod lang %d\n", result);
if (result != ERR_SUCCESS) {
char m[64];
std::snprintf(m, 64, "API LangLoad failed (could not load language) with code %d", result);
return pair<bool, string>(true, string(m));
}
return pair<bool, string>(false, string());
});*/
bool x = SetCurrentDirectoryA(settings.base_dir);
SetDllDirectoryA(settings.base_dir); SetDllDirectoryA(settings.base_dir);
printf("%d\n", x);
wchar_t buffer[1000] = {0};
DWORD sz = 1000;
GetCurrentDirectoryW(sz, buffer);
wprintf(L"%s\n", buffer);
result = adapter->LangLoad(settings.language_dir); result = adapter->LangLoad(settings.language_dir);
printf("%s %s \n", settings.base_dir, settings.language_dir);
printf("loadvoice %d\n", result);
result = adapter->VoiceLoad(settings.voice_name); result = adapter->VoiceLoad(settings.voice_name);
printf("loadvoice %s %d\n", settings.voice_name, result);
if (result != ERR_SUCCESS) if (result != ERR_SUCCESS)
{ {
delete adapter;
string message = "API Load Voice failed (Could not load voice data) with code "; string message = "API Load Voice failed (Could not load voice data) with code ";
message += std::to_string(result); message += std::to_string(result);
throw std::runtime_error(message); throw std::runtime_error(message);
@ -225,96 +143,73 @@ namespace ebyroid
result = adapter->GetParam((void *)0, &param_size); result = adapter->GetParam((void *)0, &param_size);
if (result != ERR_INSUFFICIENT) if (result != ERR_INSUFFICIENT)
{ // NOTE: Code -20 is expected here { // NOTE: Code -20 is expected here
delete adapter;
string message = "API Get Param failed (Could not acquire the size) with code "; string message = "API Get Param failed (Could not acquire the size) with code ";
message += std::to_string(result); message += std::to_string(result);
throw std::runtime_error(message); throw std::runtime_error(message);
} }
if (param_size == sizeof(TTtsParam))
printf("param->size %d\n", param_size);
if (param_size == 500)
{ // voiceroid2 { // voiceroid2
char *param_buffer = new char[param_size]; TTtsParam param;
TTtsParam *param = (TTtsParam *)param_buffer;
// TTtsParam* param = (TTtsParam*) param_buffer; // TTtsParam* param = (TTtsParam*) param_buffer;
param->size = param_size; param.size = param_size;
result = adapter->GetParam(param, &param_size); result = adapter->GetParam(&param, &param_size);
printf("%s %d\n", "GetParam", result);
if (result != ERR_SUCCESS) if (result != ERR_SUCCESS)
{ {
delete[] param_buffer;
delete adapter;
string message = "API Get Param failed with code "; string message = "API Get Param failed with code ";
message += std::to_string(result); message += std::to_string(result);
throw std::runtime_error(message); throw std::runtime_error(message);
} }
param->extend_format = BOTH; param.extend_format = BOTH;
param->proc_text_buf = HiraganaCallback; param.proc_text_buf = HiraganaCallback;
param->proc_raw_buf = SpeechCallback; param.proc_raw_buf = SpeechCallback;
param->proc_event_tts = nullptr; param.proc_event_tts = nullptr;
param->len_raw_buf_bytes = kConfigRawbufSize; param.len_raw_buf_bytes = kConfigRawbufSize;
param->volume = volume; param.volume = volume;
printf("1\n"); param.speaker[0].volume = volume;
param->speaker[0].volume = volume; /*param.speaker[0].pitch = 1.111;
/*param->speaker[0].pitch = 1.111; param.speaker[0].pause_middle = 80;
param->speaker[0].pause_middle = 80; param.speaker[0].pause_sentence = 200;
param->speaker[0].pause_sentence = 200; param.speaker[0].pause_long = 100;
param->speaker[0].pause_long = 100; param.speaker[0].range = 0.893;*/
param->speaker[0].range = 0.893;*/ param.speaker[0].speed = speed;
param->speaker[0].speed = speed; result = adapter->SetParam(&param);
//printf("2 %d %d\n", volume, speed);
result = adapter->SetParam(param);
printf("3 %d\n", result);
if (result != ERR_SUCCESS) if (result != ERR_SUCCESS)
{ {
delete[] param_buffer;
delete adapter;
string message = "API Set Param failed with code "; string message = "API Set Param failed with code ";
message += std::to_string(result); message += std::to_string(result);
throw std::runtime_error(message); throw std::runtime_error(message);
} }
printf("3\n");
delete[] param_buffer;
} }
else if (param_size == 416) else if (param_size == sizeof(AITalk_TTtsParam))
{ // voiceroid+ { // voiceroid+
char *param_buffer = new char[param_size]; AITalk_TTtsParam param;
AITalk_TTtsParam *param = (AITalk_TTtsParam *)param_buffer;
// TTtsParam* param = (TTtsParam*) param_buffer; // TTtsParam* param = (TTtsParam*) param_buffer;
param->size = param_size; param.size = param_size;
result = adapter->GetParam(param, &param_size); result = adapter->GetParam(&param, &param_size);
if (result != ERR_SUCCESS) if (result != ERR_SUCCESS)
{ {
delete[] param_buffer;
delete adapter;
string message = "API Get Param failed with code "; string message = "API Get Param failed with code ";
message += std::to_string(result); message += std::to_string(result);
throw std::runtime_error(message); throw std::runtime_error(message);
} }
printf("numSpeakers %d\n", param->numSpeakers); param.proc_text_buf = HiraganaCallback;
param->proc_text_buf = HiraganaCallback; param.proc_raw_buf = SpeechCallback;
param->proc_raw_buf = SpeechCallback; param.proc_event_tts = nullptr;
param->proc_event_tts = nullptr; param.lenRawBufBytes = kConfigRawbufSize;
param->lenRawBufBytes = kConfigRawbufSize;
param->volume = volume; param.volume = volume;
result = adapter->SetParam(param); result = adapter->SetParam(&param);
printf("SetParam ok %d\n", result);
if (result != ERR_SUCCESS) if (result != ERR_SUCCESS)
{ {
delete[] param_buffer;
delete adapter;
string message = "API Set Param failed with code "; string message = "API Set Param failed with code ";
message += std::to_string(result); message += std::to_string(result);
printf("%s\n", message.c_str());
throw std::runtime_error(message); throw std::runtime_error(message);
} }
delete[] param_buffer;
} }
auto _ = adapter.get();
printf("%s \n", "setparam all ok"); adapter.release();
return adapter; return _;
} }
inline pair<bool, string> WithDirecory(const char *dir, function<pair<bool, string>(void)> yield) inline pair<bool, string> WithDirecory(const char *dir, function<pair<bool, string>(void)> yield)
@ -360,7 +255,7 @@ namespace ebyroid
} }
int __stdcall HiraganaCallback(EventReasonCode reason_code, int32_t job_id, IntPtr user_data) int __stdcall HiraganaCallback(EventReasonCode reason_code, int32_t job_id, IntPtr user_data)
{ {
Response *const response = (Response *)user_data; auto response = (Response<char> *)user_data;
ApiAdapter *api_adapter = response->api_adapter(); ApiAdapter *api_adapter = response->api_adapter();
if (reason_code != TEXTBUF_FULL && reason_code != TEXTBUF_FLUSH && reason_code != TEXTBUF_CLOSE) if (reason_code != TEXTBUF_FULL && reason_code != TEXTBUF_FLUSH && reason_code != TEXTBUF_CLOSE)
@ -370,7 +265,7 @@ namespace ebyroid
} }
static constexpr int kBufferSize = 0x1000; static constexpr int kBufferSize = 0x1000;
char *buffer = new char[kBufferSize]; char buffer[kBufferSize];
while (true) while (true)
{ {
uint32_t size, pos; uint32_t size, pos;
@ -386,14 +281,10 @@ namespace ebyroid
break; break;
} }
} }
delete[] buffer;
if (reason_code == TEXTBUF_CLOSE) if (reason_code == TEXTBUF_CLOSE)
{ {
char eventname[32]; response->event.Set();
sprintf(eventname, "TTKLOCK:%p", response);
HANDLE event = OpenEventA(EVENT_ALL_ACCESS, FALSE, eventname);
SetEvent(event);
} }
return 0; return 0;
} }
@ -403,7 +294,7 @@ namespace ebyroid
uint64_t tick, uint64_t tick,
IntPtr user_data) IntPtr user_data)
{ {
Response *const response = (Response *)user_data; auto response = (Response<int16_t> *)user_data;
ApiAdapter *api_adapter = response->api_adapter(); ApiAdapter *api_adapter = response->api_adapter();
if (reason_code != RAWBUF_FULL && reason_code != RAWBUF_FLUSH && reason_code != RAWBUF_CLOSE) if (reason_code != RAWBUF_FULL && reason_code != RAWBUF_FLUSH && reason_code != RAWBUF_CLOSE)
@ -413,7 +304,7 @@ namespace ebyroid
} }
static constexpr int kBufferSize = 0xFFFF; static constexpr int kBufferSize = 0xFFFF;
int16_t *buffer = new int16_t[kBufferSize]; int16_t buffer[kBufferSize];
while (true) while (true)
{ {
uint32_t size, pos; uint32_t size, pos;
@ -422,20 +313,16 @@ namespace ebyroid
{ {
break; break;
} }
response->Write16(buffer, size); response->Write(buffer, size);
if (kBufferSize > size) if (kBufferSize > size)
{ {
break; break;
} }
} }
delete[] buffer;
if (reason_code == RAWBUF_CLOSE) if (reason_code == RAWBUF_CLOSE)
{ {
char eventname[32]; response->event.Set();
sprintf(eventname, "TTSLOCK:%p", response);
HANDLE event = OpenEventA(EVENT_ALL_ACCESS, FALSE, eventname);
SetEvent(event);
} }
return 0; return 0;
} }

View File

@ -1,7 +1,6 @@
#ifndef EBYROID_H #ifndef EBYROID_H
#define EBYROID_H #define EBYROID_H
namespace ebyroid namespace ebyroid
{ {
@ -24,8 +23,8 @@ namespace ebyroid
~Ebyroid(); ~Ebyroid();
static Ebyroid *Create(const std::string &base_dir, const std::string &dllpath, const std::string &voice, float volume, float speed); static Ebyroid *Create(const std::string &base_dir, const std::string &dllpath, const std::string &voice, float volume, float speed);
int Hiragana(const unsigned char *inbytes, unsigned char **outbytes, size_t *outsize); int Hiragana(const char *inbytes, std::vector<char> &);
int Speech(const unsigned char *inbytes, int16_t **outbytes, size_t *outsize, uint32_t mode = 0u); int Speech(const char *inbytes, std::vector<int16_t> &, uint32_t mode = 0u);
int Convert(const ConvertParams &params, int Convert(const ConvertParams &params,
const unsigned char *inbytes, const unsigned char *inbytes,
int16_t **outbytes, int16_t **outbytes,
@ -36,20 +35,27 @@ namespace ebyroid
ApiAdapter *api_adapter_; ApiAdapter *api_adapter_;
}; };
template <typename T>
class Response class Response
{ {
public: public:
Response(ApiAdapter *adapter) : api_adapter_(adapter) {} Response(ApiAdapter *adapter) : api_adapter_(adapter)
void Write(char *bytes, uint32_t size); {
void Write16(int16_t *shorts, uint32_t size); event.Create(NULL, FALSE, FALSE, NULL);
std::vector<unsigned char> End(); }
std::vector<int16_t> End16(); void Write(T *bytes, size_t size)
{
buffer_.insert(std::end(buffer_), bytes, bytes + size);
}
std::vector<T> End()
{
return std::move(buffer_);
}
ApiAdapter *api_adapter() { return api_adapter_; }; ApiAdapter *api_adapter() { return api_adapter_; };
CEvent event;
private: private:
ApiAdapter *api_adapter_; ApiAdapter *api_adapter_;
std::vector<unsigned char> buffer_; std::vector<T> buffer_;
std::vector<int16_t> buffer_16_;
}; };
} // namespace ebyroid } // namespace ebyroid

View File

@ -28,14 +28,11 @@ int voiceroid2wmain(int argc, wchar_t *wargv[])
SetEvent(CreateEventA(&allAccess, FALSE, FALSE, argv[4])); SetEvent(CreateEventA(&allAccess, FALSE, FALSE, argv[4]));
ConnectNamedPipe(hPipe, NULL); ConnectNamedPipe(hPipe, NULL);
int freq1; int freq1;
unsigned char input_j[4096] = {0}; char input_j[4096] = {0};
DWORD _; DWORD _;
while (true) while (true)
{ {
ZeroMemory(input_j, sizeof(input_j)); ZeroMemory(input_j, sizeof(input_j));
unsigned char *out;
size_t output_size;
int16_t *out2;
if (!ReadFile(hPipe, input_j, 4096, &_, NULL)) if (!ReadFile(hPipe, input_j, 4096, &_, NULL))
break; break;
@ -51,8 +48,8 @@ int voiceroid2wmain(int argc, wchar_t *wargv[])
{ {
delete ebyroid; delete ebyroid;
} }
ebyroid = Ebyroid::Create((const char *)argv[1], //"C:\\dataH\\Yukari2", ebyroid = Ebyroid::Create(argv[1], //"C:\\dataH\\Yukari2",
(const char *)argv[2], argv[2],
voice.c_str(), voice.c_str(),
2, 2,
rate); // 1); //0.1-2,0.5-4 rate); // 1); //0.1-2,0.5-4
@ -65,10 +62,12 @@ int voiceroid2wmain(int argc, wchar_t *wargv[])
freq1 = 44100; freq1 = 44100;
else else
freq1 = 22050; freq1 = 22050;
// int result = ebyroid->Hiragana((const unsigned char*)UnicodeToShift_jis(input), &out, &output_size); std::vector<char> output;
int result = ebyroid->Hiragana((const unsigned char *)input_j, &out, &output_size); int result = ebyroid->Hiragana(input_j, output);
output.push_back(0);
result = ebyroid->Speech(out, &out2, &output_size); std::vector<int16_t> binary;
result = ebyroid->Speech(output.data(), binary);
size_t output_size = binary.size() * 2;
int fsize = output_size + 44; int fsize = output_size + 44;
if (fsize > 1024 * 1024 * 10) if (fsize > 1024 * 1024 * 10)
{ {
@ -98,12 +97,9 @@ int voiceroid2wmain(int argc, wchar_t *wargv[])
ptr += 4; ptr += 4;
memcpy(mapview + ptr, &output_size, 4); memcpy(mapview + ptr, &output_size, 4);
ptr += 4; ptr += 4;
memcpy(mapview + ptr, out2, output_size); memcpy(mapview + ptr, binary.data(), output_size);
} }
WriteFile(hPipe, &fsize, 4, &_, NULL); WriteFile(hPipe, &fsize, 4, &_, NULL);
free(out);
free(out2);
} }
return 0; return 0;
} }

View File

@ -26,18 +26,20 @@ DECLARE_API void showintab(HWND hwnd, bool show, bool tool)
DECLARE_API bool pid_running(DWORD pid) DECLARE_API bool pid_running(DWORD pid)
{ {
DWORD code; CHandle hprocess{OpenProcess(
#ifndef WINXP #ifndef WINXP
GetExitCodeProcess(AutoHandle(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid)), &code); PROCESS_QUERY_LIMITED_INFORMATION,
#else #else
GetExitCodeProcess(AutoHandle(OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)), &code); PROCESS_QUERY_INFORMATION,
#endif #endif
FALSE, pid)};
if (!hprocess)
return false;
DWORD code;
GetExitCodeProcess(hprocess, &code);
// 句柄必須具有 PROCESS_QUERY_INFORMATION 或 PROCESS_QUERY_LIMITED_INFORMATION 訪問許可權。 如需詳細資訊,請參閱 處理安全性和訪問許可權。 // 句柄必須具有 PROCESS_QUERY_INFORMATION 或 PROCESS_QUERY_LIMITED_INFORMATION 訪問許可權。 如需詳細資訊,請參閱 處理安全性和訪問許可權。
// Windows Server 2003 和 Windows XP 句柄必須具有 PROCESS_QUERY_INFORMATION 訪問許可權。 // Windows Server 2003 和 Windows XP 句柄必須具有 PROCESS_QUERY_INFORMATION 訪問許可權。
return code == STILL_ACTIVE; return code == STILL_ACTIVE;
// auto process = AutoHandle(OpenProcess(SYNCHRONIZE, FALSE, pid));
// DWORD ret = WaitForSingleObject(process, 0);
// return ret == WAIT_TIMEOUT;
} }
struct __EnumWindowsProc struct __EnumWindowsProc
@ -79,11 +81,13 @@ DECLARE_API bool Is64bit(DWORD pid)
{ {
if (!Is64BitOS()) if (!Is64BitOS())
return false; return false;
CHandle hprocess{OpenProcess(
#ifndef WINXP #ifndef WINXP
auto hprocess = AutoHandle(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid)); PROCESS_QUERY_LIMITED_INFORMATION,
#else #else
auto hprocess = AutoHandle(OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid)); PROCESS_QUERY_INFORMATION,
#endif #endif
FALSE, pid)};
// 進程的控制碼。 控制碼必須具有PROCESS_QUERY_INFORMATION或PROCESS_QUERY_LIMITED_INFORMATION存取權限。 如需詳細資訊,請參閱 處理安全性和存取權限。 // 進程的控制碼。 控制碼必須具有PROCESS_QUERY_INFORMATION或PROCESS_QUERY_LIMITED_INFORMATION存取權限。 如需詳細資訊,請參閱 處理安全性和存取權限。
// Windows Server 2003 和 Windows XP 控制碼必須具有PROCESS_QUERY_INFORMATION存取權限。 // Windows Server 2003 和 Windows XP 控制碼必須具有PROCESS_QUERY_INFORMATION存取權限。
BOOL f64bitProc = false; BOOL f64bitProc = false;
@ -94,7 +98,7 @@ DECLARE_API bool Is64bit(DWORD pid)
DECLARE_API void getprocesses(void (*cb)(DWORD, const wchar_t *)) DECLARE_API void getprocesses(void (*cb)(DWORD, const wchar_t *))
{ {
std::unordered_map<std::wstring, std::vector<int>> exe_pid; std::unordered_map<std::wstring, std::vector<int>> exe_pid;
AutoHandle hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); CHandle hSnapshot{CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)};
if (hSnapshot == INVALID_HANDLE_VALUE) if (hSnapshot == INVALID_HANDLE_VALUE)
return; return;