|
import sys |
|
|
|
|
|
import requests |
|
import re |
|
import struct |
|
import numpy as np |
|
from concurrent.futures import ThreadPoolExecutor |
|
|
|
|
|
def fill_hann_window(size, periodic=True): |
|
if periodic: |
|
return np.hanning(size + 1)[:-1] |
|
return np.hanning(size) |
|
|
|
|
|
def irfft(n_fft, complex_input): |
|
return np.fft.irfft(complex_input, n=n_fft) |
|
|
|
|
|
def fold(buffer, n_out, n_win, n_hop, n_pad): |
|
result = np.zeros(n_out) |
|
n_frames = len(buffer) // n_win |
|
|
|
for i in range(n_frames): |
|
start = i * n_hop |
|
end = start + n_win |
|
result[start:end] += buffer[i * n_win:(i + 1) * n_win] |
|
|
|
return result[n_pad:-n_pad] if n_pad > 0 else result |
|
|
|
|
|
def process_frame(args): |
|
l, n_fft, ST, hann = args |
|
frame = irfft(n_fft, ST[l]) |
|
frame = frame * hann |
|
hann2 = hann * hann |
|
return frame, hann2 |
|
|
|
|
|
def embd_to_audio(embd, n_codes, n_embd, n_thread=4): |
|
embd = np.asarray(embd, dtype=np.float32).reshape(n_codes, n_embd) |
|
|
|
n_fft = 1280 |
|
n_hop = 320 |
|
n_win = 1280 |
|
n_pad = (n_win - n_hop) // 2 |
|
n_out = (n_codes - 1) * n_hop + n_win |
|
|
|
hann = fill_hann_window(n_fft, True) |
|
|
|
E = np.zeros((n_embd, n_codes), dtype=np.float32) |
|
for l in range(n_codes): |
|
for k in range(n_embd): |
|
E[k, l] = embd[l, k] |
|
|
|
half_embd = n_embd // 2 |
|
S = np.zeros((n_codes, half_embd + 1), dtype=np.complex64) |
|
|
|
for k in range(half_embd): |
|
for l in range(n_codes): |
|
mag = E[k, l] |
|
phi = E[k + half_embd, l] |
|
|
|
mag = np.clip(np.exp(mag), 0, 1e2) |
|
S[l, k] = mag * np.exp(1j * phi) |
|
|
|
res = np.zeros(n_codes * n_fft) |
|
hann2_buffer = np.zeros(n_codes * n_fft) |
|
|
|
with ThreadPoolExecutor(max_workers=n_thread) as executor: |
|
args = [(l, n_fft, S, hann) for l in range(n_codes)] |
|
results = list(executor.map(process_frame, args)) |
|
|
|
for l, (frame, hann2) in enumerate(results): |
|
res[l*n_fft:(l+1)*n_fft] = frame |
|
hann2_buffer[l*n_fft:(l+1)*n_fft] = hann2 |
|
|
|
audio = fold(res, n_out, n_win, n_hop, n_pad) |
|
env = fold(hann2_buffer, n_out, n_win, n_hop, n_pad) |
|
|
|
mask = env > 1e-10 |
|
audio[mask] /= env[mask] |
|
|
|
return audio |
|
|
|
|
|
def save_wav(filename, audio_data, sample_rate): |
|
num_channels = 1 |
|
bits_per_sample = 16 |
|
bytes_per_sample = bits_per_sample // 8 |
|
data_size = len(audio_data) * bytes_per_sample |
|
byte_rate = sample_rate * num_channels * bytes_per_sample |
|
block_align = num_channels * bytes_per_sample |
|
chunk_size = 36 + data_size |
|
|
|
header = struct.pack( |
|
'<4sI4s4sIHHIIHH4sI', |
|
b'RIFF', |
|
chunk_size, |
|
b'WAVE', |
|
b'fmt ', |
|
16, |
|
1, |
|
num_channels, |
|
sample_rate, |
|
byte_rate, |
|
block_align, |
|
bits_per_sample, |
|
b'data', |
|
data_size |
|
) |
|
|
|
audio_data = np.clip(audio_data * 32767, -32768, 32767) |
|
pcm_data = audio_data.astype(np.int16) |
|
|
|
with open(filename, 'wb') as f: |
|
f.write(header) |
|
f.write(pcm_data.tobytes()) |
|
|
|
|
|
def process_text(text: str): |
|
text = re.sub(r'\d+(\.\d+)?', lambda x: x.group(), text.lower()) |
|
text = re.sub(r'[-_/,\.\\]', ' ', text) |
|
text = re.sub(r'[^a-z\s]', '', text) |
|
text = re.sub(r'\s+', ' ', text).strip() |
|
return text.split() |
|
|
|
|
|
|
|
|
|
if len(sys.argv) <= 3: |
|
print("usage: python tts-outetts.py http://server-llm:port http://server-dec:port \"text\"") |
|
exit(1) |
|
|
|
host_llm = sys.argv[1] |
|
host_dec = sys.argv[2] |
|
text = sys.argv[3] |
|
|
|
prefix = """<|im_start|> |
|
<|text_start|>the<|text_sep|>overall<|text_sep|>package<|text_sep|>from<|text_sep|>just<|text_sep|>two<|text_sep|>people<|text_sep|>is<|text_sep|>pretty<|text_sep|>remarkable<|text_sep|>sure<|text_sep|>i<|text_sep|>have<|text_sep|>some<|text_sep|>critiques<|text_sep|>about<|text_sep|>some<|text_sep|>of<|text_sep|>the<|text_sep|>gameplay<|text_sep|>aspects<|text_sep|>but<|text_sep|>its<|text_sep|>still<|text_sep|>really<|text_sep|>enjoyable<|text_sep|>and<|text_sep|>it<|text_sep|>looks<|text_sep|>lovely<|text_sep|>""" |
|
|
|
words = process_text(text) |
|
words = "<|text_sep|>".join([i.strip() for i in words]) |
|
words += "<|text_end|>\n" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
suffix = [ 151667, 198, 1782, 155780, 151669, 151929, 152412, 152308, 152585, 152460, 153375, 151670, 198, 74455, |
|
155808, 151669, 151799, 151873, 151863, 152446, 152372, 152204, 152728, 152229, 152470, 151970, 153413, |
|
152419, 153334, 153289, 153374, 153199, 152040, 153260, 152721, 152680, 153297, 152419, 153248, 152400, |
|
152691, 153368, 153437, 151670, 198, 1722, 155828, 151669, 152607, 152256, 152991, 152299, 152688, 153163, |
|
153016, 152789, 153198, 152712, 151911, 153107, 152623, 152170, 152395, 152852, 152207, 152461, 153321, |
|
153309, 151750, 152137, 153340, 152573, 152267, 153347, 151789, 152681, 153339, 151992, 152512, 151751, |
|
152179, 153434, 153180, 152900, 153440, 152474, 153122, 153129, 151904, 152311, 151670, 198, 1499, 155791, |
|
151669, 152276, 152454, 153354, 152544, 153204, 153272, 152708, 153433, 152319, 153226, 153043, 152325, |
|
153267, 152622, 151670, 198, 4250, 155797, 151669, 153454, 153342, 151989, 152458, 153420, 152303, 152271, |
|
152827, 153036, 153196, 151708, 153263, 152561, 153207, 152213, 152112, 153204, 151722, 152542, 151670, 198, |
|
19789, 155796, 151669, 153353, 153182, 152345, 152471, 152477, 153014, 152002, 152191, 151734, 152312, 152810, |
|
152237, 153224, 153169, 153224, 152244, 153387, 153404, 151670, 198, 16069, 155811, 151669, 152265, 151946, |
|
151808, 152412, 152363, 152305, 153156, 152733, 152810, 153157, 152016, 152100, 152069, 153234, 152317, |
|
152589, 152707, 153121, 153341, 152159, 152114, 153156, 153001, 153504, 153376, 152272, 152433, 152325, |
|
151941, 151670, 198, 285, 155788, 151669, 152238, 152255, 153427, 152318, 153009, 152381, 152474, 152680, |
|
152157, 153255, 152324, 151682, 151670, 198, 32955, 155804, 151669, 153490, 153419, 152364, 152405, 152682, |
|
152206, 152078, 153369, 152725, 153193, 153027, 152946, 152488, 153070, 151883, 152890, 152489, 153144, |
|
153375, 152358, 151685, 152494, 152117, 152740, 151670, 198, 37448, 480, 155840, 151669, 151902, 152720, |
|
153377, 152027, 152378, 152821, 153207, 153459, 153028, 153068, 152507, 153255, 152158, 152921, 151958, |
|
152609, 152748, 152822, 152286, 151714, 152730, 152377, 152353, 152470, 152606, 152162, 152186, 153071, |
|
152244, 153118, 153375, 153018, 152712, 153098, 152976, 152336, 151843, 153202, 152297, 151736, 153380, |
|
153502, 152702, 152115, 153181, 152735, 153277, 153457, 152393, 153112, 152595, 151670, 198, 19098, 155808, |
|
151669, 152464, 153452, 152595, 153312, 151937, 151933, 153197, 152239, 153163, 152922, 153402, 152034, |
|
152591, 153438, 152215, 151673, 152005, 151785, 152642, 151924, 153278, 151805, 151974, 153482, 152718, |
|
152862, 153347, 151670, 198, 72, 155780, 151669, 151795, 152111, 152746, 152377, 153471, 152309, 151670, 198, |
|
19016, 155788, 151669, 153181, 152271, 152190, 152842, 152224, 152701, 152939, 152536, 152091, 151815, 152733, |
|
151672, 151670, 198, 14689, 155788, 151669, 152291, 152072, 152942, 151734, 153042, 153504, 152589, 153333, |
|
151839, 151941, 153038, 153180, 151670, 198, 36996, 8303, 155832, 151669, 152231, 152256, 152835, 152801, |
|
152985, 153400, 152393, 152818, 152765, 152249, 152600, 151699, 152302, 152752, 153018, 153009, 151992, |
|
153054, 152847, 153354, 153228, 152662, 153355, 152532, 153393, 151782, 152458, 152048, 152757, 152428, |
|
153195, 151906, 153006, 153178, 153250, 152331, 152284, 152780, 153138, 153319, 151980, 153142, 152418, |
|
152228, 152733, 151670, 198, 9096, 155801, 151669, 151698, 153321, 152217, 153039, 152935, 153400, 152122, |
|
152531, 153106, 152169, 152892, 152957, 151851, 152427, 152826, 152451, 151851, 152901, 152885, 152594, |
|
153446, 153080, 151670, 198, 14689, 155795, 151669, 152658, 151700, 153321, 152450, 152530, 153191, 151673, |
|
151690, 151698, 152714, 152846, 152981, 153171, 153384, 153364, 153188, 153246, 151670, 198, 1055, 155779, |
|
151669, 151869, 152388, 152711, 153334, 151736, 151670, 198, 1782, 155780, 151669, 153483, 153240, 152241, |
|
152558, 152697, 153046, 151670, 198, 5804, 1363, 155820, 151669, 152941, 152764, 152605, 153034, 153434, |
|
153372, 153347, 151887, 152453, 152758, 152133, 152510, 152694, 152431, 152321, 153088, 152676, 152223, |
|
152581, 152459, 152015, 152502, 153063, 152712, 153294, 153451, 153032, 152903, 152859, 152989, 151748, |
|
152669, 152661, 152650, 152409, 151861, 151670, 198, 300, 7973, 155828, 151669, 153095, 152469, 152988, |
|
152894, 151819, 152391, 153019, 152058, 153062, 153230, 151826, 152112, 152306, 152264, 152769, 153390, |
|
152384, 152435, 152790, 153393, 152983, 152540, 152252, 152034, 153107, 152540, 151919, 151893, 152558, |
|
152817, 152946, 152956, 152129, 152715, 153131, 153490, 151734, 152271, 152707, 151734, 153321, 152450, |
|
151670, 198, 8088, 155792, 151669, 152452, 153497, 153353, 152679, 152533, 152382, 152374, 152611, 153341, |
|
153163, 152285, 153411, 152495, 153141, 152320, 151670, 198, 1199, 155781, 151669, 151764, 152360, 153295, |
|
152634, 153342, 152199, 152271, 151670, 198, 43366, 155799, 151669, 152308, 151682, 152889, 152016, 152385, |
|
152629, 152495, 151826, 153321, 152958, 152180, 151886, 153432, 152922, 152128, 153024, 153040, 152593, |
|
152287, 151677, 151670, 198, 53660, 155808, 151669, 151727, 152092, 152680, 153331, 151699, 152316, 152938, |
|
152289, 152433, 153384, 151781, 153137, 153259, 152175, 153213, 152291, 151869, 152691, 152489, 151941, |
|
152049, 152034, 153053, 152179, 153160, 151676, 153367, 151670, 198, 268, 4123, 480, 155821, 151669, 152350, |
|
152173, 152536, 151991, 151960, 153144, 153013, 152358, 152234, 153135, 152291, 153235, 152143, 152583, |
|
152402, 153483, 152678, 152192, 152533, 152946, 151797, 153103, 152310, 152293, 151825, 152548, 153442, |
|
152109, 152659, 153325, 152781, 152570, 152957, 151752, 152265, 153381, 152515, 151670, 198, 437, 155787, |
|
151669, 152957, 152659, 151975, 152709, 152402, 152836, 152174, 151792, 153409, 153327, 152990, 151670, 198, |
|
275, 155781, 151669, 152520, 153038, 152067, 153273, 153185, 152265, 152974, 151670, 198, 94273, 155799, |
|
151669, 152953, 152938, 153427, 152244, 151920, 153423, 152929, 152367, 153052, 152129, 152331, 152257, |
|
152987, 152777, 153448, 152408, 151696, 152408, 152326, 152699, 151670, 198, 385, 16239, 155828, 151669, |
|
152306, 152268, 153438, 153228, 152978, 152957, 153153, 153393, 152795, 152110, 152918, 152923, 152467, |
|
152331, 153053, 153330, 151889, 153444, 152234, 152624, 151779, 152801, 152784, 152139, 152222, 152751, |
|
152512, 153287, 153141, 153052, 151840, 152589, 152508, 153499, 152109, 152255, 151739, 152267, 152759, |
|
153318, 153165, 153349, 151670, ] |
|
|
|
response = requests.post( |
|
host_llm + "/completion", |
|
json={ |
|
"prompt": [prefix + words, *suffix], |
|
"n_predict": 1024, |
|
"cache_prompt": True, |
|
"return_tokens": True, |
|
"samplers": ["top_k"], |
|
"top_k": 16, |
|
"seed": 1003, |
|
} |
|
) |
|
|
|
response_json = response.json() |
|
|
|
|
|
|
|
|
|
|
|
|
|
codes = response_json["tokens"] |
|
|
|
codes = [t - 151672 for t in codes if t >= 151672 and t <= 155772] |
|
|
|
response = requests.post( |
|
host_dec + "/embeddings", |
|
json={ |
|
"input": [*codes], |
|
} |
|
) |
|
|
|
response_json = response.json() |
|
|
|
|
|
|
|
|
|
embd = response_json[0]["embedding"] |
|
|
|
n_codes = len(embd) |
|
n_embd = len(embd[0]) |
|
|
|
print('spectrogram generated: n_codes: %d, n_embd: %d' % (n_codes, n_embd)) |
|
|
|
|
|
print('converting to audio ...') |
|
audio = embd_to_audio(embd, n_codes, n_embd) |
|
print('audio generated: %d samples' % len(audio)) |
|
|
|
filename = "output.wav" |
|
sample_rate = 24000 |
|
|
|
|
|
audio[:24000 // 4] = 0.0 |
|
|
|
save_wav(filename, audio, sample_rate) |
|
print('audio written to file "%s"' % filename) |
|
|