billthefarmer/mididriver

Changing instruments in midi encoding

Closed this issue · 9 comments

How can i changing instruments in midi encoding?

There are two classes MidiConstants and GeneralMidiConstants. MidiConstants defines the codes for midi messages, like PROGRAM_CHANGE and GeneralMidiConstants defines the codes for instruments. So something like this should do it...

#import org.billthefarmer.mididriver.MidiConstants;
#import org.billthefarmer.mididriver.GeneralMidiConstants;

    // Harpsichord
    programChange(HARPSICHORD);

    // Program change
    void programChange(int n)
    {
        sendMidi(PROGRAM_CHANGE, n);
    }

    // Send a midi message, 2 bytes
    void sendMidi(int m, int n)
    {
        byte msg[] = new byte[2];

        msg[0] = (byte) m;
        msg[1] = (byte) n;

        midi.write(msg);
    }

Thanks! There is still a small question, since just starting to understand the generation of midi sound, how to simultaneously play notes on two channels at once

In that case I missed a bit off of the code above, channel number. So it should be...

    // Harpsichord
    programChange(0, HARPSICHORD);
    programChange(1, TUBULAR_BELLS);

    // Program change
    void programChange(int c, int n)
    {
        sendMidi(PROGRAM_CHANGE + c, n);
    }

You will also need...

    // Note on
    noteOn(int c, int n, int v)
    {
        sendMidi(NOTE_ON + c, n, v);
    }

    // Note off
    noteOff(int c, int n, int v)
    {
        sendMidi(NOTE_OFF + c, n, v);
    }

    // Send a midi message, 3 bytes
    void sendMidi(int m, int n, int v)
    {
        byte msg[] = new byte[3];

        msg[0] = (byte) m;
        msg[1] = (byte) n;
        msg[2] = (byte) v;

        midi.write(msg);
    }

You must send as many note off messages as note on, otherwise it stops working, even for percussive instruments. The apps I've written using midi send note on messages when a button is touched, and send note off messages when it is released. You can send as many simultaneous messages to different channels as you like, within the limits. There is lots of useful info on line, like https://www.midi.org/specifications-old/item/table-1-summary-of-midi-message. You can see from that there can't be more than 16 channels.

Thank you very much)

Oh, I tried to do it, it did not work out particularly.
Here is the code I got:

i - this is ainstrument from the constants GeneralMidiConstants

void Play(int c, int i, int n, int v)
{
    noteOn(PROGRAM_CHANGE + c + i, n, v);
}

void StopPlay(int c, int i, int n, int v)
{
    noteOff(PROGRAM_CHANGE + c, n, v);
}

// Note on
void noteOn(int c, int n, int v)
{
    sendMidi(NOTE_ON + c, n, v);
}

void noteOff(int c, int n, int v)
{
    sendMidi(NOTE_OFF + c, n, v);
}

// Send a midi message, 3 bytes
void sendMidi(int m, int n, int v)
{
    byte msg[] = new byte[3];

    msg[0] = (byte) m;
    msg[1] = (byte) n;
    msg[2] = (byte) v;

    midiDriver.write(msg);
}

I also tried sending the tool code as a separate cell in the buffer 'msg'

You can't send a program change message as a three byte message, it's two bytes, you need to use the code from my first comment as well. And read the docs to see which messages are two byte and which three and how the bits fit together.

    // Send a midi message, 2 bytes
    void sendMidi(int m, int n)
    {
        byte msg[] = new byte[2];

        msg[0] = (byte) m;
        msg[1] = (byte) n;

        midi.write(msg);
    }

It turns out that in order to play sound on two different channels simultaneously, which will have different instruments, you first need to send a messages about changing the instruments, and then a message with playing notes?

That's it, figured it out. Everything worked, thanks for the help and such a wonderful library!