audio

package
v0.0.0-...-bfb89c8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 2, 2026 License: MIT Imports: 4 Imported by: 0

README

Audio Synthesis Package

This package provides procedural audio synthesis for the Venture game. All audio is generated at runtime using waveform synthesis, music theory, and audio processing techniques. No external audio files are required.

Architecture

The audio system consists of three main subsystems:

1. Synthesis (pkg/audio/synthesis)

Low-level waveform generation and audio envelopes.

Features:

  • 5 waveform types: Sine, Square, Sawtooth, Triangle, Noise
  • ADSR (Attack, Decay, Sustain, Release) envelopes
  • Deterministic generation with seed support
  • 44.1kHz sample rate (CD quality)

Usage:

import "github.com/opd-ai/venture/pkg/audio/synthesis"

// Create oscillator
osc := synthesis.NewOscillator(44100, seed)

// Generate sine wave at 440 Hz for 1 second
sample := osc.Generate(audio.WaveformSine, 440.0, 1.0)

// Generate musical note with velocity
note := audio.Note{
    Frequency: 440.0,
    Duration:  0.5,
    Velocity:  0.8,
}
sample := osc.GenerateNote(note, audio.WaveformTriangle)

// Apply ADSR envelope
env := synthesis.Envelope{
    Attack:  0.01,
    Decay:   0.1,
    Sustain: 0.7,
    Release: 0.2,
}
env.Apply(sample.Data, sample.SampleRate)
2. Sound Effects (pkg/audio/sfx)

Procedural generation of game sound effects.

Effect Types:

  • impact - Short, punchy impact sounds
  • explosion - Large boom sounds with rumble
  • magic - Magical sparkle and shimmer
  • laser - Sci-fi laser/energy weapons
  • pickup - Item collection sounds
  • hit - Combat hit/damage sounds
  • jump - Character jump sounds
  • death - Defeat/death sounds
  • powerup - Energizing powerup sounds

Features:

  • Genre-appropriate sound design
  • Pitch bending and vibrato effects
  • Procedural audio mixing
  • Deterministic with seed control

Usage:

import "github.com/opd-ai/venture/pkg/audio/sfx"

// Create SFX generator
gen := sfx.NewGenerator(44100, seed)

// Generate magic effect
magicSound := gen.Generate("magic", seed)

// Generate explosion
explosionSound := gen.Generate("explosion", seed)
3. Music (pkg/audio/music)

Procedural music composition using music theory.

Features:

  • Genre-specific scales (Major, Minor, Pentatonic, Blues, Chromatic)
  • Context-aware tempo and rhythm
  • Chord progressions per genre
  • Melody and harmony generation
  • Automatic fade in/out

Genres Supported:

  • Fantasy (Major scale, classic progressions)
  • Sci-Fi (Chromatic scale, futuristic)
  • Horror (Minor scale, dissonant)
  • Cyberpunk (Blues scale, urban)
  • Post-Apocalyptic (Pentatonic, minimal)

Contexts Supported:

  • Combat (fast tempo, driving rhythm)
  • Exploration (moderate tempo, wandering melody)
  • Ambient (slow tempo, atmospheric)
  • Victory (uplifting tempo, ascending melody)

Usage:

import "github.com/opd-ai/venture/pkg/audio/music"

// Create music generator
gen := music.NewGenerator(44100, seed)

// Generate 10-second fantasy combat music
track := gen.GenerateTrack("fantasy", "combat", seed, 10.0)

// Generate 30-second horror ambient music
ambientTrack := gen.GenerateTrack("horror", "ambient", seed, 30.0)

Performance

The audio system meets all performance targets:

  • Generation Speed:

    • Oscillator: ~10μs per second of audio
    • SFX: 1-5ms per effect
    • Music: 50-200ms per 10 seconds
  • Memory Usage:

    • ~88KB per second of audio (44.1kHz, 64-bit floats)
    • Minimal allocations in generation hot paths
  • Quality:

    • 44.1kHz sample rate (CD quality)
    • 64-bit floating point precision
    • Samples in range [-1.0, 1.0]

Testing

Comprehensive test suite with ~90% average coverage:

# Run all audio tests
go test -tags test ./pkg/audio/...

# Run with coverage
go test -tags test -cover ./pkg/audio/...

# Run benchmarks
go test -tags test -bench=. ./pkg/audio/...

Test Coverage:

  • pkg/audio: 86.2%
  • synthesis: 96.5%
  • sfx: 89.9%
  • music: 93.9%

Integration

