Skip to content
voca-synthPublic

Latest commit

 

History

1 Commit

Folders and files

Repository files navigation

svp2midi

Turn a Synthesizer V project into a plain MIDI file.

You point it at a .svp, it writes a .mid containing the notes, the tempo and the lyrics. From there you can open the melody in any DAW or notation editor, or play it back through a soundfont with an instrument of your choice.

$ svp2midi song.svp
Main Vocals -> song_Main_Vocals.mid
  443 notes, 504.5 beats, pitch C#3-C#5

No dependencies, no config file, no project to set up. One binary, one command.

Why you might want this

Synthesizer V is a singing synthesiser, and the melody you write in it is often worth more than the vocal render itself. People usually reach for this tool because they want to hear a line on some other instrument before committing to a vocal take, or because they want sheet music and a lead sheet with the words already sitting under the right notes.

It is also the quickest way to get a melody into a DAW so you can double it with a synth, write a countermelody against it, or line a guitar part up with the phrasing. Singers use the piano version to practise against, since a plain keyboard line is far easier to pitch against than a synthesised vocal. And as a backup format, MIDI will still open in thirty years, which is more than can be said for most project formats.

The tool does one thing and tries to do it exactly. Your notes come out where you put them, at the pitch you wrote, with the tempo map intact.

Install

With Go

go install github.com/voca-synth/svp2midi@latest

This puts the svp2midi binary in your GOBIN directory, which is usually ~/go/bin. If the command is not found afterwards, that directory is missing from your PATH:

export PATH="$PATH:$(go env GOPATH)/bin"

Add that line to your ~/.bashrc or ~/.zshrc to make it stick.

Prebuilt binaries

Grab a binary for your platform from the releases page, unpack it and put it anywhere on your PATH:

tar xzf svp2midi_*_linux_amd64.tar.gz
sudo mv svp2midi /usr/local/bin/

On macOS the first run may be blocked because the binary is not notarised. Right-click the file in Finder and choose Open, or clear the quarantine flag yourself:

xattr -d com.apple.quarantine svp2midi

From source

git clone https://github.com/voca-synth/svp2midi
cd svp2midi
go build

Quick start

Convert the first track that has notes in it:

svp2midi song.svp

The MIDI lands next to the project, named after the project and the track, so song.svp becomes song_Main_Vocals.mid. Nothing is overwritten except a file of that exact name, so pick your own path if you care where it goes:

svp2midi -o melody.mid song.svp

The summary line tells you what you got:

Main Vocals -> melody.mid
  443 notes, 504.5 beats, pitch C#3-C#5

That 504.5 beats is where the last note ends, counted in quarter notes from the start of the project. The pitch range at the end is handy for spotting a track someone transposed by accident.

Choosing a track

Most projects have more than one track. Ask which ones are there:

$ svp2midi -list song.svp
TRACK                           NOTES
Main Vocals                       443
Harmony (High)                     78
Harmony (Low)                     201
Instrumental                - (audio)

Tracks marked - (audio) hold an imported audio file rather than any notes, so there is nothing in them to convert. Pick any of the others by name:

svp2midi -t "Harmony (High)" song.svp

The name has to match exactly, quotes included when it contains spaces. Without -t the first track that actually has notes wins, which skips audio tracks for you.

To get every part as its own file, run it once per track:

svp2midi -t "Main Vocals"    -o lead.mid song.svp
svp2midi -t "Harmony (High)" -o high.mid song.svp
svp2midi -t "Harmony (Low)"  -o low.mid  song.svp

Options

Option Default What it does
-t, -track <name> first track with notes Which track to convert.
-o, -output <path> next to the project Where to write the MIDI. - writes to standard output.
-l, -list — List the tracks and exit without writing anything.
-program <n> 0 General MIDI instrument, 0–127. 0 is acoustic grand piano.
-channel <n> 0 MIDI channel, 0–15.
-velocity <n> 90 Velocity written for every note, 1–127.
-ppq <n> 480 Ticks per quarter note in the output file.
-no-lyrics off Leave the lyrics out.
-V, -version — Print the version and exit.

