audio

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: May 9, 2026 License: MIT Imports: 7 Imported by: 0

README

GoGPU Logo

audio

Pure Go audio engine for Windows, macOS, and Linux
Zero CGO. PCM output. WAV decoding. Mixing. Platform-native drivers.

CI Go Reference Go Report Card License Zero CGO


Overview

audio is a Pure Go audio engine for the gogpu ecosystem. It provides low-latency PCM audio output, WAV decoding, and multi-channel mixing using platform-native APIs — without CGO.

Part of the gogpu GPU computing ecosystem (~800K+ LOC Pure Go).

Features

  • Pure Go — zero CGO on all platforms. Uses goffi/syscall for platform calls
  • Platform-native drivers — WASAPI (Windows), CoreAudio (macOS), PulseAudio (Linux)
  • WAV decoder — Pure Go WAV file parsing and playback
  • Mixer — multi-channel audio mixing with per-channel volume
  • io.Reader streams — composable audio pipeline (decoder → mixer → driver)
  • Non-blocking — audio runs in background goroutine, never blocks rendering

Status

Windows audio output working (WASAPI). macOS and Linux drivers planned.

Architecture

User Code
    │
    ▼
audio.Context (singleton, manages audio device)
    │
    ├── WAV Decoder (Pure Go)
    ├── Mixer (multi-channel, volume control)
    │       ↑ ReadFloat32er (pull model)
    ▼
Platform Driver (background goroutine → hardware)
    ├── WASAPI (Windows) ✅ — COM vtable via syscall.SyscallN
    ├── CoreAudio (macOS) — planned
    └── PulseAudio (Linux) — planned

API

package audio

// Create audio context (one per application)
ctx, err := audio.NewContext()
defer ctx.Close()

// Play a WAV file
player, err := ctx.PlayWAV(wavData)
player.SetVolume(0.8)

// Play from io.Reader stream
player, err := ctx.NewPlayer(pcmReader)
player.Play()

Platform Support

Platform Driver Status
Windows WASAPI (COM vtable via syscall) ✅ Working
macOS CoreAudio (AudioQueue via goffi) Planned
Linux PulseAudio (libpulse-simple via dlopen) Planned

Ecosystem

Package Description
gogpu Application framework, windowing
gogpu/sound UI system sounds (clicks, alerts)
gogpu/audio Full audio engine (this package)
wgpu Pure Go WebGPU
gg 2D graphics
ui GUI toolkit

For simple UI feedback sounds (button clicks, notifications), use gogpu/sound — a thin platform delegation layer (~500 LOC) that plays OS system sounds via winmm.dll (Windows), NSSound (macOS), and PulseAudio (Linux).

gogpu/audio is for games, media apps, and audio visualization that need full PCM playback, mixing, and streaming.

License

MIT License — see LICENSE.

Documentation

Overview

Package audio provides a Pure Go audio engine for cross-platform PCM audio output, WAV decoding, and multi-channel mixing.

Platform drivers:

  • Windows: WASAPI (Windows Audio Session API)
  • macOS: CoreAudio (AudioUnit via goffi)
  • Linux: PulseAudio (native protocol, Pure Go)

