Source code for pyunity.audio
"""
Classes to manage the playback of audio.
It uses the sdl2.sdlmixer library.
A variable in the ``config`` module called
``audio`` will be set to ``False`` if the
mixer module cannot be initialized.
"""
__all__ = ["AudioSource", "AudioClip", "AudioListener"]
import warnings
import os
with warnings.catch_warnings():
warnings.filterwarnings("ignore")
from sdl2 import sdlmixer as mixer
from sdl2 import SDL_GetError
from . import config, logger as Logger
from .core import Component
channels = 0
if "PYUNITY_TESTING" in os.environ:
config.audio = False
Logger.LogLine(Logger.WARN, "Testing PyUnity, audio is disabled")
elif mixer.Mix_Init(mixer.MIX_INIT_MP3 | mixer.MIX_INIT_OGG) == 0:
config.audio = False
Logger.LogLine(Logger.WARN, "Cannot load sdlmixer, audio is disabled")
[docs]class AudioSource(Component):
"""
Manages playback on an AudioSource.
Attributes
----------
clip : AudioClip
Clip to play. Best way to set the clip
is to use the ``SetClip`` function.
PlayOnStart : bool
Whether it plays on start or not.
Loop : bool
Whether it loops or not. This is not
fully supported.
"""
attrs = ["PlayOnStart", "Loop"]
def __init__(self):
super(AudioSource, self).__init__()
global channels
self.clip = None
self.channel = channels
channels += 1
print(channels)
mixer.Mix_AllocateChannels(channels)
self.PlayOnStart = False
self.Loop = False
[docs] def SetClip(self, clip):
"""
Sets a clip for the AudioSource to play.
Parameters
----------
clip : AudioClip
AudioClip to play
"""
self.clip = clip
[docs] def Play(self):
"""
Plays the AudioClip attached to the AudioSource.
"""
if self.clip is None:
Logger.LogLine(Logger.WARN, "AudioSource has no AudioClip")
return
if self.clip.music is None:
self.clip.music = mixer.Mix_LoadWAV(self.clip.path.encode())
if mixer.Mix_PlayChannel(self.channel, self.clip.music, 0) == -1:
print("Unable to play file: %s" % mixer.Mix_GetError())
[docs] def Stop(self):
"""
Stops playing the AudioClip attached to the AudioSource.
"""
if self.clip is None:
Logger.LogLine(Logger.WARN, "AudioSource has no AudioClip")
mixer.Mix_HaltChannel(self.channel)
[docs] def Pause(self):
"""
Pauses the AudioClip attached to the AudioSource.
"""
if self.clip is None:
Logger.LogLine(Logger.WARN, "AudioSource has no AudioClip")
mixer.Mix_Pause(self.channel)
[docs] def UnPause(self):
"""
Unpauses the AudioClip attached to the AudioSource.
"""
if self.clip is None:
Logger.LogLine(Logger.WARN, "AudioSource has no AudioClip")
mixer.Mix_Resume(self.channel)
@property
def Playing(self):
"""
Gets if the AudioSource is playing.
"""
if self.clip is None:
Logger.LogLine(Logger.WARN, "AudioSource has no AudioClip")
return mixer.Mix_Playing(self.channel)
[docs]class AudioClip:
"""
Class to store information about an audio file.
Attributes
----------
path : str
Path to the file
music : sdl2.sdlmixer.mixer.Mix_Chunk
Sound chunk that can be played with
an SDL2 Mixer Channel.
Only set when the AudioClip is played
in an ``AudioSource``.
"""
def __init__(self, path):
self.path = path
self.music = None
[docs]class AudioListener(Component):
"""
Class to receive audio events and to base spatial
sound from. By default the Main Camera has an
AudioListener, but you can also remove it and
add a new one to another GameObject in a Scene.
There can only be one AudioListener, otherwise
sound is disabled.
"""
[docs] def Init(self):
"""
Initializes the SDL2 Mixer.
"""
if mixer.Mix_OpenAudio(22050, mixer.MIX_DEFAULT_FORMAT, 2, 4096) == -1:
print("SDL2_mixer could not be initialized!\nSDL_Error: %s" %
SDL_GetError())
[docs] def DeInit(self):
"""
Stops all AudioSources, frees memory that is used by
the AudioClips and de-initializes the SDL2 Mixer.
"""
from .scenes import SceneManager
for source in SceneManager.CurrentScene().FindComponentsByType(AudioSource):
mixer.Mix_HaltChannel(source.channel)
mixer.Mix_FreeChunk(source.clip.music)
mixer.Mix_CloseAudio()