midi.c
来自「An interactive water fountain. A realis」· C语言 代码 · 共 2,070 行 · 第 1/4 页
C
2,070 行
default : if (_MIDI_Funcs->ControlChange) { _MIDI_Funcs->ControlChange(channel, c1, c2); } } return TimeSet;}/*--------------------------------------------------------------------- Function: _MIDI_ServiceRoutine Task that interperates the MIDI data.---------------------------------------------------------------------*/static int32_t _MIDI_ServiceRoutine(void){ int32_t event; int32_t channel; int32_t command; track *Track; int32_t tracknum; int32_t status; int32_t c1 = 0; int32_t c2 = 0; int32_t TimeSet = FALSE; if (_MIDI_SongActive) { Track = _MIDI_TrackPtr; tracknum = 0; while (tracknum < _MIDI_NumTracks) { while ((Track->active) && (Track->delay == 0)) { GET_NEXT_EVENT(Track, event); if (GET_MIDI_COMMAND(event) == MIDI_SPECIAL) { switch (event) { case MIDI_SYSEX : case MIDI_SYSEX_CONTINUE : _MIDI_SysEx(Track); break; case MIDI_META_EVENT : _MIDI_MetaEvent(Track); break; } if (Track->active) { Track->delay = _MIDI_ReadDelta(Track); } continue; } if (event & MIDI_RUNNING_STATUS) { Track->RunningStatus = event; } else { event = Track->RunningStatus; Track->pos--; } channel = GET_MIDI_CHANNEL(event); command = GET_MIDI_COMMAND(event); if (_MIDI_CommandLengths[ command ] > 0) { GET_NEXT_EVENT(Track, c1); if (_MIDI_CommandLengths[ command ] > 1) { GET_NEXT_EVENT(Track, c2); } } if (_MIDI_RerouteFunctions[ channel ] != NULL) { status = _MIDI_RerouteFunctions[ channel ](event, c1, c2); if (status == MIDI_DONT_PLAY) { Track->delay = _MIDI_ReadDelta(Track); continue; } } switch (command) { case MIDI_NOTE_OFF : if (_MIDI_Funcs->NoteOff) { _MIDI_Funcs->NoteOff(channel, c1, c2); } break; case MIDI_NOTE_ON : if (_MIDI_Funcs->NoteOn) { _MIDI_Funcs->NoteOn(channel, c1, c2); } break; case MIDI_POLY_AFTER_TCH : if (_MIDI_Funcs->PolyAftertouch) { _MIDI_Funcs->PolyAftertouch(channel, c1, c2); } break; case MIDI_CONTROL_CHANGE : TimeSet = _MIDI_InterpretControllerInfo(Track, TimeSet, channel, c1, c2); break; case MIDI_PROGRAM_CHANGE : if ((_MIDI_Funcs->ProgramChange) && (!Track->EMIDI_ProgramChange)) { _MIDI_Funcs->ProgramChange(channel, MIDI_PatchMap[ c1 & 0x7f ]); } break; case MIDI_AFTER_TOUCH : if (_MIDI_Funcs->ChannelAftertouch) { _MIDI_Funcs->ChannelAftertouch(channel, c1); } break; case MIDI_PITCH_BEND : if (_MIDI_Funcs->PitchBend) { _MIDI_Funcs->PitchBend(channel, c1, c2); } break; default : break; } Track->delay = _MIDI_ReadDelta(Track); } Track->delay--; Track++; tracknum++; if (_MIDI_ActiveTracks == 0) { _MIDI_ResetTracks(); if (_MIDI_Loop) { tracknum = 0; Track = _MIDI_TrackPtr; } else { _MIDI_SongActive = FALSE; break; } } } _MIDI_AdvanceTick(); _MIDI_GlobalPositionInTicks++; } return 0;}/*--------------------------------------------------------------------- Function: _MIDI_SendControlChange Sends a control change to the proper device---------------------------------------------------------------------*/static int32_t _MIDI_SendControlChange( int32_t channel, int32_t c1, int32_t c2){ int32_t status; if (_MIDI_RerouteFunctions[ channel ] != NULL) { status = _MIDI_RerouteFunctions[ channel ](0xB0 + channel, c1, c2); if (status == MIDI_DONT_PLAY) { return(MIDI_Ok); } } if (_MIDI_Funcs == NULL) { return(MIDI_Error); } if (_MIDI_Funcs->ControlChange == NULL) { return(MIDI_Error); } _MIDI_Funcs->ControlChange(channel, c1, c2); return(MIDI_Ok);}/*--------------------------------------------------------------------- Function: MIDI_RerouteMidiChannel Sets callback function to reroute MIDI commands from specified function.---------------------------------------------------------------------*/void MIDI_RerouteMidiChannel( int32_t channel, int32_t(*function)(int32_t event, int32_t c1, int32_t c2)){ if ((channel >= 1) && (channel <= 16)) { _MIDI_RerouteFunctions[ channel - 1 ] = function; }}/*--------------------------------------------------------------------- Function: MIDI_AllNotesOff Sends all notes off commands on all midi channels.---------------------------------------------------------------------*/int32_t MIDI_AllNotesOff( void){ int32_t channel; for (channel = 0; channel < NUM_MIDI_CHANNELS; channel++) { _MIDI_SendControlChange(channel, 0x40, 0); _MIDI_SendControlChange(channel, MIDI_ALL_NOTES_OFF, 0); _MIDI_SendControlChange(channel, 0x78, 0); } return(MIDI_Ok);}/*--------------------------------------------------------------------- Function: _MIDI_SetChannelVolume Sets the volume of the specified midi channel.---------------------------------------------------------------------*/static void _MIDI_SetChannelVolume( int32_t channel, int32_t volume){ int32_t status; int32_t remotevolume; _MIDI_ChannelVolume[ channel ] = volume; if (_MIDI_RerouteFunctions[ channel ] != NULL) { remotevolume = volume * _MIDI_TotalVolume; remotevolume *= _MIDI_UserChannelVolume[ channel ]; remotevolume /= MIDI_MaxVolume; remotevolume >>= 8; status = _MIDI_RerouteFunctions[ channel ](0xB0 + channel, MIDI_VOLUME, remotevolume); if (status == MIDI_DONT_PLAY) { return; } } if (_MIDI_Funcs == NULL) { return; } if (_MIDI_Funcs->ControlChange == NULL) { return; } // For user volume volume *= _MIDI_UserChannelVolume[ channel ]; if (_MIDI_Funcs->SetVolume == NULL) { volume *= _MIDI_TotalVolume; volume /= MIDI_MaxVolume; } // For user volume volume >>= 8; _MIDI_Funcs->ControlChange(channel, MIDI_VOLUME, volume);}/*--------------------------------------------------------------------- Function: MIDI_SetUserChannelVolume Sets the volume of the specified midi channel.---------------------------------------------------------------------*/void MIDI_SetUserChannelVolume( int32_t channel, int32_t volume){ // Convert channel from 1-16 to 0-15 channel--; volume = max(0, volume); volume = min(volume, 256); if ((channel >= 0) && (channel < NUM_MIDI_CHANNELS)) { _MIDI_UserChannelVolume[ channel ] = volume; _MIDI_SetChannelVolume(channel, _MIDI_ChannelVolume[ channel ]); }}/*--------------------------------------------------------------------- Function: MIDI_ResetUserChannelVolume Sets the volume of the specified midi channel.---------------------------------------------------------------------*/void MIDI_ResetUserChannelVolume( void){ int32_t channel; for (channel = 0; channel < NUM_MIDI_CHANNELS; channel++) { _MIDI_UserChannelVolume[ channel ] = 256; } _MIDI_SendChannelVolumes();}/*--------------------------------------------------------------------- Function: _MIDI_SendChannelVolumes Sets the volume on all the midi channels.---------------------------------------------------------------------*/static void _MIDI_SendChannelVolumes( void){ int32_t channel; for (channel = 0; channel < NUM_MIDI_CHANNELS; channel++) { _MIDI_SetChannelVolume(channel, _MIDI_ChannelVolume[ channel ]); }}/*--------------------------------------------------------------------- Function: MIDI_Reset Resets the MIDI device to General Midi defaults.---------------------------------------------------------------------*/int32_t MIDI_Reset( void){ int32_t channel; MIDI_AllNotesOff(); for (channel = 0; channel < NUM_MIDI_CHANNELS; channel++) { _MIDI_SendControlChange(channel, MIDI_RESET_ALL_CONTROLLERS, 0); _MIDI_SendControlChange(channel, MIDI_RPN_MSB, MIDI_PITCHBEND_MSB); _MIDI_SendControlChange(channel, MIDI_RPN_LSB, MIDI_PITCHBEND_LSB); _MIDI_SendControlChange(channel, MIDI_DATAENTRY_MSB, 2); /* Pitch Bend Sensitivity MSB */ _MIDI_SendControlChange(channel, MIDI_DATAENTRY_LSB, 0); /* Pitch Bend Sensitivity LSB */ _MIDI_ChannelVolume[ channel ] = GENMIDI_DefaultVolume; } _MIDI_SendChannelVolumes(); Reset = TRUE; return(MIDI_Ok);}/*--------------------------------------------------------------------- Function: MIDI_SetVolume Sets the total volume of the music.---------------------------------------------------------------------*/int32_t MIDI_SetVolume( int32_t volume){ int32_t i; if (_MIDI_Funcs == NULL) { return(MIDI_NullMidiModule); } volume = min(MIDI_MaxVolume, volume); volume = max(0, volume); _MIDI_TotalVolume = volume; if (_MIDI_Funcs->SetVolume) { _MIDI_Funcs->SetVolume(volume); for (i = 0; i < NUM_MIDI_CHANNELS; i++) { if (_MIDI_RerouteFunctions[ i ] != NULL) { _MIDI_SetChannelVolume(i, _MIDI_ChannelVolume[ i ]); } } } else { _MIDI_SendChannelVolumes(); } return(MIDI_Ok);}/*--------------------------------------------------------------------- Function: MIDI_GetVolume Returns the total volume of the music.---------------------------------------------------------------------*/int32_t MIDI_GetVolume( void){ int32_t volume; if (_MIDI_Funcs == NULL) { return(MIDI_NullMidiModule); } if (_MIDI_Funcs->GetVolume) { volume = _MIDI_Funcs->GetVolume(); } else { volume = _MIDI_TotalVolume; } return(volume);}/*--------------------------------------------------------------------- Function: MIDI_SetContext Sets the song context.---------------------------------------------------------------------*/void MIDI_SetContext( int32_t context){ if ((context > 0) && (context < EMIDI_NUM_CONTEXTS)) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?