static void Play(MIDI_MusicTrack *tracks, unsigned int nofTracks) { int itemNo; uint8_t channel; uint32_t currTimeMs; TickType_t startTicks; unsigned int nofFinished; /* init defaults */ for(channel=0;channel<nofTracks;channel++) { VS1_MIDI_SetBank(channel, 0); VS1_MIDI_SetInstrument(channel, VS1_MIDI_INSTR_Default); VS1_MIDI_SetVolume(channel, 127); } startTicks = FRTOS1_xTaskGetTickCount(); itemNo = 0; for(;;) { /* breaks */ currTimeMs = (FRTOS1_xTaskGetTickCount()-startTicks)/portTICK_RATE_MS; #if 0 if (currTimeMs>15000) { break; } #endif nofFinished = 0; for(channel=0;channel<nofTracks;channel++) { if (!PlayTrackItem(&tracks[channel], currTimeMs, channel)) { nofFinished++; } } if (nofFinished==nofTracks) { /* all finished */ break; } FRTOS1_vTaskDelay(1/portTICK_RATE_MS); itemNo++; } }
static bool PlayTrackItem(MIDI_MusicTrack *track, unsigned int currTimeMs, uint8_t channel) { uint32_t beatsPerSecond = 2; /* 120 bpm */ uint32_t currentMillis; uint32_t ppqn; /* ticks per beat/quarter note */ uint32_t tempo = 110; uint8_t event; unsigned int itemNo; ppqn = track->nofTicksPerQuarterNote; for(;;) { /* breaks */ itemNo = track->currLine; if (itemNo>=track->nofLines) { /* out of list */ return FALSE; /* do not continue any more */ } currentMillis = ((uint32_t)track->lines[itemNo].beat*1000UL)/beatsPerSecond; currentMillis += ((uint32_t)track->lines[itemNo].tick*60000UL)/ppqn/tempo; if (currentMillis>currTimeMs) { return TRUE; /* continue */ } event = track->lines[itemNo].event; switch(event) { case MIDI_BANK: VS1_MIDI_SetBank(channel, track->lines[itemNo].val1); break; case MIDI_NOTE_ON: if (track->lines[itemNo].val2==0) { /* note on with velocity zero is a note off */ VS1_MIDI_NoteOff(channel, track->lines[itemNo].val1, 0); } else { VS1_MIDI_NoteOn(channel, track->lines[itemNo].val1, track->lines[itemNo].val2); } break; case MIDI_NOTE_OFF: VS1_MIDI_NoteOff(channel, track->lines[itemNo].val1, track->lines[itemNo].val2); break; case MIDI_PATCH: VS1_MIDI_SetInstrument(channel, track->lines[itemNo].val1); break; case MIDI_VOLUME: VS1_MIDI_SetVolume(channel, track->lines[itemNo].val1); break; case MIDI_PAN: VS1_MIDI_SetPan(channel, track->lines[itemNo].val1); break; case MIDI_END_OF_TRACK: VS1_MIDI_AllSoundOff(channel); break; } track->currLine++; } /* for */ return TRUE; }
static void PlayMIDI(void) { int instrument, note; VS1_MIDI_SetBank(0, 0); for(instrument=0; instrument<127; instrument++) { VS1_MIDI_SetInstrument(0, instrument); for(note=30; note<40; note++) { VS1_MIDI_NoteOn(0, note, 127); FRTOS1_vTaskDelay(200/portTICK_RATE_MS); VS1_MIDI_NoteOff(0, note, 127); FRTOS1_vTaskDelay(50/portTICK_RATE_MS); } FRTOS1_vTaskDelay(100/portTICK_RATE_MS); } }