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