Skip to content

boyvinall/sfzgen

Repository files navigation

sfzgen

A command-line tool to generate SFZ files from audio samples, using intelligent filename parsing.

Based on the soundmap project by KMIJPH, this Go implementation provides the same filename parsing logic in a standalone CLI tool.

Features

  • Intelligent filename parsing: Automatically detects MIDI note numbers, note names, dynamics, and round-robin information from filenames
  • Configurable envelope: Customize ADSR envelope parameters and loop modes
  • Key range stretching: Optionally stretches sample key ranges to fill gaps
  • Velocity mapping: Automatically maps dynamics to velocity ranges
  • Round-robin support: Detects and properly sequences round-robin samples
  • Multiple audio formats: Supports WAV, MP3, FLAC, OGG, AIF, AIFF, M4A

Installation

Prerequisites

  • Go 1.21 or later

Building

make build    # Build the executable in the current directory
make test     # Run tests
make lint     # Run golangci-lint
make install  # Install to $GOPATH/bin

Note: The lint target requires golangci-lint to be installed.

Usage

Basic usage:

./sfzgen --input /path/to/samples --output output.sfz

Command-line Options

NAME:
   sfzgen - Generate SFZ files from audio samples

USAGE:
   sfzgen [global options]

VERSION:
   1.0.0