Single and double dashes both work, so -track and --track do the same thing.

A few of these deserve more than one line. The instrument you request with -program only takes effect if whatever plays the file respects General MIDI program changes; soundfont players generally honour it, while many DAWs use the instrument on the track you dropped the file onto and ignore what the file asks for. Numbers follow the standard GM list starting at zero, so 0 is acoustic grand piano, 40 violin, 56 trumpet and 73 flute.

The -channel setting matters when you merge several of these files into one sequence and want each part kept separate. Channel 9 is reserved for drums under General MIDI, so avoid it unless you mean it.

Velocity is a single value for the whole file, since the project has no per-note velocity to copy; the section on omitted data explains why. Resolution is worth changing only if some other tool insists on it, because 480 is what most DAWs use and it divides the project's internal timing exactly.

Playing the result

A MIDI file carries note data and nothing audible, so you need a player and a sound source. FluidSynth is the usual choice on the command line. Give it a soundfont and the file:

fluidsynth -i /path/to/soundfont.sf2 melody.mid

Rendering to audio instead of playing live takes a couple more flags:

fluidsynth -ni /path/to/soundfont.sf2 melody.mid -F melody.wav -r 48000

TiMidity++ works too and needs no arguments beyond the file:

timidity melody.mid

In a DAW, drag the .mid onto a track. Most will read the tempo map from the file and offer to apply it to the project, which is usually what you want; skip it and the notes play at whatever tempo the project was already set to.

MuseScore, Dorico and Sibelius all import MIDI directly, and they read lyric events, so the words show up under the notes. Expect to fix enharmonic spelling and rhythmic notation by hand afterwards, since MIDI carries no key signature and this tool does not try to guess one.

What comes across

Notes carry over with their onset, length and pitch exactly as written in the project. Tempo comes across in full, including changes partway through, written as a standard tempo map on the first track of the MIDI file. Meter changes are placed at the correct bar.

Lyrics become MIDI lyric events, one per note, positioned at the note's start. Notation software picks these up automatically. Use -no-lyrics if your target software chokes on them or you simply want the melody on its own.

Projects can reuse a group of notes in several places, each copy shifted in time or pitch, and every placement is flattened onto the timeline where it belongs, so repeated sections come out once per placement. Muted groups are skipped to match what you hear in the editor, and a group transposed by whole semitones comes out transposed. The track name is carried over as well, so the result is labelled sensibly when you import it.

What stays behind

Some of this the format cannot express and some of it would sound worse if it did come across. Here is the honest list.

Pitch bends, vibrato and hand-drawn pitch curves are dropped on purpose. A vocal line is full of continuous pitch movement: scoops into notes, vibrato on the long ones, slides between words. Written out as MIDI pitch bend, all of that sounds wrong on a piano, because a real piano cannot bend. You would get a detuned attack on every note and nothing resembling the original vocal. What you get instead is discrete notes, which is what a keyboard instrument can actually play. The pitch curve still lives in your project file if you need it, but extracting it is a job for a different tool.

Dynamics come out flat. Loudness in the project lives in parameter curves with no faithful mapping onto MIDI velocity, so every note gets the same value. Set it with -velocity or draw dynamics in by hand after importing.

Fine detune is ignored, so notes nudged by a few cents arrive at their nominal pitch. Cents cannot be expressed per note in MIDI without pitch bend, which is dropped for the reason above.

Phonemes, timing tweaks and voice settings have no MIDI equivalent at all, so they are skipped. Imported backing tracks are audio rather than note data, which is why they show up as - (audio) in the listing and cannot be converted.

Each run handles a single track and produces a two-track MIDI file: one track for the tempo map, one for the notes. Run it again for the next part.

How accurate is the timing

Exact, under normal settings.

Synthesizer V stores time in a unit called a blick, with 705,600,000 of them to the quarter note. That figure was chosen to divide evenly by every subdivision anyone actually uses, triplets and quintuplets included, along with every common MIDI tick resolution. At the default 480 ticks per quarter note, a single tick works out to exactly 1,470,000 blicks, so every onset and every note end lands on a whole tick with nothing left over. Nothing rounds, nothing drifts, and no note creeps off the grid over the course of a five minute song.

