Skip to content

Commit aec5e61

Browse files
lebedevVallat
authored andcommitted
Fix mob_Hear runtimes (Skyrat-SS13#60)
Fix build error (Skyrat-SS13#59) Fix TTS voicing empty custom say emotes (#50) Rework TTS options with sliders (#42) TTS fixes (#41) * Fix TTS subsystem initialization status * Fix TTS statistics message TTS volume preferences (#36) * Add TTS volume preferences * Prevent mocked mobs from hearing TTS * Skip TTS logic if TTS subsystem is disabled Make humans without tts_seed fallback to Arthas (#38) Silero TTS integration (#9) * Update rust_g 1.0.2 -> 1.0.4-ss220 * Add TTS sound cache folder to .gitignore * Port Silero TTS to the build * Add TTS seed selection UI and saving * making tts module * added line * Update rust_g.dm * undefs * small fix * another fix * another include fix * Remove redundant var argument prefix * Fix TypeScript issues * Add TEMPORARY playsound_local override with wait support * Fix overriden mob/living/Hear * Fix TTS messages sanitization * regex optimization * Add languageless sounds case handling * Add non-understandable messages TTS case handling * Remove broken ffmpeg paths sanitization * Fix messages queue Fix observers not hearing TTS (#33) Add TTS as separate ss220 config (#29) TTS fixes (#30) * Fix TTS broadcasting to unconsious mobs * Silent scrambled whisper TTS fixes (#21) * Make pluses cut from chat messages instead of TTS input * Half radio loudness --------- Co-authored-by: Vallat <vox.crit2013@gmail.com>
1 parent 1d1cc87 commit aec5e61

File tree

22 files changed

+4996
-1
lines changed

22 files changed

+4996
-1
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -250,3 +250,7 @@ define_sanity_output.txt
250250

251251
# Running OpenDream locally
252252
tgstation.json
253+
254+
# Ignore cached sound files.
255+
/sound/tts_cache/**/*
256+
/sound/tts_scrambled/**/*

code/__DEFINES/sound.dm

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
//THIS SHOULD ALWAYS BE THE LOWEST ONE!
3232
//KEEP IT UPDATED
3333

34-
#define CHANNEL_HIGHEST_AVAILABLE 1005 //NOVA EDIT CHANGE - JUKEBOX > ORIGINAL VALUE 1015
34+
#define CHANNEL_HIGHEST_AVAILABLE 1004 //NOVA EDIT CHANGE - JUKEBOX > ORIGINAL VALUE 1015
3535

3636
#define MAX_INSTRUMENT_CHANNELS (128 * 6)
3737

config/config.txt

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ $include comms.txt
66
$include logging.txt
77
$include resources.txt
88
$include nova/config_nova.txt
9+
$include ss220/ss220_config.txt
910
$include interviews.txt
1011
$include lua.txt
1112
$include auxtools.txt

config/ss220/ss220_config.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
## Text-to-speech
2+
#TTS_TOKEN_SILERO mytoken
3+
#TTS_ENABLED
4+
#TTS_CACHE
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#define SOUND_EFFECT_NONE 0
2+
#define SOUND_EFFECT_RADIO 1
3+
#define SOUND_EFFECT_ROBOT 2
4+
#define SOUND_EFFECT_RADIO_ROBOT 3
5+
#define SOUND_EFFECT_MEGAPHONE 4
6+
#define SOUND_EFFECT_MEGAPHONE_ROBOT 5
7+
8+
#define CHANNEL_TTS_RADIO 1004
9+
10+
#define TTS_TRAIT_PITCH_WHISPER (1<<1)
11+
#define TTS_TRAIT_RATE_FASTER (1<<2)
12+
#define TTS_TRAIT_RATE_MEDIUM (1<<3)
13+
14+
#define rustg_file_write_b64decode(text, fname) RUSTG_CALL(RUST_G, "file_write")(text, fname, "true")
15+
16+
// Hashing Operations //
17+
#define rustg_hash_string(algorithm, text) RUSTG_CALL(RUST_G, "hash_string")(algorithm, text)
18+
#define rustg_hash_file(algorithm, fname) RUSTG_CALL(RUST_G, "hash_file")(algorithm, fname)
19+
20+
#define RUSTG_HASH_MD5 "md5"
21+
22+
#ifdef RUSTG_OVERRIDE_BUILTINS
23+
#define md5(thing) (isfile(thing) ? rustg_hash_file(RUSTG_HASH_MD5, "[thing]") : rustg_hash_string(RUSTG_HASH_MD5, thing))
24+
#endif
25+
26+
// Text Operations //
27+
#define rustg_cyrillic_to_latin(text) RUSTG_CALL(RUST_G, "cyrillic_to_latin")("[text]")
28+
#define rustg_latin_to_cyrillic(text) RUSTG_CALL(RUST_G, "latin_to_cyrillic")("[text]")
29+
30+
#define TTS_CATEGORY_OTHER "Другое"
31+
#define TTS_CATEGORY_WARCRAFT3 "WarCraft 3"
32+
#define TTS_CATEGORY_HALFLIFE2 "Half-Life 2"
33+
#define TTS_CATEGORY_STARCRAFT "StarCraft"
34+
#define TTS_CATEGORY_PORTAL2 "Portal 2"
35+
#define TTS_CATEGORY_STALKER "STALKER"
36+
#define TTS_CATEGORY_DOTA2 "Dota 2"
37+
#define TTS_CATEGORY_LOL "League of Legends"
38+
#define TTS_CATEGORY_FALLOUT "Fallout"
39+
#define TTS_CATEGORY_FALLOUT2 "Fallout 2"
40+
#define TTS_CATEGORY_POSTAL2 "Postal 2"
41+
#define TTS_CATEGORY_TEAMFORTRESS2 "Team Fortress 2"
42+
#define TTS_CATEGORY_ATOMIC_HEART "Atomic Heart"
43+
#define TTS_CATEGORY_OVERWATCH "Overwatch"
44+
#define TTS_CATEGORY_SKYRIM "Skyrim"
45+
#define TTS_CATEGORY_RITA "Rita"
46+
#define TTS_CATEGORY_METRO "Metro"
47+
#define TTS_CATEGORY_HEROESOFTHESTORM "Heroes of the Storm"
48+
#define TTS_CATEGORY_HEARTHSTONE "Hearthstone"
49+
#define TTS_CATEGORY_VALORANT "Valorant"
50+
#define TTS_CATEGORY_EVILISLANDS "Evil Islands"
51+
52+
#define TTS_GENDER_ANY "Любой"
53+
#define TTS_GENDER_MALE "Мужской"
54+
#define TTS_GENDER_FEMALE "Женский"
55+
56+
#define TTS_PHRASES list(\
57+
"Так звучит мой голос.",\
58+
"Так я звучу.",\
59+
"Я.",\
60+
"Поставьте свою подпись.",\
61+
"Пора за работу.",\
62+
"Дело сделано.",\
63+
"Станция Нанотрейзен.",\
64+
"Офицер СБ.",\
65+
"Капитан.",\
66+
"Вульпканин.",\
67+
"Съешь же ещё этих мягких французских булок, да выпей чаю.",\
68+
"Клоун, прекрати разбрасывать банановые кожурки офицерам под ноги!",\
69+
"Капитан, вы уверены что хотите назначить клоуна на должность главы персонала?",\
70+
)
71+
72+
#define LOCAL_TTS_VOLUME(mob) mob.client.prefs.read_preference(/datum/preference/numeric/sound_tts_local)
73+
#define RADIO_TTS_VOLUME(mob) mob.client.prefs.read_preference(/datum/preference/numeric/sound_tts_radio)
74+
#define LOCAL_TTS_ENABLED(mob) LOCAL_TTS_VOLUME(mob)
75+
#define RADIO_TTS_ENABLED(mob) RADIO_TTS_VOLUME(mob)
76+
77+
/proc/error(msg)
78+
log_world("## ERROR: [msg]")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/datum/tts_provider/silero
2+
name = "Silero"
3+
is_enabled = TRUE
4+
5+
/datum/tts_provider/silero/request(text, datum/tts_seed/silero/seed, datum/callback/proc_callback)
6+
if(throttle_check())
7+
return FALSE
8+
9+
var/api_url = "https://api-tts.silero.ai/voice"
10+
var/ssml_text = {"<speak>[text]</speak>"}
11+
12+
var/list/req_body = list()
13+
req_body["api_token"] = CONFIG_GET(string/tts_token_silero)
14+
req_body["text"] = ssml_text
15+
req_body["sample_rate"] = 24000
16+
req_body["ssml"] = TRUE
17+
req_body["speaker"] = seed.value
18+
req_body["lang"] = "ru"
19+
req_body["remote_id"] = "[world.port]"
20+
req_body["put_accent"] = TRUE
21+
req_body["put_yo"] = FALSE
22+
req_body["symbol_durs"] = list()
23+
req_body["format"] = "ogg"
24+
req_body["word_ts"] = FALSE
25+
// var/json_body = json_encode(req_body)
26+
// log_debug(json_body)
27+
28+
var/datum/http_request/request = new()
29+
request.prepare(RUSTG_HTTP_METHOD_POST, api_url, json_encode(req_body), list("content-type" = "application/json"))
30+
spawn(0)
31+
request.begin_async()
32+
UNTIL(request.is_complete())
33+
var/datum/http_response/response = request.into_response()
34+
proc_callback.Invoke(response)
35+
36+
return TRUE
37+
38+
/datum/tts_provider/silero/process_response(datum/http_response/response)
39+
var/data = json_decode(response.body)
40+
// log_debug(response.body)
41+
42+
if(data["timings"]["003_tts_time"] > 3)
43+
is_throttled = TRUE
44+
throttled_until = world.time + 15 SECONDS
45+
46+
return data["results"][1]["audio"]
47+
48+
//var/sha1 = data["original_sha1"]
49+
50+
/datum/tts_provider/silero/pitch_whisper(text)
51+
return {"<prosody pitch="x-low">[text]</prosody>"}
52+
53+
/datum/tts_provider/silero/rate_faster(text)
54+
return {"<prosody rate="fast">[text]</prosody>"}
55+
56+
/datum/tts_provider/silero/rate_medium(text)
57+
return {"<prosody rate="medium">[text]</prosody>"}

0 commit comments

Comments
 (0)