With ECS Framework
// Audio component
type AudioComponent struct {
    Sample   *audio.AudioSample
    Playing  bool
    Position int
}

func (c *AudioComponent) Type() string {
    return "audio"
}

// Add to entity
entity.AddComponent(&AudioComponent{
    Sample:  sfxGen.Generate("hit", seed),
    Playing: true,
})
With Game Events
// Play sound on hit using deterministic seed
func onEnemyHit(x, y float64, eventSeed int64) {
    hitSound := sfxGen.Generate("hit", eventSeed)
    audioSystem.Play(hitSound)
}

// Change music on context switch
func onContextChange(context string) {
    track := musicGen.GenerateTrack(currentGenre, context, worldSeed, 60.0)
    audioSystem.PlayMusic(track, true) // loop
}

Future Enhancements

Potential improvements for later phases:

  • Audio filters (low-pass, high-pass, reverb)
  • Multi-channel mixing with volume control
  • Spatial audio (3D sound positioning)
  • Audio compression for network transmission
  • Real-time audio playback via Ebiten
  • Dynamic music that responds to gameplay
  • More complex musical structures (bridges, variations)
  • Additional instruments via additive synthesis

Technical Details

Waveform Mathematics

Sine Wave:

y(t) = sin(2π * f * t)

Square Wave:

y(t) = sign(sin(2π * f * t))

Sawtooth Wave:

y(t) = 2 * (t * f mod 1) - 1

Triangle Wave:

y(t) = 4 * |t * f mod 1 - 0.5| - 1
ADSR Envelope

The envelope shapes audio amplitude over time:

  1. Attack: Linear ramp from 0 to 1
  2. Decay: Linear ramp from 1 to sustain level
  3. Sustain: Constant at sustain level
  4. Release: Linear ramp from sustain to 0
Musical Note Frequencies
f(n) = 440 * 2^((n - 69) / 12)

Where n is the MIDI note number (A4 = 69).

Dependencies

  • math - Mathematical functions for waveform generation
  • math/rand - Deterministic random number generation
  • github.com/opd-ai/venture/pkg/audio - Audio type definitions

No external audio libraries required!

License

See project LICENSE file.

Documentation

Overview

Package audio provides procedural audio synthesis for all sounds in the game. All audio is generated at runtime using waveform synthesis and music theory.

The audio system supports procedural music composition, sound effects generation, and adaptive audio based on game context and genre.

Architecture

The package provides a unified Manager that coordinates music and SFX systems:

  • Manager: Unified audio manager with volume controls and dependency injection
  • AdaptiveMusicSystem: Interface for context-aware music composition
  • SFXGenerator: Interface for sound effect generation

Sub-packages:

  • music: Adaptive music composition with genre awareness
  • sfx: Sound effect generation with variety management
  • synthesis: Low-level waveform synthesis and envelopes

Usage

// Create unified manager
manager := audio.NewManager(44100, seed)

// Set music system
musicSystem := music.NewAdaptiveMusicManager(44100, seed)
manager.SetMusicManager(musicSystem)

// Set SFX system
sfxSystem := sfx.NewVarietyManager(44100, seed)
manager.SetSFXManager(sfxSystem)

// Generate audio
musicSample := manager.GenerateMusicTrack(2.0)
sfxSample := manager.GenerateSFX("impact", 12345)

Phase 1.1 (PLAN.md): Full audio integration complete - December 2025

Package audio provides core audio synthesis interfaces. This file defines audio interfaces and waveform types used by the audio generation and synthesis subsystem.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AdaptiveMusicSystem

type AdaptiveMusicSystem interface {
	// SetContext updates the music based on gameplay context
	SetContext(context MusicContext) error

	// UpdateIntensity adjusts the intensity level (0.0-1.0)
	UpdateIntensity(intensity float64) error

	// AddLayer activates a specific music layer
	AddLayer(layer MusicLayer) error

	// RemoveLayer deactivates a specific music layer
	RemoveLayer(layer MusicLayer) error

	// Update performs smooth transitions between states
	Update(deltaTime float64)

	// GenerateTrack creates an audio sample with current settings
	GenerateTrack(duration float64) *AudioSample
}

AdaptiveMusicSystem manages context-aware music composition.

type AudioMixer

type AudioMixer interface {
	// PlaySample plays an audio sample
	PlaySample(sample *AudioSample, loop bool)

	// Stop stops playback
	Stop()

	// SetVolume sets the master volume (0.0 to 1.0)
	SetVolume(volume float64)
}

AudioMixer manages playback of multiple audio sources.

