SDL Audio tcod.sdl.audio#

SDL2 audio playback and recording tools.

This module includes SDL’s low-level audio API and a naive implementation of an SDL mixer. If you have experience with audio mixing then you might be better off writing your own mixer or modifying the existing one which was written using Python/Numpy.

This module is designed to integrate with the wider Python ecosystem. It leaves the loading to sound samples to other libraries like SoundFile.

Example:

# Synchronous audio example using SDL's low-level API.
import time

import soundfile  # pip install soundfile
import tcod.sdl.audio

device = tcod.sdl.audio.open()  # Open the default output device.
sound, sample_rate = soundfile.read("example_sound.wav", dtype="float32")  # Load an audio sample using SoundFile.
converted = device.convert(sound, sample_rate)  # Convert this sample to the format expected by the device.
device.queue_audio(converted)  # Play audio synchronously by appending it to the device buffer.

while device.queued_samples:  # Wait until device is done playing.
    time.sleep(0.001)

Example:

# Asynchronous audio example using BasicMixer.
import time

import soundfile  # pip install soundfile
import tcod.sdl.audio

mixer = tcod.sdl.audio.BasicMixer(tcod.sdl.audio.open())  # Setup BasicMixer with the default audio output.
sound, sample_rate = soundfile.read("example_sound.wav")  # Load an audio sample using SoundFile.
sound = mixer.device.convert(sound, sample_rate)  # Convert this sample to the format expected by the device.
channel = mixer.play(sound)  # Start asynchronous playback, audio is mixed on a separate Python thread.
while channel.busy:  # Wait until the sample is done playing.
    time.sleep(0.001)

New in version 13.5.

class tcod.sdl.audio.AllowedChanges(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]#

Which parameters are allowed to be changed when the values given are not supported.

ANY = 15#
CHANNELS = 4#
FORMAT = 2#
FREQUENCY = 1#
NONE = 0#
SAMPLES = 8#
class tcod.sdl.audio.AudioDevice(device_id: int, capture: bool, spec: Any)[source]#

An SDL audio device.

Open new audio devices using tcod.sdl.audio.open.

When you use this object directly the audio passed to queue_audio is always played synchronously. For more typical asynchronous audio you should pass an AudioDevice to BasicMixer.

Changed in version 16.0: Can now be used as a context which will close the device on exit.

__enter__() Self[source]#

Return self and enter a managed context.

__exit__(type: type[BaseException] | None, value: BaseException | None, traceback: TracebackType | None) None[source]#

Close the device when exiting the context.

__repr__() str[source]#

Return a representation of this device.

close() None[source]#

Close this audio device. Using this object after it has been closed is invalid.

convert(sound: ArrayLike, rate: int | None = None) NDArray[Any][source]#

Convert an audio sample into a format supported by this device.

Returns the converted array. This might be a reference to the input array if no conversion was needed.

Parameters:
  • sound – An ArrayLike sound sample.

  • rate – The sample-rate of the input array. If None is given then it’s assumed to be the same as the device.

New in version 13.6.

See also

convert_audio

dequeue_audio() NDArray[Any][source]#

Return the audio buffer from a capture stream.

queue_audio(samples: numpy.typing.ArrayLike) None[source]#

Append audio samples to the audio data queue.

buffer_bytes: Final[int]#

The size of the audio buffer in bytes.

buffer_samples: Final[int]#

The size of the audio buffer in samples.

property callback: Callable[[AudioDevice, NDArray[Any]], None]#

If the device was opened with a callback enabled, then you may get or set the callback with this attribute.

channels: Final[int]#

The number of audio channels for this device.

device_id: Final[int]#

The SDL device identifier used for SDL C functions.

format: Final[np.dtype[Any]]#

The format used for audio samples with this device.

frequency: Final[int]#

The audio device sound frequency.

is_capture: Final[bool]#

True if this is a recording device instead of an output device.

property paused: bool#

Get or set the device paused state.

property queued_samples: int#

The current amount of samples remaining in the audio queue.

silence: float#

The value of silence, according to SDL.

spec: Final[Any]#

The SDL_AudioSpec as a CFFI object.

property stopped: bool#

Is True if the device has failed or was closed.

class tcod.sdl.audio.BasicMixer(device: AudioDevice)[source]#

An SDL sound mixer implemented in Python and Numpy.

New in version 13.6.

close() None[source]#

Shutdown this mixer, all playing audio will be abruptly stopped.

