Roland SH-32

Hello, giving a stab at mapping out a preset for a device that most certainly needs it! Most of the parameters I can parse out with simple CC commands, but there are some that are SysEx only. I’m looking for a nudge in the right direction on how to get dynamic SysEx messages to send correctly!

I’ll provide some SysEx messages that determine Osc1 waveform types:

Header 0 1 2 3 4 5 6 7 8 9 10 11
ADDRESS
Osc1 Waveform Exclusive Status ID Number Device ID (dev) Model ID #1 Model ID #2 Command ID (DT1) MSB Upper Middle Byte Lower Middle Byte LSB Data Checksum EOX
Saw 1 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 05h 00h 57h F7h
Decimal 20 0 16 5 0 87
Saw 2 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 05h 01h 56h F7h
Decimal 20 0 16 5 1 86
Saw 3 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 05h 02h 55h F7h
Decimal 20 0 16 5 2 85
Saw 4 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 05h 03h 54h F7h
Decimal 20 0 16 5 3 84
Saw 5 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 05h 04h 53h F7h
Decimal 20 0 16 5 4 83
Saw 6 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 05h 05h 52h F7h
Decimal 20 0 16 5 5 82
Saw 7 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 05h 06h 51h F7h
Decimal 20 0 16 5 6 81
Saw 8 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 05h 07h 50h F7h
Decimal 20 0 16 5 7 80
Saw 9 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 05h 08h 4Fh F7h
Decimal 20 0 16 5 8 79
Saw 10 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 05h 09h 4Eh F7h
Decimal 20 0 16 5 9 78
Saw 11 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 05h 0Ah 4Dh F7h
Decimal 20 0 16 5 10 77
Saw 12 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 05h 0Bh 4Ch F7h
Decimal 20 0 16 5 11 76
Square 1 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 06h 00h 56h F7h
Decimal 20 0 16 6 0 86
Square 2 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 06h 01h 55h F7h
Square 3 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 06h 02h 54h F7h
Square 4 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 06h 03h 53h F7h
Square 5 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 06h 04h 52h F7h
Square 6 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 06h 05h 51h F7h
Pulse 1 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 07h 00h 55h F7h
Pulse 2 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 07h 01h 54h F7h
Pulse 3 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 07h 02h 53h F7h
Pulse 4 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 07h 03h 52h F7h
Pulse 5 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 07h 04h 51h F7h
Pulse 6 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 07h 05h 50h F7h
Pulse 7 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 07h 06h 4Fh F7h
Pulse 8 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 07h 07h 4Eh F7h
Pulse 9 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 07h 08h 4Dh F7h
PWM Wave F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 04h 03h 55h F7h
Triangle/Sine 1 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 08h 00h 54h F7h
Triangle/Sine 2 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 08h 01h 53h F7h
Triangle/Sine 3 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 08h 02h 52h F7h
Triangle/Sine 4 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 08h 03h 51h F7h
Triangle/Sine 5 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 08h 04h 50h F7h
Spectrum 1 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 00h 53h F7h
Spectrum 2 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 01h 52h F7h
Spectrum 3 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 02h 51h F7h
Spectrum 4 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 03h 50h F7h
Spectrum 5 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 04h 4Fh F7h
Spectrum 6 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 05h 4Eh F7h
Spectrum 7 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 06h 4Dh F7h
Spectrum 8 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 07h 4Ch F7h
Spectrum 9 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 08h 4Bh F7h
Spectrum 10 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 09h 4Ah F7h
Spectrum 11 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 0Ah 49h F7h
Spectrum 12 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 0Bh 48h F7h
Spectrum 13 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 0Ch 47h F7h
Spectrum 14 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 0Dh 46h F7h
Spectrum 15 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 0Eh 45h F7h
Spectrum 16 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 0Fh 44h F7h
Spectrum 17 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 10h 43h F7h
Spectrum 18 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 11h 42h F7h
Spectrum 19 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 12h 41h F7h
Spectrum 20 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 09h 13h 40h F7h
Noise 1 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 0Ah 00h 52h F7h
Noise 2 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 0Ah 01h 51h F7h
Noise 3 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 0Ah 02h 50h F7h
Noise 4 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 0Ah 03h 4Fh F7h
Noise 5 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 0Ah 04h 4Eh F7h
Noise 6 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 0Ah 05h 4Dh F7h
Noise 7 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 0Ah 06h 4Ch F7h
Noise 8 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 0Ah 07h 4Bh F7h
Noise 9 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 0Ah 08h 4Ah F7h
Noise 10 F0h 41h 10h 00h 4Ah 12h 14h 00h 10h 0Ah 09h 49h F7h

From SH-32 Midi Implementation:

OSC Parameter Address Information
image

Supplemental Roland Midi Information:


FULL PDF HERE

Here are the marked bits from the analyzer:

Now what isn’t clear to me yet, is how to make a dynamic list that will push the SysEx correctly to the unit. I understand that I need to designate some constant values and some parameter values, but it isn’t clear to me how many. The positions are kind of lost to me. If anyone can point me in the direction of some general materials or even specific electra advice, that would be great! I tried reading over the dev documentation on here, but that still is a little bit above my head!

1 Like

I think you can make a direct relationship between the number in the list and each of the variable bytes you must send. So instead of using values in the sysex, you could use three functions. Each function takes in the number of the list as a value, and returns a byte that fits the SysEx.

By function do you mean defining a LUA function? Wouldn’t mind taking a look at some examples if you there are any in the instrument presets you’ve done!

1 Like

Go look in my Korg 03R/W preset. Most controls are sysex. One of the first bytes is different depending on the base MIDI channel you set the synth to. Instead of hardcoding (and rendering the preset useless for a Korg 03R/W owner with a different base MIDI channel), you solve this with a lua function. In this preset the output for the byte is not based on the value of the control itself, like you’ll need to do, but it should help you get started.

By the way, the osc multisound control shows you also a way the send an 8 bit control value in a sysex message using two bytes. One that will take care of 7 bits, and one that takes care of the eighth bit. Might be useful for you too.

1 Like

Ah I wish I could grok this. I keep trying to reference the Electra documentation that backs up all of this but it either makes too many user knowledge assumptions or lags behind what’s currently possible in the editor.

It’s not clear what the values are when you have a list that are being passed. When it’s a midi cc list it makes sense as they represent a number (0-127) for that CC, but when set to sysex where are those values being passed to and should they be the decimal value that was converted from the hexadecimal sysex string?

Maybe I should just separate out the waveform types to “simplify” it but I wanted to avoid making it too busy just to select the waveform.

There’s a four step approach to this.

1.Are you familiar with SysEx? And with hexadecimal representations? With the way MIDI syntax is made up in Sysex? With MIDI principles?

You’ll need a bit more than just basic MIDI knowledge if you wanna work with Sysex. Sysex implementations are different for each brand, and differ within a brand from model to model. And this knowledge is independent from Electra or any other device that lets you program around Sysex.

  1. Once you have taken that hurdle, next step is you describe in plain English and arithmetic how each byte of the Sysex string should be constructed for the purpose you want to reach. If you’ve never done this before I can help you out (but not with a full sysex course :wink:) if you at least try it out for yourself first. So try to describe each of the 13 bytes what their function is.

  2. You should know a little bit about lua programming. Just a little. But it is not complicated and lots of info is found on the internet. The basics can be learned in a couple of hours I’m not a skilled programmer myself, so I learn lua along the way, once I know what it is I want to reach. That is why in my opinion step 1 and 2 you better do on your own.

  3. Once this second step is done, I or others on the forum can help you how to set this up in Electra. But for the editing part as well as for the lua.

Your request isn’t that difficult once you get the hang of it. But the sysex knowledge is mandatory if you want to make presets that you can maintain yourself whenever you change your setup.

1 Like

I’ve updated my initial post so it’s a little better structured in terms of companion information taken from the SH-32 Midi Implementation. I appreciate the 4-step approach as it allows for personal growth over just getting the answer!

For this specific instance, I seem to be hardcoding most of the start address, but will need a way to determine the offset. I’m a little confused by the way Roland structures the address portion of the bytes (positions 5-8). Maybe I need to go up another level first and define the waveform as a parameter and then link it to the waveform variations? Seem to be getting to a better understanding slowly!

Roland has made it difficult. They always have a lot of imagination when it comes to SysEx.
You don’t have an easier synth to start with? I do have a Roland XV5080, but that one too will have to wait a bit longer , because of its complexity.

And you probably have chosen the most difficult parameter to start with as well. Very ambitious! I suggest you look for another paramter you want to parse first, which has some easier characteristics.

  • for instance choose just an on/off , changing from 0 to 1 or from 0 to 64, or you choose a continuous value going from 0 to 127.
  • choose one you can easily check on your synth, and which is not far in the sysex payload.

Next, before you think about parsing parameters, first ensure you can control it. So first build the pad or fader in the Electra Editor and try to control the synth with it. in the MIDI implementation you need to look for the ‘Parameter Change’ instructions.

I think the issue is that there are a lot of functions that can be modified by standard CC messages. Once you start going into the nested menus, which is where the electra strives, is where sysex is required.Maybe I’ll workshop one of the other items like filter cutoff that already has a CC, but can also be controlled via sysex.

You don’t have an easier synth to start with?

I wish! The ones that I do have already have templates like:
Waldorf Blofeld
Access Virus B

My other pieces will be more complex than this:
Akai S1100
Kurzweil K2000RS
E-mu Ultra E6400

While I would like to venture into those pieces, I thought the Roland would have been easier, but like you said…they have made it difficult! I did start a project with the CC’s mapped out, it isn’t public yet.
ROLAND SH-32.eproj (11.7 KB)

I do have an E-mu Proteus 2000 coming in this week, but that might be even more of a bear considering the Midi Manual I found for it…here.

