Skip to content

mungewell/uno-synth-utils

Repository files navigation

uno-synth-utils

Scripts for controlling the IK UNO Synth.

Parsing of '*.unosyp' preset is done using the Python module 'Construct' https://github.com/construct/construct

$ python3 uno_synth.py --help
Usage: uno_synth.py [options] FILENAME

Options:
  -h, --help            show this help message and exit
  -v, --verbose         
  -i, --init            create an initial(empty) patch
  -d, --dump            dump configuration/sequence to text
  -m MIDI, --midi=MIDI  Select 'MIDI' device name
  -p PRESET, --preset=PRESET
                        Select 'PRESET' and use in MIDI operations
  -r, --read            Read current (or 'PRESET') config from UNO
  -w, --write           Read write config to 'PRESET' on attached UNO
  -B BACKUP, --backup=BACKUP
                        Backup all presets (21-100) from UNO to 'BACKUP'
                        directory
  -R RESTORE, --restore=RESTORE
                        Restore all presets (21-100) from 'BACKUP' directory
                        to UNO

Currently the script supports selecting the preset on the device, reading (from UNO to PC) and writing (from PC to UNO) the presets.

When reading and writing the config is saved to/from specified FILENAME.

The 'backup' function selects all presets (21..100) in turn and saves them into the specified directory. A directory of patches (21..100) can be uploaded to the UNO with the 'restore' function.

An initial patch can be created with 'init' function, this could be created and upload to preset 21 with

$ python3 uno_synth.py -i -p 21 -w

The script can also be installed as a module, allowing the functions to be used to create/process '.unosyp' files within your own scripts. See the examples directory, 'scale.py' builds a config patch from scratch with embedded sequence.

The resultant 'Construct' object is really a combination of Python Lists and Dictionaries, and can be handled accordingly.

The 'dump' function can be used to output a text representation.

$ python3 uno_synth.py -d preset/Factory\ 21-100/21.unosyp
ListContainer: 
    Container: 
        exttempo = 2
        tempo = 120
        octave = 2
        glide = 896
        scale = 0
        scale_key = 0
        delay_time = 70
        delay_mix = 0
        arp_direction = 4
        arp_octaves = 2
        seq_direction = 0
        range = 16
        osc1_wave = 334
        osc1_tune = -1200
        osc1_level = 115
        osc2_wave = 1
        osc2_tune = 0
        osc2_level = 115
        noise_level = 0
        filter_cutoff = 102
        filter_mode = 0
        filter_res = 45
        filter_drive = 84
        filter_env_amount = 41
        filter_attack = 0
        filter_delay = 73
        filter_sustain = 0
        filter_release = 255
        amp_attack = 0
        amp_delay = 255
        amp_sustain = 127
        amp_release = 71
        lfo_wave = 0
        lfo_rate = 669
        lfo_to_pitch = 0
        lfo_to_filter = 0
        tremolo_depth = 89
        vibrato_depth = 64
        wah_depth = 30
        dive_amount = 21
        scoop_amount = 21
        seq_swing = 53
        pitch_bend = 20
        unknown3 = 0
        filter_to_osc1_pwm = 64
        filter_to_osc2_pwm = 72
        lfo_to_osc1_pwm = 0
        lfo_to_osc2_pwm = 0
        filter_to_osc1_wave = 0
        filter_to_osc2_wave = 0
        lfo_to_osc1_wave = 0
        lfo_to_osc2_wave = 0
        mod_vibrato = 0
        mod_wah = 0
        mod_tremolo = 0
        mod_cutoff = 0
        vel_amp = 0
        vel_filter = 0
        vel_filter_env = 0
        unknown6 = 0
        unknown7 = 0
        unknown8 = 0
        mod_to_lfo_rate = 0
        vel_to_lfo_rate = 0
        arp_gate = 0
        unknown9 = 1
        key_track = 64
    ListContainer: 
        Container: 
            step = 1
            count = 1
            elements = ListContainer: 
                Container: 
                    element = Container: 
                        type = 2
                        fade = 0
                        unknown = 0
                    data = Container: 
                        note = 51
                        velocity = 127
                        length = 1
