63 lines
2.1 KiB
Python
63 lines
2.1 KiB
Python
import pyaudio
|
|
import logging
|
|
import audioop
|
|
|
|
mainLogger = logging.getLogger("hugvey")
|
|
logger = mainLogger.getChild("player")
|
|
|
|
class Player:
|
|
"""
|
|
Play the streamed audio
|
|
"""
|
|
|
|
def __init__(self, src_rate, out_rate):
|
|
self.p = None
|
|
self.src_rate = src_rate
|
|
self.out_rate = out_rate # unfortunately not every device plays 16kHz audio streams
|
|
self.cv_laststate = None
|
|
|
|
try:
|
|
self.p = p = pyaudio.PyAudio()
|
|
|
|
self.stream = p.open(format=pyaudio.paInt16,
|
|
channels=1,
|
|
rate=out_rate,
|
|
output=True,
|
|
output_device_index=self.get_output_idx()
|
|
)
|
|
except Exception as e:
|
|
logger.critical(f"Player not instatiated: {e}")
|
|
if self.p:
|
|
self.p.terminate()
|
|
self.p = None
|
|
|
|
def get_output_idx(self):
|
|
output_device_idx = None
|
|
output_device_idx = 14
|
|
devices_count = self.p.get_device_count()
|
|
for i in range(devices_count):
|
|
dev = self.p.get_device_info_by_index(i)
|
|
# print(dev)
|
|
if output_device_idx is None and dev['maxOutputChannels'] > 0:
|
|
output_device_idx = dev['index']
|
|
logger.info("Use device {0}: {1} {2}".format(dev['index'],dev['name'], dev['maxOutputChannels']))
|
|
logger.debug("{} {:0d} {}".format("* " if output_device_idx == i else "- ", i, dev['name']))
|
|
return output_device_idx
|
|
|
|
def receive(self, chunk):
|
|
if not self.p:
|
|
return
|
|
|
|
# logger.debug('receive {}'.format(len(chunk)))
|
|
if self.src_rate == self.out_rate:
|
|
data = chunk
|
|
else:
|
|
data, self.cv_laststate = audioop.ratecv(chunk, 2, 1, self.src_rate, self.out_rate, self.cv_laststate)
|
|
self.stream.write(data)
|
|
|
|
def shutdown(self):
|
|
if not self.p:
|
|
return
|
|
|
|
self.stream.close()
|
|
self.p.terminate()
|