This package is part of the gogpu ecosystem (https://github.com/gogpu). For simple UI feedback sounds (button clicks, notifications), use gogpu/sound instead — a thin platform delegation layer.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Context

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

Context manages audio output for an application. It owns the platform audio device and coordinates player lifecycle and mixing. Typically one Context exists per application.

The driver uses a pull model: a background goroutine inside the driver reads PCM data from the Mixer via ReadFloat32s and feeds it to the hardware. Context.Start starts the driver; Context.Close stops it.

func NewContext

func NewContext(opts ...Option) (*Context, error)

NewContext creates an audio context, opens the audio device, and starts playback. The driver pulls audio data from the internal Mixer, which sums all active players.

func (*Context) Channels

func (c *Context) Channels() int

Channels returns the context's configured channel count.

func (*Context) Close

func (c *Context) Close() error

Close stops the driver and releases the audio device.

func (*Context) NewPlayer

func (c *Context) NewPlayer(src io.Reader) *Player

NewPlayer creates a player from a PCM audio stream. The reader should provide interleaved float32 PCM samples encoded as little-endian bytes (4 bytes per sample, same layout as WAVDecoder.Read output).

func (*Context) PlayWAV

func (c *Context) PlayWAV(data []byte) (*Player, error)

PlayWAV decodes WAV data and starts playback immediately. Returns the player for volume/pause/stop control.

func (*Context) SampleRate

func (c *Context) SampleRate() int

SampleRate returns the context's configured sample rate.

type Driver

type Driver interface {
	// Open opens the audio device with the given format and buffer size.
	Open(sampleRate, channels, bufferSizeMs int) error

	// SetSource sets the audio data source. The driver's background goroutine
	// pulls PCM samples from this source via ReadFloat32s.
	SetSource(src ReadFloat32er)

	// Start begins audio playback. The driver goroutine starts pulling from
	// the source and feeding the hardware.
	Start() error

	// Stop pauses audio playback without closing the device.
	Stop() error

	// Close stops playback and releases the audio device.
	Close() error
}

Driver is the platform audio output interface. Implementations exist per platform: WASAPI (Windows), CoreAudio (macOS), PulseAudio (Linux). The NullDriver is provided for testing and headless use.

Drivers use a pull model: a background goroutine reads PCM data from the source (typically the Mixer) and feeds it to the hardware. This matches the native model of all three platforms (WASAPI event-driven, CoreAudio callback, PulseAudio write-when-ready).

type Mixer

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

Mixer combines multiple audio sources into a single output stream. Each source has its own volume, and the mixer applies a master volume after summing. Output is clamped to [-1.0, 1.0].

func NewMixer

func NewMixer() *Mixer

NewMixer creates a mixer with master volume set to 1.0.

func (*Mixer) AddSource

func (m *Mixer) AddSource(p *Player)

AddSource registers a player as a mix input.

func (*Mixer) MasterVolume

func (m *Mixer) MasterVolume() float64

MasterVolume returns the current master volume.

func (*Mixer) Mix

func (m *Mixer) Mix(out []float32)

Mix reads samples from all active sources, sums them with per-source volume, applies master volume, and writes the result into out. Inactive or finished sources contribute silence.

func (*Mixer) ReadFloat32s

func (m *Mixer) ReadFloat32s(buf []float32) (int, error)

ReadFloat32s fills buf with mixed audio from all active sources. It implements ReadFloat32er so the Mixer can be used as a Driver source.

func (*Mixer) RemoveSource

func (m *Mixer) RemoveSource(p *Player)

RemoveSource unregisters a player from the mixer.

func (*Mixer) SetMasterVolume

func (m *Mixer) SetMasterVolume(v float64)

SetMasterVolume sets the master output volume (0.0 to 1.0).

type NullDriver

type NullDriver struct{}

NullDriver discards all audio output. It is used for testing and headless environments where no audio hardware is available.

func (*NullDriver) Close

func (d *NullDriver) Close() error

Close is a no-op for the null driver.

func (*NullDriver) Open

func (d *NullDriver) Open(_, _, _ int) error

Open is a no-op for the null driver.

func (*NullDriver) SetSource

func (d *NullDriver) SetSource(_ ReadFloat32er)

SetSource is a no-op for the null driver.

func (*NullDriver) Start

func (d *NullDriver) Start() error

Start is a no-op for the null driver.

func (*NullDriver) Stop

func (d *NullDriver) Stop() error

Stop is a no-op for the null driver.

type Option

type Option func(*Context)

Option configures the audio context during construction.

func WithChannels

func WithChannels(ch int) Option

WithChannels sets the number of output channels. Default is 2 (stereo).

func WithDriver

func WithDriver(d Driver) Option

WithDriver sets a specific audio driver. If not set, NullDriver is used until platform drivers are implemented.

func WithSampleRate

func WithSampleRate(rate int) Option

WithSampleRate sets the audio sample rate in Hz. Default is 44100.

type Player

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

Player plays audio from an io.Reader source that provides float32 PCM samples encoded as little-endian bytes (4 bytes per sample).

func (*Player) IsPlaying

func (p *Player) IsPlaying() bool

IsPlaying reports whether the player is actively producing audio (playing and not paused, not finished).

func (*Player) Pause

func (p *Player) Pause()

Pause suspends playback without losing position.

func (*Player) Play

func (p *Player) Play()

Play starts playback. If the player is paused, it resumes. If playback already finished, this is a no-op.

func (*Player) Resume

func (p *Player) Resume()

Resume continues playback after a pause.

func (*Player) SetVolume

func (p *Player) SetVolume(v float64)

SetVolume sets the playback volume. Values are clamped to [0.0, 1.0].

func (*Player) Stop

func (p *Player) Stop()

Stop ends playback permanently. The player cannot be restarted.

func (*Player) Volume

func (p *Player) Volume() float64

Volume returns the current playback volume.

type ReadFloat32er

type ReadFloat32er interface {
	ReadFloat32s(buf []float32) (int, error)
}

ReadFloat32er provides interleaved float32 PCM samples. The Mixer implements this interface.

type WAVDecoder

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

WAVDecoder reads WAV data and produces interleaved float32 PCM samples via the io.Reader interface. It supports PCM 8/16/24/32-bit integer and IEEE 32-bit float formats.

func DecodeWAV

func DecodeWAV(data []byte) (*WAVDecoder, error)

DecodeWAV parses a WAV byte slice and returns a decoder that produces interleaved float32 PCM samples through its Read method.

func (*WAVDecoder) Channels

func (d *WAVDecoder) Channels() int

Channels returns the number of audio channels.

func (*WAVDecoder) Duration

func (d *WAVDecoder) Duration() time.Duration

Duration returns the total duration of the audio data.

func (*WAVDecoder) Read

func (d *WAVDecoder) Read(p []byte) (int, error)

Read produces interleaved float32 PCM samples. The output buffer p is interpreted as a []byte backing store for float32 values, so len(p) must be a multiple of 4. Each 4 bytes in p receive one float32 sample in little-endian format.

func (*WAVDecoder) Reset

func (d *WAVDecoder) Reset()

Reset rewinds the decoder to the beginning of the audio data.

func (*WAVDecoder) SampleRate

func (d *WAVDecoder) SampleRate() int

SampleRate returns the WAV file's sample rate in Hz.

Directories

Path Synopsis
examples
play_wav command
internal

Jump to

Keyboard shortcuts

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