type AudioSample

type AudioSample struct {
	// SampleRate in Hz (e.g., 44100)
	SampleRate int

	// Data contains the audio samples (-1.0 to 1.0)
	Data []float64
}

AudioSample represents a generated audio buffer.

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager is a unified audio manager that coordinates music, SFX, and voice systems. It provides a single interface for managing all game audio with support for adaptive music, varied sound effects, and voice chat.

func NewManager

func NewManager(sampleRate int, seed int64) *Manager

NewManager creates a new unified audio manager. sampleRate must be positive (typically 44100 or 48000).

func (*Manager) AddMusicLayer

func (m *Manager) AddMusicLayer(layer MusicLayer) error

AddMusicLayer activates a music layer.

func (*Manager) GenerateMusicTrack

func (m *Manager) GenerateMusicTrack(duration float64) *AudioSample

GenerateMusicTrack creates a music track with current settings.

func (*Manager) GenerateSFX

func (m *Manager) GenerateSFX(effectType string, seed int64) *AudioSample

GenerateSFX creates a sound effect.

func (*Manager) GetMasterVolume

func (m *Manager) GetMasterVolume() float64

GetMasterVolume returns the master volume.

func (*Manager) GetMusicManager

func (m *Manager) GetMusicManager() AdaptiveMusicSystem

GetMusicManager returns the current music manager.

func (*Manager) GetMusicVolume

func (m *Manager) GetMusicVolume() float64

GetMusicVolume returns the music volume.

func (*Manager) GetSFXManager

func (m *Manager) GetSFXManager() SFXGenerator

GetSFXManager returns the current SFX manager.

func (*Manager) GetSFXVolume

func (m *Manager) GetSFXVolume() float64

GetSFXVolume returns the sound effects volume.

func (*Manager) GetSampleRate

func (m *Manager) GetSampleRate() int

GetSampleRate returns the sample rate.

func (*Manager) GetSeed

func (m *Manager) GetSeed() int64

GetSeed returns the seed.

func (*Manager) GetVoiceCodec

func (m *Manager) GetVoiceCodec() VoiceCodec

GetVoiceCodec returns the current voice codec.

func (*Manager) GetVoiceProcessor

func (m *Manager) GetVoiceProcessor() *VoiceProcessor

GetVoiceProcessor returns the current voice processor.

func (*Manager) GetVoiceVolume

func (m *Manager) GetVoiceVolume() float64

GetVoiceVolume returns the voice chat volume.

func (*Manager) InitializeVoice

func (m *Manager) InitializeVoice(quality VoiceQuality, transport VoiceTransport) error

InitializeVoice sets up voice codec with the specified quality. The transport parameter may be nil for testing or when voice chat is not yet integrated with the network layer. Production deployments should provide a concrete VoiceTransport implementation that integrates with pkg/network/chat for proximity/guild/party voice channels.

TODO(integration): Wire VoiceTransport to network/chat subsystem for proximity/guild/party voice channels. Current implementation accepts nil transport for future integration.

func (*Manager) IsVoiceEnabled

func (m *Manager) IsVoiceEnabled() bool

IsVoiceEnabled returns whether voice chat is enabled.

func (*Manager) RemoveMusicLayer

func (m *Manager) RemoveMusicLayer(layer MusicLayer) error

RemoveMusicLayer deactivates a music layer.

func (*Manager) SetMasterVolume

func (m *Manager) SetMasterVolume(volume float64)

SetMasterVolume sets the master volume (0.0-1.0).

func (*Manager) SetMusicContext

func (m *Manager) SetMusicContext(context MusicContext) error

SetMusicContext updates music based on gameplay context.

func (*Manager) SetMusicManager

func (m *Manager) SetMusicManager(manager AdaptiveMusicSystem)

SetMusicManager sets the adaptive music manager implementation.

func (*Manager) SetMusicVolume

func (m *Manager) SetMusicVolume(volume float64)

SetMusicVolume sets the music volume (0.0-1.0). Note: Setting volume to 0.0 implicitly disables music playback. This is intentional to prevent silent music generation overhead. Use GetMusicVolume() to check current volume.

func (*Manager) SetSFXManager

func (m *Manager) SetSFXManager(manager SFXGenerator)

SetSFXManager sets the sound effects generator implementation.

func (*Manager) SetSFXVolume

func (m *Manager) SetSFXVolume(volume float64)

SetSFXVolume sets the sound effects volume (0.0-1.0). Note: Setting volume to 0.0 implicitly disables SFX playback. This is intentional to prevent silent sound generation overhead. Use GetSFXVolume() to check current volume.

