Skip to content

[synth] adding Yamaha SY22, SY35, TG33, SY55, TG55, SY77, TG77, SY85, TG500 - #551

Open
hmmbug wants to merge 13 commits into
christofmuc:masterfrom
hmmbug:synths/yamaha_sy77
Open

[synth] adding Yamaha SY22, SY35, TG33, SY55, TG55, SY77, TG77, SY85, TG500#551
hmmbug wants to merge 13 commits into
christofmuc:masterfrom
hmmbug:synths/yamaha_sy77

Conversation

@hmmbug

@hmmbug hmmbug commented May 29, 2026

Copy link
Copy Markdown

Here's a follow up to the recent discussion about the Yamaha SY/TG series. I've implemented adaptations based on a common abstraction class.

Implementation Status:

  • SY77: I've been testing this with read hardware but getting input from others would be valuable
  • TG77: untested but almost entirely inherits from the SY77 and the MIDI specs are identical
  • SY55/TG55: untested with real hardware. These 2 can't be distinguished from each other via MIDI without modifying patches so implemented as a single adaptation
  • SY85: untested with real hardware
  • TG500: untested with real hardware. Based on the SY85 adaptation.
  • SY22: untested with real hardware
  • SY35: untested with real hardware. Based on the SY22 adaptation.
  • TG33: untested with real hardware. Based on the SY22 adaptation.

See adaptations/yamaha/Yamaha_SY_TG_common.py for implementation notes. The adaptation abstraction class should cover sufficient functionality of this series of synths. The quirks/differences that exist in each of the models can be implemented as overrides.

adaptations/yamaha/README_SY_TG_SYSEX.md summarises the key sysex parameters used for these adaptations.

Summary by CodeRabbit

  • New Features
    • Added support for Yamaha SY22, SY35, SY55/TG55, SY77/TG77, SY85, TG33, and TG500 synthesizers.
    • Added voice-bank browsing, patch naming, program selection, device detection, and SysEx import/export.
    • Added support for internal and preset memory banks, including bulk bank transfers where available.
  • Documentation
    • Added Yamaha SY/TG SysEx format and model compatibility documentation.
  • Tests
    • Added representative patch-bank data and validation fixtures for supported instruments.

@coderabbitai

coderabbitai Bot commented May 29, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bae94e27-b6d1-49aa-9496-b0e3001cf435

📥 Commits

Reviewing files that changed from the base of the PR and between 16ec29e and 0a7ec06.

📒 Files selected for processing (5)
  • adaptations/Yamaha_SY55.py
  • adaptations/Yamaha_SY77.py
  • adaptations/Yamaha_SY85.py
  • adaptations/Yamaha_TG33.py
  • adaptations/yamaha/README_SY_TG_SYSEX.md
✅ Files skipped from review due to trivial changes (1)
  • adaptations/yamaha/README_SY_TG_SYSEX.md
🚧 Files skipped from review as they are similar to previous changes (4)
  • adaptations/Yamaha_SY77.py
  • adaptations/Yamaha_SY55.py
  • adaptations/Yamaha_TG33.py
  • adaptations/Yamaha_SY85.py

📝 Walkthrough

Walkthrough

Adds shared Yamaha SY/TG SysEx support and new model adaptations for voice detection, dump conversion, bank mapping, program changes, naming, module wiring, and test fixtures for several Yamaha synthesizers.

Changes

Yamaha SY/TG Synth Support

