Source code for libretro.drivers.audio.array
"""
An audio driver that accumulates all received samples in an :class:`~array.array`.
.. seealso::
:mod:`libretro.api.audio`
Defines the audio callback types and sample formats this driver handles.
"""
from array import array
from copy import deepcopy
from typing import override
from libretro.api.audio import retro_audio_buffer_status_callback, retro_audio_callback
from libretro.api.av import retro_system_av_info
from libretro.error import UnsupportedEnvCall
from .driver import AudioDriver
[docs]
class ArrayAudioDriver(AudioDriver):
"""
A basic :class:`.AudioDriver` that stores all audio samples in an in-memory :class:`~array.array`.
Suitable for tests that need to inspect audio output after the fact.
"""
[docs]
def __init__(self):
"""Initialize with an empty :class:`~array.array` and no AV info."""
self._buffer = array("h")
self._system_av_info: retro_system_av_info | None = None
[docs]
@override
def sample(self, left: int, right: int):
self._buffer.append(left)
self._buffer.append(right)
[docs]
@override
def sample_batch(self, frames: memoryview) -> int:
if frames.format != "h":
byte_view = frames.cast("B")
sample_view = byte_view.cast("h")
else:
sample_view = frames
self._buffer.extend(sample_view)
# Divide by two to return number of frames
return len(sample_view) // 2
@property
@override
def callbacks(self) -> retro_audio_callback | None:
"""
Audio callbacks are not supported by this driver.
:return: :obj:`None`, always.
:raises UnsupportedEnvCall: If setting this property.
"""
return None
@callbacks.setter
@override
def callbacks(self, callback: retro_audio_callback | None):
raise UnsupportedEnvCall("ArrayAudioDriver does not support setting callbacks")
@property
@override
def buffer_status(self) -> retro_audio_buffer_status_callback | None:
"""
Buffer-status callbacks are not supported by this driver.
:return: :obj:`None`, always.
:raises UnsupportedEnvCall: If setting this property.
"""
return None
@buffer_status.setter
@override
def buffer_status(self, callback: retro_audio_buffer_status_callback | None):
raise UnsupportedEnvCall(
"ArrayAudioDriver does not support setting buffer status callback"
)
@property
@override
def minimum_latency(self) -> int | None:
"""
Setting a minimum latency is not supported by this driver.
:return: :obj:`None`, always.
:raises UnsupportedEnvCall: If setting this property.
"""
return None
@minimum_latency.setter
@override
def minimum_latency(self, latency: int | None):
raise UnsupportedEnvCall("ArrayAudioDriver does not support setting minimum latency")
@property
@override
def system_av_info(self) -> retro_system_av_info | None:
return deepcopy(self._system_av_info)
@system_av_info.setter
@override
def system_av_info(self, info: retro_system_av_info):
if not isinstance(info, retro_system_av_info):
raise TypeError(f"Expected retro_system_av_info; got {type(info).__name__}")
self._system_av_info = deepcopy(info)
@property
def buffer(self) -> array[int]:
"""The accumulated audio data as an :class:`~array.array` of signed 16-bit interleaved stereo samples."""
return self._buffer
__all__ = [
"ArrayAudioDriver",
]