func (*Manager) SetVoiceCodec

func (m *Manager) SetVoiceCodec(codec VoiceCodec)

SetVoiceCodec sets the voice codec implementation.

func (*Manager) SetVoiceProcessor

func (m *Manager) SetVoiceProcessor(processor *VoiceProcessor)

SetVoiceProcessor sets the voice processor implementation.

func (*Manager) SetVoiceVolume

func (m *Manager) SetVoiceVolume(volume float64)

SetVoiceVolume sets the voice chat volume (0.0-1.0).

func (*Manager) Update

func (m *Manager) Update(deltaTime float64)

Update performs smooth transitions for music.

func (*Manager) UpdateMusicIntensity

func (m *Manager) UpdateMusicIntensity(intensity float64) error

UpdateMusicIntensity adjusts music intensity (0.0-1.0).

type MusicContext

type MusicContext struct {
	// Location describes where the player is (e.g., "dungeon", "town", "wilderness")
	Location string

	// Combat indicates if combat is active
	Combat bool

	// BossNearby indicates if a boss enemy is nearby
	BossNearby bool

	// TimeOfDay represents the time (e.g., "dawn", "day", "dusk", "night")
	TimeOfDay string

	// Danger level from 0.0 (safe) to 1.0 (deadly)
	Danger float64
}

MusicContext represents the gameplay context for adaptive music.

type MusicGenerator

type MusicGenerator interface {
	// GenerateTrack creates a music track for the given context
	GenerateTrack(genre, context string, seed int64, duration float64) *AudioSample
}

MusicGenerator creates procedural music.

type MusicLayer

type MusicLayer int

MusicLayer represents a layer in adaptive music composition.

const (
	// MusicLayerBase is the foundational ambient layer
	MusicLayerBase MusicLayer = iota
	// MusicLayerHarmony adds harmonic support
	MusicLayerHarmony
	// MusicLayerPercussion adds rhythmic elements
	MusicLayerPercussion
	// MusicLayerMelody adds the primary melodic line
	MusicLayerMelody
	// MusicLayerIntensity adds high-energy intensity
	MusicLayerIntensity
)

func (MusicLayer) String

func (m MusicLayer) String() string

String returns the string representation of a MusicLayer.

type Note

type Note struct {
	// Frequency in Hz
	Frequency float64

	// Duration in seconds
	Duration float64

	// Velocity (volume) from 0.0 to 1.0
	Velocity float64
}

Note represents a musical note with frequency and duration.

type SFXGenerator

type SFXGenerator interface {
	// Generate creates a sound effect for the given action
	Generate(effectType string, seed int64) *AudioSample
}

SFXGenerator creates sound effects.

type SimpleVoiceCodec

type SimpleVoiceCodec struct {
	// contains filtered or unexported fields
}

SimpleVoiceCodec is a basic voice codec using simple compression. Production systems would use Opus or similar, but this provides a working implementation without external dependencies.

func NewSimpleVoiceCodec

func NewSimpleVoiceCodec(sampleRate int, quality VoiceQuality) *SimpleVoiceCodec

NewSimpleVoiceCodec creates a new simple voice codec.

func (*SimpleVoiceCodec) Decode

func (c *SimpleVoiceCodec) Decode(data []byte) ([]float64, error)

Decode decompresses received data into audio samples. The output always has an even number of samples (2 samples per byte). If the original input had an odd number of samples, the decoded output will include one extra sample derived from the padding zero nibble.

func (*SimpleVoiceCodec) Encode

func (c *SimpleVoiceCodec) Encode(samples []float64) ([]byte, error)

Encode compresses audio samples using simple ADPCM-like encoding. Each sample is quantized to 4 bits, with two samples packed per byte. Note: For odd-length sample arrays, the output rounds up to ceil(n/2) bytes. During decoding, this produces an extra sample (decode always produces even count). Frame sizes (320-960 based on sample rate) are typically even, so this rarely matters.

func (*SimpleVoiceCodec) GetBitrate

func (c *SimpleVoiceCodec) GetBitrate() int

GetBitrate returns the codec bitrate.

func (*SimpleVoiceCodec) GetFrameSize

func (c *SimpleVoiceCodec) GetFrameSize() int

GetFrameSize returns the frame size.

func (*SimpleVoiceCodec) GetSampleRate

func (c *SimpleVoiceCodec) GetSampleRate() int

GetSampleRate returns the sample rate.

type Synthesizer

