g200kg/zoom-ms-utility

Setting up tempo in BPM

Opened this issue · 23 comments

Hi!
Is there no way at all for setting up patch tempo in BPM other than tapping the button on the pedal? I have CDR-70 and it can get pretty annoying to tap tempo if you need a specific BPM, especially faster tempos.
The BPM value is stored within a patch, so there must be someway to send it via midi, am I wrong?

The problem is that changing BPM is not supported in this particular zoom ms utility, and also in ToneLib Zoom, and the tempo value resets to 120 after export/import patch procedure.

hi there.
I have added ability to read in BPM from command line and patch the sysex file into my github https://github.com/shooking/ZoomPedalFun

It is under the MS70CDR folder.
The code is written in C++ but I will add Python variant soon.
You should be able to compile it on a Mac, PC with g++ or Raspberry Pi.

make

USAGE:

There are shell scripts that should work on a Pi provided you install mido, rtmidi etc.
OR you can grab a sysex file from your g200kg program - one at a time please.
Let's say your patch is stored in currentPatch.bin

./MS70CDRPatchTempo currentPatch.bin 55

will write out NEWTEMPO.bin that is "as is" but with a tempo of 55.
You can choose between 40 and 250 as per spec.

hi there. I have added ability to read in BPM from command line and patch the sysex file

Hi! I'm sorry, but I can't understand what you are talking about. I have all the patches in *.70cdr format.
Could you please explain how can I write the tempo in a *.70cdr file?

No idea what that format means. Can you post and example and I will take a look. How did you generate the file in 1st place? My tool assumed you grab current patch in binary format. The commands on how to do this are in the MS70CDR directory of my repo

So to use my code you have a computer hooked up to your MS70CDR
Put it in editor mode
request current patch
store that as, say, currentPatch.bin
load that into my program .. and that will allow you to reset the BPM

https://github.com/shooking/ZoomPedalFun/tree/main/MS70CDR

make clean all

EditorOn.sh
move to your fave patch
GetCurrentPatch.sh
-- default stores in currentPatch.bin
MS70CDRPatchTempo currentPatch.bin 100

will set new tempo to 100 bpm stored in NEWTEMPO.bin

rename that to whatever you want it to be.
Navigate to a slot on the pedal, send your renamed file back to the MS70CDR.

If you attach a 70cdr file here and let me know the tempo then maybe I can work out the format and add code to convert that.

@shooking , *.70cdr file is what you get when you press "Export patch to file" or "Export bank file" button in this utility:

https://g200kg.github.io/zoom-ms-utility

But as I have noticed, the patch stored with this file doesn't contain BPM information. So if you export a patch to the computer, and then import it again into Zoom, the BPM data will be lost and the patch will have the default BPM value (120).

I still don't understand how to use your scripts, do I have to install some apps?

I made a video a while back - https://www.youtube.com/watch?v=V5biaafMq7c
I explain the background etc - 1:30 onwards show how my scripts (on a Pi4) work.
But- they are just sending sysex. So you can do this from Mac, Windows whatever - provided you can send sysex (on Windows you could use MidiOx).

Please attach a typical 70cdr file here and I ideally make a note of the tempo on the pedal when you dumped it.
Likely there are a couple of bytes that need to be patched.

@shooking ok, here is a Delay140.70cdr file with a patch exported from my MS-79CDR pedal. My bpm was 140. But I don't think that the file contains my BPM information. Because when I import it back to the pedal, BPM becomes 120.
The file is in a zip archive, because I can't attach this kind of file here.

Delay140.zip

A common problem with the two editors that are using this file format (g200kg/zoom-ms-utility and ToneLib Zoom) is that when I do any operation with the patch e.g. copy-paste, export-import or even rename — the patch BPM is gone and is replaced with 120

ha ha - so it seems to be an ASCII version of the bytes
image

So if you have a Linux system (or Mac, or WSL on Windows)

xxd -p -r Delay140.70cdr > Delay140.bin

That converts it to a "proper" binary patch

image

 ./MS70CDRPatchUnpack000 Delay140.bin

NumFX Seen =  1 Cursor Position 2
TapTempo = 120 (78)
05 0f

So for sure the tempo is 120 bpm

Let's change that to say 150?

./MS70CDRPatchTempo Delay140.bin 150
...
   00 00 00 00 c5 12 44
04 00 00 00 00 45 12 44
   65 6c 61 79 31 34 30
00 65 6c 61 79 31 34 30
3 left.
Writing file NEWTEMPO.bin

Let's look at NEWTEMPO.bin

NumFX Seen =  1 Cursor Position 2
TapTempo = 150 (96)
c5 12

92 bytes in, 7a bytes out
OUTPUT
00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11
11 00 00 d0 f4 79 00 19 a0 00 40 06 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 c5 12 44 65 6c 61 79 31 34 30 20 20 00

NEWTEMPO.zip

and it is done.

Oh, thanks, @shooking
Now I see where is the BPM value located in this file. Too bad that even when I change this "05 0f" value to "c5 12" and try to send it back via g200kg/
zoom-ms-utility
to Zoom, the tempo is reset to 120 again. Although other values like preset name I can change.

So now my problem is that I can't send this preset to Zoom. I just don't understand how you do all this coding stuff, I've installed Midi-OX, but can't understand how to receive and send back patches to Zoom with it.

And other problem is I don't understand how do you convert 120 to "05 0f" and 150 to "c5 12".
I can understand that 120=0x78 and 150=0x96, but how do you get "05 0f" and "c5 12"?

@g200kg Hi! Could you please make an update to the utility, so it would be possible not to lose the BPM everytime doing any operations with the patches. And maybe even to define the patch BPM in the utility. That would be very nice.

@superslonic - please find a YouTube video I made
https://youtu.be/2lCYFmX8gf4

This shows me taking the file I modified and loading it into the MS70CDR. I didnt edit out my mistake - but you get the idea I hope.

I forgot what a PITA it is to see the tempo on these things :-)

Oh, thanks, @shooking Now I see where is the BPM value located in this file. Too bad that even when I change this "05 0f" value to "c5 12" and try to send it back via g200kg/ zoom-ms-utility to Zoom, the tempo is reset to 120 again. Although other values like preset name I can change.

So now my problem is that I can't send this preset to Zoom. I just don't understand how you do all this coding stuff, I've installed Midi-OX, but can't understand how to receive and send back patches to Zoom with it.

And other problem is I don't understand how do you convert 120 to "05 0f" and 150 to "c5 12". I can understand that 120=0x78 and 150=0x96, but how do you get "05 0f" and "c5 12"?

if you look at the file format in my "unpacked" space you can work out there is a bit packing going on.
so the 05 0f gets turned in f0 ... we should really look at the value as 0f05 and 12c5 ... and hence 0f0 and 12c

0xf0 = 240 ... to get tempo we divide by 2 (right shift 1) = 120
0x12c = 300 .. / 2 = 150

From midiox you can send sysex commands - best to turn on editor 1st

See also
https://github.com/shooking/ZoomPedalFun/wiki/De-re-MS-70-CDR

Specifically you type in the string into the sysex box in MidiOX, then send / receive (if you expect something back)

Identify f0 7e 00 06 01 f7 f0 7e 00 06 02 52 61 00 00 00 32 2e 31 30 f7 ****Universal String responds with model ID and firmware version. In this case 2.13
NumPatches f0 52 00 61 07 f7 f0 52 00 61 06 32 00 7a 00 f7 0x32 = 50..num patches on pedal 0x7a=122 patch size
EditorOn f0 52 00 61 50 f7   Turn Editor mode on so Zoom pedal spits out some content

so if you send the identity request you should receive back the "0x61" for a MS70CDR

send "0x50" to turn on editor mode - then when you move knobs a stream of data comes back.

To get the current patch

GetCurrentPatch F0 52 00 61 29 F7 F0 52 00 61 28 ... data ... F7 Returns current patch in raw format. More on this later

etc etc

The reason I use a Pi4 / Python is because it is much easier for me to send data to/from the pedal via programs.
Pi4 used to be cheap.
My current project - hardware control of a B1XFour - is using an ESP32 to control the B1XFour (one has to solder wires to innards) and bluetooth to "air turn" pages on my tablet.

I hope to work on other pedals like this MS70 CDR in the near future - all the designs will be open source.

Capturing data from my MS70cdr via midi ox I realized that changing the bpm via tap tempo changes the highlighted bytes, but I don't understand the increment and decrement logic. the following patches are at 40 bpm and 150 bmp respectively

40 Bpm
F0 52 00 61 28 08 49 06 00 64 03 14 00 20 00 70 10 40
41 06 00 04 00 00 00 00 61 01 00 09 10 00 64 00 22 10
70 00 31 11 70 00 00 00 00 05 00 11 00 00 32 03 5C 08
00 0B 60 62 13 00 00 00 00 00 00 00 00 11 00 21 00 30
03 00 00 19 20 00 10 40 16 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 11 05 53 00 6F 6C 6F 20 20 20 20 00 60 20
00 F7

150bpm
F0 52 00 61 28 08 49 06 00 64 03 14 00 20 00 70 10 40
41 06 00 04 00 00 00 00 61 01 00 09 10 00 64 00 22 10
70 00 31 11 70 00 00 00 00 05 00 11 00 00 32 03 5C 08
00 0B 60 62 13 00 00 00 00 00 00 00 00 11 00 21 00 30
03 00 00 19 20 00 10 40 16 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04
00 00 00 00 51 12 53 00 6F 6C 6F 20 20 20 20 00 60 20
00 F7

when activating the foot to generate the tap tempo, I read the following command in the midiox F0 52 00 61 31 03 08 16 01 F7 but if I send only this command it does not work

in response to the command quoted via foot, the device returns two commands in sequence
F0 52 00 61 32 01 00 00 01 00 00 00 00 00 F7 (this generates a forced recording of the patch)
and
F0 52 00 61 00 00 F7

I know @AndersonAOS - if you check out my YT I explored this.
Zoom's midi is incomplete. They get a bit better at it with each new pedal.
Look at the code on my git - you can see how I do it. IMHO you are looking in the wrong space - 7 bit sysex. It is much easier to look at the "on pedal" 8 bit space - and even then the packing is a bit obscure. I have provided the source for how I do it.

Since I have other Zoom pedals I tend to stick with those that are more complete (midi wise). My pedals of choice are G5n and B1XFour - the latter I am turning into a pedal board.

If I get time I will try to see what can be exposed on these older pedals.

If you find any sysex missing from my page please let me know and I will update it.

"IMHO you are looking in the wrong space - 7 bit sysex. It is much easier to look at the "on pedal" 8 bit space - and even then the packing is a bit obscure. I have provided the source for how I do it."

Sorry but I can't understand how to look in 8 bit and how I'm looking in 7 bit. I really apologize for my ignorance. I only have these readings via MidiOX and I see these bytes being changed. is all i can see.

You aren't being ignorant my friend. The sysex standard has 8 bit for start stop then 7 bit for rest.

The device can have much larger bits. They get unpacked to allow transfer over sysex.

What I do is to take the sysex and convert it to internal Zoom format. Look at my unpack code. If you don't do this then you will have to account for every 8th byte that has 0 top bit and a 1 in bit position of byte - the 7 bits tell you if to add 128 to a byte.

When you look in this space it is easier to see which bits truly are modified by tempo. I pointed them out in earlier reply. Trying to patch the raw sysex coming back is possible but much harder.

Run my C program under a debugger to see what it is doing.
1 - ask for a patch
2 - get raw sysex
3 - unpack it (in my language)
The byte count it roughly 7/8 size of sysex.
This is the space to look for bit patterns.
Modify in that space
4 - pack it (in my language) back into sysex
5 - send that back to the pedal.

Hope it makes sense. I am not trying to be clever - just hoping you see it because it illuminates what a lot of manufacturers do.

Best regards
Steve

@superslonic - please find a YouTube video I made https://youtu.be/2lCYFmX8gf4

This shows me taking the file I modified and loading it into the MS70CDR. I didnt edit out my mistake - but you get the idea I hope.

I forgot what a PITA it is to see the tempo on these things :-)

Thank you! Now I can send and receive those messages to my Zoom.

@shooking I'm sorry, but I still don't understand all this packing-unpacking stuff.

I tried to figure out how to define the BPM value in a patch with the help of this manual. And I have even found a working method, but it seems to work only with my simple one-effect delay patches.

