Add audio playback

This commit is contained in:
Correl Roush 2020-09-04 22:12:14 +01:00
parent 57cdbf8ed3
commit 08834afe21
2 changed files with 58 additions and 8 deletions

View file

@ -9,7 +9,7 @@ from typing import Any, Dict, Iterator
from dejavu import Dejavu # type: ignore from dejavu import Dejavu # type: ignore
from turntable.audio import Listener from turntable.audio import Listener, Player
from turntable.icecast import Icecast from turntable.icecast import Icecast
from turntable.models import PCM from turntable.models import PCM
from turntable.turntable import ( from turntable.turntable import (
@ -38,11 +38,12 @@ def run() -> "Iterator[Queue[Event]]":
pcm_in: "Queue[PCM]" = Queue() pcm_in: "Queue[PCM]" = Queue()
pcm_out: "Queue[PCM]" = Queue()
events: "Queue[Event]" = Queue() events: "Queue[Event]" = Queue()
audio_config = config.get("audio", dict()) audio_config = config.get("audio", dict())
listener = Listener( listener = Listener(
pcm_in, [pcm_in, pcm_out],
events, events,
audio_config.get("device", "default"), audio_config.get("device", "default"),
framerate=audio_config.get("framerate", 44100), framerate=audio_config.get("framerate", 44100),
@ -50,9 +51,17 @@ def run() -> "Iterator[Queue[Event]]":
period_size=audio_config.get("period_size", 4096), period_size=audio_config.get("period_size", 4096),
) )
player = Player(
pcm_out,
audio_config.get("output_device", "null"),
framerate=audio_config.get("framerate", 44100),
channels=audio_config.get("channels", 2),
period_size=audio_config.get("period_size", 4096),
)
dejavu = Dejavu(config.get("dejavu", dict())) dejavu = Dejavu(config.get("dejavu", dict()))
player = Turntable(listener.framerate, listener.channels, dejavu, pcm_in, events) turntable = Turntable(listener.framerate, listener.channels, dejavu, pcm_in, events)
icecast_config = config.get("icecast", dict()) icecast_config = config.get("icecast", dict())
icecast = Icecast( icecast = Icecast(
@ -63,7 +72,7 @@ def run() -> "Iterator[Queue[Event]]":
password=icecast_config.get("admin_password", "hackme"), password=icecast_config.get("admin_password", "hackme"),
) )
processes = [listener, player] processes = [listener, player, turntable]
for process in processes: for process in processes:
process.daemon = True process.daemon = True
process.start() process.start()

View file

@ -16,7 +16,7 @@ logger = logging.getLogger(__name__)
class Listener(Process): class Listener(Process):
def __init__( def __init__(
self, self,
pcm_in: "Queue[PCM]", pcm_in: "List[Queue[PCM]]",
events: Queue, events: Queue,
device: str, device: str,
sample_length: int = 30, sample_length: int = 30,
@ -25,7 +25,7 @@ class Listener(Process):
period_size: int = 1024, period_size: int = 1024,
) -> None: ) -> None:
super().__init__() super().__init__()
logger.info("Initializing Listener") logger.info(f"Initializing Listener using '{device}'")
self.pcm_in = pcm_in self.pcm_in = pcm_in
self.events = events self.events = events
self.framerate = framerate self.framerate = framerate
@ -55,13 +55,54 @@ class Listener(Process):
) )
def run(self) -> None: def run(self) -> None:
framecount = 0
event_limit = self.framerate
while True: while True:
length, data = self.capture.read() length, data = self.capture.read()
if length > 0: if length > 0:
pcm = PCM(self.framerate, self.channels, data) pcm = PCM(self.framerate, self.channels, data)
self.pcm_in.put(pcm) for queue in self.pcm_in:
queue.put(pcm)
framecount += length
if framecount >= event_limit:
framecount = 0
self.events.put(Audio(pcm)) self.events.put(Audio(pcm))
else: else:
logger.warning( logger.warning(
"Sampler error (length={}, bytes={})".format(length, len(data)) "Sampler error (length={}, bytes={})".format(length, len(data))
) )
class Player(Process):
def __init__(
self,
pcm_in: "Queue[PCM]",
device: str,
sample_length: int = 30,
framerate: int = 44100,
channels: int = 2,
period_size: int = 1024,
) -> None:
super().__init__()
logger.info(f"Initializing Player using '{device}'")
self.pcm_in = pcm_in
self.framerate = framerate
self.channels = channels
self.playback = alsaaudio.PCM(
device=device,
type=alsaaudio.PCM_PLAYBACK,
format=alsaaudio.PCM_FORMAT_S16_LE,
periodsize=period_size,
rate=framerate,
channels=channels,
)
logger.info(
"Player started on '%s' [rate=%d, channels=%d, periodsize=%d]",
device,
framerate,
channels,
period_size,
)
def run(self) -> None:
while pcm := self.pcm_in.get():
self.playback.write(pcm.raw)