Skip to content

Commit

Permalink
types::untested vlm path rn
Browse files Browse the repository at this point in the history
  • Loading branch information
rodfer0x80 committed May 27, 2024
1 parent 7ef8298 commit 099ec44
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 44 deletions.
35 changes: 28 additions & 7 deletions llmpeg/capabilities/audio/audio.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from pathlib import Path
from dataclasses import dataclass
from typing import Union
from io import BytesIO

import numpy as np

from llmpeg.capabilities.audio.audio_input import AudioInput
from llmpeg.capabilities.audio.audio_output import AudioOutput

from llmpeg.capabilities.filesystem import WaveFile
from llmpeg.types import CurrentDate, URL, Error

@dataclass
class Audio:
Expand All @@ -21,20 +23,39 @@ def __post_init__(self):
def capture_stream(self, duration: int):
return self.audio_input.capture_stream(duration)

def capture_to_file(self, duration: int):
return self.audio_input.capture_to_file(duration)
def capture_to_file(self, duration: int = 5, sr: int = 16000) -> Path:
audio_stream = self.capture_stream(duration, sr)
audio_file = self.cache_dir / f'{CurrentDate().date}.wav'
WaveFile.write(audio_stream, audio_file, sr)
return audio_file

def play_audio_stream(self, audio_stream: Union[bytes, np.float32]) -> None:
self.audio_output.play([audio_stream])
self.audio_output.play([self.process_track(audio_stream)])

def play_remote_audio_stream_url(self, url: str) -> None:
self.audio_output.play([url])
self.audio_output.play([self.process_track(URL(url))])

def play_audio_file(self, audio_file: Path) -> None:
self.audio_output.play([audio_file])
self.audio_output.play([self.process_track(audio_file)])

def play(self, tracks: list[Union[str, Path, bytes, np.float32]]) -> None:
self.audio_output.play(tracks)
self.audio_output.play([self.process_track(track) for track in tracks])

def stop(self):
self.audio_output.stop()

def process_track(self, track: Union[URL, Path, bytes, np.float32]) -> bytes:
if isinstance(track, (str, Path)):
_, data = WaveFile.read(track)
elif isinstance(track, bytes):
_, data = WaveFile.read(BytesIO(track))
elif isinstance(track, np.ndarray):
_ = 44100 # Assuming sample rate of 44100 Hz
data = (track * np.iinfo(np.int16).max).astype(np.int16)
elif isinstance(track, np.float32):
_ = 44100
else:
err = Error('Unsupported audio format').__repr__()
raise ValueError(err)
return data.tobytes()

10 changes: 3 additions & 7 deletions llmpeg/capabilities/audio/audio_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
from pathlib import Path
from functools import partial

from llmpeg.utils import CurrentDate, WaveFile
from llmpeg.types import CurrentDate
from llmpeg.capabilities.filesystem import WaveFile


@dataclass
Expand All @@ -14,7 +15,7 @@ class AudioInput:
def __post_init__(self):
self.audio = pyaudio.PyAudio()

def capture_stream(self, duration: int = 5, sr: int = 16000) -> np.float32:
def capture_stream(self, duration: int, sr: int) -> np.float32:
CHUNK = 1024
FORMAT = pyaudio.paInt16 # int16
CHANNELS = 1
Expand All @@ -41,8 +42,3 @@ def capture_stream(self, duration: int = 5, sr: int = 16000) -> np.float32:
def __del__(self):
self.audio.terminate()

def capture_to_file(self, duration: int = 5, sr: int = 16000) -> Path:
audio_stream = self.capture_stream(duration, sr)
audio_file = self.cache_dir / f'{CurrentDate().date}.wav'
WaveFile.write(audio_stream, audio_file, sr)
return audio_file
46 changes: 18 additions & 28 deletions llmpeg/capabilities/audio/audio_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
import queue
from typing import Union
from pathlib import Path
from io import BytesIO

import numpy as np
import pyaudio

from llmpeg.utils import WaveFile, Error
from llmpeg.types import Error
from llmpeg.capabilities.filesystem import WaveFile


class AudioOutput:
Expand All @@ -21,28 +21,17 @@ def __post_init__(self) -> None:
self.queue = queue.Queue()
self.pa = pyaudio.PyAudio()

def _play_audio(self, track: Union[str, Path, bytes, np.float32]) -> None:

def _play_audio(self, track: Union[bytes, np.float32]) -> None:
# 16-bit signed integer format
stream = self.pa.open(
format=pyaudio.paInt16,
channels=1,
rate=44100,
output=True,
)

if isinstance(track, (str, Path)):
_, data = WaveFile.read(track)
elif isinstance(track, bytes):
_, data = WaveFile.read(BytesIO(track))
elif isinstance(track, np.ndarray):
_ = 44100 # Assuming sample rate of 44100 Hz
data = (track * np.iinfo(np.int16).max).astype(np.int16)
else:
err = Error('Unsupported audio format').__repr__()
raise ValueError(err)

self.playing = True
stream.write(data.tobytes())
stream.write(track.tobytes())
stream.stop_stream()
stream.close()
self.playing = False
Expand All @@ -51,23 +40,24 @@ def stop(self) -> None:
self.stop_event.set()
self.queue.queue.clear()

def play(self, tracks: list[Union[str, Path, bytes, np.float32]]) -> None:
def play(self, tracks: list[Union[bytes, np.float32]]) -> None:
self.stop()
self.stop_event.clear()
self.playing = True
for track in tracks:
if track:
self.queue.put(track)
map(lambda track: self.queue.put(track), [track for track in tracks if track])
self.thread = threading.Thread(target=self._play_from_queue)
self.thread.start()

def _play(self) -> None:
if not self.queue.empty():
track = self.queue.get()
try:
self._play_audio(track)
except Exception as e:
raise Exception(Error(e).__repr__())
else:
time.sleep(0.1)

def _play_from_queue(self) -> None:
while not self.stop_event.is_set():
if not self.queue.empty():
track = self.queue.get()
try:
self._play_audio(track)
except Exception as e:
raise Exception(Error(e).__repr__())
else:
time.sleep(0.1)
self._play()
3 changes: 1 addition & 2 deletions llmpeg/capabilities/filesystem/filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ class FileCacheDirectory:

def __post_init__(self):
if not self.cache_dir:
self.cache_dir = Path(f'~/.cache/{str(
Path(__file__).cwd().name).split("/")[-1]}').expanduser()
self.cache_dir = Path(f'~/.cache/{str(Path(__file__).cwd().name).split("/")[-1]}').expanduser()
Path.mkdir(self.cache_dir, exist_ok=True)

def __str__(self) -> Path:
Expand Down

0 comments on commit 099ec44

Please sign in to comment.