From 9397f28808c0dbc0182c6641b317d81fc5bee91a Mon Sep 17 00:00:00 2001 From: Anthony Samms Date: Sun, 18 Jan 2026 14:50:21 -0500 Subject: [PATCH] Update audio.py --- libs/audio.py | 176 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 122 insertions(+), 54 deletions(-) diff --git a/libs/audio.py b/libs/audio.py index 1544f66..745fc68 100644 --- a/libs/audio.py +++ b/libs/audio.py @@ -1,5 +1,6 @@ import logging import platform +import pyray as ray from pathlib import Path import cffi @@ -132,6 +133,7 @@ class AudioEngine: self.music_streams = {} self.audio_device_ready = False self.volume_presets = volume_presets + self.lib = lib if sounds_path is None: self.sounds_path = Path(f"Skins/{get_config()['paths']['skin']}/Sounds") @@ -139,15 +141,15 @@ class AudioEngine: self.sounds_path = sounds_path def set_log_level(self, level: int): - lib.set_log_level(level) # type: ignore + self.lib.set_log_level(level) # type: ignore def list_host_apis(self): """Prints a list of available host APIs to the console""" - lib.list_host_apis() # type: ignore + self.lib.list_host_apis() # type: ignore def get_host_api_name(self, api_id: int) -> str: """Returns the name of the host API with the given ID""" - result = lib.get_host_api_name(api_id) # type: ignore + result = self.lib.get_host_api_name(api_id) # type: ignore if result == ffi.NULL: return "" result = ffi.string(result) @@ -158,12 +160,12 @@ class AudioEngine: def init_audio_device(self) -> bool: """Initialize the audio device""" try: - lib.init_audio_device(self.device_type, self.target_sample_rate, self.buffer_size) # type: ignore - self.audio_device_ready = lib.is_audio_device_ready() # type: ignore + self.lib.init_audio_device(self.device_type, self.target_sample_rate, self.buffer_size) # type: ignore + self.audio_device_ready = self.lib.is_audio_device_ready() # type: ignore file_path_str = str(self.sounds_path / 'don.wav').encode('utf-8') - self.don = lib.load_sound(file_path_str) # type: ignore + self.don = self.lib.load_sound(file_path_str) # type: ignore file_path_str = str(self.sounds_path / 'ka.wav').encode('utf-8') - self.kat = lib.load_sound(file_path_str) # type: ignore + self.kat = self.lib.load_sound(file_path_str) # type: ignore if self.audio_device_ready: logger.info("Audio device initialized successfully") return self.audio_device_ready @@ -180,9 +182,9 @@ class AudioEngine: for music_id in list(self.music_streams.keys()): self.unload_music_stream(music_id) - lib.unload_sound(self.don) # type: ignore - lib.unload_sound(self.kat) # type: ignore - lib.close_audio_device() # type: ignore + self.lib.unload_sound(self.don) # type: ignore + self.lib.unload_sound(self.kat) # type: ignore + self.lib.close_audio_device() # type: ignore self.audio_device_ready = False logger.info("Audio device closed") except Exception as e: @@ -190,15 +192,15 @@ class AudioEngine: def is_audio_device_ready(self) -> bool: """Check if audio device is ready""" - return lib.is_audio_device_ready() # type: ignore + return self.lib.is_audio_device_ready() # type: ignore def set_master_volume(self, volume: float) -> None: """Set master volume (0.0 to 1.0)""" - lib.set_master_volume(max(0.0, min(1.0, volume))) # type: ignore + self.lib.set_master_volume(max(0.0, min(1.0, volume))) # type: ignore def get_master_volume(self) -> float: """Get master volume""" - return lib.get_master_volume() # type: ignore + return self.lib.get_master_volume() # type: ignore # Sound management def load_sound(self, file_path: Path, name: str) -> str: @@ -209,13 +211,13 @@ class AudioEngine: file_path_str = str(file_path).encode('cp932', errors='replace') else: file_path_str = str(file_path).encode('utf-8') - sound = lib.load_sound(file_path_str) # type: ignore + sound = self.lib.load_sound(file_path_str) # type: ignore - if not lib.is_sound_valid(sound): # type: ignore + if not self.lib.is_sound_valid(sound): # type: ignore file_path_str = str(file_path).encode('utf-8') - sound = lib.load_sound(file_path_str) # type: ignore + sound = self.lib.load_sound(file_path_str) # type: ignore - if lib.is_sound_valid(sound): # type: ignore + if self.lib.is_sound_valid(sound): # type: ignore self.sounds[name] = sound return name else: @@ -228,7 +230,7 @@ class AudioEngine: def unload_sound(self, name: str) -> None: """Unload a sound by name""" if name in self.sounds: - lib.unload_sound(self.sounds[name]) # type: ignore + self.lib.unload_sound(self.sounds[name]) # type: ignore del self.sounds[name] else: logger.warning(f"Sound {name} not found") @@ -263,41 +265,41 @@ class AudioEngine: """Play a sound""" if name == 'don': if volume_preset: - lib.set_sound_volume(self.don, self.volume_presets[volume_preset]) # type: ignore - lib.play_sound(self.don) # type: ignore + self.lib.set_sound_volume(self.don, self.volume_presets[volume_preset]) # type: ignore + self.lib.play_sound(self.don) # type: ignore elif name == 'kat': if volume_preset: - lib.set_sound_volume(self.kat, self.volume_presets[volume_preset]) # type: ignore - lib.play_sound(self.kat) # type: ignore + self.lib.set_sound_volume(self.kat, self.volume_presets[volume_preset]) # type: ignore + self.lib.play_sound(self.kat) # type: ignore elif name in self.sounds: sound = self.sounds[name] if volume_preset: - lib.set_sound_volume(sound, self.volume_presets[volume_preset]) # type: ignore - lib.play_sound(sound) # type: ignore + self.lib.set_sound_volume(sound, self.volume_presets[volume_preset]) # type: ignore + self.lib.play_sound(sound) # type: ignore else: logger.warning(f"Sound {name} not found") def stop_sound(self, name: str) -> None: """Stop a sound""" if name == 'don': - lib.stop_sound(self.don) # type: ignore + self.lib.stop_sound(self.don) # type: ignore elif name == 'kat': - lib.stop_sound(self.kat) # type: ignore + self.lib.stop_sound(self.kat) # type: ignore if name in self.sounds: sound = self.sounds[name] - lib.stop_sound(sound) # type: ignore + self.lib.stop_sound(sound) # type: ignore else: logger.warning(f"Sound {name} not found") def is_sound_playing(self, name: str) -> bool: """Check if a sound is playing""" if name == 'don': - return lib.is_sound_playing(self.don) # type: ignore + return self.lib.is_sound_playing(self.don) # type: ignore elif name == 'kat': - return lib.is_sound_playing(self.kat) # type: ignore + return self.lib.is_sound_playing(self.kat) # type: ignore if name in self.sounds: sound = self.sounds[name] - return lib.is_sound_playing(sound) # type: ignore + return self.lib.is_sound_playing(sound) # type: ignore else: logger.warning(f"Sound {name} not found") return False @@ -305,24 +307,24 @@ class AudioEngine: def set_sound_volume(self, name: str, volume: float) -> None: """Set the volume of a specific sound""" if name == 'don': - lib.set_sound_volume(self.don, volume) # type: ignore + self.lib.set_sound_volume(self.don, volume) # type: ignore elif name == 'kat': - lib.set_sound_volume(self.kat, volume) # type: ignore + self.lib.set_sound_volume(self.kat, volume) # type: ignore elif name in self.sounds: sound = self.sounds[name] - lib.set_sound_volume(sound, volume) # type: ignore + self.lib.set_sound_volume(sound, volume) # type: ignore else: logger.warning(f"Sound {name} not found") def set_sound_pan(self, name: str, pan: float) -> None: """Set the pan of a specific sound""" if name == 'don': - lib.set_sound_pan(self.don, pan) # type: ignore + self.lib.set_sound_pan(self.don, pan) # type: ignore elif name == 'kat': - lib.set_sound_pan(self.kat, pan) # type: ignore + self.lib.set_sound_pan(self.kat, pan) # type: ignore elif name in self.sounds: sound = self.sounds[name] - lib.set_sound_pan(sound, pan) # type: ignore + self.lib.set_sound_pan(sound, pan) # type: ignore else: logger.warning(f"Sound {name} not found") @@ -335,13 +337,13 @@ class AudioEngine: else: file_path_str = str(file_path).encode('utf-8') - music = lib.load_music_stream(file_path_str) # type: ignore + music = self.lib.load_music_stream(file_path_str) # type: ignore - if not lib.is_music_valid(music): # type: ignore + if not self.lib.is_music_valid(music): # type: ignore file_path_str = str(file_path).encode('utf-8') - music = lib.load_music_stream(file_path_str) # type: ignore + music = self.lib.load_music_stream(file_path_str) # type: ignore - if lib.is_music_valid(music): # type: ignore + if self.lib.is_music_valid(music): # type: ignore self.music_streams[name] = music logger.info(f"Loaded music stream from {file_path} as {name}") return name @@ -353,10 +355,10 @@ class AudioEngine: """Play a music stream""" if name in self.music_streams: music = self.music_streams[name] - lib.seek_music_stream(music, 0) # type: ignore + self.lib.seek_music_stream(music, 0) # type: ignore if volume_preset: - lib.set_music_volume(music, self.volume_presets[volume_preset]) # type: ignore - lib.play_music_stream(music) # type: ignore + self.lib.set_music_volume(music, self.volume_presets[volume_preset]) # type: ignore + self.lib.play_music_stream(music) # type: ignore else: logger.warning(f"Music stream {name} not found") @@ -364,15 +366,15 @@ class AudioEngine: """Check if a music stream needs updating (buffers need refilling)""" if name in self.music_streams: music = self.music_streams[name] - return lib.music_stream_needs_update(music) # type: ignore + return self.lib.music_stream_needs_update(music) # type: ignore return False def update_music_stream(self, name: str) -> None: """Update a music stream (only if buffers need refilling)""" if name in self.music_streams: music = self.music_streams[name] - if lib.music_stream_needs_update(music): # type: ignore - lib.update_music_stream(music) # type: ignore + if self.lib.music_stream_needs_update(music): # type: ignore + self.lib.update_music_stream(music) # type: ignore else: logger.warning(f"Music stream {name} not found") @@ -380,7 +382,7 @@ class AudioEngine: """Get the time length of a music stream""" if name in self.music_streams: music = self.music_streams[name] - return lib.get_music_time_length(music) # type: ignore + return self.lib.get_music_time_length(music) # type: ignore else: logger.warning(f"Music stream {name} not found") return 0.0 @@ -389,7 +391,7 @@ class AudioEngine: """Get the time played of a music stream""" if name in self.music_streams: music = self.music_streams[name] - return lib.get_music_time_played(music) # type: ignore + return self.lib.get_music_time_played(music) # type: ignore else: logger.warning(f"Music stream {name} not found") return 0.0 @@ -398,7 +400,7 @@ class AudioEngine: """Set the volume of a music stream""" if name in self.music_streams: music = self.music_streams[name] - lib.set_music_volume(music, volume) # type: ignore + self.lib.set_music_volume(music, volume) # type: ignore else: logger.warning(f"Music stream {name} not found") @@ -406,7 +408,7 @@ class AudioEngine: """Check if a music stream is playing""" if name in self.music_streams: music = self.music_streams[name] - return lib.is_music_stream_playing(music) # type: ignore + return self.lib.is_music_stream_playing(music) # type: ignore else: logger.warning(f"Music stream {name} not found") return False @@ -415,7 +417,7 @@ class AudioEngine: """Stop a music stream""" if name in self.music_streams: music = self.music_streams[name] - lib.stop_music_stream(music) # type: ignore + self.lib.stop_music_stream(music) # type: ignore else: logger.warning(f"Music stream {name} not found") @@ -423,7 +425,7 @@ class AudioEngine: """Unload a music stream""" if name in self.music_streams: music = self.music_streams[name] - lib.unload_music_stream(music) # type: ignore + self.lib.unload_music_stream(music) # type: ignore del self.music_streams[name] else: logger.warning(f"Music stream {name} not found") @@ -437,10 +439,76 @@ class AudioEngine: """Seek a music stream to a specific position""" if name in self.music_streams: music = self.music_streams[name] - lib.seek_music_stream(music, position) # type: ignore + self.lib.seek_music_stream(music, position) # type: ignore + else: + logger.warning(f"Music stream {name} not found") + +class AudioEngineLegacy(AudioEngine): + def __init__(self, device_type: int, sample_rate: float, buffer_size: int, + volume_presets: VolumeConfig, sounds_path: Path | None = None): + super().__init__(device_type, sample_rate, buffer_size, volume_presets, sounds_path) + self.lib = ray + + def set_log_level(self, level: int): + pass + + def list_host_apis(self): + """Prints a list of available host APIs to the console""" + pass + + def get_host_api_name(self, api_id: int) -> str: + """Returns the name of the host API with the given ID""" + return '' + + def init_audio_device(self) -> bool: + """Initialize the audio device""" + try: + self.lib.init_audio_device() + self.audio_device_ready = self.lib.is_audio_device_ready() + file_path_str = str(self.sounds_path / 'don.wav') + self.don = self.lib.load_sound(file_path_str) + file_path_str = str(self.sounds_path / 'ka.wav') + self.kat = self.lib.load_sound(file_path_str) + if self.audio_device_ready: + logger.info("Audio device initialized successfully") + return self.audio_device_ready + except Exception as e: + logger.error(f"Failed to initialize audio device: {e}") + return False + + def load_sound(self, file_path: Path, name: str) -> str: + """Load a sound file and return sound ID""" + try: + sound = self.lib.load_sound(str(file_path)) + if self.lib.is_sound_valid(sound): + self.sounds[name] = sound + return name + else: + logger.error(f"Failed to load sound: {file_path}") + return "" + except Exception as e: + logger.error(f"Error loading sound {file_path}: {e}") + return "" + + def load_music_stream(self, file_path: Path, name: str) -> str: + """Load a music stream and return music ID""" + music = self.lib.load_music_stream(str(file_path)) + if self.lib.is_music_valid(music): + self.music_streams[name] = music + logger.info(f"Loaded music stream from {file_path} as {name}") + return name + else: + logger.error(f"Failed to load music: {file_path}") + return "" + + def update_music_stream(self, name: str) -> None: + """Update a music stream (only if buffers need refilling)""" + if name in self.music_streams: + music = self.music_streams[name] + self.lib.update_music_stream(music) else: logger.warning(f"Music stream {name} not found") # Create the global audio instance -audio = AudioEngine(get_config()["audio"]["device_type"], get_config()["audio"]["sample_rate"], get_config()["audio"]["buffer_size"], get_config()["volume"]) +audio = AudioEngineLegacy(get_config()["audio"]["device_type"], get_config()["audio"]["sample_rate"], get_config()["audio"]["buffer_size"], get_config()["volume"]) audio.set_master_volume(0.75)