添加一些关于midi播放的项目
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "SynthCore.h"
|
||||
#include "Player.h"
|
||||
|
||||
Player *GlobalPlayerPtr;
|
||||
|
||||
void Player32kProc(Player *player)
|
||||
{
|
||||
SynthAsm(&(player->synthesizer));
|
||||
if (player->decoder.status == STATUS_DECODING)
|
||||
player->decoder.currentTick++;
|
||||
if (player->synthesizer.decayGenTick < 200)
|
||||
player->synthesizer.decayGenTick += 1;
|
||||
}
|
||||
|
||||
void ScoreDecodeProcess(Player *player)
|
||||
{
|
||||
uint8_t temp;
|
||||
|
||||
if (player->decoder.status == STATUS_DECODING)
|
||||
{
|
||||
if ((player->decoder.currentTick >> 8) >= player->decoder.lastScoreTick)
|
||||
{
|
||||
do
|
||||
{
|
||||
temp = *(player->decoder.scorePointer);
|
||||
player->decoder.scorePointer++;
|
||||
if (temp == 0xFF)
|
||||
player->decoder.status = STATUS_STOP;
|
||||
else
|
||||
NoteOnAsm(&(player->synthesizer), temp);
|
||||
} while ((temp & 0x80) == 0);
|
||||
|
||||
UpdateNextScoreTick(&(player->decoder));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PlaySchedulerNextScore(Player *player)
|
||||
{
|
||||
player->scheduler.switchDirect = SCHEDULER_SCORE_NEXT;
|
||||
player->scheduler.status = SCHEDULER_SWITCHING;
|
||||
StopDecode(player);
|
||||
}
|
||||
|
||||
void PlaySchedulerPreviousScore(Player *player)
|
||||
{
|
||||
player->scheduler.switchDirect = SCHEDULER_SCORE_PREV;
|
||||
player->scheduler.status = SCHEDULER_SWITCHING;
|
||||
StopDecode(player);
|
||||
}
|
||||
|
||||
uint8_t *GetScorePhyiscalAddr(uint32_t addr)
|
||||
{
|
||||
return (uint8_t *)((uint32_t)(&ScoreDataList) + addr);
|
||||
}
|
||||
|
||||
void PlaySchedulerProcess(Player *player)
|
||||
{
|
||||
uint32_t *ScoreList = (&(player->scheduler.scoreListHeader)->firstAddr);
|
||||
|
||||
switch (player->scheduler.status)
|
||||
{
|
||||
case SCHEDULER_READY_TO_SWITCH:
|
||||
if (player->decoder.status == STATUS_STOP)
|
||||
{
|
||||
player->scheduler.switchDirect = SCHEDULER_SCORE_NEXT;
|
||||
player->scheduler.status = SCHEDULER_SWITCHING;
|
||||
StopDecode(player);
|
||||
}
|
||||
break;
|
||||
|
||||
case SCHEDULER_SWITCHING:
|
||||
player->scheduler.status = player->scheduler.switchDirect;
|
||||
break;
|
||||
|
||||
case SCHEDULER_SCORE_PREV:
|
||||
player->scheduler.currentScoreIndex--;
|
||||
if (player->scheduler.currentScoreIndex < 0)
|
||||
player->scheduler.currentScoreIndex = player->scheduler.maxScoreNum - 1;
|
||||
PlayScore(player, GetScorePhyiscalAddr(ScoreList[player->scheduler.currentScoreIndex]));
|
||||
player->scheduler.status = SCHEDULER_READY_TO_SWITCH;
|
||||
|
||||
break;
|
||||
|
||||
case SCHEDULER_SCORE_NEXT:
|
||||
player->scheduler.currentScoreIndex++;
|
||||
if (player->scheduler.currentScoreIndex >= player->scheduler.maxScoreNum)
|
||||
{
|
||||
player->scheduler.status = SCHEDULER_STOP;
|
||||
player->scheduler.currentScoreIndex = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlayScore(player, GetScorePhyiscalAddr(ScoreList[player->scheduler.currentScoreIndex]));
|
||||
player->scheduler.status = SCHEDULER_READY_TO_SWITCH;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SCHEDULER_STOP:
|
||||
/* Do nothing */
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerProcess(Player *player)
|
||||
{
|
||||
SynthGenEnvelopeProcess(&(player->synthesizer));
|
||||
ScoreDecodeProcess(player);
|
||||
PlaySchedulerProcess(player);
|
||||
}
|
||||
|
||||
void UpdateNextScoreTick(ScoreDecoder *decoder)
|
||||
{
|
||||
uint32_t tempU32;
|
||||
uint8_t temp;
|
||||
tempU32 = decoder->lastScoreTick;
|
||||
do
|
||||
{
|
||||
temp = *(decoder->scorePointer);
|
||||
decoder->scorePointer++;
|
||||
tempU32 += temp;
|
||||
} while (temp == 0xFF);
|
||||
decoder->lastScoreTick = tempU32;
|
||||
}
|
||||
|
||||
void StartPlayScheduler(Player *player)
|
||||
{
|
||||
if (ScoreDataList.identifer[0] == 'S' &&
|
||||
ScoreDataList.identifer[1] == 'C' &&
|
||||
ScoreDataList.identifer[2] == 'R' &&
|
||||
ScoreDataList.identifer[3] == 'E')
|
||||
{
|
||||
player->scheduler.scoreListHeader = &ScoreDataList;
|
||||
player->scheduler.currentScoreIndex = -1;
|
||||
player->scheduler.maxScoreNum = (player->scheduler.scoreListHeader)->scoreCount;
|
||||
player->scheduler.schedulerMode = MODE_ORDER_PLAY;
|
||||
player->scheduler.status = SCHEDULER_READY_TO_SWITCH;
|
||||
}
|
||||
else
|
||||
{
|
||||
player->scheduler.status = SCHEDULER_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
void SchedulerSetIntialRandomSeed(Player *player, uint8_t randomSeed)
|
||||
{
|
||||
player->scheduler.currentScoreIndex = (randomSeed % player->scheduler.maxScoreNum) - 1;
|
||||
}
|
||||
|
||||
void StopPlayScheduler(Player *player)
|
||||
{
|
||||
StopDecode(player);
|
||||
player->scheduler.status = SCHEDULER_STOP;
|
||||
}
|
||||
|
||||
void PlayScore(Player *player, uint8_t *score)
|
||||
{
|
||||
player->synthesizer.hwSet(SYNTH_HW_ON);
|
||||
player->decoder.currentTick = 0;
|
||||
player->decoder.lastScoreTick = 0;
|
||||
|
||||
player->decoder.scorePointer = score;
|
||||
UpdateNextScoreTick(&(player->decoder));
|
||||
player->decoder.status = STATUS_DECODING;
|
||||
}
|
||||
|
||||
void StopDecode(Player *player)
|
||||
{
|
||||
player->synthesizer.hwSet(SYNTH_HW_OFF);
|
||||
player->decoder.status = STATUS_STOP;
|
||||
player->decoder.currentTick = 0;
|
||||
player->decoder.lastScoreTick = 0;
|
||||
}
|
||||
|
||||
void PlayerInit(Player *player)
|
||||
{
|
||||
GlobalPlayerPtr = player;
|
||||
player->decoder.status = STATUS_STOP;
|
||||
player->decoder.currentTick = 0;
|
||||
player->decoder.lastScoreTick = 0;
|
||||
player->decoder.scorePointer = NULL;
|
||||
SynthInit(&(player->synthesizer));
|
||||
}
|
||||
Reference in New Issue
Block a user