Progress reverse engineering OPZ
patriciogonzalezvivo opened this issue · 6 comments
Hi! I want to thank you for the valuable documentation here. With it I manage to make some progress decoding the SYSEX messages from the OP-Z. Like for example:
My final goal is to be able to print the pattern do you happen to have an example on how to decompress the SYSEX 0x09 message for patterns using zlib?
@patriciogonzalezvivo you can double check, but I'm pretty sure sysex have the same structure as the project files. Have a look at my wiki on that: https://github.com/lrk/z-po-project/wiki/Project-file-format
Thanks @lrk ! definitely there are similarities. Notice that when changing the track quantize or note length one of the bytes match the "track chunk" byte offset https://github.com/patriciogonzalezvivo/opz/blob/main/src/OPZ.cpp#L151 that you point out on your documentation: https://github.com/lrk/z-po-project/wiki/Project-file-format#track-chunk
One thing I'm noticing is that the 8bits to/from 7bits conversion is making my scheme more complicated that it should. Any help will be appreciated.
Yes @lrk I can confirm that when changing the note length and quantize, it provides the address on memory of the pattern properties, consisting on 16 structs of the same track properties. one for every track
https://github.com/patriciogonzalezvivo/opz/blob/main/src/OPZ.cpp#L44
Making solid progress reverse engineering the OP-Z into a library 'libopz' and creating a terminal companion. But seam there are some messages I’m missin… Any idea how to sniff midi between a iOS and the OP-Z?. Here is the library so far (with some examples like this ncurses companion app https://github.com/patriciogonzalezvivo/libopz )
I used Bome MIDI Translator, set it up to forward BLE midi to and from the OP-Z and the app will connect to it fine.
Progress update, figurate how to get the entire patterns data and now I'm moving towards parsing the notes according to the data on the wiki https://github.com/lrk/z-po-project/wiki/Project-file-format#note-chunk
After following all the described data specs still can't make sense of the results. I just want to know when steps have active notes, but the duration, velocity, note and age doesn't seams to match what I have on my OP-Z
Maybe you guys can provide some feedback.
I'm using this example code to print all tracks on a pattern
This is how I'm mapping the notes to the tracks
const size_t opz_notes_offset_track[] = { 0, 2, 4, 6, 8, 12, 16, 24, 28, 29, 30, 31, 35, 41, 47, 51 };
size_t offset = _step * 55 + opz_notes_offset_track[_track];
This is how the index table look like
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16
KICK 0 55 110 165 220 275 330 385 440 495 550 605 660 715 770 825
SNARE 2 57 112 167 222 277 332 387 442 497 552 607 662 717 772 827
PERC 4 59 114 169 224 279 334 389 444 499 554 609 664 719 774 829
SAMPLE 6 61 116 171 226 281 336 391 446 501 556 611 666 721 776 831
BASS 8 63 118 173 228 283 338 393 448 503 558 613 668 723 778 833
LEAD 12 67 122 177 232 287 342 397 452 507 562 617 672 727 782 837
ARP 16 71 126 181 236 291 346 401 456 511 566 621 676 731 786 841
CHORD 24 79 134 189 244 299 354 409 464 519 574 629 684 739 794 849
FX1 28 83 138 193 248 303 358 413 468 523 578 633 688 743 798 853
FX2 29 84 139 194 249 304 359 414 469 524 579 634 689 744 799 854
TAPE 30 85 140 195 250 305 360 415 470 525 580 635 690 745 800 855
MASTER 31 86 141 196 251 306 361 416 471 526 581 636 691 746 801 856
PERFORM 35 90 145 200 255 310 365 420 475 530 585 640 695 750 805 860
MODULE 41 96 151 206 261 316 371 426 481 536 591 646 701 756 811 866
LIGHT 47 102 157 212 267 322 377 432 487 542 597 652 707 762 817 872
MOTION 51 106 161 216 271 326 381 436 491 546 601 656 711 766 821 876
From which I then can access different note properties:
Notes Duration
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16
KICK 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.39 -0.00 0.00 0.00 0.04 0.00
SNARE 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.39 -0.00 0.00 0.00 0.04 0.00
PERC 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.39 -0.00 0.00 0.00 0.04 0.00
SAMPLE 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.39 -0.00 0.00 0.00 0.04 0.00 0.00
BASS 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.39 -0.00 0.00 0.00 0.04 0.00 0.00
LEAD 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.39 -0.00 0.00 0.00 0.04 0.00 0.00 0.00
ARP 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.39 -0.00 0.00 0.00 0.04 0.00 0.00 0.00
CHORD 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.04 0.00 0.00 0.00 0.39 -0.00
FX1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.04 0.00 0.00 0.00 0.39 -0.00
FX2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.04 0.00 0.00 0.00 0.00 0.39 -0.00
TAPE 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.04 0.00 0.00 0.00 0.39 -0.00 0.00
MASTER 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.04 0.00 0.00 0.00 0.39 -0.00 0.00
PERFORM 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.04 0.00 0.00 0.00 0.00 0.39 -0.00 0.00
MODULE 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.04 0.00 0.00 0.00 0.00 0.39 -0.00 0.00 0.00
LIGHT 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.39 -0.00 0.00 0.00 0.04
MOTION 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.39 -0.00 0.00 0.00 0.04 0.00
Notes Note
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16
KICK 00 00 22 00 39 40 00 00 02 05 10 00 00 00 00 27
SNARE 01 05 10 00 00 00 2B 00 3C 40 00 00 01 05 10 00
PERC 3C 40 00 00 01 05 10 00 00 00 26 00 3C 40 00 00
SAMPLE 00 22 00 39 40 00 00 02 05 10 00 00 00 00 27 00
BASS 05 10 00 00 00 2B 00 3C 40 00 00 01 05 10 00 00
LEAD 22 00 39 40 00 00 02 05 10 00 00 00 00 27 00 3C
ARP 00 00 01 05 10 00 00 00 26 00 3C 40 00 00 01 05
CHORD 39 40 00 00 02 05 10 00 00 00 00 27 00 3C 40 00
FX1 01 05 10 00 00 00 26 00 3C 40 00 00 01 05 10 00
FX2 00 00 27 00 3C 40 00 00 01 05 10 00 00 00 26 00
TAPE 40 00 00 02 05 10 00 00 00 00 27 00 3C 40 00 00
MASTER 05 10 00 00 00 22 00 39 40 00 00 02 05 10 00 00
PERFORM 00 27 00 3C 40 00 00 01 05 10 00 00 00 26 00 3C
MODULE 27 00 3C 40 00 00 01 05 10 00 00 00 26 00 3C 40
LIGHT 00 3C 40 00 00 01 05 10 00 00 00 26 00 3C 40 00
MOTION 01 05 10 00 00 00 2B 00 3C 40 00 00 01 05 10 00
Notes Velocity
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16
KICK 10 41 00 00 FF 01 05 10 41 00 00 FF 01 05 10 41
SNARE 01 05 10 41 00 00 FF 01 05 10 41 00 00 FF 01 05
PERC 00 FF 01 05 10 41 00 00 FF 01 05 10 41 00 00 FF
SAMPLE 41 00 00 FF 01 05 10 41 00 00 FF 01 05 10 41 00
BASS 05 10 41 00 00 FF 01 05 10 41 00 00 FF 01 05 10
LEAD 00 00 FF 01 05 10 41 00 00 FF 01 05 10 41 00 00
ARP 01 05 10 41 00 00 FF 01 05 10 41 00 00 FF 01 05
CHORD FF 01 05 10 41 00 00 FF 01 05 10 41 00 00 FF 01
FX1 10 41 00 00 FF 01 05 10 41 00 00 FF 01 05 10 41
FX2 05 10 41 00 00 FF 01 05 10 41 00 00 FF 01 05 10
TAPE 01 05 10 41 00 00 FF 01 05 10 41 00 00 FF 01 05
MASTER FF 01 05 10 41 00 00 FF 01 05 10 41 00 00 FF 01
PERFORM 10 41 00 00 FF 01 05 10 41 00 00 FF 01 05 10 41
MODULE 41 00 00 FF 01 05 10 41 00 00 FF 01 05 10 41 00
LIGHT 00 00 FF 01 05 10 41 00 00 FF 01 05 10 41 00 00
MOTION 01 05 10 41 00 00 FF 01 05 10 41 00 00 FF 01 05
Notes Age
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16
KICK 01 05 10 41 00 00 FF 01 05 10 41 00 00 FF 01 05
SNARE 00 FF 01 05 10 41 00 00 FF 01 05 10 41 00 00 FF
PERC 41 00 00 FF 01 05 10 41 00 00 FF 01 05 10 41 00
SAMPLE 05 10 41 00 00 FF 01 05 10 41 00 00 FF 01 05 10
BASS FF 01 05 10 41 00 00 FF 01 05 10 41 00 00 FF 01
LEAD 10 41 00 00 FF 01 05 10 41 00 00 FF 01 05 10 41
ARP 00 FF 01 05 10 41 00 00 FF 01 05 10 41 00 00 FF
CHORD 00 00 FF 01 05 10 41 00 00 FF 01 05 10 41 00 00
FX1 01 05 10 41 00 00 FF 01 05 10 41 00 00 FF 01 05
FX2 FF 01 05 10 41 00 00 FF 01 05 10 41 00 00 FF 01
TAPE 00 FF 01 05 10 41 00 00 FF 01 05 10 41 00 00 FF
MASTER 00 00 FF 01 05 10 41 00 00 FF 01 05 10 41 00 00
PERFORM 01 05 10 41 00 00 FF 01 05 10 41 00 00 FF 01 05
MODULE 05 10 41 00 00 FF 01 05 10 41 00 00 FF 01 05 10
LIGHT 10 41 00 00 FF 01 05 10 41 00 00 FF 01 05 10 41
MOTION 00 FF 01 05 10 41 00 00 FF 01 05 10 41 00 00 FF
@lrk do this looks ok to you? Do you know of a simpler way to get know what steps are active in each track?