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