midi.c

来自「An interactive water fountain. A realis」· C语言 代码 · 共 2,070 行 · 第 1/4 页

C
2,070
字号
        _MIDI_Context = context;    }}/*---------------------------------------------------------------------   Function: MIDI_GetContext   Returns the current song context.---------------------------------------------------------------------*/int32_t MIDI_GetContext(    void){    return _MIDI_Context;}/*---------------------------------------------------------------------   Function: MIDI_SetLoopFlag   Sets whether the song should loop when finished or not.---------------------------------------------------------------------*/void MIDI_SetLoopFlag(    int32_t loopflag){    _MIDI_Loop = loopflag;}/*---------------------------------------------------------------------   Function: MIDI_ContinueSong   Continues playback of a paused song.---------------------------------------------------------------------*/void MIDI_ContinueSong(    void){    if (_MIDI_SongLoaded)    {        _MIDI_SongActive = TRUE;        MPU_Unpause();    }}/*---------------------------------------------------------------------   Function: MIDI_PauseSong   Pauses playback of the current song.---------------------------------------------------------------------*/void MIDI_PauseSong(    void){    if (_MIDI_SongLoaded)    {        _MIDI_SongActive = FALSE;        MIDI_AllNotesOff();        MPU_Pause();    }}/*---------------------------------------------------------------------   Function: MIDI_SongPlaying   Returns whether a song is playing or not.---------------------------------------------------------------------*/int32_t MIDI_SongPlaying(    void){    return(_MIDI_SongActive);}/*---------------------------------------------------------------------   Function: MIDI_SetMidiFuncs   Selects the routines that send the MIDI data to the music device.---------------------------------------------------------------------*/void MIDI_SetMidiFuncs(    midifuncs *funcs){    _MIDI_Funcs = funcs;}/*---------------------------------------------------------------------   Function: MIDI_StopSong   Stops playback of the currently playing song.---------------------------------------------------------------------*/void MIDI_StopSong(    void){    if (_MIDI_SongLoaded)    {        _MIDI_SongActive = FALSE;        _MIDI_SongLoaded = FALSE;        MIDI_Reset();        _MIDI_ResetTracks();        if (_MIDI_Funcs->ReleasePatches)        {            _MIDI_Funcs->ReleasePatches();        }        Bfree(_MIDI_TrackPtr);        _MIDI_TrackPtr     = NULL;        _MIDI_NumTracks    = 0;        _MIDI_TrackMemSize = 0;        _MIDI_TotalTime     = 0;        _MIDI_TotalTicks    = 0;        _MIDI_TotalBeats    = 0;        _MIDI_TotalMeasures = 0;        MPU_Reset();    }}/*---------------------------------------------------------------------   Function: MIDI_PlaySong   Begins playback of a MIDI song.---------------------------------------------------------------------*/int32_t MIDI_PlaySong(    char *song,    int32_t loopflag){    int32_t    numtracks;    int32_t    format;    int32_t   headersize;    int32_t   tracklength;    track *CurrentTrack;    char *ptr;    if (_MIDI_SongLoaded)    {        MIDI_StopSong();    }    MPU_Init(MUSIC_SoundDevice);    _MIDI_Loop = loopflag;    if (_MIDI_Funcs == NULL)    {        return(MIDI_NullMidiModule);    }    if (*(uint32_t *)song != MIDI_HEADER_SIGNATURE)    {        return(MIDI_InvalidMidiFile);    }    song += 4;    headersize      = _MIDI_ReadNumber(song, 4);    song += 4;    format          = _MIDI_ReadNumber(song, 2);    _MIDI_NumTracks = _MIDI_ReadNumber(song + 2, 2);    _MIDI_Division  = _MIDI_ReadNumber(song + 4, 2);    if (_MIDI_Division < 0)    {        // If a SMPTE time division is given, just set to 96 so no errors occur        _MIDI_Division = 96;    }    if (format > MAX_FORMAT)    {        return(MIDI_UnknownMidiFormat);    }    ptr = song + headersize;    if (_MIDI_NumTracks == 0)    {        return(MIDI_NoTracks);    }    _MIDI_TrackMemSize = _MIDI_NumTracks  * sizeof(track);    _MIDI_TrackPtr = Bmalloc(_MIDI_TrackMemSize);    if (_MIDI_TrackPtr == NULL)    {        return(MIDI_NoMemory);    }    CurrentTrack = _MIDI_TrackPtr;    numtracks    = _MIDI_NumTracks;    while (numtracks--)    {        if (*(uint32_t *)ptr != MIDI_TRACK_SIGNATURE)        {            Bfree(_MIDI_TrackPtr);            _MIDI_TrackPtr = NULL;            _MIDI_TrackMemSize = 0;            return(MIDI_InvalidTrack);        }        tracklength = _MIDI_ReadNumber(ptr + 4, 4);        ptr += 8;        CurrentTrack->start = ptr;        ptr += tracklength;        CurrentTrack++;    }    if (_MIDI_Funcs->GetVolume != NULL)    {        _MIDI_TotalVolume = _MIDI_Funcs->GetVolume();    }    _MIDI_InitEMIDI();    if (_MIDI_Funcs->LoadPatch)    {        MIDI_LoadTimbres();    }    _MIDI_ResetTracks();    if (!Reset)    {        MIDI_Reset();    }    Reset = FALSE;    MIDI_SetDivision(_MIDI_Division);    //MIDI_SetTempo( 120 );    _MIDI_SongLoaded = TRUE;    _MIDI_SongActive = TRUE;    while (_MPU_BuffersWaiting < 4) _MIDI_ServiceRoutine();    MPU_BeginPlayback();    return(MIDI_Ok);}/*---------------------------------------------------------------------   Function: MIDI_SetTempo   Sets the song tempo.---------------------------------------------------------------------*/void MIDI_SetTempo(    int32_t tempo){    int32_t tickspersecond;    MIDI_Tempo = tempo;    tickspersecond = ((tempo) * _MIDI_Division) / 60;    _MIDI_FPSecondsPerTick = (1 << TIME_PRECISION) / tickspersecond;    MPU_SetTempo(tempo);}void MIDI_SetDivision(int32_t division){    MPU_SetDivision(division);}/*---------------------------------------------------------------------   Function: MIDI_GetTempo   Returns the song tempo.---------------------------------------------------------------------*/int32_t MIDI_GetTempo(    void){    return(MIDI_Tempo);}/*---------------------------------------------------------------------   Function: _MIDI_ProcessNextTick   Sets the position of the song pointer.---------------------------------------------------------------------*/static int32_t _MIDI_ProcessNextTick(    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;    Track = _MIDI_TrackPtr;    tracknum = 0;    while ((tracknum < _MIDI_NumTracks) && (Track != NULL))    {        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 :                break;            case MIDI_NOTE_ON :                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, c1);                }                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)        {            break;        }    }    _MIDI_AdvanceTick();    return(TimeSet);}/*---------------------------------------------------------------------   Function: MIDI_SetSongTick   Sets the position of the song pointer.---------------------------------------------------------------------*/void MIDI_SetSongTick(    uint32_t PositionInTicks){    if (!_MIDI_SongLoaded)    {        return;    }    MIDI_PauseSong();    if (PositionInTicks < _MIDI_PositionInTicks)    {        _MIDI_ResetTracks();        MIDI_Reset();    }    while (_MIDI_PositionInTicks < PositionInTicks)    {        if (_MIDI_ProcessNextTick())        {            break;        }        if (_MIDI_ActiveTracks == 0)        {            _MIDI_ResetTracks();            if (!_MIDI_Loop)            {                return;            }            break;        }    }    MIDI_SetVolume(_MIDI_TotalVolume);    MIDI_ContinueSong();}/*---------------------------------------------------------------------   Function: MIDI_SetSongTime

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?