|
-
- #include "MidiLock.h"
- #include "MidiPlayer.h"
- #include "MidiSong.h"
-
-
- MidiPlayer::MidiPlayer(std::shared_ptr<IPlayerHost> host, std::shared_ptr<MidiSong> song) :
- host(host), song(song), trackPlayer(song->getTrack(0))
- {
- ++_mdb;
- }
-
- void MidiPlayer::timeElapsed(float seconds)
- {
-
- curMetricTime += seconds * 120.0f / 60.0f; // fixed at 120 bpm for now
- if (!isPlaying) {
- return;
- }
- bool locked = song->lock->playerTryLock();
- if (locked) {
- if (song->lock->dataModelDirty()) {
- trackPlayer.reset();
- }
- trackPlayer.updateToMetricTime(curMetricTime, host.get());
- song->lock->playerUnlock();
- } else {
- trackPlayer.reset();
- host->onLockFailed();
- }
- }
-
- TrackPlayer::TrackPlayer(MidiTrackPtr track) : track(track)
- {
- }
-
- TrackPlayer::~TrackPlayer()
- {
- //curEvent = nullptr;
-
- }
-
- void TrackPlayer::updateToMetricTime(double time, IPlayerHost* host)
- {
- // If we had a conflict and needed to reset, then
- // start all over from beginning
- if (isReset) {
- curEvent = curEvent = track->begin();
- noteOffTime = -1;
- isReset = false;
- loopStart = 0;
- }
- // keep processing events until we are caught up
- while (playOnce(time, host)) {
-
- }
- }
-
- bool TrackPlayer::playOnce(double metricTime, IPlayerHost* host)
- {
- bool didSomething = false;
-
- if (noteOffTime >= 0 && noteOffTime <= metricTime) {
- host->setGate(false);
- noteOffTime = -1;
- didSomething = true;
- }
-
- const double eventStart = (loopStart + curEvent->first);
- if (eventStart <= metricTime) {
- MidiEventPtr event = curEvent->second;
- switch (event->type) {
- case MidiEvent::Type::Note:
- {
- MidiNoteEventPtr note = safe_cast<MidiNoteEvent>(event);
- // should now output the note.
- host->setGate(true);
- host->setCV(note->pitchCV);
-
- // and save off the note-off time.
- noteOffTime = note->duration + eventStart;
- ++curEvent;
- }
- break;
- case MidiEvent::Type::End:
- // for now, should loop.
- // uh oh!
- // assert(false);
- // curMetricTime = 0;
- // trackPlayStatus.curEvent = song->getTrack(0)->begin();
- loopStart += curEvent->first;
- curEvent = track->begin();
- break;
- default:
- assert(false);
- }
-
- didSomething = true;
- }
- return didSomething;
- }
-
- #if 0
- void MidiPlayer::timeElapsed(float seconds)
- {
- curMetricTime += seconds * 120.0f / 60.0f; // fixed at 120 bpm for now
- bool locked = song->lock->playerTryLock();
- if (locked) {
- while (playOnce()) {
- }
- song->lock->playerUnlock();
- } else {
- trackPlayStatus.reset();
- host->onLockFailed();
- }
- }
-
-
- bool MidiPlayer::playOnce()
- {
- if (!isPlaying) {
- return false;
- }
- bool didSomething = false;
-
- // If we had a conflict and needed to reset, then
- // seek from the start to where we should be.
- if (trackPlayStatus.isReset) {
- trackPlayStatus.seekTo(song.get(), curMetricTime, host.get());
- return true;
- }
-
- if (trackPlayStatus.noteOffTime >= 0 && trackPlayStatus.noteOffTime <= curMetricTime) {
- host->setGate(false);
- trackPlayStatus.noteOffTime = -1;
- didSomething = true;
- }
-
- if (trackPlayStatus.curEvent->first <= curMetricTime) {
- MidiEventPtr event = trackPlayStatus.curEvent->second;
- switch (event->type) {
- case MidiEvent::Type::Note:
- {
- MidiNoteEventPtr note = safe_cast<MidiNoteEvent>(event);
- // should now output the note.
- host->setGate(true);
- host->setCV(note->pitchCV);
-
- // and save off the note-off time.
- trackPlayStatus.noteOffTime = note->duration + note->startTime;
- ++trackPlayStatus.curEvent;
- }
- break;
- case MidiEvent::Type::End:
- // for now, should loop.
- curMetricTime = 0;
- trackPlayStatus.curEvent = song->getTrack(0)->begin();
- break;
- default:
- assert(false);
- }
-
- didSomething = true;
- }
- return didSomething;
- }
-
-
- void TrackPlayStatus::seekTo(MidiSong* song, float time, IPlayerHost* host)
- {
- isReset = false;
- curEvent = song->getTrack(0)->begin();
- while (curEvent->second->startTime < time) {
- ++curEvent;
- if (curEvent == song->getTrack(0)->end()) {
- assert(false);
- return;
- }
- MidiEventPtr evt = curEvent->second;
- MidiNoteEventPtr note = safe_cast< MidiNoteEvent>(evt);
- assert(note);
- noteOffTime = note->startTime + note->duration;
- }
- }
- #endif
|