...

Handcrafted SysEx control of the device

Patch Data

CMD 0x33: Switch to preset 100 (ie 100 -> 0x64)

$ amidi -p hw:1,0,0 -S 'f0 00 21 1a 02 01 33 64 f7'

CMD 0x31: Download current/active preset (note: may be interspersed with midi clock -> set sync external)

amidi -p hw:1,0,0 -S 'f0 00 21 1a 02 01 31 f7'  -r prog.bin -t 1

# Strip off extra bits to get at 'config file' portion (note leaves 0x7f at end)
dd bs=1024 count=1 skip=19 iflag=skip_bytes if=prog.bin of=prog.unosyp

CMD 0x24: Read back specific patch without having to select it

$ amidi -p hw:1,0,0 -S 'f0 0 21 1a 2 1 24 0 2c f7' -r temp.bin -t 1 ; hexdump -C temp.bin

255 bytes read
00000000  f0 00 21 1a 02 01 00 24  00 2c 00 43 00 01 02 20  |..!....$.,.C... |
00000010  02 01 04 00 03 01 20 04  06 00 00 05 00 00 06 00  |...... .........|
00000020  00 07 67 00 08 24 00 09  02 00 0a 02 00 0b 00 00  |..g..$..........|
00000030  0c 10 20 0d 02 59 20 0e  00 00 00 0f 73 20 10 00  |.. ..Y .....s ..|
00000040  39 20 11 7f 6e 00 12 73  00 13 00 20 14 00 01 00  |9 ..n..s... ....|
00000050  15 01 00 16 24 00 17 37  20 18 00 40 20 19 01 31  |....$..7 ..@ ..1|
00000060  20 1a 00 39 00 1b 00 20  1c 01 7f 20 1d 00 00 20  | ..9... ... ... |
00000070  1e 00 00 00 1f 7f 20 20  00 78 00 21 00 20 22 05  |......  .x.!. ".|
00000080  2c 20 23 00 00 20 24 00  00 00 25 59 00 26 40 00  |, #.. $...%Y.&@.|
00000090  27 1e 00 28 15 00 29 15  00 2a 32 00 2b 14 00 2c  |'..(..)..*2. ..,|
000000a0  00 00 2d 3f 00 2e 3f 00  2f 00 00 30 00 00 31 00  |..-?..?./..0..1.|
000000b0  00 32 00 00 33 00 00 34  00 00 35 00 00 36 00 00  |.2..3..4..5..6..|
000000c0  37 00 00 38 7f 00 39 00  00 3a 00 00 3b 00 00 3c  |7..8..9..:..;..<|
000000d0  00 00 3d 00 00 3e 00 00  3f 00 00 40 00 00 41 00  |..=..>[email protected].|
000000e0  00 42 01 00 43 00 01 01  40 00 1c 7f 16 00 0d 01  |.B..C...@.......|
000000f0  40 00 1f 7f 04 00 0f 01  40 00 21 7f 03 00 f7     |@.......@.!....|
000000ff

CMD 0x30: Writes parameters and/or sequence to current preset (ie. not saved to patch memory).

If the byte after 'CMD 0x30' is '0x00' a patch is included in the data, otherwise it indicates the step within sequence.

Send a complete patch.

