human/tts/Chunk2Mal.py

108 lines
3.5 KiB
Python
Raw Normal View History

2024-09-04 16:51:14 +00:00
#encoding = utf8
2024-09-09 00:30:15 +00:00
2024-09-04 16:51:14 +00:00
import logging
import queue
2024-09-26 17:34:52 +00:00
import time
2024-09-04 16:51:14 +00:00
from queue import Queue
from threading import Thread, Event
import numpy as np
import audio
class Chunk2Mal:
def __init__(self, human):
self._audio_chunk_queue = Queue()
self._human = human
self._thread = None
2024-09-21 12:58:26 +00:00
2024-09-04 16:51:14 +00:00
self._chunks = []
2024-09-21 12:58:26 +00:00
# 320 samples per chunk (20ms * 16000 / 1000)audio_chunk
2024-09-22 08:41:19 +00:00
self._chunk_len = self._human.get_audio_sample_rate() // self._human.get_fps()
2024-09-21 12:58:26 +00:00
self._exit_event = Event()
self._thread = Thread(target=self._on_run)
self._exit_event.set()
self._thread.start()
logging.info('chunk2mal start')
2024-09-04 16:51:14 +00:00
def _on_run(self):
logging.info('chunk2mal run')
2024-09-21 12:58:26 +00:00
while self._exit_event.is_set():
2024-09-26 17:34:52 +00:00
if self._audio_chunk_queue.empty():
time.sleep(0.5)
continue
2024-09-04 16:51:14 +00:00
try:
2024-09-26 17:34:52 +00:00
chunk = self._audio_chunk_queue.get(block=True, timeout=1)
2024-09-04 16:51:14 +00:00
self._chunks.append(chunk)
2024-09-26 17:34:52 +00:00
self._human.push_audio_frames(chunk, 0)
if len(self._chunks) < 10:
continue
2024-09-04 16:51:14 +00:00
except queue.Empty:
2024-09-18 15:48:18 +00:00
# print('Chunk2Mal queue.Empty')
2024-09-04 16:51:14 +00:00
continue
2024-09-18 15:48:18 +00:00
logging.info('np.concatenate')
2024-09-26 17:34:52 +00:00
inputs = np.concatenate(self._chunks) # [N * chunk]
mel = audio.melspectrogram(inputs)
2024-09-26 12:28:49 +00:00
if np.isnan(mel.reshape(-1)).sum() > 0:
raise ValueError(
'Mel contains nan! Using a TTS voice? Add a small epsilon noise to the wav file and try again')
2024-09-04 16:51:14 +00:00
mel_step_size = 16
2024-09-26 12:28:49 +00:00
print('fps:', self._human.get_fps())
mel_idx_multiplier = 80. / self._human.get_fps()
print('mel_idx_multiplier:', mel_idx_multiplier)
2024-09-04 16:51:14 +00:00
i = 0
2024-09-26 12:28:49 +00:00
while 1:
start_idx = int(i * mel_idx_multiplier)
if start_idx + mel_step_size > len(mel[0]):
self._human.push_mel_chunks_queue(mel[:, len(mel[0]) - mel_step_size:])
break
self._human.push_mel_chunks_queue(mel[:, start_idx: start_idx + mel_step_size])
i += 1
batch_size = 128
'''
2024-09-04 16:51:14 +00:00
while i < (len(self._chunks) - self._human.get_stride_left_size()
- self._human.get_stride_right_size()) / 2:
start_idx = int(left + i * mel_idx_multiplier)
# print(start_idx)
if start_idx + mel_step_size > len(mel[0]):
mel_chunks.append(mel[:, len(mel[0]) - mel_step_size:])
else:
mel_chunks.append(mel[:, start_idx: start_idx + mel_step_size])
i += 1
self._human.push_feat_queue(mel_chunks)
# discard the old part to save memory
self._chunks = self._chunks[-(self._human.get_stride_left_size() + self._human.get_stride_right_size()):]
2024-09-26 12:28:49 +00:00
'''
2024-09-04 16:51:14 +00:00
logging.info('chunk2mal exit')
def stop(self):
if self._exit_event is None:
return
2024-09-21 12:58:26 +00:00
self._exit_event.clear()
2024-09-09 00:23:04 +00:00
if self._thread.is_alive():
self._thread.join()
2024-09-04 16:51:14 +00:00
logging.info('chunk2mal stop')
def push_chunk(self, chunk):
self._audio_chunk_queue.put(chunk)
def pull_chunk(self):
try:
2024-09-09 00:23:04 +00:00
chunk = self._audio_chunk_queue.get(block=True, timeout=1)
2024-09-04 16:51:14 +00:00
type = 1
except queue.Empty:
2024-09-22 08:41:19 +00:00
chunk = np.zeros(self._chunk_len, dtype=np.float32)
2024-09-04 16:51:14 +00:00
type = 0
return chunk, type