1 /*
2     Drumstick MIDI File Player Multiplatform Program
3     Copyright (C) 2006-2021, Pedro Lopez-Cabanillas <plcl@users.sf.net>
4 
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 3 of the License, or
8     (at your option) any later version.
9 
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14 
15     You should have received a copy of the GNU General Public License
16     along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 
19 #ifdef WIN32
20 #include <windows.h>
21 #endif
22 
23 #include <thread>
24 #include <chrono>
25 #include <typeinfo>
26 
27 #include <QAbstractEventDispatcher>
28 #include <QThread>
29 #include <QtMath>
30 #include "events.h"
31 #include "seqplayer.h"
32 #include "settings.h"
33 
34 using namespace drumstick::rt;
35 
initChannels()36 void SequencePlayer::initChannels()
37 {
38     for (int chan = 0; chan < MIDI_STD_CHANNELS; ++chan) {
39         m_lastpgm[chan] = 0;
40         m_volumeShift[chan] = 1.0;
41         m_volume[chan] = 100;
42         m_muted[chan] = false;
43         m_locked[chan] = false;
44         m_lockedpgm[chan] = 0;
45     }
46 }
47 
isLoopEnabled() const48 bool SequencePlayer::isLoopEnabled() const
49 {
50     return m_loopEnabled;
51 }
52 
setLoop(bool enabled)53 void SequencePlayer::setLoop(bool enabled)
54 {
55     m_loopEnabled = enabled;
56 }
57 
setLoop(int loopStart,int loopEnd)58 void SequencePlayer::setLoop(int loopStart, int loopEnd)
59 {
60     m_loopEnabled = true;
61     m_loopStart = loopStart;
62     m_loopEnd = loopEnd;
63 }
64 
loopEnd() const65 int SequencePlayer::loopEnd() const
66 {
67     return m_loopEnd;
68 }
69 
loopStart() const70 int SequencePlayer::loopStart() const
71 {
72     return m_loopStart;
73 }
74 
SequencePlayer()75 SequencePlayer::SequencePlayer() :
76     m_port(nullptr),
77     m_songPosition(0),
78     m_loopEnabled(false),
79     m_loopStart(0),
80     m_loopEnd(0),
81     m_echoResolution(50),
82     m_pitchShift(0),
83     m_volumeFactor(100),
84     m_latestBeat(nullptr),
85     m_firstBeat(nullptr)
86 {
87     initChannels();
88 }
89 
~SequencePlayer()90 SequencePlayer::~SequencePlayer()
91 {
92     //qDebug() << Q_FUNC_INFO;
93     if (isRunning()) {
94         stop();
95     }
96 }
97 
isRunning()98 bool SequencePlayer::isRunning()
99 {
100     return thread()->isRunning() && !thread()->isInterruptionRequested();
101 }
102 
stop()103 void SequencePlayer::stop()
104 {
105     thread()->requestInterruption();
106 }
107 
shutupSound()108 void SequencePlayer::shutupSound()
109 {
110     if (m_port != nullptr) {
111         for (int channel = 0; channel < 16; ++channel) {
112             m_port->sendController(channel, ControllerEvent::MIDI_CTL_ALL_SOUNDS_OFF, 0);
113         }
114     }
115 }
116 
playEvent(MIDIEvent * ev)117 void SequencePlayer::playEvent(MIDIEvent* ev)
118 {
119     static const std::type_info& textId = typeid(TextEvent);
120     static const std::type_info& tempoId = typeid(TempoEvent);
121     static const std::type_info& timeSigId = typeid(TimeSignatureEvent);
122     static const std::type_info& keySigId = typeid(KeySignatureEvent);
123     static const std::type_info& beatId = typeid(BeatEvent);
124     static const std::type_info& sysexId = typeid (SysExEvent);
125 
126     if (m_port == nullptr)
127         return;
128 
129     if (ev->isChannel()) {
130         ChannelEvent* ev2 = static_cast<ChannelEvent*>(ev);
131         int chan = ev2->channel();
132         if (m_muted[chan]) {
133             //qDebug() << "muted channel:" << chan;
134             return;
135         }
136         switch(ev->status()) {
137         case MIDI_STATUS_NOTEOFF: {
138                 NoteOffEvent* event = static_cast<NoteOffEvent*>(ev);
139                 int key = event->key();
140                 int vel = event->velocity();
141                 if (chan != MIDI_GM_STD_DRUM_CHANNEL) {
142                     key += m_pitchShift;
143                 }
144                 m_port->sendNoteOff(chan, key, vel);
145                 //qDebug() << m_songPosition << ev->tick() << " NoteOff: " << chan << key << vel;
146                 emit midiNoteOff(chan, key, vel);
147             }
148             break;
149         case MIDI_STATUS_NOTEON: {
150                 NoteOnEvent* event = static_cast<NoteOnEvent*>(ev);
151                 int vel = event->velocity();
152                 int key = event->key();
153                 if (chan != MIDI_GM_STD_DRUM_CHANNEL) {
154                     key += m_pitchShift;
155                 }
156                 m_port->sendNoteOn(chan, key, vel);
157                 //qDebug() << m_songPosition << ev->tick() << " NoteOn: " << chan << key << vel;
158                 emit midiNoteOn(chan, key, vel);
159             }
160             break;
161         case MIDI_STATUS_KEYPRESURE: {
162                 KeyPressEvent* event = static_cast<KeyPressEvent*>(ev);
163                 int vel = event->velocity();
164                 int key = event->key();
165                 if (chan != MIDI_GM_STD_DRUM_CHANNEL) {
166                     key += m_pitchShift;
167                 }
168                 m_port->sendKeyPressure(chan, key, vel);
169                 //qDebug() << m_songPosition << event->tick() << " KeyPress: " << chan << key << vel;
170                 emit midiKeyPressure(chan, key, vel);
171             }
172             break;
173         case MIDI_STATUS_CONTROLCHANGE: {
174                 ControllerEvent* event = static_cast<ControllerEvent*>(ev);
175                 int par = event->param();
176                 int val = event->value();
177                 if (par == ControllerEvent::MIDI_CTL_MSB_MAIN_VOLUME) {
178                     m_volume[chan] = val;
179                     val = qFloor(val * m_volumeShift[chan]);
180                     if (val < 0) val = 0;
181                     if (val > 127) val = 127;
182                 }
183                 m_port->sendController(chan, par, val);
184                 //qDebug() << m_songPosition << event->tick() << " CtrlChg: " << chan << par << val;
185                 emit midiController(chan, par, val);
186             }
187             break;
188         case MIDI_STATUS_PROGRAMCHANGE: {
189                 ProgramChangeEvent* event = static_cast<ProgramChangeEvent*>(ev);
190                 int pgm = m_locked[chan] ? m_lockedpgm[chan] : event->program();
191                 m_port->sendProgram(chan, pgm);
192                 m_lastpgm[chan] = pgm;
193                 //qDebug() << m_songPosition << event->tick() << " PgmChg: " << chan << pgm;
194                 emit midiProgram(chan, pgm);
195             }
196             break;
197         case MIDI_STATUS_CHANNELPRESSURE: {
198                 ChanPressEvent* event = static_cast<ChanPressEvent*>(ev);
199                 int val = event->value();
200                 m_port->sendChannelPressure(chan, val);
201                 //qDebug() << m_songPosition << event->tick() << " ChanPress: " << chan << val;
202                 emit midiChannelPressure(chan, val);
203             }
204             break;
205         case MIDI_STATUS_PITCHBEND: {
206                 PitchBendEvent* event = static_cast<PitchBendEvent*>(ev);
207                 int val = event->value();
208                 m_port->sendPitchBend(chan, val);
209                 //qDebug() << m_songPosition << event->tick() << " Bender: " << chan << val;
210                 emit midiPitchBend(chan, val);
211             }
212             break;
213         default:
214             //qDebug() << m_songPosition << ev->tick() << "unknown channel event status:" << ev->status();
215             break;
216         }
217     } else
218     if (ev->isMetaEvent()) {
219         if (typeid(*ev) == sysexId) {
220             SysExEvent* event = static_cast<SysExEvent*>(ev);
221             m_port->sendSysex(event->data());
222             //qDebug() << m_songPosition << event->tick() << " SysEx: "  << event->data().toHex();
223             emit midiSysex(event->data());
224         } else
225         if (typeid(*ev) == textId) {
226             TextEvent* event = static_cast<TextEvent*>(ev);
227             //qDebug() << m_songPosition << event->tick() << " Text(" << event->textType() << "): " << event->data();
228             emit midiText(event->tag(), event->textType(), event->tick(), event->data());
229         } else
230         if (typeid(*ev) == tempoId) {
231             TempoEvent* event = static_cast<TempoEvent*>(ev);
232             auto tempo = event->tempo();
233             m_song.updateTempo(tempo);
234             //qDebug() << m_songPosition << ev->tick() << " Tempo: " << tempo << "bpm:" << event->bpm();
235             emit tempoChanged(tempo);
236         } else
237         if (typeid(*ev) == beatId) {
238             BeatEvent* event = static_cast<BeatEvent*>(ev);
239             emit beat(event->bar(), event->beat(), event->barLength());
240             m_latestBeat = event;
241             //qDebug() << m_songPosition << ev->tick() << "bar:beat ->" << event->bar() << ":" << event->beat();
242         } else
243         if (typeid(*ev) == timeSigId) {
244             TimeSignatureEvent* event = static_cast<TimeSignatureEvent*>(ev);
245             emit timeSignature(event->tag(), event->numerator(), event->denominator());
246             //qDebug() << m_songPosition << ev->tick() << "TimeSignature:" << event->tag() << event->numerator() << event->denominator();
247         } else
248         if (typeid(*ev) == keySigId) {
249             KeySignatureEvent* event = static_cast<KeySignatureEvent*>(ev);
250             emit keySignature(event->tag(), event->alterations(), event->minorMode());
251         } /*else {
252             qDebug() << m_songPosition << ev->tick() << "unknown meta event:" << typeid(*ev).name();
253         } */
254     } /* else {
255         qDebug() << m_songPosition << ev->tick() << "unknown event type:" << typeid(*ev).name();
256     } */
257 }
258 
playerLoop()259 void SequencePlayer::playerLoop()
260 {
261     using namespace std::chrono;
262     typedef system_clock Clock;
263     static const std::type_info& beatId = typeid(BeatEvent);
264     int currentBar{ 0 };
265     long echoPosition{ 0 }, echoTicks{ 0 };
266     milliseconds deltaTime{0}, echoDelta{ m_echoResolution };
267     Clock::time_point currentTime{ Clock::now() },
268         nextTime{ currentTime }, nextEcho{ currentTime };
269     emit songStarted();
270     QAbstractEventDispatcher* dispatcher = thread()->eventDispatcher();
271     QEventLoop::ProcessEventsFlags eventFilter = QEventLoop::ExcludeUserInputEvents;
272     dispatcher->processEvents(eventFilter);
273 
274 #ifdef WIN32
275     timeBeginPeriod(1);
276 #endif
277 
278     do {
279         while (m_song.hasMoreEvents() && !thread()->isInterruptionRequested()) {
280             MIDIEvent* ev = m_song.nextEvent();
281             if (typeid(*ev) == beatId) {
282                 currentBar = static_cast<BeatEvent*>(ev)->bar();
283                 if (isLoopEnabled() && (currentBar > loopEnd())) {
284                     break;
285                 }
286             }
287             if (ev->delta() > 0) {
288                 deltaTime = m_song.deltaTimeOfEvent(ev);
289                 echoDelta = m_song.timeOfTicks(m_echoResolution);
290                 nextTime = currentTime + deltaTime;
291                 nextEcho = currentTime + echoDelta;
292                 echoPosition = m_songPosition;
293                 while (nextEcho < nextTime) {
294                     dispatcher->processEvents(eventFilter);
295                     std::this_thread::sleep_until(nextEcho);
296                     echoPosition += echoDelta.count();
297                     echoTicks += m_echoResolution;
298                     emit songEchoTime(echoPosition, echoTicks);
299                     currentTime = Clock::now();
300                     nextEcho = currentTime + echoDelta;
301                 }
302                 dispatcher->processEvents(eventFilter);
303                 std::this_thread::sleep_until(nextTime);
304                 echoTicks = ev->tick();
305                 m_songPosition += deltaTime.count();
306                 currentTime = Clock::now();
307                 emit songEchoTime(m_songPosition, ev->tick());
308                 //qDebug() << "echo:" << m_songPosition << ev->tick() << deltaTime.count();
309             }
310             playEvent(ev);
311         }
312         if (isLoopEnabled()) {
313             jumpToBar(loopStart());
314         }
315     } while (m_song.hasMoreEvents() && !thread()->isInterruptionRequested());
316 
317 #ifdef WIN32
318     timeEndPeriod(1);
319 #endif
320 
321     emit songStopped();
322     if (!m_song.hasMoreEvents()) {
323         //qDebug() << "Final Song Position:" << m_songPosition;
324         emit songFinished();
325     }
326     dispatcher->processEvents(eventFilter);
327     thread()->quit();
328 }
329 
setPort(drumstick::rt::MIDIOutput * p)330 void SequencePlayer::setPort(drumstick::rt::MIDIOutput *p)
331 {
332     m_port = p;
333 }
334 
port() const335 MIDIOutput *SequencePlayer::port() const
336 {
337     return m_port;
338 }
339 
bpm(qreal tempo) const340 qreal SequencePlayer::bpm(qreal tempo) const
341 {
342     return 6e7 / tempo;
343 }
344 
currentBPM() const345 qreal SequencePlayer::currentBPM() const
346 {
347     return bpm(m_song.currentTempo());
348 }
349 
song()350 Sequence *SequencePlayer::song()
351 {
352     return &m_song;
353 }
354 
getPosition()355 int SequencePlayer::getPosition()
356 {
357     //qDebug() << Q_FUNC_INFO << m_songPosition;
358     return m_songPosition;
359 }
360 
getEchoResolution()361 int SequencePlayer::getEchoResolution()
362 {
363     return m_echoResolution;
364 }
365 
getPitchShift()366 int SequencePlayer::getPitchShift()
367 {
368     return m_pitchShift;
369 }
370 
getVolumeFactor()371 int SequencePlayer::getVolumeFactor()
372 {
373     return m_volumeFactor;
374 }
375 
loadFile(QString fileName)376 void SequencePlayer::loadFile(QString fileName)
377 {
378     m_song.loadFile(fileName);
379     m_echoResolution = 50; //m_song.getDivision() / 12;
380     m_songPosition = 0;
381     m_firstBeat = m_song.firstBeat();
382     m_latestBeat = m_firstBeat;
383     m_loopStart = 1;
384     m_loopEnd = m_song.lastBar();
385     m_loopEnabled = false;
386 }
387 
pause()388 void SequencePlayer::pause()
389 {
390     stop();
391     thread()->wait();
392 }
393 
resetPosition()394 void SequencePlayer::resetPosition()
395 {
396     //qDebug() << Q_FUNC_INFO;
397     if (!m_song.isEmpty()) {
398         m_song.resetPosition();
399         m_songPosition = 0;
400         m_latestBeat = m_firstBeat;
401     }
402 }
403 
setPosition(long pos)404 void SequencePlayer::setPosition(long pos)
405 {
406     //qDebug() << Q_FUNC_INFO << pos;
407     allNotesOff();
408     m_song.setTickPosition(pos);
409     m_songPosition = pos;
410 }
411 
setPitchShift(unsigned int pitch)412 void SequencePlayer::setPitchShift(unsigned int pitch)
413 {
414     //qDebug() << Q_FUNC_INFO;
415     allNotesOff();
416     m_pitchShift = pitch;
417 }
418 
setVolumeFactor(unsigned int vol)419 void SequencePlayer::setVolumeFactor(unsigned int vol)
420 {
421     //qDebug() << Q_FUNC_INFO;
422     m_volumeFactor = vol;
423     if (m_port != nullptr) {
424         for(int chan = 0; chan < MIDI_STD_CHANNELS; ++chan) {
425             int value = m_volume[chan];
426             value = qFloor(value * m_volumeFactor / 100.0);
427             if (value < 0) value = 0;
428             if (value > 127) value = 127;
429             m_port->sendController(chan, ControllerEvent::MIDI_CTL_MSB_MAIN_VOLUME, value);
430         }
431     }
432 }
433 
allNotesOff()434 void SequencePlayer::allNotesOff()
435 {
436     //qDebug() << Q_FUNC_INFO;
437     if (m_port != nullptr) {
438         for(int chan = 0; chan < MIDI_STD_CHANNELS; ++chan) {
439             m_port->sendController(chan, ControllerEvent::MIDI_CTL_ALL_NOTES_OFF, 0);
440             m_port->sendController(chan, ControllerEvent::MIDI_CTL_ALL_SOUNDS_OFF, 0);
441         }
442     }
443 }
444 
resetControllers()445 void SequencePlayer::resetControllers()
446 {
447     //qDebug() << Q_FUNC_INFO;
448     if (m_port != nullptr) {
449         for(int chan = 0; chan < MIDI_STD_CHANNELS; ++chan) {
450             m_port->sendController(chan, ControllerEvent::MIDI_CTL_RESET_CONTROLLERS, 0);
451             m_port->sendController(chan, ControllerEvent::MIDI_CTL_MSB_MAIN_VOLUME, 100);
452         }
453     }
454 }
455 
resetPrograms()456 void SequencePlayer::resetPrograms()
457 {
458     if (m_port != nullptr) {
459         for(int chan = 0; chan < MIDI_STD_CHANNELS; ++chan) {
460             int pgm = m_locked[chan] ? m_lockedpgm[chan] : 0;
461             m_port->sendProgram(chan, pgm);
462             //qDebug() << Q_FUNC_INFO << chan << m_locked[chan] << pgm;
463         }
464     }
465 }
466 
sendResetMessage()467 void SequencePlayer::sendResetMessage()
468 {
469     static const QByteArray gmreset = QByteArray::fromHex("f07e7f0901f7");
470     static const QByteArray gsreset = QByteArray::fromHex("f04110421240007f0041f7");
471     static const QByteArray xgreset = QByteArray::fromHex("f043104c00007e00f7");
472     int reset_msg = Settings::instance()->getSysexResetMessage();
473     if (m_port != nullptr && reset_msg > 0 ) {
474         switch (reset_msg) {
475         case 1:
476             m_port->sendSysex(gmreset);
477             break;
478         case 2:
479             m_port->sendSysex(gsreset);
480             break;
481         case 3:
482             m_port->sendSysex(xgreset);
483             break;
484         }
485         //qDebug() << Q_FUNC_INFO << reset_msg;
486     }
487 }
488 
sendVolumeEvents()489 void SequencePlayer::sendVolumeEvents()
490 {
491     //qDebug() << Q_FUNC_INFO;
492     if (m_port != nullptr) {
493         for(int chan = 0; chan < MIDI_STD_CHANNELS; ++chan) {
494             int value = m_volume[chan] = 100;
495             value = floor(value * m_volumeFactor / 100.0);
496             if (value < 0) value = 0;
497             if (value > 127) value = 127;
498             m_port->sendController(chan, ControllerEvent::MIDI_CTL_MSB_MAIN_VOLUME, value);
499         }
500     }
501 }
502 
volume(int channel)503 qreal SequencePlayer::volume(int channel)
504 {
505     if (channel >=0 && channel < MIDI_STD_CHANNELS)
506         return m_volumeShift[channel];
507     return -1.0;
508 }
509 
isMuted(int channel)510 bool SequencePlayer::isMuted(int channel)
511 {
512     if (channel >= 0 && channel < MIDI_STD_CHANNELS) {
513         return m_muted[channel];
514     }
515     return false;
516 }
517 
isLocked(int channel)518 bool SequencePlayer::isLocked(int channel)
519 {
520     if (channel >= 0 && channel < MIDI_STD_CHANNELS) {
521         return m_locked[channel];
522     }
523     return false;
524 }
525 
beatByTickPosition(int pos)526 void SequencePlayer::beatByTickPosition(int pos)
527 {
528     BeatEvent* ev = m_song.nearestBeatByTicks(pos);
529     m_latestBeat = ev;
530 }
531 
beatForward()532 void SequencePlayer::beatForward()
533 {
534     BeatEvent* ev = m_song.nextBar(m_latestBeat);
535     if (ev != nullptr) {
536         setBeatPosition(ev);
537     }
538 }
539 
beatBackward()540 void SequencePlayer::beatBackward()
541 {
542     BeatEvent* ev = m_song.previousBar(m_latestBeat);
543     if (ev != nullptr) {
544         setBeatPosition(ev);
545     }
546 }
547 
setBeatPosition(BeatEvent * ev)548 void SequencePlayer::setBeatPosition(BeatEvent* ev)
549 {
550     setPosition(ev->tick());
551     emit beat(ev->bar(), ev->beat(), ev->barLength());
552     m_latestBeat = ev;
553 }
554 
jumpToBar(int bar)555 void SequencePlayer::jumpToBar(int bar)
556 {
557     BeatEvent* ev = m_song.jumpToBar(bar);
558     if (ev != nullptr) {
559         setBeatPosition(ev);
560     }
561 }
562 
currentBeatStr()563 QString SequencePlayer::currentBeatStr()
564 {
565     QString tmp;
566     if (m_latestBeat != nullptr) {
567         tmp = QString("%1:%2").arg(m_latestBeat->bar()).arg(m_latestBeat->beat());
568     }
569     return tmp;
570 }
571 
setVolume(int channel,qreal value)572 void SequencePlayer::setVolume(int channel, qreal value)
573 {
574     //qDebug() << Q_FUNC_INFO << channel << value;
575     if (channel >= 0 && channel < MIDI_STD_CHANNELS) {
576         m_volumeShift[channel] = value;
577         int volume = qFloor(m_volume[channel] * value);
578         if (volume < 0) volume = 0;
579         if (volume > 127) volume = 127;
580         m_port->sendController(channel, MIDI_CONTROL_MSB_MAIN_VOLUME, volume);
581         emit volumeChanged( channel, value );
582     } else if ( channel == -1 ) {
583         for (int chan = 0; chan < MIDI_STD_CHANNELS; ++chan) {
584             m_volumeShift[chan] = value;
585             int volume = qFloor(m_volume[chan] * value);
586             if (volume < 0) volume = 0;
587             if (volume > 127) volume = 127;
588             m_port->sendController(chan, MIDI_CONTROL_MSB_MAIN_VOLUME, volume);
589             emit volumeChanged( chan, value );
590         }
591     }
592 }
593 
setMuted(int channel,bool mute)594 void SequencePlayer::setMuted(int channel, bool mute)
595 {
596     //qDebug() << Q_FUNC_INFO << channel << mute;
597     if (channel >= 0 && channel < MIDI_STD_CHANNELS) {
598         if (m_muted[channel] != mute) {
599             if (mute) {
600                 m_port->sendController(channel, MIDI_CONTROL_ALL_NOTES_OFF, 0);
601                 m_port->sendController(channel, MIDI_CONTROL_ALL_SOUNDS_OFF, 0);
602             }
603             m_muted[channel] = mute;
604             emit mutedChanged( channel, mute );
605         }
606     }
607 }
608 
setLocked(int channel,bool lock)609 void SequencePlayer::setLocked(int channel, bool lock)
610 {
611     //qDebug() << Q_FUNC_INFO << channel << lock;
612     if (channel >= 0 && channel < MIDI_STD_CHANNELS) {
613         if (m_locked[channel] != lock) {
614             m_locked[channel] = lock;
615             if (lock) {
616                 m_lockedpgm[channel] = m_lastpgm[channel];
617             }
618             emit lockedChanged( channel, lock );
619         }
620     }
621 }
622 
setPatch(int channel,int patch)623 void SequencePlayer::setPatch(int channel, int patch)
624 {
625     //qDebug() << Q_FUNC_INFO << channel << patch;
626     if (channel >= 0 && channel < MIDI_STD_CHANNELS) {
627         m_lastpgm[channel] = patch;
628         if (m_locked[channel]) {
629             m_lockedpgm[channel] = patch;
630         }
631     }
632 }
633 
634