tttapa / Control-Surface

Arduino library for creating MIDI controllers and other MIDI devices.
GNU General Public License v3.0
1.24k stars 139 forks source link

Midi Button types CC vs Note #316

Closed digimbyte closed 3 years ago

digimbyte commented 3 years ago

I hate to bother but I'm no midi expert, and I don't know what to google or search for.

but to my knowledge, a Midi Note, fires once while CC is continious?

I'm interested in playing a note while a button is pressed but the only things I can find is {note(C, 4), CHANNEL_1} { MIDI_CC::General_Purpose_Controller_1, CHANNEL_1}

I also want to be able to shift the notes up/down octaves if possible with a potentiometer, to allow it to play in b/flat or C major, etc It's like an electrik keyboard with 24 keys, or 3 octaves and shifting the note up and down would be great. I also need volume modifiers on the notes, but I'm sure that's done in the synthesiser side

tttapa commented 3 years ago

but to my knowledge, a Midi Note, fires once while CC is continious?

There is no "continuous" in digital systems.
Control Change buttons send a MIDI Control Change message with a value of 127 when they're pressed, and with a value of 0 when they're released.
Similarly, Note buttons send a MIDI Note On event when pressed, and a Note Off event when released.

If you just want something like a piano key, NoteButton is the right choice. CCButton can be useful for controlling settings in your DAW, for instance.

You can use the MIDI debug interface to try this out for yourself. Upload the following code, and observe the output in the serial monitor (@ 115200 baud).

#include <Control_Surface.h> // Include the Control Surface library

// Instantiate a MIDI over USB interface.
USBDebugMIDI_Interface midi = 115200;

using namespace MIDI_Notes;
NoteButton notebutton = {
  5,                       // Push button on pin 5
  {note(C, 4), CHANNEL_1}, // Note C4 on MIDI channel 1
};
CCButton ccbutton = {
  6,                       // Push button on pin 6
  {MIDI_CC::General_Purpose_Controller_1, CHANNEL_1}, // Controller #16 on MIDI channel 1
};

void setup() { Control_Surface.begin(); }
void loop() { Control_Surface.loop(); }

I'm interested in playing a note while a button is pressed but the only things I can find is {note(C, 4), CHANNEL_1} { MIDI_CC::General_Purpose_Controller_1, CHANNEL_1}

I'm not sure what you mean, for more information about MIDI addresses, see the MIDI Addresses page.

I also want to be able to shift the notes up/down octaves

Then you'll need a Transposer: https://tttapa.github.io/Control-Surface-doc/Doxygen/da/d2d/Transposer_8ino-example.html

if possible with a potentiometer

This isn't supported out of the box, but you can implement your own potentiometer selector, see Selectors/ManyButtonsSelector.hpp as an example.

I also need volume modifiers on the notes, but I'm sure that's done in the synthesiser side

See the setVelocity() method explained here: https://github.com/tttapa/Control-Surface/issues/283#issuecomment-698462870

Alternatively (if your synthesizer supports it), you could do volume control using a CCPotentiometer for controller #7 (channel volume), see https://tttapa.github.io/Control-Surface-doc/Doxygen/de/de4/Control-Change-Potentiometer_8ino-example.html.

digimbyte commented 3 years ago

I'm interested in continuous sounds, so when you hold the piano button, it keeps playing a looping note then fades out on release. is that a note or a CC? I have also no idea what 'General_Purpose_Controller_1' refers too, I just don't know if its usable to map 24 notes to it

digimbyte commented 3 years ago

I have 3 multiplexers 2 for digital, 1 analog

CD74HC4067 analogMux = {
  A0,           // analog pin
  {2, 0, 4, 5}, // Address pins S0, S1, S2, S3
};
CD74HC4067 digitalMux1 = {
  14,           // digital pin
  {2, 0, 4, 5}, // Address pins S0, S1, S2, S3
};
CD74HC4067 digitalMux2 = {
  12,           // digital pin
  {2, 0, 4, 5}, // Address pins S0, S1, S2, S3
};

