Applies any number of events to a MIDI stream.
DWORD BASS_MIDI_StreamEvents( HSTREAM handle, DWORD mode, void *events, DWORD length );
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. |
BASS_ERROR_HANDLE | handle is not valid. |
BASS_ERROR_ILLPARAM | mode is not valid. |
BASS_ERROR_NOTAVAIL | This function cannot be called from a MIDIFILTERPROC callback with BASS_MIDI_EVENTS_FILTER set, or with BASS_MIDI_EVENTS_SYNC set while seeking. |
The MIDI port meta-event (21h) is supported in raw MIDI data, allowing access to more than the standard 16 channels: port 0 = channels 1-16, port 1 = channels 17-32, etc. The active port number persists across calls of this function.
The BASS_MIDI_EVENTS_TIME and BASS_MIDI_EVENTS_ABSTIME flags allow events to be delayed until specific positions. With raw MIDI data, they enable delta-time info to be included in the data. With an BASS_MIDI_EVENT array, they enable processing of the tick and pos members (only one should be used). The events do not necessarily need to be provided in chronological order; they will be sorted automatically. The BASS_MIDI_EVENTS_CANCEL flag can be used to remove any old pending events. Any pending events are also cancelled by BASS_ChannelSetPosition.
If the BASS_MIDI_EVENTS_ASYNC flag is used without the BASS_MIDI_EVENTS_TIME or BASS_MIDI_EVENTS_ABSTIME flags then the events will be processed in the next update cycle, at an offset determined by the time that has passed since the last update cycle. For example, if the last update cycle was 3ms ago then the events will be applied 3ms into the next update cycle's output. This unties the event's timing from the stream's update period for greater resolution, without having to resort to the BASS_MIDI_EVENTS_TIME or BASS_MIDI_EVENTS_ABSTIME options. If this function is called during an update cycle then the events will be processed at the end of that, or immediately if the call is from a MIDIFILTERPROC callback.
During playback, there will be some delay in the effect of the events being heard even if no delay is requested in the event data/flags, due to buffering. This latency can be reduced via the BASS_ATTRIB_BUFFER attribute.
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