get_channel(key: Hashable) Channel[source]#

Return a channel tied to with the given key.

Channels are initialized as you access them with this function. int channels starting from zero are used internally.

This can be used to generate a "music" channel for example.

play(sound: numpy.typing.ArrayLike, *, volume: float | tuple[float, ...] = 1.0, loops: int = 0, on_end: Callable[[Channel], None] | None = None) Channel[source]#

Play a sound, return the channel the sound is playing on.

Parameters:
  • sound – The sound to play. This a Numpy array matching the format of the loaded audio device.

  • volume – The volume to play the sound at. You can also pass a tuple of floats to set the volume for each channel/speaker.

  • loops – How many times to play the sound, -1 can be used to loop the sound forever.

  • on_end – A function to call when this sound has ended. This is called with the Channel which was playing the sound.

run() None[source]#

Method representing the thread’s activity.

You may override this method in a subclass. The standard run() method invokes the callable object passed to the object’s constructor as the target argument, if any, with sequential and keyword arguments taken from the args and kwargs arguments, respectively.

stop() None[source]#

Stop playback on all channels from this mixer.

device#

The AudioDevice

class tcod.sdl.audio.Channel[source]#

An audio channel for BasicMixer. Use BasicMixer.get_channel to initialize this object.

New in version 13.6.

fadeout(time: float) None[source]#

Fadeout this channel then stop playing.

play(sound: numpy.typing.ArrayLike, *, volume: float | tuple[float, ...] = 1.0, loops: int = 0, on_end: Callable[[Channel], None] | None = None) None[source]#

Play an audio sample, stopping any audio currently playing on this channel.

Parameters are the same as BasicMixer.play.

stop() None[source]#

Stop audio on this channel.

property busy: bool#

Is True when this channel is playing audio.

mixer: BasicMixer#

The BasicMixer is channel belongs to.

tcod.sdl.audio.convert_audio(in_sound: ArrayLike, in_rate: int, *, out_rate: int, out_format: DTypeLike, out_channels: int) NDArray[Any][source]#

Convert an audio sample into a format supported by this device.

Returns the converted array. This might be a reference to the input array if no conversion was needed.

Parameters:
  • in_sound – The input ArrayLike sound sample. Input format and channels are derived from the array.

  • in_rate – The sample-rate of the input array.

  • out_rate – The sample-rate of the output array.

  • out_format – The output format of the converted array.

  • out_channels – The number of audio channels of the output array.

New in version 13.6.

Changed in version 16.0: Now converts floating types to np.float32 when SDL doesn’t support the specific format.

tcod.sdl.audio.get_capture_devices() Iterator[str][source]#

Iterate over the available audio capture devices.

tcod.sdl.audio.get_devices() Iterator[str][source]#

Iterate over the available audio output devices.

tcod.sdl.audio.open(name: str | None = None, capture: bool = False, *, frequency: int = 44100, format: DTypeLike = <class 'numpy.float32'>, channels: int = 2, samples: int = 0, allowed_changes: AllowedChanges = AllowedChanges.NONE, paused: bool = False, callback: None | Literal[True] | Callable[[AudioDevice, NDArray[Any]], None] = None) AudioDevice[source]#

Open an audio device for playback or capture and return it.

Parameters:
  • name – The name of the device to open, or None for the most reasonable default.

  • capture – True if this is a recording device, or False if this is an output device.

  • frequency – The desired sample rate to open the device with.

  • format – The data format to use for samples as a NumPy dtype.

  • channels – The number of speakers for the device. 1, 2, 4, or 6 are typical options.

  • samples – The desired size of the audio buffer, must be a power of two.

  • allowed_changes – By default if the hardware does not support the desired format than SDL will transparently convert between formats for you. Otherwise you can specify which parameters are allowed to be changed to fit the hardware better.

  • paused – If True then the device will begin in a paused state. It can then be unpaused by assigning False to AudioDevice.paused.

  • callback – If None then this device will be opened in push mode and you’ll have to use AudioDevice.queue_audio to send audio data or AudioDevice.dequeue_audio to receive it. If a callback is given then you can change it later, but you can not enable or disable the callback on an opened device. If True then a default callback which plays silence will be used, this is useful if you need the audio device before your callback is ready.

If a callback is given then it will be called with the AudioDevice and a Numpy buffer of the data stream. This callback will be run on a separate thread. Exceptions not handled by the callback become unraiseable and will be handled by sys.unraisablehook.