Layer / File(s) Summary
Shared SysEx protocol
adaptations/yamaha/Yamaha_SY_TG_common.py
Adds Yamaha message construction, checksum validation, device detection, program/edit-buffer conversion, bank helpers, naming, fingerprinting, installation, and byte utilities.
SY22 family bank parsing and adapters
adaptations/Yamaha_SY22.py, adaptations/Yamaha_SY35.py, adaptations/Yamaha_TG33.py
Adds SY22 bulk-bank extraction and memory mapping, then configures SY22, SY35, and TG33-specific identifiers, validation, fixtures, and bank metadata.
SY55 and TG55 mapping
adaptations/Yamaha_SY55.py
Adds internal/preset bank conversion, direct-mode program changes, friendly naming, patch mapping, module wiring, and test fixtures.
SY85 and TG500 selection
adaptations/Yamaha_SY85.py, adaptations/Yamaha_TG500.py
Adds device detection, voice-dump handling, model-specific program changes, bank naming, patch mapping, configuration, and test fixtures.
SY77 and TG77 voice-only support
adaptations/Yamaha_SY77.py, adaptations/Yamaha_TG77.py
Adds three-bank voice mapping, bank-dump generation, direct-mode program changes, friendly naming, model configuration, and test fixtures.
SysEx fixtures and reference
adaptations/testData/*, adaptations/yamaha/README_SY_TG_SYSEX.md
Adds Yamaha test-bank payloads and documents message identifiers, offsets, checksum rules, request formats, and model-specific behavior.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Host
  participant ModelAdapter
  participant YamahaSYTGBase
  participant YamahaSynth
  Host->>ModelAdapter: request program or bank dump
  ModelAdapter->>YamahaSYTGBase: build model-specific SysEx request
  YamahaSYTGBase->>YamahaSynth: send request
  YamahaSynth-->>YamahaSYTGBase: return voice or bank SysEx data
  YamahaSYTGBase->>ModelAdapter: validate, split, and recalculate checksums
  ModelAdapter-->>Host: expose patches, names, and program mappings
Loading

Suggested labels: New device

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding multiple Yamaha synth adaptations.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@adaptations/Yamaha_SY77.py`:
- Around line 84-95: convertPatchesToBankDump is clobbering per-patch metadata
(device id, memory type and slot number) which breaks round-tripping with
extractPatchesFromBank; stop overwriting those bytes — do not assign
buf[OFFSET_DEVICE_ID], buf[self.offset_memory_type] or
buf[self.offset_memory_number] in convertPatchesToBankDump, instead preserve the
bytes already in each patch, then recompute and store the checksum with
OFFSET_CHECKSUM = self._calculateChecksum(buf) before appending to bank; keep
the rest of the loop and return behavior unchanged.

In `@adaptations/yamaha/Yamaha_SY_TG_common.py`:
- Around line 196-198: In channelIfValidDeviceResponse, when buf is too short
you currently return False which coerces to 0; change that to return -1 to
indicate "no match" and preserve the function's int return contract (update the
early-return in channelIfValidDeviceResponse to return -1 instead of False and
ensure any callers expect/handle -1 as the invalid/no-match sentinel).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f74b9b4e-6fa8-4368-b0dc-b1b59120090c

📥 Commits

Reviewing files that changed from the base of the PR and between 783f4a9 and 974afc4.

📒 Files selected for processing (7)
  • adaptations/Yamaha_SY77.py
  • adaptations/Yamaha_TG77.py
  • adaptations/testData/Yamaha_SY77/bank.syx
  • adaptations/testData/Yamaha_TG77/Preset1.syx
  • adaptations/testData/Yamaha_TG77/Preset1_01_SP_Cosmo__.syx
  • adaptations/yamaha/Yamaha_SY_TG_common.py
  • adaptations/yamaha/__init__.py

Comment thread adaptations/Yamaha_SY77.py
Comment thread adaptations/yamaha/Yamaha_SY_TG_common.py Outdated
@hmmbug
hmmbug marked this pull request as draft June 6, 2026 22:16
@hmmbug hmmbug changed the title [synth] adding Yamaha SY77 & TG77 [synth] adding Yamaha SY77 & TG77, SY55 & TG55, SY85 & TG500 Jun 6, 2026
@hmmbug hmmbug changed the title [synth] adding Yamaha SY77 & TG77, SY55 & TG55, SY85 & TG500 [synth] adding Yamaha SY77, TG77, SY55, TG55, SY85, TG500 Jun 6, 2026
@hmmbug hmmbug changed the title [synth] adding Yamaha SY77, TG77, SY55, TG55, SY85, TG500 [synth] adding Yamaha SY22, SY35, TG33, SY55, TG55, SY77, TG77, SY85, TG500 Jun 13, 2026
@hmmbug

hmmbug commented Jul 11, 2026

Copy link
Copy Markdown
Author

The SY77 adaptation has been in use for a few weeks now and seems stable. Taking out of draft for review.

@hmmbug
hmmbug marked this pull request as ready for review July 11, 2026 14:07

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (1)
adaptations/testData/Yamaha_SY22_SY35_TG33/ext.py (1)

38-38: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Rename unused loop variable x to _.

♻️ Proposed fix
-        for x in range(4):
+        for _ in range(4):
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@adaptations/testData/Yamaha_SY22_SY35_TG33/ext.py` at line 38, Rename the
unused loop variable x to _ in the four-iteration loop, preserving the loop
count and body behavior.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@adaptations/testData/Yamaha_SY22_SY35_TG33/ext.py`:
- Line 39: Update the patch construction in the surrounding extraction logic to
slice exactly patch_len bytes from bank starting at offset, removing the -1
adjustment. Preserve the existing prefix and suffix concatenation and offset
advancement so each voice slot yields all 574 bytes.

In `@adaptations/Yamaha_SY55.py`:
- Around line 108-119: Update friendlyProgramName to use the full SY55 slot
range by replacing the bankslot calculation based on memnum % 16 with memnum +
1. Preserve the existing memtype mapping, two-digit formatting, logging, and
returned name format so slots display I01–I64 or P01–P64 without wrapping.

In `@adaptations/Yamaha_SY77.py`:
- Around line 166-173: Update the patch-number validation around the visible
patchno mapping so negative values are rejected before the INTERNAL range maps
them to a tuple. Ensure invalid negative patchno values raise the existing
ValueError and cannot reach createCustomProgramChange() as MIDI data, while
preserving the current mappings for valid ranges.

In `@adaptations/Yamaha_SY85.py`:
- Around line 144-150: Update createProgramDumpRequest in the drum-voice branch
to replace the request identifier at the correct offset, changing the existing
“VC” bytes at indices 12–13 to “DR” without modifying the padding. Preserve the
current patch-number condition and return behavior.

In `@adaptations/Yamaha_TG33.py`:
- Around line 65-68: Rename the YamahaTG33 class attribute msg_id_alt_bulk_dump
to msg_id_alt_all_voice_dump while preserving the "PK  2203VM" value, so
YamahaSY22.extractPatchesFromBank() recognizes TG33 bank dumps.

In `@adaptations/yamaha/README_SY_TG_SYSEX.md`:
- Around line 6-29: Complete the NOTES column for every table row in the Yamaha
SY/TG SYSEX documentation by adding the missing trailing empty cell (`| |`)
where needed. Ensure the Voice Data Dump row also ends with a closing pipe after
its existing note, resolving the MD056 formatting issue without changing table
content.

---

Nitpick comments:
In `@adaptations/testData/Yamaha_SY22_SY35_TG33/ext.py`:
- Line 38: Rename the unused loop variable x to _ in the four-iteration loop,
preserving the loop count and body behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2c45e66d-401d-4a9c-b816-70384ce50576

📥 Commits

Reviewing files that changed from the base of the PR and between dbfd9f4 and 16ec29e.

📒 Files selected for processing (19)
  • adaptations/Yamaha_SY22.py
  • adaptations/Yamaha_SY35.py
  • adaptations/Yamaha_SY55.py
  • adaptations/Yamaha_SY77.py
  • adaptations/Yamaha_SY85.py
  • adaptations/Yamaha_TG33.py
  • adaptations/Yamaha_TG500.py
  • adaptations/Yamaha_TG77.py
  • adaptations/testData/Yamaha_SY22_SY35_TG33/SY22A.syx
  • adaptations/testData/Yamaha_SY22_SY35_TG33/TG33-p1.syx
  • adaptations/testData/Yamaha_SY22_SY35_TG33/ext.py
  • adaptations/testData/Yamaha_SY55/sy55.syx
  • adaptations/testData/Yamaha_SY55/sy55_1.syx
  • adaptations/testData/Yamaha_SY55/sy55_presets.syx
  • adaptations/testData/Yamaha_SY55/sy55ptch.syx
  • adaptations/testData/Yamaha_SY85/SY85_test_bank.syx
  • adaptations/testData/Yamaha_TG500/TG500_test_bank.syx
  • adaptations/yamaha/README_SY_TG_SYSEX.md
  • adaptations/yamaha/Yamaha_SY_TG_common.py
✅ Files skipped from review due to trivial changes (5)
  • adaptations/testData/Yamaha_SY55/sy55.syx
  • adaptations/testData/Yamaha_SY22_SY35_TG33/TG33-p1.syx
  • adaptations/testData/Yamaha_SY55/sy55_presets.syx
  • adaptations/testData/Yamaha_SY55/sy55ptch.syx
  • adaptations/testData/Yamaha_SY85/SY85_test_bank.syx
🚧 Files skipped from review as they are similar to previous changes (1)
  • adaptations/Yamaha_TG77.py

Comment thread adaptations/testData/Yamaha_SY22_SY35_TG33/ext.py Outdated
Comment thread adaptations/Yamaha_SY55.py
Comment thread adaptations/Yamaha_SY77.py Outdated
Comment thread adaptations/Yamaha_SY85.py
Comment thread adaptations/Yamaha_TG33.py Outdated
Comment thread adaptations/yamaha/README_SY_TG_SYSEX.md Outdated
@christofmuc

Copy link
Copy Markdown
Owner

Release-readiness follow-up (no fixes applied here):

  • Add all eight adaptations to the shipping list and package the shared yamaha/ directory in the installer, Linux install, and app-bundle copy paths; top-level Python-file copying alone will not include the helper package. Add README entries.
  • SY22-family isBankDumpFinished treats any message ending in F7 as a completed bank and raises IndexError on []. Reimporting a valid SY22 edit-buffer patch through testing.librarian.Librarian.load_sysex raises Unsupported message_id because it is incorrectly sent to the bank extractor. Add individual-patch reimport, empty/unrelated-message, and live bank-transfer regressions for SY22/SY35/TG33.
  • Exercise all advertised bank descriptors; SY85/TG500 friendlyBankName currently expects hardware bank IDs rather than the descriptor's consecutive bank numbers.

All eight current suites pass on Python 3.12 (186 tests total); the above cases are not covered. The earlier Enum membership failures on Python 3.10 are not a current 3.12 release blocker. SY77 hardware testing reported by the author should not be generalized to the whole family.

@christofmuc

Copy link
Copy Markdown
Owner

That was codex 5.6 - I will have a look at this later to see if we need to harden some of the non-77 adaptations before including them in the official release. Thanks for the contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants