Hydrogen is a software drum machine and pattern editor.

While it can export and play through MIDI, which is enough to play through my SR-16, it is not clear how one could record patterns and songs from Hydrogen.

As Hydrogen is much more comfortable for editing I'd like to explore the idea of using the SysEx MIDI extensions of the device in order to save patterns and songs into it.

Originally, I was thinking in converting the Hydrogen XML into sysex MIDI commands, however, after looking at the source code of the exporters to MIDI and Lilypond, it seems much easier to iterate over the in-memory song model.

Day 1

  • Spent on a different Hackweek project
  • Bought MIDI USB Adapter

Day 2

  • Spent on a different Hackweek project
  • Received MIDI USB Adapter

Day 3

Sending Pattern data from the SR-16

(from manual)

  • The source SR-16 should be in User Pattern mode and stopped. Connect the source SR-16 MIDI out to the destination SR-16 MIDI in.
  • Select the Pattern to be copied.
  • Press and hold the COPY button, and keep holding it down until step (5). The display says COPY TO PATT.
  • Do not enter any destination Pattern number—just press PLAY to send the data out over MIDI. The display says PATT OUT MIDI. The source SR-16's Pattern will end up in the receiving SR-16's currently selected Pattern location.

Testing it out

  • Change to pattern 6 in user mode

    amidi --port=hw:1,0,0 -r pat.syx
    139 bytes read
    
  • Change to pattern 7 in user mode

    amidi --port=hw:1,0,0 -s pat.syx
    

Restore works. It goes in the current selected pattern.

