Question

Using FM8.

I want to play the flute on channel 2 at volume 0 and the organ on channel 3 at full volume. I want to then gradually reduce the volume of the organ and raise the volume of the flute.

The problem is that I do not hear the flute sound raising at all, but only the organ volume going down.

I may be misunderstanding something very fundamental about MIDI?

I tinkered withe the value of 'MUTE' below replacing 0 with 1 (in the worry that 0 could be interpreted as some kind of "note off") to no avail.

Here's the relevant part of the code:

#define ORGAN   1
#define FLUTE   2

#define FULL    63
#define MUTE    1

#define BASE    0
#define M2nd    2
#define M3rd    4
#define M4th    5
#define M5th    7

#define FLUTE_CHANNEL       2
#define ORGAN_CHANNEL       3

#define CHANNEL_VOLUME      7

typedef enum {

    MIDIStatusBytesNotOff           =   0x80
,   MIDIStatusBytesNotOn            =   0x90
,   MIDIStatusBytesAfterTouch       =   0xa0
,   MIDIStatusBytesControlChange    =   0xb0
,   MIDIStatusBytesProgramChange    =   0xc0
,   MIDIStatusBytesChannelPressure  =   0xd0
,   MIDIStatusBytesPitchWheel       =   0xe0

} MIDIStatusBytes ;

- (void) sendSlowMo {

    const UInt8 baseNote = 69 ;
    const UInt8 start[]  = {
        MIDIStatusBytesProgramChange + FLUTE_CHANNEL,                   FLUTE
    ,   MIDIStatusBytesProgramChange + ORGAN_CHANNEL,                   ORGAN
    ,   MIDIStatusBytesNotOn + FLUTE_CHANNEL, baseNote+M4th,            MUTE
    ,   MIDIStatusBytesNotOn + ORGAN_CHANNEL, baseNote+BASE,            FULL
    } ;

    const UInt8 stop[]  = {
        MIDIStatusBytesNotOff + FLUTE_CHANNEL, baseNote+M4th,           MUTE
    ,   MIDIStatusBytesNotOff + ORGAN_CHANNEL, baseNote+BASE,           MUTE
    ,   MIDIStatusBytesControlChange + FLUTE_CHANNEL, CHANNEL_VOLUME,   FULL
    ,   MIDIStatusBytesControlChange + ORGAN_CHANNEL, CHANNEL_VOLUME,   FULL        
    } ;

    UInt8 stepUpDown[]  = {
        MIDIStatusBytesControlChange + FLUTE_CHANNEL, CHANNEL_VOLUME,   MUTE
    ,   MIDIStatusBytesControlChange + ORGAN_CHANNEL, CHANNEL_VOLUME,   FULL        
    } ;

    [midi sendBytes:start size:sizeof(start)];

    for (int i = 1 ; i < 128 ; ++i) {
        stepUpDown[2] = (UInt8) i ;
        stepUpDown[5] = (UInt8) (127 - i) ;

        [midi sendBytes:stepUpDown size:sizeof(stepUpDown)];
        [NSThread sleepForTimeInterval:0.10];
    }

    [midi sendBytes:stop size:sizeof(stop)];
}

I am using Pete Goodliffe's Excellent sample code as a starting point.

Any idea?

Was it helpful?

Solution

    ,   MIDIStatusBytesNotOn + FLUTE_CHANNEL, baseNote+M4th,            MUTE

If I'm not mistaken you are sending NoteOn with 0 velocity. This usually means NoteOff according to the MIDI specification. What you want is to set the controller value of the channel volume to 0 before issuing NoteOn with the final velocity. Note the velocity parameter tells how hard you hit a key. Everything else must be done either by aftertouch (channel pressure/key pressure) or using controllers like expression.

You can compare the situation with fading between audio tracks: Velocity tells something about the recorded volume of the note, while channel volume is the value of the slider you are using while performing the fade.

Edit: I overlooked that you define MUTE equal to 1. But that doesn't change the general discussion; its a (nearly) unhearable note that won't get much louder by channel volume messages.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top