I am then assigning them to an array modified from the existing code

 CCPotentiometer volumePotentiometers[] = { 
  { digitalMux1.pin(0), {note(C, 4), CHANNEL_1} },
  { digitalMux2.pin(0), {note(C, 5), CHANNEL_1} },
  { analogMux.pin(0), { MIDI_CC::Channel_Volume, CHANNEL_1 } }
// etc...

CCPotentiometer is probably the wrong thing but I've not found the correct type for the arrays

tttapa commented 3 years ago

I'm interested in continuous sounds, so when you hold the piano button, it keeps playing a looping note then fades out on release.

That's what NoteButton does. The synthesizer/sampler might play a continuous sound, but the Control Surface library isn't concerned with sound generation, it just sends a Note On event when pressed and a Note Off event when released, as required by the MIDI Standard.

I have also no idea what 'General_Purpose_Controller_1' refers too, I just don't know if its usable to map 24 notes to it

It's part of the MIDI Standard. Please see the MIDI Addresses link I sent earlier, go to the “MIDI Control Change constants” section, and click the link to “MIDI_CC” in that section.
Control Surface just provides these constants as a convenience, if you want to know what they mean, please refer to the MIDI Standard. These are MIDI controller numbers, they are for Control Change messages only, they have nothing to do with playing notes.

tttapa commented 3 years ago
 CCPotentiometer volumePotentiometers[] = { 
  { digitalMux1.pin(0), {note(C, 4), CHANNEL_1} },
  { digitalMux2.pin(0), {note(C, 5), CHANNEL_1} },
  { analogMux.pin(0), { MIDI_CC::Channel_Volume, CHANNEL_1 } }
// etc...

That doesn't make much sense. CCPotentiometer reads the input from an analog potentiometer, and sends the value of that potentiometer as a MIDI Control Change message. Passing digital pins to CCPotentiometer won't work as expected. You also seem to be using MIDI notes for the addresses. This is meaningless as well, since CCPotentiometer sends MIDI Control Change messages, not MIDI Note On/Off messages.

CCPotentiometer is probably the wrong thing

Yes, if you want to trigger notes on a MIDI synth/sampler, you need the NoteButton class.

but I've not found the correct type for the arrays

What do you mean? You can create arrays of any type, including NoteButton, e.g.


NoteButton buttons[] = {
   { digitalMux1.pin(0), {note(C, 4), CHANNEL_1} },
   { digitalMux1.pin(1), {note(D, 4), CHANNEL_1} },
   { digitalMux1.pin(2), {note(E, 4), CHANNEL_1} },
   // ...
};
tttapa commented 3 years ago

For the MIDI Control Change constants, also see https://www.midi.org/specifications-old/item/table-3-control-change-messages-data-bytes-2.

digimbyte commented 3 years ago

Cool, I found that, I'll use the breath, volume, and I guess modulation. just looking for the standard instrument set.

I seperated the digital pins from pots, guess the last thing is, if I update constants in the loop, it will update the note if I assign it a value rather than a pin? I suspect that is the purpose for bankable but not sure if that would translate to { myValue, {note(C, 4), CHANNEL_1} }

tttapa commented 3 years ago

All parameters to the NoteButton constructor are passed by value. This means that they are copied. If you later change your myValue constant, for example, you don't change the copy of that value in the NoteButton object.

I've started working on a FAQ which includes an introduction to banks, you can find a first draft here: https://tttapa.github.io/Control-Surface-doc/new-input/Doxygen/df/df5/md_pages_FAQ.html#faq-change-address-runtime

You probably want to use the Transposer class, see the Transposer.ino example I linked to in my first reply. A transposer is a special kind of bank, designed to transpose MIDI notes.

digimbyte commented 3 years ago

Thank you, you've been very helpful!