Go Down

Topic: MIDI commands to change Bank Program and Instrument on Synth (Read 957 times) previous topic - next topic

wayro

Firstly Im no expert Im just getting into this amazing tech.
I have Arduino Leonardo connected to a Rasberry Pi running Jack and Yoshimi synth via USB.


Im trying to 1. change the "bank" from default to say chorus or any other , and then to change the instrument and also to be able to use a button(s) to increment through different banks and instruments , so when i use my arduino keypad it will then play those sounds.

this is the code Im using for the synth and arduino. Now I wanted to add the bank program, instrument change and got stuck.?
Can someone please advise what code and its syntax to use to change the banks and instruments to be able to play other instruments?
Code:

#include "MIDI_Controller.h" // Include the library

const int c = 60;

const uint8_t velocity = 0b1111111; // Maximum velocity (0b1111111 = 0x7F = 127)
const uint8_t addresses[3][4] = { // button keymap
{c+0, c-5, c+2, c+3},
{c+4, c+5, c+6, c+7},
{c+12, c+9, c+14, c+11},
};

ButtonMatrix<3, 4> buttonmatrix({7, 6,5}, {11, 10, 9, 8} , addresses, 1, velocity);

// Create a new instance of the class 'Analog', called 'potentiometer', on pin A0,
// that sends MIDI messages with controller 7 (channel volume) on channel 1
Analog potentiometer1(A0, MIDI_CC::Channel_Volume, 1);

// Create a new instance of the class 'AnalogHiRes', called 'potentiometer', on pin A1,
// that sends MIDI Pitch Bend messages on channel 1
AnalogHiRes potentiometer2(A1, 1);


void setup() {}

void loop() {
MIDI_Controller.refresh();
}

Grumpy_Mike

Quote
Now I wanted to add the bank program, instrument change and got stuck.?
What exactly do you mean by bank?

To change the instrument you need to send a program change message which starts 0xC0. Some of my MIDI sound generating modules have a bank select that should be changed before the program change message to get variations on those instrument sounds. The bank are controlled by two controller messages number zero and 32 for the upper and lower bank number. Controller messages start with 0xB0.

I am not sure you are using the word bank in this way.

slipstick

You need to know what the Yoshimi MIDI implementation of Bank Select is. Bank Select isn't part of the official MIDI specification so there are many different variations. And from what I recall Yoshimi is based on ZynAddSubFx which probably means that it's very complex and in some places really odd. Do you have any documentation for it's MIDI implementation that you can provide a link to?

Steve


wayro

Unfortunately the documentation doesnt specify the bank implementation.
Im also not sure how to implement the code sending hex characters .
How would I do this using the code I have above?

Grumpy_Mike

Look at the examples that came with the library.

Quote
Unfortunately the documentation doesnt specify the bank implementation.
Then maybe it doesn't implement them?

slipstick

Never used Yoshimi (or Linux) but if it is like ZynAddSubFx then I guess what you're trying to do is to select preset "banks" e.g. Strings, Choir and Voice, Brass etc. Is that right? I don't know that they're available via MIDI because they weren't in ZASFx. Apart from anything else a "bank" can contain more than 128 presets and MIDI Program Change can only handle 128.

If that's not what you're trying to achieve can you provide more details.

Steve

PieterP

We've had a similar discussion on GitHub:
https://github.com/tttapa/MIDI_controller/issues/102

To send MIDI Program Change and Bank Select using the MIDI Controller library, you would use

  uint16_t bank = 1234;
  uint8_t program = 40;
  uint8_t channel = 1;
  MIDI_Controller.MIDI()->send(CONTROL_CHANGE, channel, MIDI_CC::Bank_Select,     (bank >> 7) & 0x7F);
  MIDI_Controller.MIDI()->send(CONTROL_CHANGE, channel, MIDI_CC::Bank_Select_LSB, (bank >> 0) & 0x7F)
  MIDI_Controller.MIDI()->send(PROGRAM_CHANGE, channel, program);



Using the newer Control Surface library, you could use something like this:

  uint16_t bank = 1234;
  uint8_t program = 40;
  MIDICNChannel channel = CHANNEL_1;
  midi.sendCC({MIDI_CC::Bank_Select,     channel}, (bank >> 7) & 0x7F)
  midi.sendCC({MIDI_CC::Bank_Select_LSB, channel}, (bank >> 0) & 0x7F);
  midi.sendPC(channel, program);



Pieter

Grumpy_Mike


wayro

Yes that's what I'm looking for thanks PieterP

We've had a similar discussion on GitHub:
https://github.com/tttapa/MIDI_controller/issues/102

To send MIDI Program Change and Bank Select using the MIDI Controller library, you would use

  uint16_t bank = 1234;
  uint8_t program = 40;
  uint8_t channel = 1;
  MIDI_Controller.MIDI()->send(CONTROL_CHANGE, channel, MIDI_CC::Bank_Select,     (bank >> 7) & 0x7F);
  MIDI_Controller.MIDI()->send(CONTROL_CHANGE, channel, MIDI_CC::Bank_Select_LSB, (bank >> 0) & 0x7F)
  MIDI_Controller.MIDI()->send(PROGRAM_CHANGE, channel, program);



Using the newer Control Surface library, you could use something like this:

  uint16_t bank = 1234;
  uint8_t program = 40;
  MIDICNChannel channel = CHANNEL_1;
  midi.sendCC({MIDI_CC::Bank_Select,     channel}, (bank >> 7) & 0x7F)
  midi.sendCC({MIDI_CC::Bank_Select_LSB, channel}, (bank >> 0) & 0x7F);
  midi.sendPC(channel, program);



Pieter

wayro

Made some real headway with your help thank you!.

I'm seeing a lot of noise coming across to the pi from the arduino midi and cant work out how to stop it.
Please can you advise.
this is what I'm getting and it doesn't stop:
 20:0   Pitch bend              0, value 1689
 20:0   Pitch bend              0, value 1673
 20:0   Pitch bend              0, value 1657
 20:0   Pitch bend              0, value 1641
 20:0   Pitch bend              0, value 1609
 20:0   Pitch bend              0, value 1625

Using this test code below using the Control Surface library:
 *
 */

//#include <Encoder.h> // Needed for the EncoderSelector to work
// Encoder must be included before Control Surface
#include <Control_Surface.h> // Include the Control Surface library

// Instantiate a MIDI interface to use for the Control Surface.
//USBDebugMIDI_Interface midi;
USBMIDI_Interface midi;
// Instantiate a program changer with four programs: 0x10, 0x20, 0x30, 0x40
// on channel 1
ProgramChanger<4> pc = {
    {0x10, 0x20, 0x30, 0x40},
    CHANNEL_1,
};

// Instantiate a selector for the program changer on pins 5 (increment) and
// pin 6 (decrement).
// It doesn't wrap around when the maximum/minimum is reached.
IncrementDecrementSelector<4> sel = {
  pc,
  {11, 12},
  Wrap::NoWrap,
};

// Instantiate a PBPotentiometer object
PBPotentiometer potentiometer1 = {
  A0,        // Analog pin connected to potentiometer
  CHANNEL_1, // MIDI Channel 1
};



void setup() {
 
    Control_Surface.begin(); // Initialize Control Surface
   
}

void loop() {
  Control_Surface.loop(); // Update the Control Surface
   
}

PieterP

What is the resistance of the potentiometer you are using? How did you wire it?
I'm using 5 kΩ potentiometers and 25 cm wires  on my Arduino Leonardo, and it works without any noise.

You can try increasing the amount of filtering on the analog inputs:
https://tttapa.github.io/Control-Surface-doc/Doxygen/dc/d69/namespaceAH.html#a74cef1adb51d95add8b2bea344b6c755

But double check your hardware first.

wayro

Im using a 10K breadboard mounted pot, about 10cm jumper leads from it to the arduino.
Ok Ill check the link you posted and also look at changing the pots.

Grumpy_Mike

Quote
and also look at changing the pots.
Don't bother 5K is fine and in fact better in this respect than a 10K one.

The trick is to remember the last pitchbend you send and only send a new one if it is different by some amount to the one you want to send.

Code: [Select]
newPitchbend = analogRead(potPin);
if ( abs(newPitchbend - oldPitchbend) > threshold) {
    // send new pitch bend value
   oldPitchbend = newPitchbend ;
}

PieterP

The trick is to remember the last pitchbend you send and only send a new one if it is different by some amount to the one you want to send.
The library already does this, which is why I suspect a hardware issue. The default threshold and filter settings of the library work fine for me on all boards I've tested it on.

If increasing the amount of filtering doesn't work, or if it reduces the responsiveness too much, you can change the resolution from 10 bits to 9 bits:

https://github.com/tttapa/Control-Surface/blob/30254f65de4a8ec4f766c51d5cd6d20bde380ba1/src/MIDI_Outputs/PBPotentiometer.hpp#L25
You have to change 10 to 9 on two different lines.

wayro

Its odd because I've tried this on 2 Leonardo boards and same results.
Ill change the pots and test.
Any suggestions for a hardware fix to debounce the pot and minimise chatter? capacitors?

Go Up