Interpreting the received data

    00000000  f0 00 00 0e 05 05 00 02  6e 00 36 40 07 10 00 21  |........n.6@...!|
    00000010  0c 20 29 1b 6c 36 59 00  6e 20 40 1c 0c 2b 02 4a  |. ).l6Y.n @..+.J|
    00000020  60 70 31 1d 36 05 15 41  60 62 58 14 56 07 03 55  |`p1.6..A`bX.V..U|
    00000030  07 30 21 2c 0e 06 15 41  25 30 38 18 4e 5b 02 0a  |.0!,...A%08.N[..|
    00000040  60 70 31 2c 0a 2b 03 41  6a 43 58 18 76 0f 7c 01  |`p1,.+.AjCX.v.|.|
    00000050  60 6a 58 10 56 07 03 09  6b 30 21 28 0a 29 03 40  |`jX.V...k0!(.).@|
    00000060  67 30 31 2c 0e 07 13 55  77 30 21 2c 0e 06 15 41  |g01,...Uw0!,...A|
    00000070  25 30 38 10 4e 5b 02 4e  40 51 48 1c 36 07 35 41  |%08.N[.N@QH.6.5A|
    00000080  6a 77 58 16 16 0f 78 78  00 13 f7                 |jwX...xx...|
    0000008b
  • SysEx Header f0 00 00 0e 05
  • Code for Copy Pattern, Drum or song 05
  • 00 02 6e 000000xxB x: MSB of number of unpacked bytes of data after header 0xxxxxxyB y: LSB of number of unpacked bytes of data after header 0yyyyyyyB if y_0, then x=x+1
  • Copy mode (pattern, in this case) 00
  • Data, packed as 8 MIDI bytes per 7 data bytes
  • Here should be a 0, for proper operation, but it is not
  • F7 (EOX)

  • Can't figure the number of unpacked bytes. I should have 16 blocks of 8 bytes (128) which should pack 16x7 bytes = 119 6e is 110 -> 1101110, but if I add the 0x2 of the next significant part I already get 101101110 -> 366 So definitely I am not getting it right

Day 4

  • Managed to unpack data

    // unpack data
    uint64_t block = 0;
    uint64_t block_decoded = 0;
    
    while (!is.eof()) {
        is.read((char*)&block, sizeof(uint64_t));
        block_decoded = block;
        // shift the most significant 64-k blocks to the right
        for (int k=7; k <= 49; k=k+7) {
            uint64_t mask = (((uint64_t)1 << k) - (uint64_t)1);
            block_decoded = ((block_decoded >> 1) & ~mask) | (block_decoded & mask);
        }
        cout << "enc: " << block << endl << "dec: " << block_decoded << endl;
        // now for each block:
        for (int i=0; i < 7; i++) {
            char byte = (block_decoded >> 8*i) & 0xFF;
            cout << bitset<8>(byte) << endl;
        }
        cout << endl;
    }
    
  • Unfortunately, still stuck with the data length encoding I should see 128 bytes (16 blocks) packaed -> 112 unpacked bytes But I am seeing a completely different number

Looking for hackers with the skills:

drums midi music qt qt5

This project is part of:

Hack Week 19

Activity

  • almost 5 years ago: dmacvicar started this project.
  • almost 5 years ago: dmacvicar added keyword "music" to this project.
  • almost 5 years ago: dmacvicar added keyword "qt" to this project.
  • almost 5 years ago: dmacvicar added keyword "qt5" to this project.
  • almost 5 years ago: dmacvicar added keyword "drums" to this project.
  • almost 5 years ago: dmacvicar added keyword "midi" to this project.
  • almost 5 years ago: dmacvicar originated this project.

  • Comments

    Be the first to comment!

    Similar Projects

    Software for musicians / guitarists and their integration in Aeon by fcrozat

    Description

    As a beginner in playing guitar, I'm discovering the wonderful world of music software on Linux.

    I'd like to spend time on listing which software is available for which purpose and see if they are working well in Aeon (either as Flatpak or RPM).

    I also want to dig deeper into Pipewire pro-audio handling.

    Goals

    List (or find a list) equivalent to "awesome list" Learn about pipewire pro-audio handling. Improve Aeon / Tumbleweed if needed

    Resources


    Create an Android app for Syncthing as part of the Syncthing Tray project by mkittler

    Description

    There's already an app but code/features already in Syncthing Tray could be reused to create a nicer app with additional features like managing ignore patterns more easily. The additional UI code for the app could then in turn be re-used by other parts of Syncthing Tray, e.g. to implement further steps in the wizard as requested by some users. This way one "UI wrapper codebase" could serve GNU/Linux, Windows and Android (and in theory MacOS) at the same time which is kind of neat.

    Goals

    • DONE: Learn more about development for Android and development of UIs with Qt Quick
    • DONE: Create an experimental app reusing as much existing Syncthing Tray code as possible
    • DONE: Build Syncthing as a library also for Android and use it in the app (already done but needs further testing and integration with the rest of the app configuration)
    • DONE: Update the Syncthing Tray website, documentation
    • Extend the app so it has at least a start page and an import that can cope with an export of the other app
    • Update forum thread
    • Upload an experimental build on GitHub
    • Extend the Syncthing API to download single files on demand (instead of having to sync the whole directory or use ignore patterns)

    Resources

    • Android SDK/NDK and emulator
    • Qt Quick


    YQPkg - Bringing the Single Package Selection Back to Life by shundhammer

    tl;dr

    Rip out the high-level YQPackageSelector widget from YaST and make it a standalone Qt program without any YaST dependencies.

    See section "Result" at the bottom for the current status after the hack week.

    The Past and the Present

    We used to have and still have a powerful software selection with the YaST sw_single module (and the YaST patterns counterpart): You can select software down to the package level, you can easily select one of many available package versions, you can select entire patterns - or just view them and pick individual packages from patterns.

    You can search packages based on name, description, "requires" or "provides" level, and many more things.

    The Future

    YaST is on its way out, to be replaced by the new Agama installer and Cockpit for system administration. Those tools can do many things, but fine-grained package selection is not among them. And there are also no other Open Source tools available for that purpose that even come close to the YaST package selection.

    Many aspects of YaST have become obsolete over the years; many subsystems now come with a good default configuration, or they can configure themselves automatically. Just think about sound or X11 configuration; when did you last need to touch them?

    For others, the desktops bring their own tools (e.g. printers), or there are FOSS configuration tools (NetworkManager, BlueMan). Most YaST modules are no longer needed, and for many others there is a replacement in tools like Cockpit.

    But no longer having a powerful fine-grained package selection like in YaST sw_single will hurt. Big time. At least until there is an adequate replacement, many users will want to keep it.

    The Idea

    YaST sw_single always revolved around a powerful high-level widget on the abstract UI level. Libyui has low-level widgets like YPushButton, YCheckBox, YInputField, more advanced ones like YTable, YTree; and some few very high-level ones like YPackageSelector and YPatternSelector that do the whole package selection thing alone, working just on the libzypp level and changing the status of packages or patterns there.

    For the YaST Qt UI, the YQPackageSelector / YQPatternSelector widgets work purely on the Qt and libzypp level; no other YaST infrastructure involved, in particular no Ruby (or formerly YCP) interpreter, no libyui-level widgets, no bindings between Qt / C++ and Ruby / YaST-core, nothing. So it's not too hard to rip all that part out of YaST and create a standalone program from it.

    For the NCurses UI, the NCPackageSelector / NCPatternSelector create a lot of libyui widgets (inheriting YWidget / NCWidget) and use a lot of libyui calls to glue them together; and all that of course still needs a lot of YaST / libyui / libyui-ncurses infrastructure. So NCurses is out of scope here.

    Preparatory Work: Initializing the Package Subsystem

    To see if this is feasible at all, the existing UI examples needed some fixing to check what is needed on that level. That was the make-or-break decision: Would it be realistically possible to set the needed environment in libzypp up (without being stranded in the middle of that task alone at the end of the hack week)?

    Yes, it is: That part is already working:

    https://github.com/yast/yast-ycp-ui-bindings/pull/71

    Go there for a screenshot

    That's already halfway there.

    The complete Ruby code of this example is here. The real thing will be pure C++ without any YaST dependencies.

    The Plan