type Synthesizer interface {
	// Generate creates an audio sample from parameters
	Generate(waveform WaveformType, frequency, duration float64) *AudioSample

	// GenerateNote creates an audio sample for a musical note
	GenerateNote(note Note, waveform WaveformType) *AudioSample
}

Synthesizer generates audio waveforms.

type VoiceCodec

type VoiceCodec interface {
	// Encode compresses audio samples for transmission
	Encode(samples []float64) ([]byte, error)

	// Decode decompresses received data into audio samples
	Decode(data []byte) ([]float64, error)

	// GetBitrate returns the codec bitrate in bits per second
	GetBitrate() int

	// GetSampleRate returns the expected sample rate
	GetSampleRate() int

	// GetFrameSize returns the expected frame size in samples
	GetFrameSize() int
}

VoiceCodec defines the interface for voice encoding and decoding.

type VoiceProcessor

type VoiceProcessor struct {
	// contains filtered or unexported fields
}

VoiceProcessor manages voice encoding, decoding, and transmission.

func NewVoiceProcessor

func NewVoiceProcessor(codec VoiceCodec, transport VoiceTransport) *VoiceProcessor

NewVoiceProcessor creates a new voice processor.

func (*VoiceProcessor) ClearBuffers

func (p *VoiceProcessor) ClearBuffers()

ClearBuffers clears all internal buffers.

func (*VoiceProcessor) GetCodec

func (p *VoiceProcessor) GetCodec() VoiceCodec

GetCodec returns the voice codec.

func (*VoiceProcessor) GetTransport

func (p *VoiceProcessor) GetTransport() VoiceTransport

GetTransport returns the voice transport.

func (*VoiceProcessor) IsEnabled

func (p *VoiceProcessor) IsEnabled() bool

IsEnabled returns whether voice processing is enabled.

func (*VoiceProcessor) ProcessInput

func (p *VoiceProcessor) ProcessInput(channelID string, samples []float64) error

ProcessInput processes input audio samples and sends them if ready. channelID identifies the voice channel (e.g., "team", "proximity", "guild") that the encoded audio will be transmitted to via the transport layer. Samples are accumulated in an internal buffer and encoded into frames when enough data is available.

Returns an error if channelID is empty or if transport transmission fails.

func (*VoiceProcessor) ProcessOutput

func (p *VoiceProcessor) ProcessOutput() (map[string][]float64, error)

ProcessOutput receives and decodes voice data.

func (*VoiceProcessor) SetEnabled

func (p *VoiceProcessor) SetEnabled(enabled bool)

SetEnabled enables or disables voice processing.

type VoiceQuality

type VoiceQuality int

VoiceQuality defines the quality preset for voice encoding.

const (
	// VoiceQualityLow provides minimal bandwidth (8 kbps, suitable for high-latency)
	VoiceQualityLow VoiceQuality = iota
	// VoiceQualityMedium provides balanced quality (16 kbps)
	VoiceQualityMedium
	// VoiceQualityHigh provides high quality (32 kbps)
	VoiceQualityHigh
)

type VoiceSystem

type VoiceSystem interface {
	// GetCodec returns the voice codec for encoding/decoding
	GetCodec() VoiceCodec

	// GetProcessor returns the voice processor for transmission
	GetProcessor() *VoiceProcessor

	// SetQuality sets the voice quality preset
	SetQuality(quality VoiceQuality) error

	// IsAvailable returns whether voice chat is available
	IsAvailable() bool
}

VoiceSystem provides voice chat capabilities with codec integration.

type VoiceTransport

type VoiceTransport interface {
	// SendVoice transmits encoded voice data to a channel
	SendVoice(channelID string, data []byte) error

	// ReceiveVoice gets received voice data for processing
	ReceiveVoice() (channelID, senderID string, data []byte, ok bool)

	// SetSpatialParams sets spatial audio parameters for transmission
	SetSpatialParams(volume, pan float64)
}

VoiceTransport handles network transmission of voice data.

type WaveformType

type WaveformType int

WaveformType represents different basic waveform types.

const (
	WaveformSine WaveformType = iota
	WaveformSquare
	WaveformSawtooth
	WaveformTriangle
	WaveformNoise
)

Waveform type constants.

Directories

Path Synopsis
Package music provides adaptive music composition.
Package music provides adaptive music composition.
Package sfx provides procedural sound effect generation.
Package sfx provides procedural sound effect generation.
Package synthesis provides low-level audio waveform generation.
Package synthesis provides low-level audio waveform generation.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL