Bank dump format

Tips and techniques for Minimoog Analog Synthesizers
retango
Posts: 2
Joined: Wed Mar 15, 2023 11:37 am

Re: Bank dump format

Post by retango » Wed Mar 15, 2023 11:59 am

RL wrote: Sun Apr 10, 2016 4:48 am Hi music.maker,
there is an additional byte (the preset number) in the single preset dump. The System Exclusive format sends 7 bits instead 8 bits cause bit 7 always must be zero. And that means bit seven of the preset number is on position bit 0 of the second sysex byte (the first preset data byte).

Have fun,
Rudi
Hi all, thanks for this, but I can't seem to use it to decode a Voyager sysex bank. A sysex sysex bank is a single sysex message of 18732 bytes (exluding F0 and F7). It you substract the first 4 bites for ID, and command (04 01 deice 01) you get 18728 bytes for patch info. If you divide this number by 128 (the number of available patches in a bank) you get 146.3 bytes.. already strange that's not a round number of bytes.
Each patch, without header or patch number info, it's supposed to be 143 bytes long according to the sysex spec (http://www.moogmusic.de/SysEx.pdf), so the total patch info in a bank should be 18304 bytes long, short 428 bytes of the actual bank data.
If you add 1 byte per patch for patch number (you don't need 8 bits as patch numbers only go up to 128, so 1 "sysex" byte of 7 bits should suffice), a bank should use 18,432 bytes, still short of the total number by 296 byes. Even adding 1 byte + 1 bit, or 2 bytes for patch numbers, the total is still short (280 and 40 bytes short).
I've tried too many combinations, decoding different subgroups of the the bank data according to www.moogmusic.de/SysEx.pdf, with strange results, but no success.

Does anyone know how to split the 18728 bytes of a Voyager sysex bank into 128 sysex patches which follow the sysex decoding map from here www.moogmusic.de/SysEx.pdf? Or if we should use a different mapping to decode a sysex bank?
Thanks again

retango
Posts: 2
Joined: Wed Mar 15, 2023 11:37 am

Re: Bank dump format

Post by retango » Thu Mar 16, 2023 7:27 pm

music.maker wrote: Mon Dec 21, 2015 11:31 am Assumed that a bank dump should be just a collection of single preset dumps, so it would be possible to quickly extract (by software) the 128 presets of a bank dump. Surprisingly, the format of bank dumps appears to be completely different. Is there a specification of the bank dump format ?
Hi,
A bit late in the game, but after many attempts, I think I decoded the secret format of Voyager bank dumps. A bank dump is 18,732 bytes long (exlcluding the initial F0 and F7). Each patch should be 143 bytes long according to www.moogmusic.de/SysEx.pdf (excluding header info, 4 or 5 bytes), so you already see theres a problem: 143 (bytes per patch) x 128 (patches)=18,304, much less than the bank dump.

I found that patches are byte- and bit-shifted within the bank data. Patch 1 starts on byte 7 of the bank dump (counting from starting byte=0), bit 3 (counting bits 0 to 7 for right to left). Patch number 2 starts 146 bytes and 2 bits afterwards, i.e. byte 154 (again starting from 0), bit 5 (starting at 0 on the right). To convert these "hidden patches" into proper patch sysex data, you have to compensate the bit offset, cosidering that always bit# 7 should be zero. I have no idea what info is in these extra bytes in the bank dump (e.g. from byte 4 to 7, of the extra bytes within the patches). If somebody finds out, please let me know!

I wrote a python function that does just this. I copy it here for better understanding of the details. The function receives the bank dump as a list of integers (mido can easily do that), and returns patch data as another list of integers 143 integers long. As far as I know right know, I think that to decode these bytes you have to use the "Voyager System Exclusive Single Preset Dump Format" (as opposed to Panel Dump Format) detailed in www.moogmusic.de/SysEx.pdf. So add the first 5 bytes (header + patch number), and treat these 148 bytes as a Single Preset Dump.
In order to read the Patch name, you can use this SysEx.pdf document, and look at byte #102 of the PDF document Single Preset Format (byte 96 within the 143-long data without header) and decode from there.
Hope this helps!

def unpack_bank_voyager(packed_bytes, patch_nr=1):
import bitstring
from bitstring import BitArray, BitStream
bitstring.lsb0 = True
if len(packed_bytes) != 18732: #this is the size of a vogager bank (excluding F0 and F7)
print ('Wrong Length')
return None
if patch_nr -1 not in range(128): #patch numbers must be 1 to 128
print('Patch Number must be 1 to 128')
return None
# first patch info within the bank data is at byte 7, with 3 bits offset: starts at !: 0000!000
start_bit = (3 + (patch_nr -1)*2) %7 #distance within patches is 146 bytes and 2 bits. This one for shifting the bits
byte_offset = (3 + (patch_nr -1)*2) // 7 # this one calculates bytes to move based of the 2 bits each patch adds
start_byte=7 + (146*(patch_nr-1)) + byte_offset
patch_data_len=144 #1 more than needed, for the extra bits in byte 144
bit_array=BitArray()
for i in range(patch_data_len): #create bitarray, adding all the 7 bit bytes together (higher byte nr to the left)
bit_array.append (BitArray(uint=packed_bytes[start_byte+i], length=7))
del bit_array [:start_bit] #offsets bits to the right so the bitarray starts in bit #0 as it should
bit_array.append([0]*start_bit) #add 0s at the beginning, the # of removed bits on the right
patch_data=[0]*(patch_data_len-1) #143 is the patch packed data length
i=0
for byte in bit_array.cut(7):
if i==143:
break
patch_data=byte.uint
i +=1
return patch_data

User avatar
ummagumma
Posts: 827
Joined: Sun Aug 21, 2016 8:37 pm
Location: Canada

Re: Bank dump format

Post by ummagumma » Sat Mar 18, 2023 1:45 pm

Hey that's useful, thanks for posting

Post Reply