so the 05 0f gets turned in f0 ... we should really look at the value as 0f05 and 12c5 ... and hence 0f0 and 12c

0xf0 = 240 ... to get tempo we divide by 2 (right shift 1) = 120 0x12c = 300 .. / 2 = 150

And this is still beyound my understanding

Let me make a video next week and post it. How are your coding / math skills? Just so o know what level to pitch it. On my ZoomPedalFun site - on the landing page - search for Phil D Thrill (maybe just phil) - he made nifty pedal in raw sysex space.

But I assert it is MUCH easier to see what is going on in 8 bit space.

I will try to show how whilst trying to make it interesting. Might be tough.

Let me make a video next week and post it. How are your coding / math skills? Just so o know what level to pitch it.

That would be great! I have no programming skills at all. I mean I had some programming at school, but it was very long ago.

All last week I had been trying to install all those things (python, rtmidi) on my windows 10, but I'm getting errors all the time.
So I still cannot use your scripts.

It seems to me I finally understood how to define tempo. I found a little mistake in this manual in this part:

Screenshot (7)

In fact tempo bits 2 and 1 are first byte's bits 7 and 6 respectively. Not bits 3 and 2, as it's written there.

And when I realised that, everything became clear to me.

So, this is how you can set up a new tempo in a given patch:

Three bytes are responcible for the BPM in a patch, here they are:

Screenshot (8)

For this patch (the factory 01 C-D-R preset) they are 00 11 0F, which indicates the tempo of 120 BPM.
But how does in the world "00 11 0F" mean 120 BPM?
I'll try to explain.

The point is that two of those bytes (00 and 11) contain not only BPM information but also something else. And to edit just the tempo we have to deal with the binary values, not hexadecimal.

Let's convert them to binary (7 digits):
00 = 0000000
11 = 0010001
0F = 0001111

Now we take the first five bits (from the right) of the third byte (0F = 0001111), so we have 01111.
Then we take the third bit (also from the right) of the first byte (00 = 0000000), we have 0.
And finally we take bits 7 and 6 (counting from the right) of the second byte (11 = 0010001), we have 00.

Now we put them together exactly in that order: 01111 , 0 , 00
We have a 8-digit binary value 01111000
Let's convert it to decimal: 01111000=120

Voilà!

So to set new tempo we have to convert the three bytes from the given patch to binary, change only these specific bits values according to the new BPM, and then convert them back to hexadecimal and then send the new patch code to Zoom. For me it worked perfectly with all the effects.

If we try to edit just the hexadecimal values of the bytes, we can damage the rest information of the patch that doesn't relate to BPM.

And now let's say we want to set new tempo of 149 to our patch.
First convert 149 from decimal to binary (it has to be an 8-digit value, for slower tempos just add zeros on the left).
149=10010101
Break this value into parts as mentioned above (five, one, two digits) : 10010 , 1 , 01

The first part (10010) goes to the first 5 bits (from the right) of the Third "tempo" byte. In our patch with the tempo 120 it was 0F = 0001111. We change only the first 5 bits: 0010010 and convert it to hex 0010010=12

The second part (1) goes to the 3rd bit (from the right) of the First "tempo" byte. It was 00 = 0000000 with 120 BPM, now it becomes 0000100. It's important to change only this one bit, because in other patches not necessarily all the rest bits will be zeros, so we will have to keep them and change only one bit. Convert 0000100 to hex =04

The last part (01) goes to bits 7 and 6 of the Second "tempo" byte. This byte always contains other bits that we have to keep. For 120 BPM it was 11 = 0010001, so we put in bits 7 and 6: 0110001 and convert to hex 0110001=31

So, we have the three bytes that will change our patch to the new tempo of 149.
They are 04 , 31 , 12

And here is a little illustration to make it more clear:
(Important: we must change only these highlighted bits, all the other bits must remain what they were in the patch that we modify tempo in.)
photo_2023-04-04_15-49-29

I've made this little converter in a spreadsheet format. I use it with MIDI-OX.

ZoomMS-70CDR_PatchBPM_Editor.ods

It works good in LibreOffice Calc, didn't test it in Excel.