DESCRIPTION:
   sfzgen automatically generates SFZ sampler files from a directory of audio samples.
   It intelligently parses filenames to extract musical information like note names,
   MIDI numbers, dynamics, and round-robin variations.

   FILENAME PARSING RULES:
     - Parts separated by underscore (_) or dot (.)
     - First part: key name (e.g., c4, c#4, bb3) or MIDI note number (0-127)
     - Optional: dynamic marking (pp, p, mp, mf, f, ff)
     - Optional: round-robin number (integer)

   EXAMPLES:
     bongo_c4_p_3.wav    -> C4, piano dynamic, round-robin 3
     piano_60_mf.wav     -> MIDI note 60, mezzo-forte
     kick_36.wav         -> MIDI note 36, no dynamic

AUTHOR:
   Based on soundmap by KMIJPH (codeberg.org/KMIJPH/soundmap)

GLOBAL OPTIONS:
   --help, -h     show help
   --quiet, -q    suppress informational output
   --version, -v  print the version

   Envelope settings

   --attack float      envelope attack time in seconds (default: 0)
   --decay float       envelope decay time in seconds (default: 0)
   --delay float       envelope delay time in seconds (default: 0)
   --loop-mode string  loop mode: no_loop, one_shot, loop_continuous, loop_sustain (default: "no_loop")
   --release float     envelope release time in seconds (default: 0.001)
   --sustain float     envelope sustain level (0-100) (default: 100)

   Input/Output

   --input string, -i string   input directory containing audio files (default: ".")
   --output string, -o string  output SFZ file path (default: "output.sfz")

   Key mapping

   --c4 int, -c int  MIDI note number for C4 reference (default: 60)
   --stretch, -s     stretch key ranges to fill gaps

Examples

Generate SFZ from samples in a directory:

./sfzgen -i ./samples -o piano.sfz

Use a different C4 reference (e.g., for non-standard tuning):

./sfzgen -i ./samples -o piano.sfz -c 72

Disable key stretching:

./sfzgen -i ./samples -o piano.sfz --stretch=false

Quiet mode (no output except errors):

./sfzgen -i ./samples -o piano.sfz -q

Custom envelope settings for a pad sound:

./sfzgen -i ./samples -o pad.sfz --attack 0.5 --release 2.0 --sustain 80

Looping samples:

./sfzgen -i ./samples -o loops.sfz --loop-mode loop_continuous

Complete example with all envelope settings:

./sfzgen -i ./samples -o custom.sfz \
  --attack 0.01 \
  --decay 0.3 \
  --sustain 70 \
  --release 1.5 \
  --delay 0.0 \
  --loop-mode loop_sustain

Show help:

./sfzgen --help

Envelope Settings

The tool allows customization of ADSR (Attack, Decay, Sustain, Release) envelope parameters and loop mode:

  • Attack: Time in seconds for the sound to reach full volume (default: 0.0)
  • Decay: Time in seconds for the sound to decay from peak to sustain level (default: 0.0)
  • Sustain: Level (0-100) at which the sound is held while a note is pressed (default: 100.0)
  • Release: Time in seconds for the sound to fade out after note release (default: 0.001)
  • Delay: Time in seconds before the envelope starts (default: 0.0)

Loop Modes

  • no_loop: Play sample once, no looping (default)
  • one_shot: Play sample once, ignore note-off
  • loop_continuous: Loop continuously while note is held
  • loop_sustain: Loop during sustain phase, then continue to end

Filename Parsing Rules

The tool parses filenames by splitting on underscores (_) and dots (.). It looks for these components in order:

  1. Key number or note name (required):

    • MIDI note number: 0 to 127
    • Note name: c4, c#4, bb3, f#5, etc.
  2. Dynamic marking (optional):

    • pp (pianissimo)
    • p (piano)
    • mp (mezzo-piano)
    • mf (mezzo-forte)
    • f (forte)
    • ff (fortissimo)
  3. Round-robin number (optional):

    • Any integer value

Filename Examples

  • bongo_c4_p_3.wav → C4, piano dynamic, round-robin 3
  • piano_60_mf.wav → MIDI note 60 (C4), mezzo-forte
  • kick_36.wav → MIDI note 36, no dynamic
  • snare_d3_ff_1.mp3 → D3, fortissimo, round-robin 1
  • hihat_42.flac → MIDI note 42, no dynamic
  • bass_bb3.wav → B♭3 (MIDI 58), no dynamic
  • guitar_b4_f.wav → B4 (MIDI 71), forte

Files that don't contain a valid key number or note name will be skipped with a warning.

How It Works

  1. Scanning: Recursively scans the input directory for audio files
  2. Parsing: Parses each filename to extract musical information
  3. Processing:
    • Groups samples by key number and dynamic
    • Stretches key ranges if enabled
    • Fixes round-robin numbering
    • Calculates velocity ranges based on dynamics
  4. Writing: Generates an SFZ file with proper region mappings

SFZ Output Format

The generated SFZ file includes:

  • Default envelope settings (attack, decay, sustain, release)
  • Loop mode configuration
  • Per-sample regions with:
    • Sample path
    • Pitch key center
    • Key range (lokey/hikey)
    • Velocity range (lovel/hivel)
    • Round-robin sequencing (seq_length/seq_position)

Comparison with Original

This Go implementation is based on the core filename parsing logic from the PureScript soundmap project, with improvements:

  • ✅ Same filename parsing rules
  • ✅ Same dynamic marking detection
  • ✅ Same round-robin handling
  • ✅ Same key range stretching algorithm
  • ✅ Same velocity mapping
  • Fixed: Correct note name to MIDI conversion (the original had a bug where 'B' notes were parsed as 'A')

Key Differences

Improvements:

  • Standalone CLI tool with proper command-line interface
  • Correct parsing of B notes (e.g., bb3 → B♭3/MIDI 58, not A♭3/MIDI 56)
  • Configurable envelope settings (attack, decay, sustain, release, delay, loop mode)
  • Short flag aliases for convenience (-i, -o, -q, etc.)
  • Quiet mode for scripting
  • Better error handling and messages with validation

Scope Changes:

  • Only generates SFZ format (not DecentSampler)
  • Command-line only (no web interface)
  • Simpler configuration (flags instead of UI)

Format Compliance

The generated SFZ files conform to the official SFZ specification and are compatible with:

  • SFZ Players:

    • sforzando (Plogue)
    • LinuxSampler
    • Sfizz
    • Carla (SFZ plugin)
    • ARIA Engine (Plogue)
  • DAWs with SFZ support:

    • Reaper (via ReaSamplomatic5000 or SFZ plugins)
    • Ardour (via LinuxSampler)
    • LMMS

Tested Opcodes: All opcodes used in the generated files are part of the SFZ 1.0 specification and widely supported:

  • Basic sample mapping: sample, pitch_keycenter, lokey, hikey
  • Velocity layers: lovel, hivel
  • Round-robin: seq_length, seq_position
  • Envelope: ampeg_attack, ampeg_decay, ampeg_sustain, ampeg_release, ampeg_delay
  • Looping: loop_mode

License

GPL-3.0 (same as the original soundmap project)

Credits

Based on soundmap by KMIJPH.

About

Small cli tool to generate sfz sound font files

Resources

Stars

1 star

Watchers

0 watching

Forks

Contributors