BASS MIDI

BASS_MIDI_StreamEvents


Applies any number of events to a MIDI stream.

DWORD BASS_MIDI_StreamEvents(
    HSTREAM handle,
    DWORD mode,
    void *events,
    DWORD length
);

Parameters

handleThe MIDI stream to apply the events to.
modeThe type of event data to apply. One of the following, with optional flags.
BASS_MIDI_EVENTS_RAWRaw MIDI event data, as would be sent to a MIDI device. To overcome the 16 channel limit, the event data's channel information can optionally be overridden by adding the new channel number to this parameter, where +1 = the 1st channel.
BASS_MIDI_EVENTS_STRUCTAn array of BASS_MIDI_EVENT structures.
BASS_MIDI_EVENTS_CANCELFlag: Cancel pending events from a previous call of this function.
BASS_MIDI_EVENTS_NORSTATUSFlag: Disable running status, meaning each event must include a status byte. Only applicable with BASS_MIDI_EVENTS_RAW.
BASS_MIDI_EVENTS_SYNCFlag: Trigger BASS_SYNC_MIDI_EVENT syncs for the processed events.
BASS_MIDI_EVENTS_TIMEFlag: The raw MIDI data includes delta-time info (when used with BASS_MIDI_EVENTS_RAW) or the BASS_MIDI_EVENT tick and pos members should be processed (without BASS_MIDI_EVENTS_RAW). The BASS_MIDI_EVENT tick and pos members will otherwise be ignored.
eventsThe event data.
lengthThe length of the event data. The number of bytes or BASS_MIDI_EVENT structures, depending on the type of event data.

Return value

If successful, the number of events processed is returned, else -1 is returned. Use BASS_ErrorGetCode to get the error code.

Error codes

BASS_ERROR_HANDLEhandle is not valid.
BASS_ERROR_ILLPARAMmode is not valid.

Remarks

Events applied to a MIDI file stream can subsequently be overridden by events in the file itself, and will also be overridden when seeking or looping. That can be avoided by using additional channels, allocated via the BASS_ATTRIB_MIDI_CHANS attribute.

The BASS_MIDI_EVENTS_TIME flag allows events to be delayed. With raw MIDI data, it enables delta-time info to be included in the data. With an BASS_MIDI_EVENT array, it enables processing of the tick and pos members (only one should be used). In both cases, the values are relative to the current decoding position, ie. 0 = no delay. The events do not necessarily need to be provided in chronological order; they will be sorted automatically. Tick-based delays are ignored on streams created with BASS_MIDI_StreamCreate because the Pulses Per Quarter Note (BASS_ATTRIB_MIDI_PPQN) is undefined; BASS_MIDI_StreamCreateEvents could be used instead when tick-based delays are wanted.

If the MIDI stream is being played (it is not a decoding channel), then there will be some delay in the effect of the event being heard even if no delay is requested in the event data. This latency can be reduced by making use of the BASS_CONFIG_BUFFER and BASS_CONFIG_UPDATEPERIOD config options when creating the stream.

Example

Play a C major chord with a velocity of 100, on channel 1 for 2 seconds.
BASS_MIDI_EVENT events[3];
memset(events, 0, sizeof(events));
events[0].event=MIDI_EVENT_NOTE;
events[0].param=MAKEWORD(60, 100); // C
events[1].event=MIDI_EVENT_NOTE;
events[1].param=MAKEWORD(64, 100); // E
events[2].event=MIDI_EVENT_NOTE;
events[2].param=MAKEWORD(67, 100); // G
BASS_MIDI_StreamEvents(handle, BASS_MIDI_EVENTS_STRUCT, events, 3); // process the events
Sleep(2000); // wait 2 seconds
// modify the event data to release the keys
events[0].param=MAKEWORD(60, 0); // release C
events[1].param=MAKEWORD(64, 0); // release E
events[2].param=MAKEWORD(67, 0); // release G
BASS_MIDI_StreamEvents(handle, BASS_MIDI_EVENTS_STRUCT, events, 3); // process the events

The same thing using raw MIDI event data.

BYTE events[7]={0x90, 60, 100, 64, 100, 67, 100}; // the event data
BASS_MIDI_StreamEvents(handle, BASS_MIDI_EVENTS_RAW, events, 7); // process the events
Sleep(2000); // wait 2 seconds
// modify the event data to release the keys
events[2]=0; // release C
events[4]=0; // release E
events[6]=0; // release G
BASS_MIDI_StreamEvents(handle, BASS_MIDI_EVENTS_RAW, events, 7); // process the events

The same thing in a single event sequence, making use of pos to delay the release.

BASS_MIDI_EVENT events[6];
memset(events, 0, sizeof(events));
events[0].event=MIDI_EVENT_NOTE;
events[0].param=MAKEWORD(60, 100); // C
events[1].event=MIDI_EVENT_NOTE;
events[1].param=MAKEWORD(64, 100); // E
events[2].event=MIDI_EVENT_NOTE;
events[2].param=MAKEWORD(67, 100); // G
events[3].event=MIDI_EVENT_NOTE;
events[3].param=MAKEWORD(60, 0); // release C
events[3].pos=BASS_ChannelSeconds2Bytes(handle, 2); // 2 seconds
events[4].event=MIDI_EVENT_NOTE;
events[4].param=MAKEWORD(64, 0); // release E
events[4].pos=events[3].pos;
events[5].event=MIDI_EVENT_NOTE;
events[5].param=MAKEWORD(67, 0); // release G
events[5].pos=events[3].pos;
BASS_MIDI_StreamEvents(handle, BASS_MIDI_EVENTS_STRUCT|BASS_MIDI_EVENTS_TIME, events, 6); // process the events

See also

BASS_MIDI_StreamCreate, BASS_MIDI_StreamEvent, BASS_MIDI_StreamGetEvent