Control SRC slot on Digitakt

Hi everyone,

I’m trying to control the slot of my Digitakt for an automated live set from a custom app on my raspberry-pi.

I’m not sure how to read the documentation : it says page 72 that the Sample Slot can be accessed using the CC MSB 19 and the MSL LSB of the NRPN are 1 and 3.

Does it mean that we can’t access those parameters because they are not assigned?

Or is there a way to create some sort of mask and send packages to it?

I’m using a midi library for openframeworks, and manages to trigger the 8 channels, with control over velocity and height.

I saw this post about it, and @DreamXcape has maybe some solution for me? :slight_smile:

Best,

P

Alright I sorted it.

Thanks to some good references online :
[elektronauts link](Alright I sorted it.

Thanks to some good references online :
elektronauts link,
somascape,
midi specs for Elektron,
digitakt documentation.

So I sent this message, and it changed the src slot to the number 5 :

 vector<unsigned char> sysexMsg;
        
        // F0
        sysexMsg.push_back(MIDI_SYSEX);
        // elektron manufacturer ID :
        // 00 20 3C
        sysexMsg.push_back(0x00);
        sysexMsg.push_back(0x20);
        sysexMsg.push_back(0x3C);
        
        // channel 0
        sysexMsg.push_back(0x00);
        
        // 19 for sample Slot
        // from
        // https://www.elektron.se/wp-content/uploads/2019/06/Digitakt-User-Manual_ENG.pdf
        // page 72
        
        // change Sample slot to 5th slot
        // B0 -> CC
        // 13 -> Sample Slot (18)
        // 05 -> sample set to 5th
        sysexMsg.push_back(0xB0);
        sysexMsg.push_back(0x13);
        sysexMsg.push_back(0x05);
        
        // Data Entry MSB to 0
        // B0 -> CC
        // 06 -> Most Significant Bit
        // 00 -> set to 0
        sysexMsg.push_back(0xB0);
        sysexMsg.push_back(0x06);
        sysexMsg.push_back(0x00);
        
        // Data Entry LSB to 0
        // B0 -> CC
        // 06 -> Least Significant Bit
        // 00 -> set to 0
        sysexMsg.push_back(0xB0);
        sysexMsg.push_back(0x26);
        sysexMsg.push_back(0x00);

        sysexMsg.push_back(MIDI_SYSEX_END);
        
        midiOut.sendMidiBytes(sysexMsg);

I set the MSB and LSB to 0 as it doesn’t seem to affect.

I’ll release a bridge app once it’s done and ready for other to play with.

Best,

P

3 Likes

Hmm, Raspberry Pi controlling SRC on the Digitakt!

That’s a brilliant idea! I need to poke around with raspberry Pi myself and a device solely dedicated to src on Digitakt is the best beginner project I think!

Thanks for the inspiration and the documentation! I look forward to seeing how your project progresses!

Ok, so the control of the sample slot is working.

I’ll make a control panel for the rest of the parameters accessible in midi, for whoever is interested.

I have tested on my MAC with Mojave ( 10.14.6), and the Digitakt 1.11 firmware. ( will publish the code open source once once full app is done and compile it for other platforms).

Link to Download
( this is just a link to my website, nothing doggy : http://codingcoolsh.it/Digitakt/SampleSlotControl.app.zip ).

Best,

P

2 Likes

You could simply use CC# 19 for Sample Slot on each channel.

Or you could use the NRPN from the manual.

But since the Sample Slot parameter has only 128 positions, CC’s are preferred because a single NRPN message requires 4 times the data (12 bytes vs 3 bytes for CC).

2 Likes

Ok,

I have a pretty much managed.
But I still can’t really change the negatives float, not sure how to really.

If anyone is interested, it’s here :

( there is a pre compiled version for MAC OS but no Raspberry-pi yet).

There is a couple of bugs to solve, but the core settings is working.

Best,

P

2 Likes

If you want high resolution control you have to use NRPN.
The Digitakt manual is a bit confusing on the subject.

An NRPN message is made up out of 4 CC messages.
If for instance, you want to change Filter Frequency on Channel 1 it goes like this:

  • The first message is Channel 1, CC# 99, with value of NRPN MSB mentioned in the manual(1).
    (0xB0, 0x63, 0x01)
  • The Second message is Channel 1, CC# 98, with value of NRPN LSB mentioned in the manual(20).
    (0xB0, 0x62, 0x14)
  • Third message is Channel 1, CC# 6, MSB value you want to send.
    (0xB0, 0x06, MSB value)
  • Fourth message is Channel 1, CC# 38, LSB value you want to send.
    (0xB0, 0x26, LSB value)

The MSB and LSB values together represent a value from 0 to 16383 (MSB * 128 + LSB).

Good luck with your app :slightly_smiling_face:

3 Likes

Ok amazing, this is now sorted.

Thanks to @DreamXcape!

Will patch up the rest now.
++

2 Likes

Ok, I have finished patching the code.

The way the Digitakt works is how you described it @DreamXcape, but it also requires to "run the status in effect " :

0xB0
0x63 // MSB
0x7F

0xB0
0x62 // LSB
0x7F

and this needs to be added at the end of each NRPN command - as far as I’ve experienced it -.

MSB and LSB are constructed with the MSB for the integer value, and LSB for the decimal value. For example for an LFO Speed value of -35.4898 :
MSB codes the -35.
LSB codes 0.4898.

-35 in this case needs to be remapped from the scale of the Lfo : (-64, 63), to the map of the NRPN scale (0, 127), then transformed into hexadecimal.
So : -35 -> 28 -> 0x1C

0.4898 will be remapped from scale (0, 1), to NRPN scale (0, 127), then into hexa.
So : 0.4898 -> 65 -> 0x41

Hope this helps others with the Digitakt.

++

1 Like

Close, but incorrect.
I have no idea what you mean by “run the status in effect”, but the messages you quoted should’nt do anything at all:

0xB0  // Signals a Control Change message on Channel 1
0x63  // Control Change 99 (NRPN MSB), this is the same for every NRPN message
0x7F  // Value 127
         This now signals NRPN MSB of 127 (essentially NRPN Bank 127)

0xB0  // Signals a Control Change message on Channel 1
0x62  // Control Change 98 (NRPN LSB), also the same for every NRPN message
0x7F  // Value 127
         This now signals NRPN LSB of 127 (essentially NRPN Message number 127)

Since you’re already on bank 127, you’re telling the Digitakt to change NRPN number 16383.
(Bank 127, Control 127)
This is because

> NRPN = NRPN-MSB * 128 + NRPN-LSB
> in your message, this would be:
> 127 * 128 + 127 = 16383

NRPN control number 16383 doesn’t exist so the Digitakt will probably just ignore this.

A complete NRPN message for Channel 1, LFO Speed: -35.49 would be:

0xB0  // Control Change Channel 1
0x63  // Control Change Number 99 (NRPN MSB), same for every NRPN message
0x01  // NRPN Control MSB, for LFO Speed this value is 1 (0x01),
         as quoted in the Digitakt manual under LFO Speed NRPN MSB
0xB0  // Control Change Channel 1
0x62  // Control Change Number 98 (NRPN LSB), same for every NRPN message
0x20  // NRPN Control LSB, for LFO Speed this value is 32 (0x20),
         as quoted in the Digitakt manual under LFO Speed NRPN MSB
0xB0  // Control Change Channel 1
0x06  // Control Change Number 6 (DATA Entry MSB), same for every NRPN message
0x1C  // NRPN Control DATA MSB, this is where you put your course value.

0xB0  // Control Change Channel 1
0x26  // Control Change Number 38 (DATA Entry LSB), same for every NRPN message
0x41  // NRPN Control DATA LSB, this is where you put your decimal value.

This is also exactly what the Digitakt sends back for that value.

Now the confusing part.
This also works:

// Set Control Number to use
0xB0 0x63 0x01
0xB0 0x62 0x20
// From this point forward, CC 6 and CC 38 can be use for LFO Speed
0xB0 0x06 0x1C
0xB0 0x26 0x41
// LFO Speed is now -35.49
0xB0 0x06 0x50
0xB0 0x26 0x00
// LFO Speed is now 16
0xB0 0x06 0x52
0xB0 0x26 0x16
// LFO Speed is now 18.17

While the above also works on most equipment, it’s a bad idea.
As soon as you try to change more then 1 parameter (on the same channel, at the same time), this won’t work anymore.

That’s why a NRPN message is always 4 MIDI CC messages long.
Also, CC numbers 99, 98, 6 and 38 are part of the MIDI spec. and reserved for NRPN on almost all hardware.
In short, the example above should be:

0xB0 0x63 0x01, 0xB0 0x62 0x20, 0xB0 0x06 0x1C, 0xB0 0x26 0x41
// LFO Speed is now -35.49
0xB0 0x63 0x01, 0xB0 0x62 0x20, 0xB0 0x06 0x50, 0xB0 0x26 0x00
// LFO Speed is now 16
0xB0 0x63 0x01, 0xB0 0x62 0x20, 0xB0 0x06 0x52, 0xB0 0x26 0x16 
// LFO Speed is now 18.17

You get the right values for the coarse and decimal mapping, but the explanation seems a bit off.
0.49 doesn’t translate to 65, but to 63.
0.51 translates to 65.
-0.49 translates to 65 because the split values would actually be -1.00 and +0.51.

That’s why it’s easier to handle control inside software as integer range 0-16383 with 8192 as the exact half-way point, or -8192 to 8191, with 0 as the half-way point if you will.
If you plan on doing more with the values than just sending them this is a lot easier to handle. Splitting values would best only be done before sending them over MIDI or displaying them in a UI.

I hope this clears things up a bit for everyone making cool apps and stuff :slightly_smiling_face:

So… Long post… Gonna do some of my own MIDI stuff now… :wink:

1 Like

Hi @DreamXcape!

Thanks for the long post, I guess you seem to know more than me on this, i appreciate you spending time to clarify!

update : Well yes it’s not needed. thanks for the help.

Ah yeah I’m glad I got the scale right, because it took me some time to figure that one out, I guess i messed up my math somehow, lol.

Ah, well I’m not planning on re-mapping the float values, but I take good notes of this comment as maybe I will use it some day.

Thanks for the help, :).

Best,

P

I read the information on the site you linked.
The "running status in effect is this:
“It is recommended that the Null Function (RPN 7F,7F) should be sent immediately after a RPN or NRPN and its value are sent.”
A Null Function to disable the last assigned NRPN and release CC 6 and 38.
So I guess I learned something new about midi :slightly_smiling_face:

I still think it’s a useless function and probably not supported by all hardware, but it is in the midi spec. so technically a valid option.

I call it useless because it makes no sense to implement it.
Let’s take their recommendation and put it behind every NRPN message in my last example:

0xB0 0x63 0x01, 0xB0 0x62 0x20, 0xB0 0x06 0x1C, 
0xB0 0x26 0x41, 0xB0 0x63 0x7F, 0xB0 0x62 0x7F
// LFO Speed is now -35.49
0xB0 0x63 0x01, 0xB0 0x62 0x20, 0xB0 0x06 0x50,
0xB0 0x26 0x00, 0xB0 0x63 0x7F, 0xB0 0x62 0x7F
// LFO Speed is now 16
0xB0 0x63 0x01, 0xB0 0x62 0x20, 0xB0 0x06 0x52,
0xB0 0x26 0x16, 0xB0 0x63 0x7F, 0xB0 0x62 0x7F
// LFO Speed is now 18.17

That just gives you 6 extra bytes per message for no good reason, adding 2 milliseconds of transfer time over a MIDI DIN Connection(for a whopping 6ms total per NRPN message).
Why would you want to release the control that’s gonna get re-assigned anyway as soon as the next NRPN message arrives?
In the example above, CC 6 and 38 get assigned and released 3 times(for the same control).

The only thing that makes sorta sense is this:

0xB0 0x63 0x01, 0xB0 0x62 0x20, 0xB0 0x06 0x1C, 0xB0 0x26 0x41
// LFO Speed is now -35.49
0xB0 0x06 0x50, 0xB0 0x26 0x00
// LFO Speed is now 16
0xB0 0x06 0x52, 0xB0 0x26 0x16
// LFO Speed is now 18.17

This method actually reduces the amount of data by more than half.
But this is still kind of a bad idea because of the single control restriction.
To make this work, you would have to continuously keep track of every control that gets sent.
And if a hardware device gets input from multiple sources or a midi-merger is part of the chain, there is no reasonable way to keep track of that.

So I guess this is still the way to go:

0xB0 0x63 0x01, 0xB0 0x62 0x20, 0xB0 0x06 0x1C, 0xB0 0x26 0x41
// LFO Speed is now -35.49
0xB0 0x63 0x01, 0xB0 0x62 0x20, 0xB0 0x06 0x50, 0xB0 0x26 0x00
// LFO Speed is now 16
0xB0 0x63 0x01, 0xB0 0x62 0x20, 0xB0 0x06 0x52, 0xB0 0x26 0x16 
// LFO Speed is now 18.17

That’s probably why most midi device works like this.

It’s still a very interesting topic, not bad for a protocol from 1982 :smiley:

2 Likes

I’m very interested.
Are digitakt sysex information available somewhere?