Remove a bunch on unnecessary copies when constructing output messages

Also start work on custom mark support
This commit is contained in:
Kovid Goyal 2023-01-25 11:14:22 +05:30
parent aa11af3510
commit f7bbbbaf3f
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 23 additions and 12 deletions

View File

@ -341,7 +341,7 @@ output(id_type cmd_id, std::string_view const &msg_type, json_val const &&msg) {
static void static void
output_error(id_type cmd_id, std::string_view const &msg, std::string_view const &error, int64_t line, HRESULT hr=S_OK) { output_error(id_type cmd_id, std::string_view const &msg, std::string_view const &error, int64_t line, HRESULT hr=S_OK) {
std::map<std::string, json_val> m = {{"msg", json_val(msg)}, {"error", json_val(error)}, {"file", json_val("winspeech.cpp")}, {"line", json_val(line)}}; std::map<std::string, json_val> m = {{"msg", msg}, {"error", error}, {"file", "winspeech.cpp"}, {"line", line}};
if (hr != S_OK) m["hr"] = json_val::from_hresult(hr); if (hr != S_OK) m["hr"] = json_val::from_hresult(hr);
output(cmd_id, "error", std::move(m)); output(cmd_id, "error", std::move(m));
} }
@ -770,19 +770,19 @@ class Synthesizer {
revoker.playback_state_changed = player.PlaybackSession().PlaybackStateChanged( revoker.playback_state_changed = player.PlaybackSession().PlaybackStateChanged(
winrt::auto_revoke, [cmd_id](auto session, auto const&) { winrt::auto_revoke, [cmd_id](auto session, auto const&) {
if (main_loop_is_running.load()) sx.output( if (main_loop_is_running.load()) sx.output(
cmd_id, "playback_state_changed", {{"state", json_val(session.PlaybackState())}}); cmd_id, "playback_state_changed", {{"state", session.PlaybackState()}});
}); });
revoker.media_opened = player.MediaOpened(winrt::auto_revoke, [cmd_id](auto player, auto const&) { revoker.media_opened = player.MediaOpened(winrt::auto_revoke, [cmd_id](auto player, auto const&) {
if (main_loop_is_running.load()) sx.output( if (main_loop_is_running.load()) sx.output(
cmd_id, "media_state_changed", {{"state", json_val("opened")}}); cmd_id, "media_state_changed", {{"state", "opened"}});
}); });
revoker.media_ended = player.MediaEnded(winrt::auto_revoke, [cmd_id](auto player, auto const&) { revoker.media_ended = player.MediaEnded(winrt::auto_revoke, [cmd_id](auto player, auto const&) {
if (main_loop_is_running.load()) sx.output( if (main_loop_is_running.load()) sx.output(
cmd_id, "media_state_changed", {{"state", json_val("ended")}}); cmd_id, "media_state_changed", {{"state", "ended"}});
}); });
revoker.media_failed = player.MediaFailed(winrt::auto_revoke, [cmd_id](auto player, auto const& args) { revoker.media_failed = player.MediaFailed(winrt::auto_revoke, [cmd_id](auto player, auto const& args) {
if (main_loop_is_running.load()) sx.output( if (main_loop_is_running.load()) sx.output(
cmd_id, "media_state_changed", {{"state", json_val("failed")}, {"error", args.ErrorMessage()}, {"code", json_val(args.Error())}}); cmd_id, "media_state_changed", {{"state", "failed"}, {"error", args.ErrorMessage()}, {"code", args.Error()}});
}); });
current_stream = stream; current_stream = stream;
current_source = MediaSource::CreateFromStream(current_stream, current_stream.ContentType()); current_source = MediaSource::CreateFromStream(current_stream, current_stream.ContentType());
@ -826,8 +826,6 @@ class Synthesizer {
void initialize() { void initialize() {
synth = SpeechSynthesizer(); synth = SpeechSynthesizer();
// synth.Options().IncludeSentenceBoundaryMetadata(true);
synth.Options().IncludeWordBoundaryMetadata(true);
player = MediaPlayer(); player = MediaPlayer();
player.AudioCategory(MediaPlayerAudioCategory::Speech); player.AudioCategory(MediaPlayerAudioCategory::Speech);
player.AutoPlay(true); player.AutoPlay(true);
@ -851,8 +849,10 @@ class Synthesizer {
{ std::scoped_lock sl(recursive_lock); { std::scoped_lock sl(recursive_lock);
stop_current_activity(); stop_current_activity();
current_cmd_id.store(cmd_id); current_cmd_id.store(cmd_id);
synth.Options().IncludeSentenceBoundaryMetadata(true);
synth.Options().IncludeWordBoundaryMetadata(true);
} }
output(cmd_id, "synthesizing", {{"ssml", json_val(is_ssml)}}); output(cmd_id, "synthesizing", {{"ssml", is_ssml}});
bool ok = false; bool ok = false;
try { try {
if (is_ssml) stream = co_await synth.SynthesizeSsmlToStreamAsync(text); if (is_ssml) stream = co_await synth.SynthesizeSsmlToStreamAsync(text);
@ -888,6 +888,7 @@ handle_speak(id_type cmd_id, std::vector<std::wstring_view> &parts) {
} }
parts.erase(parts.begin(), parts.begin() + 2); parts.erase(parts.begin(), parts.begin() + 2);
std::wstring address; std::wstring address;
std::wstring_view text;
id_type shm_size = 0; id_type shm_size = 0;
if (is_shm) { if (is_shm) {
shm_size = parse_id(parts.at(0)); shm_size = parse_id(parts.at(0));
@ -903,11 +904,13 @@ handle_speak(id_type cmd_id, std::vector<std::wstring_view> &parts) {
return; return;
} }
address = winrt::to_hstring((const char*)mapping.ptr()); address = winrt::to_hstring((const char*)mapping.ptr());
text = address;
} else { } else {
address = join(parts); address = join(parts);
if (address.size() == 0) throw std::string("Address missing"); if (address.size() == 0) throw std::string("Address missing");
text = address;
} }
sx.speak(cmd_id, address, is_ssml); sx.speak(cmd_id, text, is_ssml);
} }
static int64_t static int64_t
@ -953,7 +956,7 @@ handle_stdin_message(winrt::hstring const &&msg) {
auto vol = parse_double(parts[0].data()); auto vol = parse_double(parts[0].data());
sx.volume(vol); sx.volume(vol);
} }
output(cmd_id, "volume", {{"value", json_val(sx.volume())}}); output(cmd_id, "volume", {{"value", sx.volume()}});
} }
else throw std::string("Unknown command: ") + winrt::to_string(command); else throw std::string("Unknown command: ") + winrt::to_string(command);
} CATCH_ALL_EXCEPTIONS("Error handling input message", cmd_id); } CATCH_ALL_EXCEPTIONS("Error handling input message", cmd_id);

