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
handle | The MIDI stream to apply the events to. | ||||||||||||
mode | The type of event data to apply. One of the following, with optional flags.
| ||||||||||||
events | The event data. | ||||||||||||
length | The 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_HANDLE | handle is not valid. |
BASS_ERROR_ILLPARAM | mode 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