Documentation
¶
Overview ¶
Package gofxr generates retro game sound effects. It is a Go port of jsfxr (https://github.com/chr15m/jsfxr), which is itself a port of DrPetter's sfxr. Sounds are described by a Params struct, which can be randomized with preset algorithms (PickupCoin, LaserShoot, Explosion, ...), serialized to/from the base58 format used by https://sfxr.me share URLs, and rendered to raw PCM or WAV.
The port is faithful to jsfxr: identical parameters produce identical audio, and base58 strings are interchangeable between the two libraries.
Index ¶
- type Params
- func (p *Params) BlipSelect(rng RNG) *Params
- func (p *Params) Click(rng RNG) *Params
- func (p *Params) Explosion(rng RNG) *Params
- func (p *Params) HitHurt(rng RNG) *Params
- func (p *Params) JSON() ([]byte, error)
- func (p *Params) Jump(rng RNG) *Params
- func (p *Params) LaserShoot(rng RNG) *Params
- func (p *Params) Mutate(rng RNG) *Params
- func (p *Params) PickupCoin(rng RNG) *Params
- func (p *Params) PowerUp(rng RNG) *Params
- func (p *Params) Random(rng RNG) *Params
- func (p *Params) Render(rng RNG) *Sound
- func (p *Params) Synth(rng RNG) *Params
- func (p *Params) ToB58() string
- func (p *Params) Tone() *Params
- type Preset
- type RNG
- type Sound
- type WaveType
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Params ¶
type Params struct {
WaveType WaveType `json:"wave_type"`
// Envelope
EnvAttack float64 `json:"p_env_attack"` // Attack time
EnvSustain float64 `json:"p_env_sustain"` // Sustain time
EnvPunch float64 `json:"p_env_punch"` // Sustain punch
EnvDecay float64 `json:"p_env_decay"` // Decay time
// Tone
BaseFreq float64 `json:"p_base_freq"` // Start frequency
FreqLimit float64 `json:"p_freq_limit"` // Min frequency cutoff
FreqRamp float64 `json:"p_freq_ramp"` // Slide (SIGNED)
FreqDramp float64 `json:"p_freq_dramp"` // Delta slide (SIGNED)
// Vibrato
VibStrength float64 `json:"p_vib_strength"` // Vibrato depth
VibSpeed float64 `json:"p_vib_speed"` // Vibrato speed
// Tonal change
ArpMod float64 `json:"p_arp_mod"` // Change amount (SIGNED)
ArpSpeed float64 `json:"p_arp_speed"` // Change speed
// Square wave duty (proportion of time signal is high vs. low)
Duty float64 `json:"p_duty"` // Square duty
DutyRamp float64 `json:"p_duty_ramp"` // Duty sweep (SIGNED)
// Repeat
RepeatSpeed float64 `json:"p_repeat_speed"` // Repeat speed
// Flanger
PhaOffset float64 `json:"p_pha_offset"` // Flanger offset (SIGNED)
PhaRamp float64 `json:"p_pha_ramp"` // Flanger sweep (SIGNED)
// Low-pass filter
LpfFreq float64 `json:"p_lpf_freq"` // Low-pass filter cutoff
LpfRamp float64 `json:"p_lpf_ramp"` // Low-pass filter cutoff sweep (SIGNED)
LpfResonance float64 `json:"p_lpf_resonance"` // Low-pass filter resonance
// High-pass filter
HpfFreq float64 `json:"p_hpf_freq"` // High-pass filter cutoff
HpfRamp float64 `json:"p_hpf_ramp"` // High-pass filter cutoff sweep (SIGNED)
// Sample parameters
SoundVol float64 `json:"sound_vol"`
SampleRate int `json:"sample_rate"` // 44100, 22050, 11025 or 5512
SampleSize int `json:"sample_size"` // bits per sample: 8 or 16
}
Params holds the sound generation parameters. All float parameters are on [0,1] unless marked SIGNED, which are on [-1,1]. The JSON encoding matches jsfxr's synthdef format, so files exported from https://sfxr.me load directly with FromJSON.
func FromB58 ¶
FromB58 decodes a jsfxr/sfxr.me base58 sound string. A leading "#" (or a full sfxr.me URL) is accepted. Parameters not covered by the encoding (volume, sample rate, sample size) get the NewParams defaults.
Example ¶
Render a sound designed on https://sfxr.me by pasting its share URL.
package main
import (
"fmt"
"github.com/domano/gofxr"
)
func main() {
params, err := gofxr.FromB58("https://sfxr.me/#34T6Pknn6QP7YJBMdYAFzZHibZojmNg4iwGuSayTBZuHpEKgakmZq8mD9LSKHrE8GN9988sAmVMxvFZgkeFaUCr5XV7bv3YTnZyWHMAbZeArr84YxA7Vhf5xB")
if err != nil {
panic(err)
}
sound := params.Render(nil)
fmt.Println(sound.SampleRate)
}
Output: 44100
func FromJSON ¶
FromJSON parses a jsfxr synthdef JSON object (as exported by sfxr.me). Fields absent from the JSON keep the NewParams defaults.
func Generate ¶
Generate creates parameters using a named preset, mirroring jsfxr's sfxr.generate: volume 0.25, 44100 Hz, 8-bit. A nil rng uses the shared math/rand generator.
Example ¶
Generate a random coin sound and write it to a WAV file. Seeding the RNG makes the sound reproducible across runs.
package main
import (
"math/rand/v2"
"os"
"github.com/domano/gofxr"
)
func main() {
rng := rand.New(rand.NewPCG(42, 0))
params, err := gofxr.Generate(gofxr.PresetPickupCoin, rng)
if err != nil {
panic(err)
}
params.SampleSize = 16
f, err := os.CreateTemp("", "coin-*.wav")
if err != nil {
panic(err)
}
defer os.Remove(f.Name())
defer f.Close()
if err := params.Render(rng).WriteWAV(f); err != nil {
panic(err)
}
}
Output:
func NewParams ¶
func NewParams() *Params
NewParams returns parameters with the same defaults as jsfxr's Params constructor: a short square-wave blip at 44100 Hz, 8-bit.
func (*Params) BlipSelect ¶
BlipSelect randomizes the parameters into a blip/menu selection sound.
func (*Params) Click ¶
Click randomizes the parameters into a short click, built on top of the Explosion or HitHurt presets.
func (*Params) LaserShoot ¶
LaserShoot randomizes the parameters into a laser/shoot sound.
func (*Params) Mutate ¶
Mutate randomly nudges each parameter by up to ±0.05 with 50% probability, like jsfxr's mutate. (jsfxr also touches an unused, never-serialized p_vib_delay field; that has no audible effect and is omitted here.)
func (*Params) PickupCoin ¶
PickupCoin randomizes the parameters into a coin/point pickup sound.
func (*Params) Render ¶
Render synthesizes the sound described by the parameters. The rng is only consumed by the Noise wave type (and a fixed 32 draws of priming that jsfxr performs for every wave type); a nil rng uses the shared math/rand generator. Render does not modify p and may be called repeatedly.
It panics if p.WaveType is not one of the four defined shapes, matching jsfxr's throw.
Example ¶
The tone preset is deterministic: a one-second 440 Hz sine.
package main
import (
"fmt"
"github.com/domano/gofxr"
)
func main() {
sound := gofxr.NewParams().Tone().Render(nil)
fmt.Println(sound.SampleRate, sound.BitDepth, len(sound.Samples))
}
Output: 44100 8 44104
func (*Params) ToB58 ¶
ToB58 encodes the parameters as a base58 string compatible with jsfxr and https://sfxr.me share URLs (the part after the #).
type Preset ¶
type Preset string
Preset names a randomized sound design algorithm, matching the preset names used by jsfxr and sfxr.me.
const ( PresetPickupCoin Preset = "pickupCoin" PresetLaserShoot Preset = "laserShoot" PresetExplosion Preset = "explosion" PresetPowerUp Preset = "powerUp" PresetHitHurt Preset = "hitHurt" PresetJump Preset = "jump" PresetBlipSelect Preset = "blipSelect" PresetSynth Preset = "synth" PresetTone Preset = "tone" PresetClick Preset = "click" PresetRandom Preset = "random" )
type RNG ¶
type RNG interface {
Float64() float64
}
RNG is the source of randomness used by the preset generators and by noise-wave synthesis. *rand.Rand from math/rand/v2 satisfies it. Passing a nil RNG to any function in this package uses the shared math/rand/v2 generator; pass a seeded source for reproducible sounds.
type Sound ¶
type Sound struct {
SampleRate int
BitDepth int // bits per sample in PCM: 8 or 16
// Samples holds the normalized floating point samples. Values are
// nominally in [-1, 1] but can exceed it; clipping is only applied
// during PCM quantization.
Samples []float64
// PCM holds the quantized samples: unsigned bytes for BitDepth 8,
// signed little-endian for BitDepth 16.
PCM []byte
// Clipped counts the samples that were clamped during quantization.
Clipped int
}
Sound is rendered audio: a single mono channel both as normalized floats and as quantized PCM.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
gofxr
command
Command gofxr generates retro game sound effects as WAV files, using the same algorithms and formats as jsfxr / https://sfxr.me.
|
Command gofxr generates retro game sound effects as WAV files, using the same algorithms and formats as jsfxr / https://sfxr.me. |