1 Like

Let’s stick tot the Roland then.
And as a test let’s control the filter cutoff first, what do you say?

Sounds good, I’ll have to parse that one out manually as that typically transmits over CC so it’ll be good practice.

I was able to successfully implement a toggle switch for the INS-FX which is a sysex only option which is working correctly, but isn’t bidirectional at this time (electra → SH-32 only).

So I implemented the filter freq, analog feel and FX-INS. I’ve noticed no issues with the FX-INS toggle, but for the analog feel and filter freq (127 sliders) they freeze the electra around 40-50 value inputs. If I go slower I can maybe get a little higher, but never a full up/down transmission of data.

Can you send me the link to your preset?

Here you go: Roland SH-32 Preset

You make me get appetite to start working on the XV5080. The SH32 and the XV are from the same era (2000-2001), they have similar complexities in their MIDI implementation , but they share part of the architecture.

So although I may not be making a full XV5080 preset at this stage, I can try out the challenges you have with a synth that I have. I will give you access to my preset as well, so we can share the findings during the development.

I’ll be starting with similar controls like cutoff control, but in the early stage will already try to use the E1 for selecting patches , performances or rhythm sets. Then move on the effects control.

During lunch I did a quick compare between both synth’s SysEx.
The good news: very comparable. If we solve your challenge, we’ve solved mine as well !

Bad news: the regular parsing as foreseen on the Electra One will not work.

Most synth suppliers foresaw a SysEx where you can request a memory dump, and then receive a dump in a known format. Easy then to parse , as f.i. the twelfth byte always has the same meaning.
For individual parameter changes (outside of CC) these synths then find recourse to NRPN’s or SysEx Parameter Change messages, where only one address is mentioned. The Sysex Parameter change is then typically only used from Electra to the synth. The dump is used for getting all data at once form Synth to Electra.

This Roland SysEx doesn’t use any of these messages. Instead in a data request, we must add a pointer (= the starting address) as well as the length of the requested answer. And if formatted correctly we’ll get an answer to the exact question. In this case, the exact position of a parameter in a SysEx reply will depend on that starting address, or may not even be in the requested answer. There are literally hundreds of ways the header of the replies may look like. Impossible to get that worked out via standard parsing.

So we’ll need a cleverer way of working: one that allows us to define the address in a generic way, depening on patch, part, tone, partial and parameter number. Then we’ll need to read the full string of any incoming data dump, split it according the the start address of the dump and assign it to the appropiate parameter.
Another challenge is to send a parameter change that. We’ll have to do that first. If that doesn’t work the extra work on defining the clever ‘find my address’ algorithm isn’t really valuable. If it does work, we might escape having to define SysEx changes one by one for each parameter.

Sounds like a solid plan to me. I was certainly curious of the start address and offsets and that does make a bit more sense. It may even work if the preset was only meant to modify a temporary patch, but not really a fully fledged editor that the Electra can do! Let me know how you want to proceed, I’m pretty handy with gathering things/researching as needed.

1 Like

Hi @Cubeinthebox , just to signal I haven’t forgotten you.

But there are 3 presets I desperately want to get finished, so I’m giving these priority. It maye take me a couple of months.

Fyi , I was looking into the MIDI manual of Roland’s Aria TB-3 and to my surprise it has a similar sysex syntax as the older Rolands. That was a bit unexpected.

No problem at all! I’ve been exploring the Proteus 2000 I got (composer and Xtreme Lead ROMs) along with incorporating Reaper into my Renoise workflow, so I certainly have enough things to keep me busy outside of my day job… :sweat_smile: :sweat_smile:

Fyi , I was looking into the MIDI manual of Roland’s Aria TB-3 and to my surprise it has a similar sysex syntax as the older Rolands. That was a bit unexpected.

Wouldn’t put it past Roland!!

1 Like

a tip

if you add this to your lua, it’ll show you in the console whatever control you change.
I will use this function in our exercise. Not to show these values, but to select certain controls and convert their data to send appropiate sysEx strings to the XV5080. That way the sysEx can be set up flexibly without having to enter them for each control separately.

The code below will help you understand with you can intercept whenever you turn a knob, or receive a control from elsewhere that changes a control

function parameterMap.onChange (valueObjects, origin, value)-- callback function retrieving MIDI value
  local parameterNumber = 0 
  local parameterType = 0
  for i, valueObject in ipairs (valueObjects) do
    local control  = valueObject:getControl ()
    parameterNumber = valueObject:getMessage():getParameterNumber ()
    parameterType   = valueObject:getMessage():getType ()
    print(string.format ("Parameter %d (origin %d, type %d) => Control '%s'.%s with midiValue %d"
       , parameterNumber, origin, parameterType, control:getName(), valueObject:getId(),value))
    print(string.format ("   Control has minimum value %d and maximum value %d"
       , control:getValue("min"):getMin(), control:getValue("max"):getMax() ))
    break
  end
end