$ amidi -p hw:1,0,0 -S 'f0 0 21 1a 2 1 30 0 43 0 1 2 20 2 0 78 0 3 2 20 4 7 0 0 5 0 0 6 0 0 7 46 0 8 0 0 9 4 0 a 2 0 b 0 0 c 10 20 d 2 1b 20 e 0 0 0 f 7f 20 10 0 1 20 11 7f 4b 0 12 7f 0 13 53 20 14 1 2c 0 15 0 0 16 2d 0 17 54 20 18 0 29 20 19 0 0 20 1a 0 0 0 1b 0 20 1c 1 7f 20 1d 0 14 20 1e 0 59 0 1f 2e 20 20 1 41 0 21 0 20 22 2 68 20 23 0 46 20 24 0 3f 0 25 59 0 26 40 0 27 1e 0 28 15 0 29 15 0 2a 35 0 2b 14 0 2c 0 0 2d 40 0 2e 48 0 2f 0 0 30 0 0 31 0 0 32 0 0 33 0 0 34 0 0 35 0 0 36 0 0 37 0 0 38 0 0 39 0 0 3a 0 0 3b 0 0 3c 0 0 3d 0 0 3e 0 0 3f 0 0 40 0 0 41 0 0 42 1 0 43 40 1 1 40 0 33 7f 1 0 2 1 40 0 27 7d 1 0 4 1 40 0 33 7d 1 0 6 1 40 0 31 7a 1 0 7 1 40 0 2e 72 1 0 9 1 40 0 36 76 1 0 b 1 40 0 38 7d 1 0 d 1 40 0 38 76 2 0 e 1 40 0 36 6a 5 0  f7' -r temp.bin -t 1 ; hexdump -C temp.bin 

9 bytes read
00000000  f0 00 21 1a 02 01 00 30  f7                       |..!....0.|
00000009

Can also be used to change specific param(s) (LFO in this case), which can be useful as it allows greater granuality on 14bit parameters than can be achieved via the dials and Midi CC.

Note: it is not possible to set Tempo via this method.

$ amidi -p hw:1,0,0 -S 'f0 00 21 1a 02 01 30 00 01 20 22 00 03 f7'
                                                         ^^ ^^ Param Value 
                                                   ^^ ^^ Param ID
                                                ^^ Param count

Normally a patch contains both configuration followed by sequence, but a sequence can be written directly with 'CMD 0x30 0x01'.

Data can be notes and/or parameter automation, as per patch format.

Note: If a sequence is currently playing changes are loaded when end of sequence is reached.

$ amidi -p hw:1,0,0 -S 'f0 0 21 1a 2 1 30 01 01 40 00 30 64 01 00 f7' -r temp.bin -t 1 ; hexdump -C temp.bin
                                                               ^^ const 0x00
                                                            ^^ Length
                                                         ^^ Velocity
                                                      ^^ Note
                                                ^^ ^^ "SeqNote"   const 0x00
                                             ^^ Item count
                                          ^^ First Step
9 bytes read
00000000  f0 00 21 1a 02 01 00 30  f7                       |..!....0.|
00000009

$ amidi -p hw:1,0,0 -S 'f0 0 21 1a 2 1 30 01 01 40 00 30 64 01 00 08 01 40 00 30 64 01 00 f7' -r temp.bin -t 1 ; hexdump -C temp.bin

Patch name

The patch name is not displayed on the device, but is stored and read back by the official patch editor application.

CMD 0x24 0x01: Read back name.

$ amidi -p hw:1,0,0 -S 'f0 0 21 1a 2 1 24 1 2c f7' -r temp.bin -t 1 ; hexdump -C temp.bin

43 bytes read
00000000  f0 00 21 1a 02 01 00 24  01 2c 00 00 00 00 00 00  |..!....$.,......|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000020  00 00 00 00 00 00 00 00  00 00 f7                 |...........|
0000002b

In order to set a name a system (unknown) command must be sent first.

$ amidi -p hw:1,0,0 -S 'f0 00 21 1a 02 01 11 01 0a f7'
$ amidi -p hw:1,0,0 -S 'f0 00 21 1a 02 01 23 01 63 55 4e 4f 2d 55 74 69 6c 73 f7'
                                                   ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ASCII name
                                                ^^ preset number

Device Configuration (Setup)

CMD 0x21: Write setup parameter, need to enter 'setup mode' first

$ amidi -p hw:1,0,0 -S 'f0 0 21 1a 2 1 11 01 7f f7' -r temp.bin -t 1 ; hexdump -C temp.bin

9 bytes read
00000000  f0 00 21 1a 02 01 00 11  f7                       |..!......|
00000009