View File

@ -61,7 +61,7 @@ def encode_to_file_object(text, output) -> int:
return sz return sz
def develop_speech(text='Lucca Brazzi sleeps with the fishes.'): def develop_speech(text='Lucca Brazzi sleeps with the fishes.', mark_words=False):
p = start_worker() p = start_worker()
print('\x1b[32mSpeaking', text, '\x1b[39m]]'[:-2], flush=True) print('\x1b[32mSpeaking', text, '\x1b[39m]]'[:-2], flush=True)
q = Queue() q = Queue()
@ -79,8 +79,16 @@ def develop_speech(text='Lucca Brazzi sleeps with the fishes.'):
Thread(name='Echo', target=echo_output, args=(p,), daemon=True).start() Thread(name='Echo', target=echo_output, args=(p,), daemon=True).start()
exit_code = 0 exit_code = 0
st = 'ssml' if '<speak' in text else 'text'
if mark_words:
words = text.split()
text = []
for i, w in enumerate(words):
text.append(i+1)
text.append(w)
if w is not words[-1]:
text.append(' ')
with closing(p.stdin), closing(p.stdout), SharedMemory(size=max_buffer_size(text)) as shm: with closing(p.stdin), closing(p.stdout), SharedMemory(size=max_buffer_size(text)) as shm:
st = 'ssml' if '<speak' in text else 'text'
sz = encode_to_file_object(text, shm) sz = encode_to_file_object(text, shm)
try: try:
send('1 echo Synthesizer started') send('1 echo Synthesizer started')