1 //=============================================================================
2 // MuseScore
3 // Linux Music Score Editor
4 //
5 // Copyright (C) 2002-2011 Werner Schweer and others
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2.
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, write to the Free Software
17 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //=============================================================================
19
20 #include "config.h"
21 #include "seq.h"
22 #include "musescore.h"
23
24 #include "audio/midi/msynthesizer.h"
25 #include "libmscore/rendermidi.h"
26 #include "libmscore/slur.h"
27 #include "libmscore/tie.h"
28 #include "libmscore/score.h"
29 #include "libmscore/segment.h"
30 #include "libmscore/note.h"
31 #include "libmscore/chord.h"
32 #include "libmscore/tempo.h"
33 #include "scoreview.h"
34 #include "playpanel.h"
35 #include "libmscore/staff.h"
36 #include "libmscore/measure.h"
37 #include "preferences.h"
38 #include "libmscore/part.h"
39 #include "libmscore/ottava.h"
40 #include "libmscore/utils.h"
41 #include "libmscore/repeatlist.h"
42 #include "libmscore/audio.h"
43 #include "synthcontrol.h"
44 #include "pianoroll/pianoroll.h"
45 #include "pianotools.h"
46
47 #include "click.h"
48
49 #define OV_EXCLUDE_STATIC_CALLBACKS
50 #include <vorbis/vorbisfile.h>
51
52 #ifdef USE_PORTMIDI
53 #if defined(Q_OS_MAC) || defined(Q_OS_WIN)
54 #include "portmidi/porttime/porttime.h"
55 #else
56 #include <porttime.h>
57 #endif
58 #endif
59
60 namespace Ms {
61
62 Seq* seq;
63
64 static const int guiRefresh = 10; // Hz
65 static const int peakHoldTime = 1400; // msec
66 static const int peakHold = (peakHoldTime * guiRefresh) / 1000;
67 static OggVorbis_File vf;
68
69 static constexpr int minUtickBufferSize = 480 * 4 * 10; // about 10 measures of 4/4 time signature
70
71 #if 0 // yet(?) unused
72 static const int AUDIO_BUFFER_SIZE = 1024 * 512; // 2 MB
73 #endif
74
75 //---------------------------------------------------------
76 // VorbisData
77 //---------------------------------------------------------
78
79 struct VorbisData {
80 int pos; // current position in audio->data()
81 QByteArray data;
82 };
83
84 static VorbisData vorbisData;
85
86 static size_t ovRead(void* ptr, size_t size, size_t nmemb, void* datasource);
87 static int ovSeek(void* datasource, ogg_int64_t offset, int whence);
88 static long ovTell(void* datasource);
89
90 static ov_callbacks ovCallbacks = {
91 ovRead, ovSeek, 0, ovTell
92 };
93
94 //---------------------------------------------------------
95 // ovRead
96 //---------------------------------------------------------
97
ovRead(void * ptr,size_t size,size_t nmemb,void * datasource)98 static size_t ovRead(void* ptr, size_t size, size_t nmemb, void* datasource)
99 {
100 VorbisData* vd = (VorbisData*)datasource;
101 size_t n = size * nmemb;
102 if (vd->data.size() < int(vd->pos + n))
103 n = vd->data.size() - vd->pos;
104 if (n) {
105 const char* src = vd->data.data() + vd->pos;
106 memcpy(ptr, src, n);
107 vd->pos += int(n);
108 }
109 return n;
110 }
111
112 //---------------------------------------------------------
113 // ovSeek
114 //---------------------------------------------------------
115
ovSeek(void * datasource,ogg_int64_t offset,int whence)116 static int ovSeek(void* datasource, ogg_int64_t offset, int whence)
117 {
118 VorbisData* vd = (VorbisData*)datasource;
119 switch(whence) {
120 case SEEK_SET:
121 vd->pos = offset;
122 break;
123 case SEEK_CUR:
124 vd->pos += offset;
125 break;
126 case SEEK_END:
127 vd->pos = vd->data.size() - offset;
128 break;
129 }
130 return 0;
131 }
132
133 //---------------------------------------------------------
134 // ovTell
135 //---------------------------------------------------------
136
ovTell(void * datasource)137 static long ovTell(void* datasource)
138 {
139 VorbisData* vd = (VorbisData*)datasource;
140 return vd->pos;
141 }
142
143 //---------------------------------------------------------
144 // Seq
145 //---------------------------------------------------------
146
Seq()147 Seq::Seq()
148 : midi(nullptr)
149 {
150 running = false;
151 playlistChanged = false;
152 cs = 0;
153 cv = 0;
154 tackRemain = 0;
155 tickRemain = 0;
156 maxMidiOutPort = 0;
157
158 endUTick = 0;
159 state = Transport::STOP;
160 oggInit = false;
161 _driver = 0;
162 playPos = events.cbegin();
163 playFrame = 0;
164 metronomeVolume = 0.3;
165 useJackTransportSavedFlag = false;
166
167 inCountIn = false;
168 countInPlayPos = countInEvents.cbegin();
169 countInPlayFrame = 0;
170
171 meterValue[0] = 0.0;
172 meterValue[1] = 0.0;
173 meterPeakValue[0] = 0.0;
174 meterPeakValue[1] = 0.0;
175 peakTimer[0] = 0;
176 peakTimer[1] = 0;
177
178 heartBeatTimer = new QTimer(this);
179 connect(heartBeatTimer, SIGNAL(timeout()), this, SLOT(heartBeatTimeout()));
180
181 noteTimer = new QTimer(this);
182 noteTimer->setSingleShot(true);
183 connect(noteTimer, SIGNAL(timeout()), this, SLOT(stopNotes()));
184 noteTimer->stop();
185
186 connect(this, SIGNAL(toGui(int, int)), this, SLOT(seqMessage(int, int)), Qt::QueuedConnection);
187
188 prevTimeSig.setNumerator(0);
189 prevTempo = 0;
190 connect(this, SIGNAL(timeSigChanged()),this,SLOT(handleTimeSigTempoChanged()));
191 connect(this, SIGNAL(tempoChanged()),this,SLOT(handleTimeSigTempoChanged()));
192
193 initialMillisecondTimestampWithLatency = 0;
194 }
195
196 //---------------------------------------------------------
197 // Seq
198 //---------------------------------------------------------
199
~Seq()200 Seq::~Seq()
201 {
202 delete _driver;
203 }
204
205 //---------------------------------------------------------
206 // setScoreView
207 //---------------------------------------------------------
208
setScoreView(ScoreView * v)209 void Seq::setScoreView(ScoreView* v)
210 {
211 if (oggInit) {
212 ov_clear(&vf);
213 oggInit = false;
214 }
215 if (cv !=v && cs) {
216 unmarkNotes();
217 stopWait();
218 }
219 cv = v;
220 if (cs)
221 disconnect(cs, SIGNAL(playlistChanged()), this, SLOT(setPlaylistChanged()));
222 cs = cv ? cv->score()->masterScore() : 0;
223 midi = MidiRenderer(cs);
224 midi.setMinChunkSize(10);
225
226 if (!heartBeatTimer->isActive())
227 heartBeatTimer->start(20); // msec
228
229 playlistChanged = true;
230 _synti->reset();
231 if (cs) {
232 initInstruments();
233 connect(cs, SIGNAL(playlistChanged()), this, SLOT(setPlaylistChanged()));
234 }
235 }
236
237 //---------------------------------------------------------
238 // Seq::CachedPreferences::update
239 //---------------------------------------------------------
240
update()241 void Seq::CachedPreferences::update()
242 {
243 portMidiOutputLatencyMilliseconds = preferences.getInt(PREF_IO_PORTMIDI_OUTPUTLATENCYMILLISECONDS);
244 jackTimeBaseMaster = preferences.getBool(PREF_IO_JACK_TIMEBASEMASTER);
245 useJackTransport = preferences.getBool(PREF_IO_JACK_USEJACKTRANSPORT);
246 useJackMidi = preferences.getBool(PREF_IO_JACK_USEJACKMIDI);
247 useJackAudio = preferences.getBool(PREF_IO_JACK_USEJACKAUDIO);
248 useAlsaAudio = preferences.getBool(PREF_IO_ALSA_USEALSAAUDIO);
249 usePortAudio = preferences.getBool(PREF_IO_PORTAUDIO_USEPORTAUDIO);
250 usePulseAudio = preferences.getBool(PREF_IO_PULSEAUDIO_USEPULSEAUDIO);
251 }
252
253 //---------------------------------------------------------
254 // startTransport
255 //---------------------------------------------------------
256
startTransport()257 void Seq::startTransport()
258 {
259 cachedPrefs.update();
260 _driver->startTransport();
261 }
262
263 //---------------------------------------------------------
264 // stopTransport
265 //---------------------------------------------------------
266
stopTransport()267 void Seq::stopTransport()
268 {
269 _driver->stopTransport();
270 }
271
272 //---------------------------------------------------------
273 // init
274 // return false on error
275 //---------------------------------------------------------
276
init(bool hotPlug)277 bool Seq::init(bool hotPlug)
278 {
279 if (!_driver || !_driver->start(hotPlug)) {
280 qDebug("Cannot start I/O");
281 running = false;
282 return false;
283 }
284 cachedPrefs.update();
285 running = true;
286 return true;
287 }
288
289 //---------------------------------------------------------
290 // exit
291 //---------------------------------------------------------
292
exit()293 void Seq::exit()
294 {
295 if (_driver) {
296 if (MScore::debugMode)
297 qDebug("Stop I/O");
298 stopWait();
299 delete _driver;
300 _driver = 0;
301 }
302 }
303
304 //---------------------------------------------------------
305 // rewindStart
306 //---------------------------------------------------------
307
rewindStart()308 void Seq::rewindStart()
309 {
310 seek(0);
311 }
312
313 //---------------------------------------------------------
314 // loopStart
315 //---------------------------------------------------------
316
loopStart()317 void Seq::loopStart()
318 {
319 start();
320 // qDebug("LoopStart. playPos = %d", playPos);
321 }
322
323 //---------------------------------------------------------
324 // canStart
325 // return true if sequencer can be started
326 //---------------------------------------------------------
327
canStart()328 bool Seq::canStart()
329 {
330 if (!_driver)
331 return false;
332 collectEvents(getPlayStartUtick());
333 return (!events.empty() && endUTick != 0);
334 }
335
336 //---------------------------------------------------------
337 // start
338 // called from gui thread
339 //---------------------------------------------------------
340
start()341 void Seq::start()
342 {
343 if (!_driver) {
344 qDebug("No driver!");
345 return;
346 }
347
348 mscore->moveControlCursor();
349
350 allowBackgroundRendering = true;
351 collectEvents(getPlayStartUtick());
352 if (cs->playMode() == PlayMode::AUDIO) {
353 if (!oggInit) {
354 vorbisData.pos = 0;
355 vorbisData.data = cs->audio()->data();
356 int n = ov_open_callbacks(&vorbisData, &vf, 0, 0, ovCallbacks);
357 if (n < 0) {
358 qDebug("ogg open failed: %d", n);
359 }
360 oggInit = true;
361 }
362 }
363
364 if (!preferences.getBool(PREF_IO_JACK_USEJACKTRANSPORT) || (preferences.getBool(PREF_IO_JACK_USEJACKTRANSPORT) && state == Transport::STOP))
365 seek(getPlayStartUtick());
366
367 if (preferences.getBool(PREF_IO_JACK_USEJACKTRANSPORT) && mscore->countIn() && state == Transport::STOP) {
368 // Ready to start playing count in, switching to fake transport
369 // to prevent playing in other applications with our ticks simultaneously
370 useJackTransportSavedFlag = true;
371 preferences.setPreference(PREF_IO_JACK_USEJACKTRANSPORT, false);
372 }
373 startTransport();
374 }
375
376 //---------------------------------------------------------
377 // stop
378 // called from gui thread
379 //---------------------------------------------------------
380
stop()381 void Seq::stop()
382 {
383 const bool seqStopped = (state == Transport::STOP);
384 const bool driverStopped = !_driver || _driver->getState() == Transport::STOP;
385 if (seqStopped && driverStopped)
386 return;
387
388 allowBackgroundRendering = false;
389 if (oggInit) {
390 ov_clear(&vf);
391 oggInit = false;
392 }
393 if (!_driver)
394 return;
395 if (!preferences.getBool(PREF_IO_JACK_USEJACKTRANSPORT) || (preferences.getBool(PREF_IO_JACK_USEJACKTRANSPORT) && _driver->getState() == Transport::PLAY))
396 stopTransport();
397 if (cv)
398 cv->setCursorOn(false);
399 if (midiRenderFuture.isRunning())
400 midiRenderFuture.waitForFinished();
401 if (cs) {
402 cs->setUpdateAll();
403 cs->update();
404 }
405 }
406
407 //---------------------------------------------------------
408 // stopWait
409 //---------------------------------------------------------
410
stopWait()411 void Seq::stopWait()
412 {
413 stop();
414 QWaitCondition sleep;
415 int idx = 0;
416 while (state != Transport::STOP) {
417 qDebug("State %d", (int)state);
418 mutex.lock();
419 sleep.wait(&mutex, 100);
420 mutex.unlock();
421 ++idx;
422 Q_ASSERT(idx <= 10);
423 }
424 }
425
426 //---------------------------------------------------------
427 // seqStarted
428 //---------------------------------------------------------
429
seqStarted()430 void MuseScore::seqStarted()
431 {
432 if (cv)
433 cv->setCursorOn(true);
434 if (cs)
435 cs->update();
436 }
437
438 //---------------------------------------------------------
439 // seqStopped
440 // JACK has stopped
441 // executed in gui environment
442 //---------------------------------------------------------
443
seqStopped()444 void MuseScore::seqStopped()
445 {
446 cv->setCursorOn(false);
447 }
448
449 //---------------------------------------------------------
450 // unmarkNotes
451 //---------------------------------------------------------
452
unmarkNotes()453 void Seq::unmarkNotes()
454 {
455 foreach(const Note* n, markedNotes) {
456 n->setMark(false);
457 cs->addRefresh(n->canvasBoundingRect());
458 }
459 markedNotes.clear();
460 PianoTools* piano = mscore->pianoTools();
461 if (piano && piano->isVisible())
462 piano->setPlaybackNotes(markedNotes);
463 }
464
465 //---------------------------------------------------------
466 // guiStop
467 //---------------------------------------------------------
468
guiStop()469 void Seq::guiStop()
470 {
471 QAction* a = getAction("play");
472 a->setChecked(false);
473
474 unmarkNotes();
475 if (!cs)
476 return;
477
478 int tck = cs->repeatList().utick2tick(cs->utime2utick(qreal(playFrame) / qreal(MScore::sampleRate)));
479 cs->setPlayPos(Fraction::fromTicks(tck));
480 cs->update();
481 emit stopped();
482 }
483
484 //---------------------------------------------------------
485 // seqSignal
486 // sequencer message to GUI
487 // execution environment: gui thread
488 //---------------------------------------------------------
489
seqMessage(int msg,int arg)490 void Seq::seqMessage(int msg, int arg)
491 {
492 switch(msg) {
493 case '5': {
494 // Update the screen after seeking from the realtime thread
495 Segment* seg = cs->tick2segment(Fraction::fromTicks(arg));
496 if (seg)
497 mscore->currentScoreView()->moveCursor(seg->tick());
498 cs->setPlayPos(Fraction::fromTicks(arg));
499 cs->update();
500 break;
501 }
502 case '4': // Restart the playback at the end of the score
503 loopStart();
504 break;
505 case '3': // Loop restart while playing
506 seek(cs->repeatList().tick2utick(cs->loopInTick().ticks()));
507 break;
508 case '2':
509 guiStop();
510 // heartBeatTimer->stop();
511 if (_driver && mscore->getSynthControl()) {
512 meterValue[0] = .0f;
513 meterValue[1] = .0f;
514 meterPeakValue[0] = .0f;
515 meterPeakValue[1] = .0f;
516 peakTimer[0] = 0;
517 peakTimer[1] = 0;
518 mscore->getSynthControl()->setMeter(0.0, 0.0, 0.0, 0.0);
519 }
520 seek(0);
521 break;
522 case '0': // STOP
523 guiStop();
524 // heartBeatTimer->stop();
525 if (_driver && mscore->getSynthControl()) {
526 meterValue[0] = .0f;
527 meterValue[1] = .0f;
528 meterPeakValue[0] = .0f;
529 meterPeakValue[1] = .0f;
530 peakTimer[0] = 0;
531 peakTimer[1] = 0;
532 mscore->getSynthControl()->setMeter(0.0, 0.0, 0.0, 0.0);
533 }
534 break;
535
536 case '1': // PLAY
537 emit started();
538 // heartBeatTimer->start(1000/guiRefresh);
539 break;
540
541 default:
542 qDebug("MScore::Seq:: unknown seq msg %d", msg);
543 break;
544 }
545 }
546
547 //---------------------------------------------------------
548 // playEvent
549 // send one event to the synthesizer
550 //---------------------------------------------------------
551
playEvent(const NPlayEvent & event,unsigned framePos)552 void Seq::playEvent(const NPlayEvent& event, unsigned framePos)
553 {
554 int type = event.type();
555 if (type == ME_NOTEON) {
556 if (!event.isMuted()) {
557 if (event.discard()) { // ignore noteoff but restrike noteon
558 if (event.velo() > 0)
559 putEvent(NPlayEvent(ME_NOTEON, event.channel(), event.pitch(), 0) ,framePos);
560 else
561 return;
562 }
563 putEvent(event, framePos);
564 }
565 }
566 else if (type == ME_CONTROLLER || type == ME_PITCHBEND || type == ME_AFTERTOUCH || type == ME_POLYAFTER)
567 putEvent(event, framePos);
568 }
569
570 //---------------------------------------------------------
571 // recomputeMaxMidiOutPort
572 // Computes the maximum number of midi out ports
573 // in all opened scores
574 //---------------------------------------------------------
575
recomputeMaxMidiOutPort()576 void Seq::recomputeMaxMidiOutPort()
577 {
578 if (!(preferences.getBool(PREF_IO_JACK_USEJACKMIDI) || preferences.getBool(PREF_IO_ALSA_USEALSAAUDIO)))
579 return;
580 int max = 0;
581 for (Score * s : MuseScoreCore::mscoreCore->scores()) {
582 if (s->masterScore()->midiPortCount() > max)
583 max = s->masterScore()->midiPortCount();
584 }
585 maxMidiOutPort = max;
586 }
587
588 //---------------------------------------------------------
589 // processMessages
590 // from gui to process thread
591 //---------------------------------------------------------
592
processMessages()593 void Seq::processMessages()
594 {
595 for (;;) {
596 if (toSeq.empty())
597 break;
598 SeqMsg msg = toSeq.dequeue();
599 switch(msg.id) {
600 case SeqMsgId::TEMPO_CHANGE:
601 {
602 if (!cs)
603 continue;
604 if (playFrame != 0) {
605 int utick = cs->utime2utick(qreal(playFrame) / qreal(MScore::sampleRate));
606 cs->tempomap()->setRelTempo(msg.realVal);
607 playFrame = cs->utick2utime(utick) * MScore::sampleRate;
608 if (cachedPrefs.jackTimeBaseMaster && cachedPrefs.useJackTransport)
609 _driver->seekTransport(utick + 2 * cs->utime2utick(qreal((_driver->bufferSize()) + 1) / qreal(MScore::sampleRate)));
610 }
611 else
612 cs->tempomap()->setRelTempo(msg.realVal);
613 cs->masterScore()->updateRepeatListTempo();
614 prevTempo = curTempo();
615 emit tempoChanged();
616 }
617 break;
618 case SeqMsgId::PLAY:
619 putEvent(msg.event);
620 break;
621 case SeqMsgId::SEEK:
622 setPos(msg.intVal);
623 break;
624 case SeqMsgId::ALL_NOTE_OFF:
625 _synti->allNotesOff(msg.intVal);
626 break;
627 default:
628 break;
629 }
630 }
631 }
632
633 //---------------------------------------------------------
634 // metronome
635 //---------------------------------------------------------
636
metronome(unsigned n,float * p,bool force)637 void Seq::metronome(unsigned n, float* p, bool force)
638 {
639 if (!mscore->metronome() && !force) {
640 tickRemain = 0;
641 tackRemain = 0;
642 return;
643 }
644 if (tickRemain) {
645 tackRemain = 0;
646 int idx = tickLength - tickRemain;
647 int nn = n < tickRemain ? n : tickRemain;
648 for (int i = 0; i < nn; ++i) {
649 qreal v = tick[idx] * tickVolume * metronomeVolume;
650 *p++ += v;
651 *p++ += v;
652 ++idx;
653 }
654 tickRemain -= nn;
655 }
656 if (tackRemain) {
657 int idx = tackLength - tackRemain;
658 int nn = n < tackRemain ? n : tackRemain;
659 for (int i = 0; i < nn; ++i) {
660 qreal v = tack[idx] * tackVolume * metronomeVolume;
661 *p++ += v;
662 *p++ += v;
663 ++idx;
664 }
665 tackRemain -= nn;
666 }
667 }
668
669 //---------------------------------------------------------
670 // addCountInClicks
671 //---------------------------------------------------------
672
addCountInClicks()673 void Seq::addCountInClicks()
674 {
675 const Fraction plPos = cs->playPos();
676 Measure* m = cs->tick2measure(plPos);
677 Fraction msrTick = m->tick();
678 qreal tempo = cs->tempomap()->tempo(msrTick.ticks());
679 TimeSigFrac timeSig = cs->sigmap()->timesig(m->tick()).nominal();
680
681 const int clickTicks = timeSig.isBeatedCompound(tempo) ? timeSig.beatTicks() : timeSig.dUnitTicks();
682
683 // add at least one full measure of just clicks.
684 Fraction endTick = Fraction::fromTicks(timeSig.ticksPerMeasure());
685
686 // add extra clicks if...
687 endTick += plPos - msrTick; // ...not starting playback at beginning of measure
688
689 if (m->isAnacrusis()) // ...measure is incomplete (anacrusis)
690 endTick += Fraction::fromTicks(timeSig.ticksPerMeasure()) - m->ticks();
691
692 for (int t = 0; t < endTick.ticks(); t += clickTicks) {
693 const int rtick = t % timeSig.ticksPerMeasure();
694 countInEvents.insert(std::pair<int,NPlayEvent>(t, NPlayEvent(timeSig.rtick2beatType(rtick))));
695 }
696
697 NPlayEvent event;
698 event.setType(ME_INVALID);
699 event.setPitch(0);
700 countInEvents.insert( std::pair<int,NPlayEvent>(endTick.ticks(), event));
701 // initialize play parameters to count-in events
702 countInPlayPos = countInEvents.cbegin();
703 countInPlayFrame = 0;
704 }
705
706 //-------------------------------------------------------------------
707 // process
708 // This function is called in a realtime context. This
709 // means that no blocking operations are allowed which
710 // includes memory allocation. The usual thread synchronisation
711 // methods like semaphores can also not be used.
712 //-------------------------------------------------------------------
713
process(unsigned framesPerPeriod,float * buffer)714 void Seq::process(unsigned framesPerPeriod, float* buffer)
715 {
716 unsigned framesRemain = framesPerPeriod; // the number of frames remaining to be processed by this call to Seq::process
717 Transport driverState = _driver->getState();
718 // Checking for the reposition from JACK Transport
719 _driver->checkTransportSeek(playFrame, framesRemain, inCountIn);
720
721 if (driverState != state) {
722 // Got a message from JACK Transport panel: Play
723 if (state == Transport::STOP && driverState == Transport::PLAY) {
724 if ((cachedPrefs.useJackMidi || cachedPrefs.useJackAudio) && !getAction("play")->isChecked()) {
725 // Do not play while editing elements
726 if (mscore->state() != STATE_NORMAL || !isRunning() || !canStart())
727 return;
728 getAction("play")->setChecked(true);
729 getAction("play")->triggered(true);
730
731 // If we just launch MuseScore and press "Play" on JACK Transport with time 0:00
732 // MuseScore doesn't seek to 0 and guiPos is uninitialized, so let's make it manually
733 if (cachedPrefs.useJackTransport && getCurTick() == 0)
734 seekRT(0);
735
736 // Switching to fake transport while playing count in
737 // to prevent playing in other applications with our ticks simultaneously
738 if (cachedPrefs.useJackTransport && mscore->countIn()) {
739 // Stopping real JACK Transport
740 stopTransport();
741 // Starting fake transport
742 useJackTransportSavedFlag = preferences.getBool(PREF_IO_JACK_USEJACKTRANSPORT);
743 preferences.setPreference(PREF_IO_JACK_USEJACKTRANSPORT, false);
744 startTransport();
745 }
746 }
747 // Initializing instruments every time we start playback.
748 // External synth can have wrong values, for example
749 // if we switch between scores
750 initInstruments(true);
751 // Need to change state after calling collectEvents()
752 state = Transport::PLAY;
753 if (mscore->countIn() && cs->playMode() == PlayMode::SYNTHESIZER) {
754 countInEvents.clear();
755 inCountIn = true;
756 }
757 emit toGui('1');
758 }
759 // Got a message from JACK Transport panel: Stop
760 else if (state == Transport::PLAY && driverState == Transport::STOP) {
761 state = Transport::STOP;
762 // Muting all notes
763 stopNotes(-1, true);
764 initInstruments(true);
765 if (playPos == eventsEnd) {
766 if (mscore->loop()) {
767 qDebug("Seq.cpp - Process - Loop whole score. playPos = %d, cs->pos() = %d", playPos->first, cs->pos().ticks());
768 emit toGui('4');
769 return;
770 }
771 else {
772 emit toGui('2');
773 }
774 }
775 else {
776 emit toGui('0');
777 }
778 }
779 else if (state != driverState)
780 qDebug("Seq: state transition %d -> %d ?",
781 (int)state, (int)driverState);
782 }
783
784 memset(buffer, 0, sizeof(float) * framesPerPeriod * 2); // assume two channels
785 float* p = buffer;
786
787 processMessages();
788
789 if (state == Transport::PLAY) {
790 if (!cs)
791 return;
792
793 // if currently in count-in, these pointers will reference data in the count-in
794 EventMap::const_iterator* pPlayPos = &playPos;
795 EventMap::const_iterator pEventsEnd = eventsEnd;
796 int* pPlayFrame = &playFrame;
797 if (inCountIn) {
798 if (countInEvents.size() == 0)
799 addCountInClicks();
800 pEventsEnd = countInEvents.cend();
801 pPlayPos = &countInPlayPos;
802 pPlayFrame = &countInPlayFrame;
803 }
804
805 //
806 // play events for one segment
807 //
808 unsigned framePos = 0; // frame currently being processed relative to the first frame of this call to Seq::process
809 int periodEndFrame = *pPlayFrame + framesPerPeriod; // the ending frame (relative to start of playback) of the period being processed by this call to Seq::process
810 int scoreEndUTick = cs->repeatList().tick2utick(cs->lastMeasure()->endTick().ticks());
811 while (*pPlayPos != pEventsEnd) {
812 int playPosUTick = (*pPlayPos)->first;
813 int n; // current frame (relative to start of playback) that is being synthesized
814
815 if (inCountIn) {
816 qreal beatsPerSecond = curTempo() * cs->tempomap()->relTempo(); // relTempo needed here to ensure that bps changes as we slide the tempo bar
817 qreal ticksPerSecond = beatsPerSecond * MScore::division;
818 qreal playPosSeconds = playPosUTick / ticksPerSecond;
819 int playPosFrame = playPosSeconds * MScore::sampleRate;
820 if (playPosFrame >= periodEndFrame)
821 break;
822 n = playPosFrame - *pPlayFrame;
823 if (n < 0) {
824 qDebug("Count-in: playPosUTick %d: n = %d - %d", playPosUTick, playPosFrame, *pPlayFrame);
825 n = 0;
826 }
827 }
828 else {
829 qreal playPosSeconds = cs->utick2utime(playPosUTick);
830 int playPosFrame = playPosSeconds * MScore::sampleRate;
831 if (playPosFrame >= periodEndFrame)
832 break;
833 n = playPosFrame - *pPlayFrame;
834 if (n < 0) {
835 qDebug("%d: %d - %d", playPosUTick, playPosFrame, *pPlayFrame);
836 n = 0;
837 }
838 if (mscore->loop()) {
839 int loopOutUTick = cs->repeatList().tick2utick(cs->loopOutTick().ticks());
840 if (loopOutUTick < scoreEndUTick) {
841 qreal framesPerPeriodInTime = static_cast<qreal>(framesPerPeriod) / MScore::sampleRate;
842 int framesPerPeriodInTicks = cs->utime2utick(framesPerPeriodInTime);
843 // Also make sure we are inside the loop
844 if (playPosUTick >= loopOutUTick - 2 * framesPerPeriodInTicks || cs->repeatList().utick2tick(playPosUTick) < cs->loopInTick().ticks()) {
845 qDebug ("Process: playPosUTick = %d, cs->loopInTick().ticks() = %d, cs->loopOutTick().ticks() = %d, getCurTick() = %d, loopOutUTick = %d, playFrame = %d",
846 playPosUTick, cs->loopInTick().ticks(), cs->loopOutTick().ticks(), getCurTick(), loopOutUTick, *pPlayFrame);
847 if (cachedPrefs.useJackTransport) {
848 int loopInUTick = cs->repeatList().tick2utick(cs->loopInTick().ticks());
849 _driver->seekTransport(loopInUTick);
850 if (loopInUTick != 0) {
851 int seekto = loopInUTick - 2 * cs->utime2utick((qreal)_driver->bufferSize() / MScore::sampleRate);
852 seekRT((seekto > 0) ? seekto : 0 );
853 }
854 }
855 else {
856 emit toGui('3'); // calls loopStart()
857 }
858 // Exit this function to avoid segmentation fault in Scoreview
859 return;
860 }
861 }
862 }
863 }
864 if (n) {
865 if (cs->playMode() == PlayMode::SYNTHESIZER) {
866 metronome(n, p, inCountIn);
867 _synti->process(n, p);
868 p += n * 2;
869 *pPlayFrame += n;
870 framesRemain -= n;
871 framePos += n;
872 }
873 else {
874 while (n > 0) {
875 int section;
876 float** pcm;
877 long rn = ov_read_float(&vf, &pcm, n, §ion);
878 if (rn == 0)
879 break;
880 for (int i = 0; i < rn; ++i) {
881 *p++ = pcm[0][i];
882 *p++ = pcm[1][i];
883 }
884 *pPlayFrame += rn;
885 framesRemain -= rn;
886 framePos += rn;
887 n -= rn;
888 }
889 }
890 }
891 const NPlayEvent& event = (*pPlayPos)->second;
892 playEvent(event, framePos);
893 if (event.type() == ME_TICK1) {
894 tickRemain = tickLength;
895 tickVolume = event.velo() ? qreal(event.value()) / 127.0 : 1.0;
896 }
897 else if (event.type() == ME_TICK2) {
898 tackRemain = tackLength;
899 tackVolume = event.velo() ? qreal(event.value()) / 127.0 : 1.0;
900 }
901 mutex.lock();
902 ++(*pPlayPos);
903 mutex.unlock();
904 }
905 if (framesRemain) {
906 if (cs->playMode() == PlayMode::SYNTHESIZER) {
907 metronome(framesRemain, p, inCountIn);
908 _synti->process(framesRemain, p);
909 *pPlayFrame += framesRemain;
910 }
911 else {
912 int n = framesRemain;
913 while (n > 0) {
914 int section;
915 float** pcm;
916 long rn = ov_read_float(&vf, &pcm, n, §ion);
917 if (rn == 0)
918 break;
919 for (int i = 0; i < rn; ++i) {
920 *p++ = pcm[0][i];
921 *p++ = pcm[1][i];
922 }
923 *pPlayFrame += rn;
924 framesRemain -= rn;
925 framePos += rn;
926 n -= rn;
927 }
928 }
929 }
930 if (*pPlayPos == pEventsEnd) {
931 if (inCountIn) {
932 inCountIn = false;
933 // Connecting to JACK Transport if MuseScore was temporarily disconnected from it
934 if (useJackTransportSavedFlag) {
935 // Stopping fake driver
936 stopTransport();
937 preferences.setPreference(PREF_IO_JACK_USEJACKTRANSPORT, true);
938 // Starting the real JACK Transport. All applications play in sync now
939 startTransport();
940 }
941 }
942 else
943 stopTransport();
944 }
945 }
946 else {
947 // Outside of playback mode
948 while (!liveEventQueue()->empty()) {
949 const NPlayEvent& event = liveEventQueue()->dequeue();
950 if (event.type() == ME_TICK1) {
951 tickRemain = tickLength;
952 tickVolume = event.velo() ? qreal(event.value()) / 127.0 : 1.0;
953 }
954 else if (event.type() == ME_TICK2) {
955 tackRemain = tackLength;
956 tackVolume = event.velo() ? qreal(event.value()) / 127.0 : 1.0;
957 }
958 }
959 if (framesRemain) {
960 metronome(framesRemain, p, true);
961 _synti->process(framesRemain, p);
962 }
963 }
964 //
965 // metering / master gain
966 //
967 qreal lv = 0.0f;
968 qreal rv = 0.0f;
969 p = buffer;
970 for (unsigned i = 0; i < framesRemain; ++i) {
971 qreal val = *p;
972 lv = qMax(lv, qAbs(val));
973 p++;
974
975 val = *p;
976 rv = qMax(rv, qAbs(val));
977 p++;
978 }
979 meterValue[0] = lv;
980 meterValue[1] = rv;
981 if (meterPeakValue[0] < lv) {
982 meterPeakValue[0] = lv;
983 peakTimer[0] = 0;
984 }
985 if (meterPeakValue[1] < rv) {
986 meterPeakValue[1] = rv;
987 peakTimer[1] = 0;
988 }
989 }
990
991 //---------------------------------------------------------
992 // initInstruments
993 //---------------------------------------------------------
994
initInstruments(bool realTime)995 void Seq::initInstruments(bool realTime)
996 {
997 // Add midi out ports if necessary
998 if (cs && (cachedPrefs.useJackMidi || cachedPrefs.useAlsaAudio)) {
999 // Increase the maximum number of midi ports if user adds staves/instruments
1000 int scoreMaxMidiPort = cs->masterScore()->midiPortCount();
1001 if (maxMidiOutPort < scoreMaxMidiPort)
1002 maxMidiOutPort = scoreMaxMidiPort;
1003 // if maxMidiOutPort is equal to existing ports number, it will do nothing
1004 if (_driver)
1005 _driver->updateOutPortCount(maxMidiOutPort + 1);
1006 }
1007
1008 for (const MidiMapping& mm : cs->midiMapping()) {
1009 const Channel* channel = mm.articulation();
1010 for (const MidiCoreEvent& e : channel->initList()) {
1011 if (e.type() == ME_INVALID)
1012 continue;
1013 NPlayEvent event(e.type(), channel->channel(), e.dataA(), e.dataB());
1014 if (realTime)
1015 putEvent(event);
1016 else
1017 sendEvent(event);
1018 }
1019 // Setting pitch bend sensitivity to 12 semitones for external synthesizers
1020 if ((cachedPrefs.useJackMidi || cachedPrefs.useAlsaAudio) && mm.channel() != 9) {
1021 if (realTime) {
1022 putEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_LRPN, 0));
1023 putEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_HRPN, 0));
1024 putEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_HDATA,12));
1025 putEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_LRPN, 127));
1026 putEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_HRPN, 127));
1027 }
1028 else {
1029 sendEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_LRPN, 0));
1030 sendEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_HRPN, 0));
1031 sendEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_HDATA,12));
1032 sendEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_LRPN, 127));
1033 sendEvent(NPlayEvent(ME_CONTROLLER, channel->channel(), CTRL_HRPN, 127));
1034 }
1035 }
1036 }
1037 }
1038
1039 //---------------------------------------------------------
1040 // renderChunk
1041 //---------------------------------------------------------
1042
renderChunk(const MidiRenderer::Chunk & ch,EventMap * eventMap)1043 void Seq::renderChunk(const MidiRenderer::Chunk& ch, EventMap* eventMap)
1044 {
1045 SynthesizerState synState = mscore->synthesizerState();
1046 MidiRenderer::Context ctx(synState);
1047 ctx.metronome = true;
1048 ctx.renderHarmony = true;
1049 midi.renderChunk(ch, eventMap, ctx);
1050 renderEventsStatus.setOccupied(ch.utick1(), ch.utick2());
1051 }
1052
1053 //---------------------------------------------------------
1054 // updateEventsEnd
1055 //---------------------------------------------------------
1056
updateEventsEnd()1057 void Seq::updateEventsEnd()
1058 {
1059 auto end = events.cend();
1060 eventsEnd = end;
1061 endUTick = events.empty() ? 0 : (--end)->first;
1062 }
1063
1064 //---------------------------------------------------------
1065 // collectEvents
1066 //---------------------------------------------------------
1067
collectEvents(int utick)1068 void Seq::collectEvents(int utick)
1069 {
1070 //do not collect even while playing
1071 if (state == Transport::PLAY && playlistChanged)
1072 return;
1073
1074 mutex.lock();
1075
1076 if (midiRenderFuture.isRunning())
1077 midiRenderFuture.waitForFinished();
1078
1079 if (playlistChanged) {
1080 midi.setScoreChanged();
1081 events.clear();
1082 renderEvents.clear();
1083 renderEventsStatus.clear();
1084 }
1085 else if (!renderEvents.empty()) {
1086 events.insert(renderEvents.begin(), renderEvents.end());
1087 renderEvents.clear();
1088 }
1089
1090 int unrenderedUtick = renderEventsStatus.occupiedRangeEnd(utick);
1091 while (unrenderedUtick - utick < minUtickBufferSize) {
1092 const MidiRenderer::Chunk chunk = midi.getChunkAt(unrenderedUtick);
1093 if (!chunk)
1094 break;
1095 renderChunk(chunk, &events);
1096 unrenderedUtick = renderEventsStatus.occupiedRangeEnd(utick);
1097 }
1098
1099 updateEventsEnd();
1100 playPos = mscore->loop() ? events.find(cs->loopInTick().ticks()) : events.cbegin();
1101 playlistChanged = false;
1102 mutex.unlock();
1103 }
1104
1105 //---------------------------------------------------------
1106 // ensureBufferAsync
1107 //---------------------------------------------------------
1108
ensureBufferAsync(int utick)1109 void Seq::ensureBufferAsync(int utick)
1110 {
1111 if (mutex.tryLock()) { // sync with possible collectEvents calls
1112
1113 if (midiRenderFuture.isRunning() || !allowBackgroundRendering) {
1114 mutex.unlock();
1115 return;
1116 }
1117
1118 if (!renderEvents.empty()) {
1119 // TODO: use C++17 map::merge()?
1120 events.insert(renderEvents.begin(), renderEvents.end());
1121 updateEventsEnd();
1122 renderEvents.clear();
1123 }
1124
1125 const int unrenderedUtick = renderEventsStatus.occupiedRangeEnd(utick);
1126 if (unrenderedUtick - utick < minUtickBufferSize) {
1127 const MidiRenderer::Chunk chunk = midi.getChunkAt(unrenderedUtick);
1128 if (chunk) {
1129 midiRenderFuture = QtConcurrent::run([this, chunk]() {
1130 renderChunk(chunk, &renderEvents);
1131 });
1132 }
1133 }
1134 mutex.unlock();
1135 }
1136 }
1137
1138 //---------------------------------------------------------
1139 // getCurTick
1140 //---------------------------------------------------------
1141
getCurTick()1142 int Seq::getCurTick()
1143 {
1144 return cs->utime2utick(qreal(playFrame) / qreal(MScore::sampleRate));
1145 }
1146
1147 //---------------------------------------------------------
1148 // setRelTempo
1149 // relTempo = 1.0 = normal tempo
1150 //---------------------------------------------------------
1151
setRelTempo(double relTempo)1152 void Seq::setRelTempo(double relTempo)
1153 {
1154 guiToSeq(SeqMsg(SeqMsgId::TEMPO_CHANGE, relTempo));
1155 }
1156
1157 //---------------------------------------------------------
1158 // setPos
1159 // seek
1160 // realtime environment
1161 //---------------------------------------------------------
1162
setPos(int utick)1163 void Seq::setPos(int utick)
1164 {
1165 if (cs == 0)
1166 return;
1167 stopNotes(-1, true);
1168
1169 int ucur;
1170 mutex.lock();
1171 if (playPos != events.end())
1172 ucur = cs->repeatList().utick2tick(playPos->first);
1173 else
1174 ucur = utick - 1;
1175 if (utick != ucur)
1176 updateSynthesizerState(ucur, utick);
1177
1178 playFrame = cs->utick2utime(utick) * MScore::sampleRate;
1179 playPos = events.lower_bound(utick);
1180 mutex.unlock();
1181 }
1182
1183 //---------------------------------------------------------
1184 // getPlayStartUtick
1185 //---------------------------------------------------------
1186
getPlayStartUtick()1187 int Seq::getPlayStartUtick()
1188 {
1189 if ((mscore->loop())) {
1190 if (preferences.getBool(PREF_APP_PLAYBACK_LOOPTOSELECTIONONPLAY)) {
1191 setLoopSelection();
1192 }
1193 return cs->repeatList().tick2utick(cs->loopInTick().ticks());
1194 }
1195 return cs->repeatList().tick2utick(cs->playPos().ticks());
1196 }
1197
1198 //---------------------------------------------------------
1199 // seekCommon
1200 // a common part of seek() and seekRT(), contains code
1201 // that could be safely called from any thread.
1202 // Do not use explicitly, use seek() or seekRT()
1203 //---------------------------------------------------------
1204
seekCommon(int utick)1205 void Seq::seekCommon(int utick)
1206 {
1207 if (cs == 0)
1208 return;
1209
1210 collectEvents(utick);
1211
1212 if (cs->playMode() == PlayMode::AUDIO) {
1213 ogg_int64_t sp = cs->utick2utime(utick) * MScore::sampleRate;
1214 ov_pcm_seek(&vf, sp);
1215 }
1216
1217 guiPos = events.lower_bound(utick);
1218 mscore->setPos(Fraction::fromTicks(cs->repeatList().utick2tick(utick)));
1219 unmarkNotes();
1220 }
1221
1222 //---------------------------------------------------------
1223 // seek
1224 // send seek message to sequencer
1225 // gui thread
1226 //---------------------------------------------------------
1227
seek(int utick)1228 void Seq::seek(int utick)
1229 {
1230 if (preferences.getBool(PREF_IO_JACK_USEJACKTRANSPORT)) {
1231 if (utick > endUTick)
1232 utick = 0;
1233 _driver->seekTransport(utick);
1234 if (utick != 0)
1235 return;
1236 }
1237 seekCommon(utick);
1238
1239 int t = cs->repeatList().utick2tick(utick);
1240 Segment* seg = cs->tick2segment(Fraction::fromTicks(t));
1241 if (seg)
1242 mscore->currentScoreView()->moveCursor(seg->tick());
1243 cs->setPlayPos(Fraction::fromTicks(t));
1244 cs->update();
1245 guiToSeq(SeqMsg(SeqMsgId::SEEK, utick));
1246 }
1247
1248 //---------------------------------------------------------
1249 // seekRT
1250 // realtime thread
1251 //---------------------------------------------------------
1252
seekRT(int utick)1253 void Seq::seekRT(int utick)
1254 {
1255 if (cachedPrefs.useJackTransport && utick > endUTick)
1256 utick = 0;
1257 seekCommon(utick);
1258 setPos(utick);
1259 // Update the screen in GUI thread
1260 emit toGui('5', cs->repeatList().utick2tick(utick));
1261 }
1262
1263 //---------------------------------------------------------
1264 // startNote
1265 //---------------------------------------------------------
1266
startNote(int channel,int pitch,int velo,double nt)1267 void Seq::startNote(int channel, int pitch, int velo, double nt)
1268 {
1269 if (state != Transport::STOP && state != Transport::PLAY)
1270 return;
1271 NPlayEvent ev(ME_NOTEON, channel, pitch, velo);
1272 ev.setTuning(nt);
1273 sendEvent(ev);
1274 }
1275
startNote(int channel,int pitch,int velo,int duration,double nt)1276 void Seq::startNote(int channel, int pitch, int velo, int duration, double nt)
1277 {
1278 stopNotes();
1279 startNote(channel, pitch, velo, nt);
1280 startNoteTimer(duration);
1281 }
1282
1283 //---------------------------------------------------------
1284 // playMetronomeBeat
1285 //---------------------------------------------------------
1286
playMetronomeBeat(BeatType type)1287 void Seq::playMetronomeBeat(BeatType type)
1288 {
1289 if (state != Transport::STOP)
1290 return;
1291 liveEventQueue()->enqueue(NPlayEvent(type));
1292 }
1293
1294 //---------------------------------------------------------
1295 // startNoteTimer
1296 //---------------------------------------------------------
1297
startNoteTimer(int duration)1298 void Seq::startNoteTimer(int duration)
1299 {
1300 if (duration) {
1301 noteTimer->setInterval(duration);
1302 noteTimer->start();
1303 }
1304 }
1305 //---------------------------------------------------------
1306 // stopNoteTimer
1307 //---------------------------------------------------------
1308
stopNoteTimer()1309 void Seq::stopNoteTimer()
1310 {
1311 if (noteTimer->isActive()) {
1312 noteTimer->stop();
1313 stopNotes();
1314 }
1315 }
1316
1317 //---------------------------------------------------------
1318 // stopNotes
1319 //---------------------------------------------------------
1320
stopNotes(int channel,bool realTime)1321 void Seq::stopNotes(int channel, bool realTime)
1322 {
1323 auto send = [this, realTime](const NPlayEvent& event) {
1324 if (realTime)
1325 putEvent(event);
1326 else
1327 sendEvent(event);
1328 };
1329 // For VSTs/devices that do not support All Notes Off
1330 // CTRL_ALL_NOTES_OFF should still be evoked after calling this function, even if it seems redundant
1331 auto turnAllNotesOff = [send](int channel) {
1332 for (unsigned note = 0; note < 128; note++)
1333 send(NPlayEvent(ME_NOTEOFF, channel, note, 0));
1334 };
1335 // Stop notes in all channels
1336 if (channel == -1) {
1337 for(unsigned ch = 0; ch < cs->midiMapping().size(); ch++) {
1338 send(NPlayEvent(ME_CONTROLLER, ch, CTRL_SUSTAIN, 0));
1339 turnAllNotesOff(ch);
1340 send(NPlayEvent(ME_CONTROLLER, ch, CTRL_ALL_NOTES_OFF, 0));
1341 if (cs->midiChannel(ch) != 9)
1342 send(NPlayEvent(ME_PITCHBEND, ch, 0, 64));
1343 }
1344 }
1345 else {
1346 send(NPlayEvent(ME_CONTROLLER, channel, CTRL_SUSTAIN, 0));
1347 turnAllNotesOff(channel);
1348 send(NPlayEvent(ME_CONTROLLER, channel, CTRL_ALL_NOTES_OFF, 0));
1349 if (cs->midiChannel(channel) != 9)
1350 send(NPlayEvent(ME_PITCHBEND, channel, 0, 64));
1351 }
1352 if (cachedPrefs.useAlsaAudio || cachedPrefs.useJackAudio || cachedPrefs.usePulseAudio || cachedPrefs.usePortAudio) {
1353 guiToSeq(SeqMsg(SeqMsgId::ALL_NOTE_OFF, channel));
1354 }
1355 }
1356
1357 //---------------------------------------------------------
1358 // setController
1359 //---------------------------------------------------------
1360
setController(int channel,int ctrl,int data)1361 void Seq::setController(int channel, int ctrl, int data)
1362 {
1363 NPlayEvent event(ME_CONTROLLER, channel, ctrl, data);
1364 sendEvent(event);
1365 }
1366
1367 //---------------------------------------------------------
1368 // sendEvent
1369 // called from GUI context to send a midi event to
1370 // midi out or synthesizer
1371 //---------------------------------------------------------
1372
sendEvent(const NPlayEvent & ev)1373 void Seq::sendEvent(const NPlayEvent& ev)
1374 {
1375 guiToSeq(SeqMsg(SeqMsgId::PLAY, ev));
1376 }
1377
1378 //---------------------------------------------------------
1379 // nextMeasure
1380 //---------------------------------------------------------
1381
nextMeasure()1382 void Seq::nextMeasure()
1383 {
1384 Measure* m = cs->tick2measure(Fraction::fromTicks(guiPos->first));
1385 if (m) {
1386 if (m->nextMeasure())
1387 m = m->nextMeasure();
1388 seek(m->tick().ticks());
1389 }
1390 }
1391
1392 //---------------------------------------------------------
1393 // nextChord
1394 //---------------------------------------------------------
1395
nextChord()1396 void Seq::nextChord()
1397 {
1398 int t = guiPos->first;
1399 for (auto i = guiPos; i != eventsEnd; ++i) {
1400 if (i->second.type() == ME_NOTEON && i->first > t && i->second.velo()) {
1401 seek(i->first);
1402 break;
1403 }
1404 }
1405 }
1406
1407 //---------------------------------------------------------
1408 // prevMeasure
1409 //---------------------------------------------------------
1410
prevMeasure()1411 void Seq::prevMeasure()
1412 {
1413 auto i = guiPos;
1414 if (i == events.begin())
1415 return;
1416 --i;
1417 Measure* m = cs->tick2measure(Fraction::fromTicks(i->first));
1418 if (m) {
1419 if ((i->first == m->tick().ticks()) && m->prevMeasure())
1420 m = m->prevMeasure();
1421 seek(m->tick().ticks());
1422 }
1423 }
1424
1425 //---------------------------------------------------------
1426 // prevChord
1427 //---------------------------------------------------------
1428
prevChord()1429 void Seq::prevChord()
1430 {
1431 int t = playPos->first;
1432 //find the chord just before playpos
1433 EventMap::const_iterator i = events.upper_bound(cs->repeatList().tick2utick(t));
1434 for (;;) {
1435 if (i->second.type() == ME_NOTEON) {
1436 const NPlayEvent& n = i->second;
1437 if (i->first < t && n.velo()) {
1438 t = i->first;
1439 break;
1440 }
1441 }
1442 if (i == events.cbegin())
1443 break;
1444 --i;
1445 }
1446 //go the previous chord
1447 if (i != events.cbegin()) {
1448 i = playPos;
1449 for (;;) {
1450 if (i->second.type() == ME_NOTEON) {
1451 const NPlayEvent& n = i->second;
1452 if (i->first < t && n.velo()) {
1453 seek(i->first);
1454 break;
1455 }
1456 }
1457 if (i == events.cbegin())
1458 break;
1459 --i;
1460 }
1461 }
1462 }
1463
1464 //---------------------------------------------------------
1465 // seekEnd
1466 //---------------------------------------------------------
1467
seekEnd()1468 void Seq::seekEnd()
1469 {
1470 qDebug("seek to end");
1471 }
1472
1473 //---------------------------------------------------------
1474 // guiToSeq
1475 //---------------------------------------------------------
1476
guiToSeq(const SeqMsg & msg)1477 void Seq::guiToSeq(const SeqMsg& msg)
1478 {
1479 if (!_driver || !running)
1480 return;
1481 toSeq.enqueue(msg);
1482 }
1483
1484 //---------------------------------------------------------
1485 // eventToGui
1486 //---------------------------------------------------------
1487
eventToGui(NPlayEvent e)1488 void Seq::eventToGui(NPlayEvent e)
1489 {
1490 fromSeq.enqueue(SeqMsg(SeqMsgId::MIDI_INPUT_EVENT, e));
1491 }
1492
1493 //---------------------------------------------------------
1494 // midiInputReady
1495 //---------------------------------------------------------
1496
midiInputReady()1497 void Seq::midiInputReady()
1498 {
1499 if (_driver)
1500 _driver->midiRead();
1501 }
1502
1503 //---------------------------------------------------------
1504 // SeqMsgFifo
1505 //---------------------------------------------------------
1506
SeqMsgFifo()1507 SeqMsgFifo::SeqMsgFifo()
1508 {
1509 maxCount = SEQ_MSG_FIFO_SIZE;
1510 clear();
1511 }
1512
1513 //---------------------------------------------------------
1514 // enqueue
1515 //---------------------------------------------------------
1516
enqueue(const SeqMsg & msg)1517 void SeqMsgFifo::enqueue(const SeqMsg& msg)
1518 {
1519 int i = 0;
1520 int n = 50;
1521
1522 QMutex mutex;
1523 QWaitCondition qwc;
1524 mutex.lock();
1525 for (; i < n; ++i) {
1526 if (!isFull())
1527 break;
1528 qwc.wait(&mutex,100);
1529 }
1530 mutex.unlock();
1531 if (i == n) {
1532 qDebug("===SeqMsgFifo: overflow");
1533 return;
1534 }
1535 messages[widx] = msg;
1536 push();
1537 }
1538
1539 //---------------------------------------------------------
1540 // dequeue
1541 //---------------------------------------------------------
1542
dequeue()1543 SeqMsg SeqMsgFifo::dequeue()
1544 {
1545 SeqMsg msg = messages[ridx];
1546 pop();
1547 return msg;
1548 }
1549
1550 //---------------------------------------------------------
1551 // putEvent
1552 //---------------------------------------------------------
1553
putEvent(const NPlayEvent & event,unsigned framePos)1554 void Seq::putEvent(const NPlayEvent& event, unsigned framePos)
1555 {
1556 if (!cs)
1557 return;
1558 int channel = event.channel();
1559 if (channel >= int(cs->midiMapping().size())) {
1560 qDebug("bad channel value %d >= %d", channel, int(cs->midiMapping().size()));
1561 return;
1562 }
1563
1564 // audio
1565 int syntiIdx= _synti->index(cs->midiMapping(channel)->articulation()->synti());
1566 _synti->play(event, syntiIdx);
1567
1568 // midi
1569 if (_driver != 0 && (cachedPrefs.useJackMidi || cachedPrefs.useAlsaAudio || cachedPrefs.usePortAudio))
1570 _driver->putEvent(event, framePos);
1571 }
1572
1573 //---------------------------------------------------------
1574 // heartBeat
1575 // update GUI
1576 //---------------------------------------------------------
1577
heartBeatTimeout()1578 void Seq::heartBeatTimeout()
1579 {
1580 SynthControl* sc = mscore->getSynthControl();
1581 if (sc && _driver) {
1582 if (++peakTimer[0] >= peakHold)
1583 meterPeakValue[0] *= .7f;
1584 if (++peakTimer[1] >= peakHold)
1585 meterPeakValue[1] *= .7f;
1586 sc->setMeter(meterValue[0], meterValue[1], meterPeakValue[0], meterPeakValue[1]);
1587 }
1588
1589 while (!fromSeq.empty()) {
1590 SeqMsg msg = fromSeq.dequeue();
1591 if (msg.id == SeqMsgId::MIDI_INPUT_EVENT) {
1592 int type = msg.event.type();
1593 if (type == ME_NOTEON)
1594 mscore->midiNoteReceived(msg.event.channel(), msg.event.pitch(), msg.event.velo());
1595 else if (type == ME_NOTEOFF)
1596 mscore->midiNoteReceived(msg.event.channel(), msg.event.pitch(), 0);
1597 else if (type == ME_CONTROLLER)
1598 mscore->midiCtrlReceived(msg.event.controller(), msg.event.value());
1599 }
1600 }
1601
1602 if (state != Transport::PLAY || inCountIn)
1603 return;
1604
1605 int endFrame = playFrame;
1606
1607 mutex.lock();
1608 auto ppos = playPos;
1609 if (ppos != events.cbegin())
1610 --ppos;
1611 mutex.unlock();
1612
1613 ensureBufferAsync(ppos->first);
1614
1615 if (cs && cs->sigmap()->timesig(getCurTick()).nominal()!=prevTimeSig) {
1616 prevTimeSig = cs->sigmap()->timesig(getCurTick()).nominal();
1617 emit timeSigChanged();
1618 }
1619 if (cs && curTempo()!=prevTempo) {
1620 prevTempo = curTempo();
1621 emit tempoChanged();
1622 }
1623
1624 QRectF r;
1625 for (;guiPos != eventsEnd; ++guiPos) {
1626 if (guiPos->first > ppos->first)
1627 break;
1628 if (mscore->loop())
1629 if (guiPos->first >= cs->repeatList().tick2utick(cs->loopOutTick().ticks()))
1630 break;
1631 const NPlayEvent& n = guiPos->second;
1632 if (n.type() == ME_NOTEON) {
1633 const Note* note1 = n.note();
1634 if (n.velo()) {
1635 while (note1) {
1636 for (ScoreElement* se : note1->linkList()) {
1637 if (!se->isNote())
1638 continue;
1639 Note* currentNote = toNote(se);
1640 currentNote->setMark(true);
1641 markedNotes.append(currentNote);
1642 r |= currentNote->canvasBoundingRect();
1643 }
1644 note1 = note1->tieFor() ? note1->tieFor()->endNote() : 0;
1645 }
1646 }
1647 else {
1648 while (note1) {
1649 for (ScoreElement* se : note1->linkList()) {
1650 if (!se->isNote())
1651 continue;
1652 Note* currentNote = toNote(se);
1653 currentNote->setMark(false);
1654 r |= currentNote->canvasBoundingRect();
1655 markedNotes.removeOne(currentNote);
1656 }
1657 note1 = note1->tieFor() ? note1->tieFor()->endNote() : 0;
1658 }
1659 }
1660 }
1661 }
1662 int utick = ppos->first;
1663 int t = cs->repeatList().utick2tick(utick);
1664 mscore->currentScoreView()->moveCursor(Fraction::fromTicks(t));
1665 mscore->setPos(Fraction::fromTicks(t));
1666
1667 emit(heartBeat(t, utick, endFrame));
1668
1669 PianorollEditor* pre = mscore->getPianorollEditor();
1670 if (pre && pre->isVisible())
1671 pre->heartBeat(this);
1672
1673 PianoTools* piano = mscore->pianoTools();
1674 if (piano && piano->isVisible())
1675 piano->setPlaybackNotes(markedNotes);
1676
1677 cv->update(cv->toPhysical(r));
1678 }
1679
1680 //---------------------------------------------------------
1681 // updateSynthesizerState
1682 // collect all controller events between tick1 and tick2
1683 // and send them to the synthesizer
1684 // Called from RT thread
1685 //---------------------------------------------------------
1686
updateSynthesizerState(int tick1,int tick2)1687 void Seq::updateSynthesizerState(int tick1, int tick2)
1688 {
1689 if (tick1 > tick2)
1690 tick1 = 0;
1691 // Making a local copy of events to avoid touching it
1692 // from different threads at the same time
1693 EventMap ev = events;
1694 EventMap::const_iterator i1 = ev.lower_bound(tick1);
1695 EventMap::const_iterator i2 = ev.upper_bound(tick2);
1696
1697 for (; i1 != i2; ++i1) {
1698 if (i1->second.type() == ME_CONTROLLER)
1699 playEvent(i1->second, 0);
1700 }
1701 }
1702
1703 //---------------------------------------------------------
1704 // curTempo
1705 //---------------------------------------------------------
1706
curTempo() const1707 double Seq::curTempo() const
1708 {
1709 if (playPos != events.end())
1710 return cs ? cs->tempomap()->tempo(playPos->first) : 0.0;
1711
1712 return 0.0;
1713 }
1714
1715 //---------------------------------------------------------
1716 // set Loop in position
1717 //---------------------------------------------------------
1718
setLoopIn()1719 void Seq::setLoopIn()
1720 {
1721 Fraction t;
1722 if (state == Transport::PLAY) { // If in playback mode, set the In position where note is being played
1723 auto ppos = playPos;
1724 if (ppos != events.cbegin())
1725 --ppos; // We have to go back one pos to get the correct note that has just been played
1726 t = Fraction::fromTicks(cs->repeatList().utick2tick(ppos->first));
1727 }
1728 else
1729 t = cs->pos(); // Otherwise, use the selected note.
1730 if (t >= cs->loopOutTick()) // If In pos >= Out pos, reset Out pos to end of score
1731 cs->setPos(POS::RIGHT, cs->lastMeasure()->endTick());
1732 cs->setPos(POS::LEFT, t);
1733 }
1734
1735 //---------------------------------------------------------
1736 // set Loop Out position
1737 //---------------------------------------------------------
1738
setLoopOut()1739 void Seq::setLoopOut()
1740 {
1741 Fraction t;
1742 if (state == Transport::PLAY) { // If in playback mode, set the Out position where note is being played
1743 t = Fraction::fromTicks(cs->repeatList().utick2tick(playPos->first));
1744 }
1745 else
1746 t = cs->pos() + cs->inputState().ticks(); // Otherwise, use the selected note.
1747 if (t <= cs->loopInTick()) // If Out pos <= In pos, reset In pos to beginning of score
1748 cs->setPos(POS::LEFT, Fraction(0,1));
1749 else
1750 if (t > cs->lastMeasure()->endTick())
1751 t = cs->lastMeasure()->endTick();
1752 cs->setPos(POS::RIGHT, t);
1753 if (state == Transport::PLAY)
1754 guiToSeq(SeqMsg(SeqMsgId::SEEK, t.ticks()));
1755 }
1756
setPos(POS,unsigned t)1757 void Seq::setPos(POS, unsigned t)
1758 {
1759 qDebug("seq: setPos %d", t);
1760 }
1761
1762 //---------------------------------------------------------
1763 // set Loop In/Out position based on the selection
1764 //---------------------------------------------------------
1765
setLoopSelection()1766 void Seq::setLoopSelection()
1767 {
1768 const Score* score = mscore->currentScore();
1769 Q_ASSERT(!score || score->masterScore() == cs);
1770
1771 if (score && score->selection().isRange()) {
1772 cs->setLoopInTick(score->selection().tickStart());
1773 cs->setLoopOutTick(score->selection().tickEnd());
1774 }
1775
1776 // add a dummy event to loop end if it is not already there
1777 // this is to let the playback reach the end completely before starting again
1778 if (!events.count(cs->loopOutTick().ticks())) {
1779 NPlayEvent ev;
1780 ev.setValue(ME_INVALID);
1781 events.insert(std::pair<int, Ms::NPlayEvent>(cs->loopOutTick().ticks(), ev));
1782 }
1783 }
1784
1785 //---------------------------------------------------------
1786 // Called after tempo or time signature
1787 // changed while playback
1788 //---------------------------------------------------------
1789
handleTimeSigTempoChanged()1790 void Seq::handleTimeSigTempoChanged()
1791 {
1792 _driver->handleTimeSigTempoChanged();
1793 }
1794
1795 //---------------------------------------------------------
1796 // setInitialMillisecondTimestampWithLatency
1797 // Called whenever seq->process() starts.
1798 // Sets a starting reference time for which subsequent PortMidi events will be offset from.
1799 // Time is relative to the start of PortMidi's initialization.
1800 //---------------------------------------------------------
1801
setInitialMillisecondTimestampWithLatency()1802 void Seq::setInitialMillisecondTimestampWithLatency()
1803 {
1804 #ifdef USE_PORTMIDI
1805 initialMillisecondTimestampWithLatency = Pt_Time() + cachedPrefs.portMidiOutputLatencyMilliseconds;
1806 //qDebug("PortMidi initialMillisecondTimestampWithLatency: %d = %d + %d", initialMillisecondTimestampWithLatency, unsigned(Pt_Time()), preferences.getInt(PREF_IO_PORTMIDI_OUTPUTLATENCYMILLISECONDS));
1807 #endif
1808 }
1809
1810 //---------------------------------------------------------
1811 // getCurrentMillisecondTimestampWithLatency
1812 // Called when midi messages are sent to PortMidi device.
1813 // Returns the time in milliseconds of the current play cursor.
1814 // Time is relative to the start of PortMidi's initialization.
1815 //---------------------------------------------------------
1816
getCurrentMillisecondTimestampWithLatency(unsigned framePos) const1817 unsigned Seq::getCurrentMillisecondTimestampWithLatency(unsigned framePos) const
1818 {
1819 #ifdef USE_PORTMIDI
1820 unsigned playTimeMilliseconds = unsigned(framePos * 1000) / unsigned(MScore::sampleRate);
1821 //qDebug("PortMidi timestamp = %d + %d", initialMillisecondTimestampWithLatency, playTimeMilliseconds);
1822 return initialMillisecondTimestampWithLatency + playTimeMilliseconds;
1823 #else
1824 qDebug("Shouldn't be using this function if not using PortMidi");
1825 return 0;
1826 #endif
1827 }
1828 }
1829