$ amidi -p hw:1,0,0 -S 'f0 0 21 1a 2 1 21 00 01 00 f7' -r temp.bin -t 1 ; hexdump -C temp.bin

9 bytes read
00000000  f0 00 21 1a 02 01 00 21  f7                       |..!....!.|
00000009

CMD 0x22: Read setup parameter.

$ amidi -p hw:1,0,0 -S 'f0 0 21 1a 2 1 22 00 01 f7' -r temp.bin -t 1 ; hexdump -C temp.bin

12 bytes read
00000000  f0 00 21 1a 02 01 00 22  00 01 01 f7              |..!...."....|
0000000c

$ amidi -p hw:1,0,0 -S 'f0 0 21 1a 2 1 22 4 1 0 1 f7' -r temp.bin -t 1 ; hexdump -C temp.bin

15 bytes read
00000000  f0 00 21 1a 02 01 00 22  00 01 01 00 01 01 f7     |..!....".......|
0000000f

Setup Parameters are:

00 - 0
01 - Pot Mode (0=Absolute, 1=Pass-Thru, 2=Relative)
02 - Midi Soft Thru (0=Off, 1=On)
03 - 0
04 - Battery Type (0=Alkaline, 1=NiMH)
05 - 1
06 - Receive Program Change (0=Off, 1=On)
07 - 1
08 - Send Program Change (0=Off, 1=On)
09 - 1
0A - 1
0B - Midi Interface Mode (0=Off, 1=On)
0C - MIDI Clock Sync (0=Int, 1=USB, 2=Either)
0D - Metronome (0=Off, 1=On)

CMD 0x14: Report Sequence State

$ amidi -p hw:1,0,0 -S 'f0 0 21 1a 2 1 14 f7' -r temp.bin -t 1 ; hexdump -C temp.bin

13 bytes read
00000000  f0 00 21 1a 02 01 00 14  02 44 17 02 f7           |..!......D...|
                                         ^^ Patch 
                                       ^ Toggles 0<->4, except when play note, unknown
                                      ^ 4=SEQ lit
00000000  f0 00 21 1a 02 01 00 14  02 00 17 42 f7           |..!........B.|
                                            ^ 4=ARP lit
00000000  f0 00 21 1a 02 01 00 14  02 0c 17 42 f7           |..!........B.|
                                       ^ 8=Hold lit
00000000  f0 00 21 1a 02 01 00 14  02 45 17 02 f7           |..!......E...|
                                       ^ 1=PLAY lit
00000000  f0 00 21 1a 02 01 00 14  02 46 15 02 f7           |..!......F...|
                                       ^ 2 = Rec (flashing)
00000000  f0 00 21 1a 02 01 00 14  02 54 14 02 f7           |..!......T...|
                                      ^ 1=Metronome

00000000  f0 00 21 1a 02 01 00 14  01 f7                    |..!.......|
                                    ^ Tuning

System Commands

CMD 0x10: System Reset, reboots and re-cals

$ amidi -p hw:1,0,0 -S 'f0 0 21 1a 2 1 10 0 f7' -r temp.bin -t 1 ; hexdump -C temp.bin

10 bytes read
00000000  f0 00 21 1a 02 01 32 15  15 f7                    |..!...2...|
0000000a

CMD 0x10: Device mode

ie. enter 'setup mode'

$ amidi -p hw:1,0,0 -S 'f0 0 21 1a 2 1 11 01 7f f7' -r temp.bin -t 1 ; hexdump -C temp.bin

9 bytes read
00000000  f0 00 21 1a 02 01 00 11  f7                       |..!......|
00000009

CMD 0x12: Read F/W version

$ amidi -p hw:1,0,0 -S 'f0 0 21 1a 2 1 12 f7' -r temp.bin -t 1 ; hexdump -C temp.bin 

28 bytes read
00000000  f0 00 21 1a 02 01 00 12  01 30 31 2e 31 34 20 23  |..!......01.14 #|
00000010  23 2e 23 23 20 23 23 2e  23 23 00 f7              |#.## ##.##..|
0000001c