Generating sounds¶
pyfxr has 3 sound generation algorithms, described below.
sfxr-style sounds¶
sfxr is a user interface for generating sounds with a wide array of parameters. pyfxr provides a full API to generate these sounds in Python programs.
-
class
pyfxr.
SFX
(**kwargs)¶ Build a sound effect using a set of parameters.
The list of parameters is long and the sensible ranges for the parameters aren’t that clear. This class acts as a validator and builder for the parameters, making it simpler to experiment with sound effects.
You can also serialise this class in several ways:
The
repr()
is suitable for pasting into code.You can serialise it as JSON using
.as_dict()
.You can pickle the class.
In any of these case the size is much smaller than the generated SoundBuffer.
SFX supports the buffer protocol much like
SoundBuffer
; accessing the object as a buffer generates and caches a sound.-
base_freq
: float¶ The initial frequency of the sound
-
freq_limit
: float¶ The minimum frequency of the sound
-
freq_ramp
: float¶ The rate of change of the frequency of the sound
-
freq_dramp
: float¶ The acceleration of the change in frequency of the sound
-
duty
: float¶ If using square wave, the duty cycle of the waveform
-
duty_ramp
: float¶ The rate of change of the square wave duty cycle
-
vib_strength
: float¶ Vibrato strength
-
vib_speed
: float¶ Vibrato speed
-
vib_delay
: float¶ Vibrato delay
-
env_attack
: float¶ The duration of the attack phase of the ADSR envelope
-
env_sustain
: float¶ The duration of the sustain phase of the ADSR envelope
-
env_decay
: float¶ The duration of the decay phase of the ADSR envelope
-
env_punch
: float¶ Causes the volume to decrease during the sustain phase of the envelope
-
lpf_resonance
: float¶ Low-pass filter resonance
-
lpf_freq
: float¶ Low-pass filter cutoff frequency
-
lpf_ramp
: float¶ Low-pass filter cutoff ramp
-
hpf_freq
: float¶ High-pass filter frequency
-
hpf_ramp
: float¶ High-pass filter ramp
-
pha_offset
: float¶ Phaser offset
-
pha_ramp
: float¶ Phaser ramp
-
repeat_speed
: float¶ Repeat speed
-
arp_speed
: float¶ Arpeggio speed
-
arp_mod
: float¶ Arpeggio mod
-
property
wave_type
¶ Get the wave type.
-
as_dict
() → dict¶ Get the parameters as a dict.
The dict is suitable for serialising as JSON; to reconstruct the object, pass the parameters as kwargs to the constructor, eg.
>>> s = SFX(...) >>> params = s.as_dict() >>> s2 = SFX(**params)
-
build
() → _pyfxr.SoundBuffer¶ Get the generated sound (memoised).
-
envelope
(attack: float = 0.0, sustain: float = 0.3, decay: float = 0.4, punch: float = 0.0)¶ Set the ADSR envelope for this sound effect.
The wave_type
of an SFX must be one of these values:
-
class
pyfxr.
WaveType
(value)¶ The wave types available for the SFX builder.
Pure tones with tone() use arbitrary wavetables rather than this enumeration.
-
SQUARE
= 0¶ A square-wave waveform
-
SAW
= 1¶ A saw-wave waveform
-
SINE
= 2¶ A sine wave
-
NOISE
= 3¶ Random noise
-
You can also randomly generate those parameters:
Wavetable sounds¶
pyfxr can also generate pure tones using a wavetable. A wavetable gives the shape of a waveform, such as these:
(Source code, png, hires.png, pdf)
Wavetables can have any shape. To construct a Wavetable with a custom shape, pass an iterable to the constructor. This should return 1024 float values in [-1, 1].
from math import pi, sin
from pyfxr import Wavetable
def gen():
for i in range(1024):
t = pi / 512 * i
yield 0.75 * sin(t) + 0.25 * sin(3 * t + 0.5)
wt = Wavetable(gen())
Or perhaps more simply, use Wavetable.from_function()
:
Wavetable.from_function(
lambda t: 0.75 * sin(t) + 0.25 * sin(3 * t + 0.5)
)
(Source code, png, hires.png, pdf)
-
class
pyfxr.
Wavetable
(gen)¶ -
static
from_function
(f)¶ Generate a wavetable by calling a function f.
f should take a single float argument between 0 and tau (pi * 2) and return values in [-1, 1].
-
static
saw
()¶ Construct a saw waveform.
-
static
sine
()¶ Construct a sine waveform.
-
static
square
(float duty_cycle=0.5)¶ Generate a square-wave waveform.
duty_cycle is the fraction of the period during which the waveform is greater than zero.
-
static
triangle
()¶ Construct a triangle waveform.
-
static
-
pyfxr.
tone
(pitch: Union[float, str] = 440.0, attack: float = 0.1, decay: float = 0.1, sustain: float = 0.75, release: float = 0.25, wavetable: _pyfxr.Wavetable = <_pyfxr.Wavetable object>) → _pyfxr.SoundBuffer¶ Generate a tone using a wavetable.
The tone will be modulated by an ADSR envelope (attack-decay-sustain-release) which gives the tone a more natural feel, and avoids clicks when played. The total length of the tone is the sum of these durations.
- Parameters
wavetable – The wavetable to use (default is a sine wave).
pitch – The pitch of the tone to generate, either float Hz or a note name/number like
Bb4
for B-flat in the 4th octave.attack – Attack time in seconds
decay – Decay time in seconds
sustain – Sustain time in seconds
release – Release time in seconds
ADSR Envelopes¶
Tones are bounded by a 4-phase “ADSR Envelope”. The phases are:
Attack - initial increase in volume
Decay - volume decreases to the sustain level
Sustain - the volume stays constant while the note is held
Release - the volume fades to zero
(Source code, png, hires.png, pdf)
The default ADSR envelope has this shape. Note that durations for any of the ADSR phases can be set to zero to omit that phase. It is recommended to skip only decay and sustain phases, as attack and release phases help to avoid clicks when the sound plays.
This is applied to a waveform by multiplication:
(Source code, png, hires.png, pdf)