Pick an unusual resolution that does not divide evenly and values are rounded to the nearest tick, halves to even. Even then the error stays under half a tick and never accumulates, because each note is converted from its own absolute position rather than from the note before it.

One more detail is worth knowing. Where two notes of the same pitch overlap, the earlier one is shortened to end where the later one begins, because a single channel cannot sustain two copies of one pitch: the first note-off would end both. Overlapping notes at different pitches are left alone, so chords and held harmony come through untouched.

Recipes

Convert every project in a folder:

for f in *.svp; do svp2midi "$f"; done

Convert a whole tree recursively:

find . -name '*.svp' -exec svp2midi {} \;

Write to standard output and pipe it straight into a player:

svp2midi -o - song.svp | fluidsynth -i soundfont.sf2 -

Render a piano version to audio in two steps:

svp2midi -o /tmp/melody.mid song.svp
fluidsynth -ni soundfont.sf2 /tmp/melody.mid -F piano.wav -r 48000

Put a backing part on its own channel so it stays separate when merged:

svp2midi -t "Backing" -channel 1 -o backing.mid song.svp

Ask for strings instead of the default piano:

svp2midi -program 48 -o strings.mid song.svp

Troubleshooting

no track named "..." — the name must match exactly, including capitals, spaces and brackets. Run svp2midi -list song.svp and copy it from there.

track "..." has no notes to convert — that track holds audio, or all of its groups are muted. The listing shows which tracks have notes in them.

does not look like a Synthesizer V project — the file is not a .svp, or it is damaged. Projects written by very old versions of the editor can also land here, and re-saving from a current version usually sorts it out.

The MIDI plays at the wrong speed — your DAW imported the notes but left the tempo map behind. Look for an option about importing tempo from the MIDI file, or set the project tempo by hand to match.

The lyrics do not show up — not every program reads lyric events, and some show them only in notation view. Open the file in MuseScore to confirm they made it in.

Everything plays as piano despite -program — the program change is in the file, but your player is overriding it, which DAWs routinely do.

The melody sounds stiff next to the vocal — it will. All the expression lives in the pitch and parameter curves that get left out. What you have here is the written melody rather than a performance of it.

svp2midi: command not found after installing — ~/go/bin is missing from your PATH. See Install.

Building from source

Requires Go 1.21 or newer.

git clone https://github.com/voca-synth/svp2midi
cd svp2midi
go build        # produces ./svp2midi
go test ./...   # runs the test suite

The tests write MIDI files in memory and read them back with a separate parser, so the checks never simply trust the code that produced the bytes.

There are no third-party dependencies anywhere in the project. Both the MIDI writer and the project reader live in this repository.

License

Mozilla Public License 2.0. See LICENSE for the full text.

Disclaimer

This is an independent, community-maintained tool. It has no affiliation with Dreamtonics Co., Ltd., and it carries no sponsorship, endorsement or approval from them or from any other company named here. Do not contact Dreamtonics about problems with this software; open an issue on this repository instead.

Synthesizer V is a trademark of Dreamtonics Co., Ltd. MIDI and General MIDI are trademarks of their respective owners. FluidSynth, TiMidity++, MuseScore, Dorico and Sibelius belong to their respective owners as well. Every one of those names appears here only to describe what this tool works with, which is the sort of descriptive use that trademark law allows. No claim of ownership is made over any of them.

The project file reader was written independently by inspecting the JSON that the editor saves. It includes no source code, assets, documentation or other material from Dreamtonics, and it bundles nothing from the editor. Because the format is undocumented and free to change between releases, a future version may save projects this tool cannot read.

Converting a file changes nothing about who owns the music inside it. Rights in a melody, its lyrics and any recording stay with whoever held them beforehand. Checking that you may convert a given project, and that you may use or share what comes out, is down to you.

The software comes with no warranty of any kind, as set out in the license. It only ever writes new files and never modifies the project you point it at, though keeping backups of your work remains a good habit.

Releases

Packages

Contributors

Languages