utau resampler using td-psola & glottal pulse pitch marks
README.md

sublimit #

a cross-platform, dependency-free utau resampler written in rust

sublimit uses time-domain psola on pitch marks placed on the source's glottal pulses. a yin f0 track finds them and cross-correlation snaps them, then they are re-laid at the target period. the periodic part isn't resampled (similar to tips/macres, more on that in provenance), so formants remain intact and the excitation stays phase-coherent (..most of the time)

basically it sounds really niceys okay. it doesnt have a lot of flags IM SORRY

provenance #

sublimit is not a clean-room design. it was developed by reverse-engineering the behaviour of tips by rendering the original and comparing measurements and sound. no tips code or binary is redistributed in this repo

build #

cargo build --release        # -> target/release/sublimit
cargo test --release         # unit + integration tests
cargo clippy --all-targets   # lints

cargo fmt is not enforced. prefer --release for tests; the debug build is much slower on multi-second samples.

version stamp #

sublimit --version (or -V) prints the crate version and the git revision it was built from, for example sublimit 0.2.1 (a1b2c3d4e5). a -dirty suffix means the working tree had uncommitted changes.

install into openutau #

copy sublimit (or sublimit.exe) and sublimit.yaml into openutau's resamplers folder, then select it under preferences > rendering. usual locations:

  • macOS: ~/Library/OpenUtau/Resamplers/
  • Windows: %APPDATA%\OpenUtau\Resamplers\
  • Linux: ~/.local/share/OpenUtau/Resamplers/

use the install's own resamplers folder if it differs. sublimit.yaml must sit beside the binary and share its name or its (very few) renderer flags wont show up

usage #

sublimit <in.wav> <out.wav> <note> <velocity> [flags] [offset] [length]
     [consonant] [cutoff] [volume] [modulation] [tempo] [pitchbend]

every argument after <out.wav> is optional and positional. anything omitted or unparseable falls back to its default

Argument Meaning Default
in.wav / out.wav input / output paths. input may be mono or multichannel, 8/16/24/32-bit pcm or 32-bit float, but output is 16-bit pcm mono at the input sample rate required
note target note, e.g. C4, F#3, Bb5, or a midi note number A4
velocity utau velocity; the fixed consonant scales by 2^(1 - velocity/100), so 100 is neutral and higher is faster 100
flags combined flag string, see below none
offset source start, ms 0
length output length, ms; 0 uses the source window length 0
consonant fixed consonant length, ms 0
cutoff oto "right blank", ms. if >= 0, source end = wav end - cutoff; if < 0, source end = offset + abs(cutoff) 0
volume output volume, percent 100
modulation vibrato depth, percent; used only when no pitch bend is given 0
tempo bpm, used to step the pitch bend 100
pitchbend utau base64 rle pitch data none

flags are concatenated with no separators, e.g. g-20P86t+15R:

Flag Name Range Default
g formant shift. positive is deeper, negative is brighter -100..100 0
P peak compressor strength 0..100 86
R remove dc offset (subtracts the mean) on/off off
t pitch offset, cents any 0
target/release/sublimit in.wav out.wav C4 100 "g-20P86" 0 1000 0 0 100 0 "!120" "AA"

behaviour #

  • output length is capped at 600000 ms (ten minutes); anything longer is an error
  • a 5 ms fade is applied at both ends
  • writing the output path nul (any case) exits successfully without writing, which is what utau asks for on a silent render
  • unsupported wav encodings (adpcm, mu-law, a-law) and malformed headers exit non-zero

debug output #

two environment variables dump internals to stderr:

  • SUBLIMIT_DEBUG_MARKS=1: the f0 track (one value per hop, - for unvoiced) and the mark spacings of the analysed slice
  • SUBLIMIT_DEBUG_SYNTH=1: one line per synthesis grain (time, source position, mark, period)

tests #

cargo test --release

this runs the unit tests plus the integration suite in tests/:

  • synthetic.rs needs no voicebank and runs everywhere. it exercises the full command line, the analysis/synthesis chain and the wav I/O the binary uses
  • voicebank.rs and vcv.rs run against a local voicebank and check duration, level, pitch tracking and formant independence
  • canary.rs is a high-pitch canary against a second local bank

the bank-dependent tests skip cleanly (and print a skip message) when the bank is not installed. point them at banks outside the repo, with:

SUBLIMIT_TEST_VBANK=/path/to/bank         cargo test --release
SUBLIMIT_TEST_VBANK2=/path/to/second-bank cargo test --release

the test fixtures in tests/fixtures/ are synthetic and generated by tools/make_fixtures.py

corpus sweep #

tests/sweep.rs is a bug-discovery sweep over a voicebank, ignored by default:

cargo test --release --test sweep -- --ignored --nocapture

it renders oto entries from the bank and reports the worst offenders for f0, per-cycle correlation, phantom band and hollowed H1. useful knobs:

Variable Effect
SUBLIMIT_TEST_VBANK bank root
SUBLIMIT_SWEEP_BANK2=1 sweep SUBLIMIT_TEST_VBANK2 instead
SUBLIMIT_SWEEP_FOLDERS substring filter on folder names
SUBLIMIT_SWEEP_ALIAS substring filter on aliases
SUBLIMIT_SWEEP_LIMIT max entries rendered, evenly strided (default 80, 0 = all)
SUBLIMIT_SWEEP_SHIFT semitones above/below the folder pitch
SUBLIMIT_SWEEP_LEN output length, ms (default 700)
SUBLIMIT_SWEEP_FLAGS resampler flags, e.g. g-20
SUBLIMIT_SWEEP_CSV also write every row to this csv path
SUBLIMIT_SWEEP_STRICT=1 fail if any entry trips a threshold

tools/onset_sweep.py and tools/onset_split.py are numpy-only instruments for consonant-onset glitches; tools/make_refs.py and tools/worldline_ref.py build cached worldline references for the sweep. each file's docstring has its own usage

license #

MIT