Skip to content

GeoffreyPlitt/gosfzplayer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

61 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SFZ Player Library

Release Go Report Card Go Reference Test codecov Go Version

A lightweight Go library (~595K) that implements a simple SFZ sampler with WAV and FLAC sample loading.

Note: You must manually connect the JACK ports for audio and MIDI:

  • Connect JACK output port MyInstrument:out_1 and MyInstrument:out_2 to your system audio outputs
  • Connect your MIDI controller to JACK input port MyInstrument:midi_in

Audio Demo

🎵 Piano Arpeggio Sample - Generated by TestRenderPianoArpeggio

🎧 Listen to piano_arpeggio.wav

Audio file automatically updated on every successful CI run to main branch

The sample demonstrates:

  • FLAC sample loading (FreePats Upright Piano KW)
  • Multi-velocity layers (soft/loud playing dynamics)
  • Pitch-shifting (full 88-key range from sparse sample set)
  • ADSR envelope processing (attack/decay/sustain/release)
  • Loop support (continuous loops for sustained notes)
  • Decent-quality reverb (Freeverb algorithm with hall-like acoustics)

API

Primary Interface:

func NewSfzPlayer(sfzPath string, jackClientName string) (*SfzPlayer, error)

Supported SFZ Opcodes

Core Sample Opcodes

  • sample - Path to the audio sample file (required)
  • key - Root key for the sample
  • pitch_keycenter - Reference pitch for the sample

Key/Velocity Mapping

  • lokey - Lowest key that triggers this region
  • hikey - Highest key that triggers this region
  • lovel - Lowest velocity that triggers this region
  • hivel - Highest velocity that triggers this region

Playback Control

  • volume - Volume adjustment in dB
  • pan - Stereo panning (-100 to 100)
  • tune - Fine tuning in cents
  • transpose - Transposition in semitones
  • pitch - Pitch adjustment

ADSR Envelope

  • ampeg_attack - Attack time in seconds
  • ampeg_decay - Decay time in seconds
  • ampeg_sustain - Sustain level (0-100%)
  • ampeg_release - Release time in seconds

Looping

  • loop_mode - Loop mode (no_loop, one_shot, loop_continuous, loop_sustain)
  • loop_start - Loop start point in samples
  • loop_end - Loop end point in samples

Reverb Opcodes

  • reverb_send - Reverb send level (0-100)
  • reverb_room_size - Room size parameter (0-100)
  • reverb_damping - Damping amount (0-100)
  • reverb_wet - Wet signal level (0-100)
  • reverb_dry - Dry signal level (0-100)
  • reverb_width - Stereo width (0-100)

Features

  • SFZ File Parsing: Complete parser for SFZ files with structured data representation
  • Multi-Format Sample Loading: Automatic loading and caching of WAV and FLAC audio samples
  • Decent-Quality Reverb: Built-in Freeverb algorithm with real-time control
  • MIDI Control: Full MIDI CC support for reverb parameters (CC91-95)
  • SFZ Reverb Opcodes: Support for reverb opcodes in SFZ files
  • Sample Caching: Efficient caching system to avoid duplicate sample loads
  • Normalized Audio Data: Audio samples normalized to float64 range (-1.0 to 1.0)
  • Error Handling: Graceful handling of missing files and invalid syntax
  • Debug Logging: Comprehensive logging with configurable namespaces
  • Type Conversion: Helper functions for string to numeric type conversion

Usage

package main

import (
    "fmt"
    "gosfzplayer"
)

func main() {
    // Create SFZ player - parses file, loads samples, starts JACK client
    player, err := gosfzplayer.NewSfzPlayer("path/to/instrument.sfz", "MyInstrument")
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }
    
    fmt.Println("SFZ Player created successfully!")
    
    // Player is now ready for MIDI input and audio output
    // Use JACK connection tools like QJackCtl to connect MIDI and audio
}

Debug Logging

Enable debug output with the DEBUG environment variable:

# Enable all debug output
DEBUG=sfzplayer:* go run gosfzplayer.go

# Enable only parser debug output  
DEBUG=sfzplayer:parser go run gosfzplayer.go

Reverb System

The SFZ player includes a decent-quality Freeverb implementation with low CPU usage (~5-10% overhead) and good sound quality.

Programmatic Control

// Create SFZ player
player, err := gosfzplayer.NewSfzPlayer("instrument.sfz", "MyInstrument")

// Configure reverb
player.SetReverbSend(0.3)        // 30% reverb send
player.SetReverbRoomSize(0.7)    // Large room size  
player.SetReverbDamping(0.4)     // Moderate damping
player.SetReverbWet(0.8)         // High reverb level
player.SetReverbDry(0.6)         // Moderate dry signal
player.SetReverbWidth(1.0)       // Full stereo width

MIDI CC Control (Real-time)

MIDI CC Parameter Range Description
CC91 Reverb Send 0-127 Standard MIDI reverb depth
CC92 Room Size 0-127 Reverb decay time
CC93 Damping 0-127 High-frequency absorption
CC94 Wet Level 0-127 Reverb signal level
CC95 Dry Level 0-127 Direct signal level

SFZ File Opcodes

Add reverb settings directly to your SFZ files:

<global>
reverb_send=30          // 30% reverb send
reverb_room_size=70     // Large room
reverb_damping=40       // Moderate damping
reverb_wet=80          // High wet level
reverb_dry=60          // Moderate dry level

<region>
sample=piano_c4.flac
// Inherits global reverb settings

Testing

Run tests:

go test -v

Run tests with debug output:

DEBUG=sfzplayer:* go test -v

Dependencies

Indirect dependencies:

About

SFZ Player in Go

Resources

License

Stars

Watchers

Forks

Packages

No packages published