billthefarmer / mididriver

Android midi driver using Sonivox EAS library
176 stars 52 forks source link

Changing instruments in midi encoding #37

Closed HotsHom closed 4 years ago

HotsHom commented 4 years ago

How can i changing instruments in midi encoding?

billthefarmer commented 4 years ago

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);
    }
HotsHom commented 4 years ago

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

billthefarmer commented 4 years ago

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.

HotsHom commented 4 years ago

Thank you very much)

HotsHom commented 4 years ago

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);
}
HotsHom commented 4 years ago

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

billthefarmer commented 4 years ago

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);
    }
HotsHom commented 4 years ago

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?

HotsHom commented 4 years ago

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