pyxen.Sound

A short audio clip attached to an Entity as a component.

Sounds are loaded entirely into memory — use them for short effects like jumps, hits, and pickups.

For audio concepts, see Audio.


Constructor

Sound(filename, *, volume=1.0, pan=0.0, loop=False, delay=0.0, pitch=1.0)

filename is the one positional argument: the name of a WAV audio asset in the project. The other five are keyword-only and set the starting value of the property of the same name (see Component Properties).


Parameters

ParameterTypeDescription
filenamestrName of the WAV asset, without its extension; a sound inside a sound bank is bank/sound
volumefloatStarting gain. Defaults to 1.0
panfloatStarting stereo position, -1.0 to 1.0. Defaults to 0.0
loopboolRestart when the sound ends. Defaults to False
delayfloatSeconds of silence before it starts. Defaults to 0.0
pitchfloatPlayback rate, 0.25 to 4.0. Defaults to 1.0

Example

jump_sound = Sound("jump")
quiet_echo = Sound("jump", volume=0.3, delay=0.15)
high_jump = Sound("jump", pitch=2.0)

Attaching a Sound

During spawn:

sfx = world.spawn(sound=Sound("jump"))

Or later:

entity.sound = Sound("jump")

Assigning a sound starts playback immediately.


Component Properties

Access via entity.sound:

PropertyTypeR/WDescription
loopboolR/WEnable looping
volumefloatR/WGain (clamped >= 0.0)
panfloatR/WStereo panning (-1.0 to 1.0)
timefloatR/WCurrent playback position (seconds)
delayfloatR/WSeconds of silence before it starts
pitchfloatR/WPlayback rate (0.25 to 4.0)
durationfloatRTotal length (seconds)
finishedboolRTrue when playback has completed

loop

entity.sound.loop = True

When enabled, the sound restarts automatically after finishing.


volume

entity.sound.volume = 0.5

Values below 0.0 are clamped to 0.0.


pan

entity.sound.pan = -1.0  # full left
entity.sound.pan =  1.0  # full right
entity.sound.pan =  0.0  # center

Clamped to the range -1.0 to 1.0.


time

t = entity.sound.time
entity.sound.time = 0.25     # skip the first quarter second

The playback position in seconds. Assigning to it seeks; a value past the end is clamped to the end, and seeking a finished sound starts it playing again.


delay

entity.sound.delay = 0.002   # start two milliseconds from now

Seconds of silence before the sound starts. Unlike time this does not skip anything — the sound still begins at its first sample, it just begins later.

This is what to reach for when the same effect fires several times in one frame. Copies of one waveform that start on the same sample add up in phase: two are twice the amplitude, not 1.4 times, and ten will take a mix past full scale however carefully each one was set. A few milliseconds apart is enough to decorrelate them and far too short to hear as a gap.

for i, brick in enumerate(broken):
    e = world.spawn(sound=Sound("brick"))
    e.sound.delay = i * 0.002

What a delay separates is the attacks, so it helps most with short percussive effects and does nothing for a sustained tone — once every copy of a steady sound is playing, they sum to the same level whatever order they started in.


pitch

entity.sound.pitch = 2.0     # an octave up
entity.sound.pitch = 0.5     # an octave down

How fast the sound is played: 1.0 as recorded, 2.0 an octave higher and in half the time, 0.5 an octave lower and twice as long. Values are clamped to 0.25 to 4.0, two octaves either way. One sound at a rising pitch is a scale, so a chain or a streak needs one sound, not one per note:

def on_match(step):
    world.spawn(sound=Sound("match", pitch=1 + 0.12 * step))

time and duration stay in the sound’s own seconds: at pitch 2.0, a one-second sound plays for half a second while its time runs from 0.0 to 1.0.


duration

d = entity.sound.duration

Read-only. Total length of the sound in seconds, as recorded (whatever its pitch).


finished

if entity.sound.finished:
    world.destroy(entity)

Read-only. True when the sound has finished playing (and loop is False).


Format

Sound assets must be WAV files.


Common Errors

Missing Filename

Sound()
ValueError: Sound must have a file

Invalid Asset

Sound("nonexistent")
ValueError: Sound 'nonexistent' not found. For sounds inside a sound bank, use 'bank/sound'.

The game stops with this error. Name the asset without its .wav extension; a sound inside a sound bank is named bank/sound.


Snippets

In Pyxen’s home, under Snippets:

  • Sound() one-shot — Click to play a short WAV.
  • sound.loop / pan / volume — Continuous sound — mouse drives stereo pan.