Have you ever wanted to convert a Yamaha QY100 Style into a Yamaha QY70 Style but found the conversion process to be overly tedious and time consuming? Well, with this new Python code, you don’t have to worry about manually converting your files between devices. With a bit of technical know-how, you can convert .syx files between the two devices with ease, and even mass-convert multiple .syx files in a single code execution!
What’s a “.syx” and why do QY70 & QY100 bulk dumps differ?
SysEx (.syx) files are raw System Exclusive messages—manufacturer-specific MIDI packets that let hardware send/receive bulk data: patterns, phrases, voice tables, effect settings, and more. Unlike standard MIDI files (which store note events and basic controller data), SysEx dumps are device-aware snapshots of internal memory, formatted exactly the way a particular synth/groovebox/sequencer expects.
Here’s the nice part: QY100 exports already conform to the fixed 148-byte bulk format the QY70 expects. So for converting in this direction we don’t need to split or reshape the data—we simply swap the address bytes and recompute checksums. That’s why the QY100→QY70 path is generally straightforward.
In the past, the common workaround was to convert styles by hand:
- Export each QY100 track as standard MIDI,
- Import into the QY70, then
- Rebuild the missing device-specific bits (kits, effects, voices, phrase links) manually.
It worked, but it was slow and easy to mess up…
The Python script I have provided automates the QY100 to QY70 .syx conversion without having to reprogram everything by hand.
STEP 1 – Prepare a QY100 .syx bulk file
To get started, you of course will need to export a .syx Style bulk file from the QY100. This is done by going to Menu>Utility>Bulk Dump in pattern mode, and setting the Bulk Data to “Style.”
Note: If you want to include the XG parameters in the dump, make sure that XG PARAM OUT is enabled in the MIDI settings. Found under Menu>Utility>MIDI.
Connect your QY100 to you computer using a MIDI to USB cable, and ready a SysEx Library program on your computer like: SysEx Librarian to prepare for the dump.
Execute the dump from the QY100 to transfer the .syx file to your computer. You now have a working QY100 .syx file backed up on your computer… now to make it cross-compatible with the QY70!
Packet anatomy (quick mental model)
- Control (open/close): 9 bytes
F0 43 10 5F 00 00 00 01 F7(open),F0 43 10 5F 00 00 00 00 F7(close) - Bulk (QY70 target): 158 bytes
F0 43 00 5F 01 13 02 7E [148 data bytes] [checksum] F7
STEP 2 – Execute Python code: QY100 ➜ QY70
#!/usr/bin/env python3
"""
QY100 -> QY70 SysEx converter (simple relabel + checksum)
================================================================
HOW TO USE:
1) Put your QY100 .syx files somewhere on your computer.
2) In the PLACEHOLDERS below, choose ONE of these:
A) List your files explicitly in INPUT_FILES, e.g.:
INPUT_FILES = [r"C:\styles\X.syx", r"C:\styles\Y.syx"]
(leave INPUT_FOLDER as "")
B) Point INPUT_FOLDER to a folder that contains .syx files:
INPUT_FOLDER = r"C:\styles_qy100"
Set SCAN_SUBFOLDERS = True if you want to search inside subfolders.
(leave INPUT_FILES as [])
3) Set OUTPUT_FOLDER to where you want the converted files written.
4) Run this file. The converted files will be created with the suffix
" - for QY70.syx".
================================================================
"""
# ===================== PLACEHOLDERS (EDIT THESE) =====================
INPUT_FILES = [] # e.g. [r"C:\styles\X.syx", r"C:\styles\Y.syx"]
INPUT_FOLDER = r"" # e.g. r"C:\styles_qy100" (leave "" if using INPUT_FILES)
SCAN_SUBFOLDERS = False
OUTPUT_FOLDER = r"" # e.g. r"C:\styles_qy70_out" ("" = next to each input)
OUTPUT_SUFFIX = " - for QY70" # final name: "<original><suffix>.syx"
# =====================================================================
from pathlib import Path
from typing import List
# ---------- Low-level helpers ----------
def split_sysex(blob: bytes):
"""Return a list of SysEx messages (each from F0 to F7 inclusive)."""
out=[]; i=0; b=bytearray(blob)
while True:
try:
s=b.index(0xF0,i); e=b.index(0xF7,s)
except ValueError:
break
out.append(b[s:e+1]); i=e+1
return out
def is_qy100_bulk(m: bytearray) -> bool:
"""Identify Yamaha bulk messages (QY100): F0 43 ?? 5F 01 ..."""
return len(m)>=12 and m[0]==0xF0 and m[1]==0x43 and m[3]==0x5F and m[4]==0x01
def y_checksum(addr_and_data: bytes) -> int:
"""Yamaha checksum = 0x7F - (sum(bytes) & 0x7F), masked to 7 bits."""
return (0x7F - (sum(addr_and_data) % 0x80)) & 0x7F
# ---------- Core converter ----------
def convert_qy100_to_qy70(src: Path, dst: Path):
"""
Simple relabel:
- QY100 bulks already have 148 data bytes (type + 147).
- Swap to QY70 address [13 02 7E] + fresh checksum.
- Surround with 9-byte opener/closer accepted by QY70.
"""
raw = src.read_bytes()
msgs = split_sysex(raw)
opener = bytearray([0xF0,0x43,0x10,0x5F,0x00,0x00,0x00,0x01,0xF7])
closer = bytearray([0xF0,0x43,0x10,0x5F,0x00,0x00,0x00,0x00,0xF7])
out = bytearray(opener)
for m in msgs:
if not is_qy100_bulk(m):
continue
payload_148 = bytes(m[8:-2]) # [type] + 147 bytes
if not payload_148:
continue
addr_and_data = bytes([0x13,0x02,0x7E]) + payload_148
chk = y_checksum(addr_and_data)
out += bytearray([0xF0,0x43,0x00,0x5F,0x01]) \
+ bytearray(addr_and_data) \
+ bytearray([chk,0xF7])
out += closer
dst.write_bytes(out)
# ---------- File discovery & running ----------
def discover_inputs(files: List[str], folder: str, recursive: bool) -> List[Path]:
"""
Decide *what* to process:
- If INPUT_FILES is non-empty: use those.
- Else if INPUT_FOLDER is set: gather *.syx (recursively if chosen).
"""
result: List[Path] = []
if files:
for f in files:
p = Path(f)
if p.is_file() and p.suffix.lower()==".syx":
result.append(p)
elif folder:
base = Path(folder)
glob = base.rglob("*.syx") if recursive else base.glob("*.syx")
result.extend(sorted(glob))
return result
def main():
inputs = discover_inputs(INPUT_FILES, INPUT_FOLDER, SCAN_SUBFOLDERS)
if not inputs:
print("No .syx inputs found. Edit the PLACEHOLDERS at the top of the file.")
return
outdir = Path(OUTPUT_FOLDER) if OUTPUT_FOLDER else None
for src in inputs:
dst_dir = outdir if outdir else src.parent
dst_dir.mkdir(parents=True, exist_ok=True)
dst = dst_dir / f"{src.stem}{OUTPUT_SUFFIX}.syx"
convert_qy100_to_qy70(src, dst)
print("Wrote:", dst)
if __name__ == "__main__":
main()
A working converted .syx file
And there you have it, a working converted .syx file for you to import into you Yamaha QY70!
Note: The files won’t always sound identical between devices as the instruments weren’t built to be cross-compatible. Since the QY100 has more effects and instrument voicings than the QY70, there will be some instances where the conversion will select the closest available voice or effect parameter in memory. The result when back-converting a style which has missing voices and effects can be significantly different sounding and will take some manual adjustment. Though still the process is not very time consuming when compared to trying to convert the entire file track-by-tack manually.