View on GitHub

ptn2midi

Export your Roland SP-404SX patterns and samples to MIDI and SoundFont files

Download this project as a .zip file Download this project as a tar.gz file

Introduction

The Roland SP-404SX Sampler is well-made, portable, and it has a slick user interface. Unfortunately its samples and patterns are stored in an undocumented proprietary format on an SD card.

Until now, the only way to collaborate with other producers and Digital Audio Workstation ("DAW") users was to "play" a pattern on the sampler and record its line-out to a single stereo track. This eliminates the ability to apply per-sample effects and make fine-grained changes to the arrangement.

With the help of ModuLR's notes on SP-FORUMS, I've created a utility in Python called "ptn2midi" that translates a pattern on the SP-40SX's SD card to a MIDI (.mid) file and a SoundFont v1.2 (.sf2) file.

The MIDI file includes the note pitches, durations, and timing data. The SoundFont file contains the associated samples, trimmed, just as they were on the sampler itself.

How to use the utility

  1. Create a pattern on the SP-404SX. Store it, for example, on pad A1
  2. Download and extract the ptn2midi repository from https://github.com/TylerOderkirk/ptn2midi/archive/master.zip
  3. Install the MIDIUtil Python library
  4. Insert the sampler's SD card into your computer and run the utility: ./ptn2midi.py /media/tz/SP-404SX/ A1 95 where the first argument is the path (with trailing delimiter) to the SD card, the second is the name of the pattern, and the third is the tempo
  5. Load the resulting files e.g. PTN_A1.mid and PTN_A1.sf2 into your DAW of choice

Demonstration

I loaded the factory default samples and created a pattern at 95 BPM on pad F1. Here's a recording from the sampler's line-out. Pay no mind to the clipping!

My sampler playing the pattern

And... here's what I got when I created a new track in Ableton Live 9, imported the .sf2 and .mid files from the utility, and did "Export audio/video".

Ableton's MIDI note editor view

This is a portion of the program's debugging output:

[...]
Pad(start=512, end=91068, user_start=512, user_end=91068, volume=127, lofi=False, loop=False, gate=True, reverse=False, unknown1=1, channels=1, tempo_mode=0, tempo=1168, user_tempo=1168)
Pad(start=512, end=87612, user_start=512, user_end=87612, volume=127, lofi=False, loop=False, gate=True, reverse=False, unknown1=1, channels=1, tempo_mode=0, tempo=1215, user_tempo=1215)
Pad(start=512, end=83132, user_start=512, user_end=83132, volume=127, lofi=False, loop=False, gate=True, reverse=False, unknown1=1, channels=1, tempo_mode=0, tempo=1281, user_tempo=1281)
Pad(start=512, end=87872, user_start=512, user_end=87872, volume=127, lofi=False, loop=False, gate=True, reverse=False, unknown1=1, channels=1, tempo_mode=0, tempo=1211, user_tempo=1211)
[...]
Note(delay=144, pad=47, bank_switch=1, unknown2=0, velocity=127, unknown3=64, length=113)
Note(delay=144, pad=47, bank_switch=1, unknown2=0, velocity=127, unknown3=64, length=137)
Note(delay=96, pad=49, bank_switch=1, unknown2=0, velocity=127, unknown3=64, length=84)
Note(delay=136, pad=47, bank_switch=1, unknown2=0, velocity=127, unknown3=64, length=122)
[...]
pitch: 36 - /media/tz/SP-404SX/ROLAND/SP-404SX/SMPL/F0000001.WAV -> /tmp/F0000001.WAV_mono.wav -> template01.wav
pitch: 37 - /media/tz/SP-404SX/ROLAND/SP-404SX/SMPL/F0000003.WAV -> /tmp/F0000003.WAV_mono.wav -> template02.wav
pitch: 38 - /media/tz/SP-404SX/ROLAND/SP-404SX/SMPL/F0000002.WAV -> /tmp/F0000002.WAV_mono.wav -> template03.wav
[...]

If you don't have your sampler's SD card handy, you can use sp-404sx_sd_demo_img.zip (25MB) from the repository. It's a zip image of the card used above.

How it works

  1. get_pad_info() - The utility parses PAD_INFO.BIN from the SD card to determine the "start" and "end" points for every sample on the SD card. These points have been set with the "Mark" button and "Start/End" feature on the sampler
  2. get_pattern() - The utility parses the .BIN file corresponding to the pattern to determine when, and for how long, each "note" in the pattern should be played
  3. create_midi_file() - The utility assigns a unique pitch (starting at C1[36]) to each sample used by the pattern, truncating each and converting it to a single channel (see "Future Improvements"), overwriting the WAVs of an included "template" SoundFont
  4. create_soundfont() - The utility assembles the samples and associated pitches into a SoundFont v2.1 (.sf2) file using pysf and a SoundFont descriptor named template.xml

System architecture diagram

Future Improvements:

  1. Support more than 12 samples per pattern. Trivial - expand Template .xml
  2. Support stereo samples. Trivial - assign two samples (left and right) per SoundFont pitch/note
  3. Support AIF samples. Trivial - convert to PCM WAV intitially
  4. Support "looped" samples. Use <loop> entries in <wavetable> nodes in template.xml? create_looped_wav()?
  5. Support platforms other than Ubuntu Linux Saucy (13.10). Temporary file locations
  6. Implement robust command-line argument parsing
  7. Support other samplers in the Roland SP family
  8. Support DAWs other than Ableton Live 9
  9. Support creation of "superset" SoundFonts comprised of samples from more than 1 patterns
  10. Replicate effects such as "lo-fi", "reverse", etc on the host machine
  11. Support the reverse operation: creating patterns from MIDI files. See this SP-FORUMS post.

Thanks/Credits

Chris for sharing his Ableton knowledge and for dealing with a lot of broken SoundFont files. Ben Collver for placing his excellent Python SoundFont library, pysf, in the Public Domain. Mark Conway Wirt for his MIDIUtil Python library. Mark Germani and HammerSound for the "Cola" SoundFont I created my "template" SoundFont from. EnjoyPA on FreeSound.org for the WAVs I used in the "template".