mirror of
https://github.com/correl/turntable.git
synced 2024-11-23 11:09:56 +00:00
Add audio playback
This commit is contained in:
parent
57cdbf8ed3
commit
08834afe21
2 changed files with 58 additions and 8 deletions
|
@ -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()
|
||||||
|
|
|
@ -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:
|
||||||
self.events.put(Audio(pcm))
|
queue.put(pcm)
|
||||||
|
framecount += length
|
||||||
|
if framecount >= event_limit:
|
||||||
|
framecount = 0
|
||||||
|
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)
|
||||||
|
|
Loading…
Reference in a new issue