SMK37 OPEN:eight-track, multi-engine firmware for SMK-37 Pro / Elite, with a browser workbench and SDK
Hi everyone, we're M-VAVE. We've released SMK37 OPEN V01 for SMK-37 Pro and SMK-37 Elite, with tools for sequencing, live playing and developer extensions.
Here's what it offers:
- Eight tracks, six engines: DX7 FM, 303, 808, PSG, plucked string and sampler, with 16–64-step sequences, arpeggiators, chords, parameter locks, effects and 16 project slots.
- Independent DX7 library: 128 presets across four banks, with standard single-voice and 32-voice bank SysEx import/export. Extension parameters are not handled.
- PROJECT / LIVE / OFF track modes: combine sequencing with live playing. LIVE tracks keep sounds and held notes across project changes without recording notes. Export LIVE timbre edits separately, or save DX7 voices to the library.
- Independent keyboard and Pad assignments: four faders control eight tracks in two banks, with pickup to reduce level jumps. Pads send channel aftertouch, which DX7 responds to with vibrato.
- Performance and connectivity: step and real-time recording, 30–300 BPM, tap tempo and synchronized delay; USB/BLE MIDI input and DIN/USB/BLE MIDI output. Pro and Elite have no DIN MIDI input.
- Browser workbench: browser playback, firmware updates, and project, sample and voice management. Browser edits must be written to the device explicitly; the browser does not send performance MIDI to external devices.
Application and web source, build scripts and a matching native binary SDK are available. Application and web application sources use GPLv3 with an SDK linking exception; the SDK and other components retain their separate terms. We welcome feedback, feature discussions, and code or documentation contributions.
Choose the correct Pro/Elite model and back up projects, voices and samples separately before flashing. The workbench includes factory V16 restoration for the matching model; switching firmware does not make data formats interchangeable. Eight sample slots share about 19.55 seconds of new storage, and projects do not include sample audio. Flashing can cause data loss or prevent startup; keep power and USB connected.
Thanks to Vikram Rojo for the per-track tuning contribution, and to the upstream projects and community for their support.
Workbench and development kit · Source and README · Issues and suggestions
22 points · 6 comments
All right, stop, collaborate and listen
Before you dive into writing your own firmware, or adding the next feature to your existing firmware, please read this, it may save you a lot of time and frustration.
First up, I'm not trying to discourage anyone - build the firmware, learn the thing, get your ideas out there. I'm not trying to call anyone out, not saying this for clout, karma, or whuffies - I just want people to know this stuff. Hopefully someone with more spare time than me will start a wiki (the easy part) and drive enough engagement there (the hard part) that it becomes a single point where people can share, correct, and expand on this kind of info, but 'til then:
CMake and Ninja ara a pair of excellent build tools. Use them! Your agent knows how to maintain CMake configurations with far less effort and potential confusion than the custom build.py it might offer to create for you.
The JieLi AC7911B8 MCU at the heart of the FM-1 / SMK-37 has a hardware floating point unit. You may still get better performance using integers, but you'd be mad not to enable it with the compiler switches "-mcpu=r3 -mfprev1". M-VAVE's open firmware gives you a good starting point for the compiler switches: github.com/m-vave/fm1_open/blob/4c7496daac04a95ff…
You might as well try out their linker switches too: github.com/m-vave/fm1_open/blob/4c7496daac04a95ff…
If you are using integers, sometimes you'll need 64 bits in the middle of a calculation, but the final result fits into 32 bits. Try to avoid storing the 64 bit values to actual variables - that way the compiler knows it can throw away certain data, and generates much more efficient assembly for the MCU:
int32_t bad_fn(int32_t a, int32_t b, int32_t c) {
int64_t acc = (int64_t)a * b;
acc = (acc >> 16) * c;
return (int32_t)(acc >> 16);
}
int32_t good_fn(int32_t a, int32_t b, int32_t c) {
int32_t step1 = (int32_t)(((int64_t)a * b) >> 16);
return (int32_t)(((int64_t)step1 * c) >> 16);
}
Likewise, multiplications are faster than divisions. So if you find yourself dividing by a constant (or infrequently changed) value one or more times per frame of audio, maybe calculate inv_const = 1/const at startup, then your code can just multiply by inv_const.
Not everything needs to be optimised the same way. Back to compiler switches: when you're trying to pack the 22nd synth engine into your kitchen-sink firmware, blanket size optimisations like "-Os" or "-Oz" can seem attractive, but can quickly kill performance. The key is to be selective - try to arrange your files so all your hot loop code (anything that runs one or more times per frame of audio) is kept separate from the code that runs less frequently. Apply "-O2" to the hot code, and "-Os" or "-Oz" for everything else.
Think about what really needs to be in the per-frame loop too. Some values might not change that much over time, so you can get away with only calculating them once every 32 frames, 64 frames, or 128 frames. Even where the value does need to change from one frame to the next, you might get away with only doing the heavyweight version of the calculation once per block of frames, then running a fast, per-frame linear interpolation.
Take care about where that hot code runs from. Ideally you want it sitting in SRAM permenantly rather than executing in place from the NOR flash. XiP sounds like a great deal until your otherwise lightly loaded system starts having buffer underruns because a background process on the other core was fetching some data from flash. If you've got so many complex sound engines they won't all fit in SRAM at once, and you're feeling spicy, you might like to create little loading harness, reserve some space in SRAM, and load the current engine code into it at runtime.
Speaking of cores - use them both, overclock them to 360MHz, increase the voltage the same way M-VAVE does, expect the same level of reliability as the stock ROM. This isn't a gaming PC with a BIOS that gives you the freedom to fry the CPU if it's not cooled with liquid nitrogen. It's a mass-market MCU where the biggest concern from increasing the voltage is decreased battery life.
Don't reinvent the wheel. You can make a perfectly capable, performant firmware running both cores under FreeRTOS, which takes care of a lot of things you'd probably be better off not worrying about, like scheduling low priority vs. high priority tasks. If you're really worried about the overheads, consider FreeRTOS on one core, and pure, bare metal DSP on the other.
Support the SMK-37. Okay this is just my personal barrow to push. It's basically the same electronics, just with a few more keys, some pads, and some faders.
Okay, that's all I've got for now, and it's late. I'll check in for your questions, additions, disagreements, insults, etc. in the morning.
80 points · 27 comments
Mentions
SMK37 OPEN:eight-track, multi-engine firmware for SMK-37 Pro / Elite, with a browser workbench and SDK Hi everyone, we're M-VAVE. We've released SMK37 OPEN V01 for SMK-37 Pro and SMK-37 Elite, with tools for sequencing, live playing and developer extensions. Here's what it offers: - Eight tracks, six engines: DX7 FM, 303, 808, PSG, plucked string and sampler, with 16–64-step sequences, arpeggiators, chords, parameter locks, effects and 16 project slots. - Independent DX7 library: 128 presets across four banks, with standard single-voice and 32-voice bank SysEx import/export. Extension parameters are not handled. - PROJECT / LIVE / OFF track modes: combine sequencing with live playing. LIVE tracks keep sounds and held notes across project changes without recording notes. Export LIVE timbre edits separately, or save DX7 voices to the library. - Independent keyboard and Pad assignments: four faders control eight tracks in two banks, with pickup to reduce level jumps. Pads send channel aftertouch, which DX7 responds to with vibrato. - Performance and connectivity: step and real-time recording, 30–300 BPM, tap tempo and synchronized delay; USB/BLE MIDI input and DIN/USB/BLE MIDI output. Pro and Elite have no DIN MIDI input. - Browser workbench: browser playback, firmware updates, and project, sample and voice management. Browser edits must be written to the device explicitly; the browser does not send performance MIDI to external devices. Application and web source, build scripts and a matching native binary SDK are available. Application and web application sources use GPLv3 with an SDK linking exception; the SDK and other components retain their separate terms. We welcome feedback, feature discussions, and code or documentation contributions. Choose the correct Pro/Elite model and back up projects, voices and samples separately before flashing. The workbench includes factory V16 restoration for the matching model; switching firmware does not make data formats interchangeable. Eight sample slots share about 19.55 seconds of new storage, and projects do not include sample audio. Flashing can cause data loss or prevent startup; keep power and USB connected. Thanks to Vikram Rojo for the per-track tuning contribution, and to the upstream projects and community for their support. Workbench and development kit · Source and README · Issues and suggestions
All right, stop, collaborate and listen Before you dive into writing your own firmware, or adding the next feature to your existing firmware, please read this, it may save you a lot of time and frustration. First up, I'm not trying to discourage anyone - build the firmware, learn the thing, get your ideas out there. I'm not trying to call anyone out, not saying this for clout, karma, or whuffies - I just want people to know this stuff. Hopefully someone with more spare time than me will start a wiki (the easy part) and drive enough engagement there (the hard part) that it becomes a single point where people can share, correct, and expand on this kind of info, but 'til then: CMake and Ninja ara a pair of excellent build tools. Use them! Your agent knows how to maintain CMake configurations with far less effort and potential confusion than the custom build.py it might offer to create for you. The JieLi AC7911B8 MCU at the heart of the FM-1 / SMK-37 has a hardware floating point unit. You may still get better performance using integers, but you'd be mad not to enable it with the compiler switches "-mcpu=r3 -mfprev1". M-VAVE's open firmware gives you a good starting point for the compiler switches: github.com/m-vave/fm1_open/blob/4c7496daac04a95ff… You might as well try out their linker switches too: github.com/m-vave/fm1_open/blob/4c7496daac04a95ff… If you are using integers, sometimes you'll need 64 bits in the middle of a calculation, but the final result fits into 32 bits. Try to avoid storing the 64 bit values to actual variables - that way the compiler knows it can throw away certain data, and generates much more efficient assembly for the MCU: int32_t bad_fn(int32_t a, int32_t b, int32_t c) { int64_t acc = (int64_t)a * b; acc = (acc >> 16) * c; return (int32_t)(acc >> 16); } int32_t good_fn(int32_t a, int32_t b, int32_t c) { int32_t step1 = (int32_t)(((int64_t)a * b) >> 16); return (int32_t)(((int64_t)step1 * c) >> 16); } Likewise, multiplications are faster than divisions. So if you find yourself dividing by a constant (or infrequently changed) value one or more times per frame of audio, maybe calculate inv_const = 1/const at startup, then your code can just multiply by inv_const. Not everything needs to be optimised the same way. Back to compiler switches: when you're trying to pack the 22nd synth engine into your kitchen-sink firmware, blanket size optimisations like "-Os" or "-Oz" can seem attractive, but can quickly kill performance. The key is to be selective - try to arrange your files so all your hot loop code (anything that runs one or more times per frame of audio) is kept separate from the code that runs less frequently. Apply "-O2" to the hot code, and "-Os" or "-Oz" for everything else. Think about what really needs to be in the per-frame loop too. Some values might not change that much over time, so you can get away with only calculating them once every 32 frames, 64 frames, or 128 frames. Even where the value does need to change from one frame to the next, you might get away with only doing the heavyweight version of the calculation once per block of frames, then running a fast, per-frame linear interpolation. Take care about where that hot code runs from. Ideally you want it sitting in SRAM permenantly rather than executing in place from the NOR flash. XiP sounds like a great deal until your otherwise lightly loaded system starts having buffer underruns because a background process on the other core was fetching some data from flash. If you've got so many complex sound engines they won't all fit in SRAM at once, and you're feeling spicy, you might like to create little loading harness, reserve some space in SRAM, and load the current engine code into it at runtime. Speaking of cores - use them both, overclock them to 360MHz, increase the voltage the same way M-VAVE does, expect the same level of reliability as the stock ROM. This isn't a gaming PC with a BIOS that gives you the freedom to fry the CPU if it's not cooled with liquid nitrogen. It's a mass-market MCU where the biggest concern from increasing the voltage is decreased battery life. Don't reinvent the wheel. You can make a perfectly capable, performant firmware running both cores under FreeRTOS, which takes care of a lot of things you'd probably be better off not worrying about, like scheduling low priority vs. high priority tasks. If you're really worried about the overheads, consider FreeRTOS on one core, and pure, bare metal DSP on the other. Support the SMK-37. Okay this is just my personal barrow to push. It's basically the same electronics, just with a few more keys, some pads, and some faders. Okay, that's all I've got for now, and it's late. I'll check in for your questions, additions, disagreements, insults, etc. in the morning.
This is the repository for the “FM1 Open” firmware from M-VAVE. FM1 Open is M-VAVE’s official, open-source C SDK for the FM-1’s JieLi chip. It allows developers to write their own synthesiser engines, MIDI functions and audio routines from scratch.
Context: The FM-1 is an inexpensive synth ($80ish on amazon/aliexpress) which was reverse engineered [0]. The company that makes it now endorses the open firmware movement around it [1] [2]. You can see a review for the synth here [3]. Wow, also see this Firmware Hub! [4] [0] aroum/fm1-custom-fw [1] m-vave/fm1_open [2] forum.m-vave.com [3] youtube.com [4] thefirmwarehub.com
FM-1のメーカー(M-VAVE)が自前でgithubリポジトリを作ったんですって。/"GitHub - m-vave/fm1_open · GitHub" m-vave/fm1_open
Official FM-1 Open from M-Wave: m-vave/fm1_open
いや草 もう全部好き放題にできるじゃん m-vave/fm1_open
FM-1公式がこれを出すのはすごいなー 教授が生きていたらどんな反応示すだろうか、 真っ先に反応して、ヘタしたら自分の作品に取り入れてるかもしれないなとか想像 m-vave/fm1_open
M-VAVEが公式「FM1 Open V13」を公開。8トラック・8サンプル枠・16種のFXデモに、ソースとSDK、ブラウザWorkbenchも。メーカー自身がCFW開発の土台を提供。ただし実機用エンジンの一部はバイナリ提供です。 m-vave/fm1_open
M-VAVEが公式のrepo公開 m-vave/fm1_open コレで全部終わった気がする...