midi.c
来自「An interactive water fountain. A realis」· C语言 代码 · 共 2,070 行 · 第 1/4 页
C
2,070 行
Sets the position of the song pointer.---------------------------------------------------------------------*/void MIDI_SetSongTime( uint32_t milliseconds){ uint32_t mil; uint32_t sec; uint32_t newtime; if (!_MIDI_SongLoaded) { return; } MIDI_PauseSong(); mil = ((milliseconds % 1000) << TIME_PRECISION) / 1000; sec = (milliseconds / 1000) << TIME_PRECISION; newtime = sec + mil; if (newtime < _MIDI_Time) { _MIDI_ResetTracks(); MIDI_Reset(); } while (_MIDI_Time < newtime) { if (_MIDI_ProcessNextTick()) { break; } if (_MIDI_ActiveTracks == 0) { _MIDI_ResetTracks(); if (!_MIDI_Loop) { return; } break; } } MIDI_SetVolume(_MIDI_TotalVolume); MIDI_ContinueSong();}/*--------------------------------------------------------------------- Function: MIDI_SetSongPosition Sets the position of the song pointer.---------------------------------------------------------------------*/void MIDI_SetSongPosition( int32_t measure, int32_t beat, int32_t tick){ uint32_t pos; if (!_MIDI_SongLoaded) { return; } MIDI_PauseSong(); pos = RELATIVE_BEAT(measure, beat, tick); if (pos < (uint32_t)RELATIVE_BEAT(_MIDI_Measure, _MIDI_Beat, _MIDI_Tick)) { _MIDI_ResetTracks(); MIDI_Reset(); } while ((uint32_t)RELATIVE_BEAT(_MIDI_Measure, _MIDI_Beat, _MIDI_Tick) < pos) { if (_MIDI_ProcessNextTick()) { break; } if (_MIDI_ActiveTracks == 0) { _MIDI_ResetTracks(); if (!_MIDI_Loop) { return; } break; } } MIDI_SetVolume(_MIDI_TotalVolume); MIDI_ContinueSong();}/*--------------------------------------------------------------------- Function: MIDI_GetSongPosition Returns the position of the song pointer in Measures, beats, ticks.---------------------------------------------------------------------*/void MIDI_GetSongPosition( songposition *pos){ uint32_t mil; uint32_t sec; mil = (_MIDI_Time & ((1 << TIME_PRECISION) - 1)) * 1000; sec = _MIDI_Time >> TIME_PRECISION; pos->milliseconds = (mil >> TIME_PRECISION) + (sec * 1000); pos->tickposition = _MIDI_PositionInTicks; pos->measure = _MIDI_Measure; pos->beat = _MIDI_Beat; pos->tick = _MIDI_Tick;}/*--------------------------------------------------------------------- Function: MIDI_GetSongLength Returns the length of the song.---------------------------------------------------------------------*/void MIDI_GetSongLength( songposition *pos){ uint32_t mil; uint32_t sec; mil = (_MIDI_TotalTime & ((1 << TIME_PRECISION) - 1)) * 1000; sec = _MIDI_TotalTime >> TIME_PRECISION; pos->milliseconds = (mil >> TIME_PRECISION) + (sec * 1000); pos->measure = _MIDI_TotalMeasures; pos->beat = _MIDI_TotalBeats; pos->tick = _MIDI_TotalTicks; pos->tickposition = 0;}/*--------------------------------------------------------------------- Function: MIDI_InitEMIDI Sets up the EMIDI---------------------------------------------------------------------*/static void _MIDI_InitEMIDI( void){ int32_t event; int32_t command; int32_t channel; int32_t length; int32_t IncludeFound; track *Track; int32_t tracknum; int32_t type; int32_t c1; int32_t c2; type = EMIDI_GeneralMIDI; _MIDI_ResetTracks(); _MIDI_TotalTime = 0; _MIDI_TotalTicks = 0; _MIDI_TotalBeats = 0; _MIDI_TotalMeasures = 0; Track = _MIDI_TrackPtr; tracknum = 0; while ((tracknum < _MIDI_NumTracks) && (Track != NULL)) { _MIDI_Tick = 0; _MIDI_Beat = 1; _MIDI_Measure = 1; _MIDI_Time = 0; _MIDI_BeatsPerMeasure = 4; _MIDI_TicksPerBeat = _MIDI_Division; _MIDI_TimeBase = 4; _MIDI_PositionInTicks = 0; _MIDI_ActiveTracks = 0; _MIDI_Context = -1; Track->RunningStatus = 0; Track->active = TRUE; Track->EMIDI_ProgramChange = FALSE; Track->EMIDI_VolumeChange = FALSE; Track->EMIDI_IncludeTrack = TRUE; memset(Track->context, 0, sizeof(Track->context)); while (Track->delay > 0) { _MIDI_AdvanceTick(); Track->delay--; } IncludeFound = FALSE; while (Track->active) { 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); while (Track->delay > 0) { _MIDI_AdvanceTick(); Track->delay--; } } 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); length = _MIDI_CommandLengths[ command ]; if (command == MIDI_CONTROL_CHANGE) { if (*Track->pos == MIDI_MONO_MODE_ON) { length++; } GET_NEXT_EVENT(Track, c1); GET_NEXT_EVENT(Track, c2); length -= 2; switch (c1) { case EMIDI_LOOP_START : case EMIDI_SONG_LOOP_START : if (c2 == 0) { Track->context[ 0 ].loopcount = EMIDI_INFINITE; } else { Track->context[ 0 ].loopcount = c2; } Track->context[ 0 ].pos = Track->pos; Track->context[ 0 ].loopstart = Track->pos; Track->context[ 0 ].RunningStatus = Track->RunningStatus; Track->context[ 0 ].time = _MIDI_Time; Track->context[ 0 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick; Track->context[ 0 ].tick = _MIDI_Tick; Track->context[ 0 ].beat = _MIDI_Beat; Track->context[ 0 ].measure = _MIDI_Measure; Track->context[ 0 ].BeatsPerMeasure = _MIDI_BeatsPerMeasure; Track->context[ 0 ].TicksPerBeat = _MIDI_TicksPerBeat; Track->context[ 0 ].TimeBase = _MIDI_TimeBase; break; case EMIDI_LOOP_END : case EMIDI_SONG_LOOP_END : if (c2 == EMIDI_END_LOOP_VALUE) { Track->context[ 0 ].loopstart = NULL; Track->context[ 0 ].loopcount = 0; } break; case EMIDI_INCLUDE_TRACK : if (EMIDI_AffectsCurrentCard(c2, type)) { //printf( "Include track %d on card %d\n", tracknum, c2 ); IncludeFound = TRUE; Track->EMIDI_IncludeTrack = TRUE; } else if (!IncludeFound) { //printf( "Track excluded %d on card %d\n", tracknum, c2 ); IncludeFound = TRUE; Track->EMIDI_IncludeTrack = FALSE; } break; case EMIDI_EXCLUDE_TRACK : if (EMIDI_AffectsCurrentCard(c2, type)) { //printf( "Exclude track %d on card %d\n", tracknum, c2 ); Track->EMIDI_IncludeTrack = FALSE; } break; case EMIDI_PROGRAM_CHANGE : if (!Track->EMIDI_ProgramChange) //printf( "Program change on track %d\n", tracknum ); Track->EMIDI_ProgramChange = TRUE; break; case EMIDI_VOLUME_CHANGE : if (!Track->EMIDI_VolumeChange) //printf( "Volume change on track %d\n", tracknum ); Track->EMIDI_VolumeChange = TRUE; break; case EMIDI_CONTEXT_START : if ((c2 > 0) && (c2 < EMIDI_NUM_CONTEXTS)) { Track->context[ c2 ].pos = Track->pos; Track->context[ c2 ].loopstart = Track->context[ 0 ].loopstart; Track->context[ c2 ].loopcount = Track->context[ 0 ].loopcount; Track->context[ c2 ].RunningStatus = Track->RunningStatus; Track->context[ c2 ].time = _MIDI_Time; Track->context[ c2 ].FPSecondsPerTick = _MIDI_FPSecondsPerTick; Track->context[ c2 ].tick = _MIDI_Tick; Track->context[ c2 ].beat = _MIDI_Beat; Track->context[ c2 ].measure = _MIDI_Measure; Track->context[ c2 ].BeatsPerMeasure = _MIDI_BeatsPerMeasure; Track->context[ c2 ].TicksPerBeat = _MIDI_TicksPerBeat; Track->context[ c2 ].TimeBase = _MIDI_TimeBase; } break; case EMIDI_CONTEXT_END : break; } } Track->pos += length; Track->delay = _MIDI_ReadDelta(Track); while (Track->delay > 0) { _MIDI_AdvanceTick(); Track->delay--; } } _MIDI_TotalTime = max(_MIDI_TotalTime, _MIDI_Time); if (RELATIVE_BEAT(_MIDI_Measure, _MIDI_Beat, _MIDI_Tick) > RELATIVE_BEAT(_MIDI_TotalMeasures, _MIDI_TotalBeats, _MIDI_TotalTicks)) { _MIDI_TotalTicks = _MIDI_Tick; _MIDI_TotalBeats = _MIDI_Beat; _MIDI_TotalMeasures = _MIDI_Measure; } Track++; tracknum++; } _MIDI_ResetTracks();}/*--------------------------------------------------------------------- Function: MIDI_LoadTimbres Preloads the timbres on cards that use patch-caching.---------------------------------------------------------------------*/void MIDI_LoadTimbres( void){ int32_t event; int32_t command; int32_t channel; int32_t length; int32_t Finished; track *Track; int32_t tracknum; Track = _MIDI_TrackPtr; tracknum = 0; while ((tracknum < _MIDI_NumTracks) && (Track != NULL)) { Finished = FALSE; while (!Finished) { GET_NEXT_EVENT(Track, event); if (GET_MIDI_COMMAND(event) == MIDI_SPECIAL) { switch (event) { case MIDI_SYSEX : case MIDI_SYSEX_CONTINUE : length = _MIDI_ReadDelta(Track); Track->pos += length; break; case MIDI_META_EVENT : GET_NEXT_EVENT(Track, command); GET_NEXT_EVENT(Track, length); if (command == MIDI_END_OF_TRACK) { Finished = TRUE; } Track->pos += length; break; } if (!Finished) { _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); length = _MIDI_CommandLengths[ command ]; if (command == MIDI_CONTROL_CHANGE) { if (*Track->pos == MIDI_MONO_MODE_ON) { length++; } if (*Track->pos == EMIDI_PROGRAM_CHANGE) { _MIDI_Funcs->LoadPatch(*(Track->pos + 1)); } } if (channel == MIDI_RHYTHM_CHANNEL) { if (command == MIDI_NOTE_ON) { _MIDI_Funcs->LoadPatch(128 + *Track->pos); } } else { if (command == MIDI_PROGRAM_CHANGE) { _MIDI_Funcs->LoadPatch(*Track->pos); } } Track->pos += length; _MIDI_ReadDelta(Track); } Track++; tracknum++; } _MIDI_ResetTracks();}void MIDI_UpdateMusic(void){ if (!_MIDI_SongLoaded || !_MIDI_SongActive) return; while (_MPU_BuffersWaiting < 4) _MIDI_ServiceRoutine();}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?