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 + -
显示快捷键?