1 //=========================================================
2 // MusE
3 // Linux Music Editor
4 // $Id: midi.cpp,v 1.43.2.22 2009/11/09 20:28:28 terminator356 Exp $
5 //
6 // (C) Copyright 1999/2004 Werner Schweer (ws@seh.de)
7 // (C) Copyright 2011-2016 Tim E. Real (terminator356 on users dot sourceforge dot net)
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; version 2 of
12 // the License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 // GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with this program; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 //=========================================================
24
25 #include "muse_math.h"
26 #include <errno.h>
27
28 #include "song.h"
29 #include "midi.h"
30 #include "drummap.h"
31 #include "event.h"
32 #include "globals.h"
33 #include "midictrl.h"
34 #include "marker/marker.h"
35 #include "midiport.h"
36 #include "minstrument.h"
37 #include "midictrl.h"
38 #include "sync.h"
39 #include "audio.h"
40 #include "audiodev.h"
41 #include "mididev.h"
42 #include "driver/alsamidi.h"
43 #include "driver/jackmidi.h"
44 #include "wave.h"
45 #include "synth.h"
46 #include "sync.h"
47 #include "midiseq.h"
48 #include "gconfig.h"
49 #include "ticksynth.h"
50 #include "mpevent.h"
51 #include "metronome_class.h"
52 #include "tempo.h"
53 #include "sig.h"
54 #include "keyevent.h"
55 #include "track.h"
56
57 // REMOVE Tim. Persistent routes. Added. Make this permanent later if it works OK and makes good sense.
58 #define _USE_MIDI_ROUTE_PER_CHANNEL_
59
60 // Undefine if and when multiple output routes are added to midi tracks.
61 #define _USE_MIDI_TRACK_SINGLE_OUT_PORT_CHAN_
62
63 // For debugging output: Uncomment the fprintf section.
64 #define DEBUG_MIDI(dev, format, args...) // fprintf(dev, format, ##args);
65 // For debugging metronome and precount output: Uncomment the fprintf section.
66 #define DEBUG_MIDI_METRONOME(dev, format, args...) // fprintf(dev, format, ##args);
67 // For debugging midi timing: Uncomment the fprintf section.
68 #define DEBUG_MIDI_TIMING(dev, format, args...) // fprintf(dev, format, ##args);
69 // For debugging midi event time differences.
70 //#define DEBUG_MIDI_TIMING_DIFFS ;
71
72 namespace MusECore {
73
74 #ifdef DEBUG_MIDI_TIMING_DIFFS
75 // For testing.
76 unsigned _lastEvTime = 0;
77 #endif
78
79
80 extern void dump(const unsigned char* p, int n);
81
82 // Division can be zero meaning the event times are to be taken verbosely
83 // (as ticks already), no conversion is to be applied.
84 #define CALC_TICK(the_tick) (div > 0 ? lrintf((float(the_tick) * float(MusEGlobal::config.division) + float(div/2)) / float(div)) : the_tick);
85
86 /*---------------------------------------------------------
87 * midi_meta_name
88 *---------------------------------------------------------*/
89
midiMetaName(int meta)90 QString midiMetaName(int meta)
91 {
92 const char* s = "";
93 switch (meta) {
94 case 0: s = "Text 0: Sequence Number"; break;
95 case 1: s = "Text 1: Track comment"; break;
96 case 2: s = "Text 2: Copyright"; break;
97 case 3: s = "Text 3: Sequence/Track Name"; break;
98 case 4: s = "Text 4: Instrument Name"; break;
99 case 5: s = "Text 5: Lyric"; break;
100 case 6: s = "Text 6: Marker"; break;
101 case 7: s = "Text 7: Cue Point"; break;
102 case 8: s = "Text 8"; break;
103 case 9: s = "Text 9: Device Name"; break;
104 case 0x0a: s = "Text A"; break;
105 case 0x0b: s = "Text B"; break;
106 case 0x0c: s = "Text C"; break;
107 case 0x0d: s = "Text D"; break;
108 case 0x0e: s = "Text E"; break;
109 case 0x0f: s = "Text F"; break;
110 case 0x20: s = "Channel Prefix"; break;
111 case 0x21: s = "Port Change"; break;
112 case 0x2f: s = "End of Track"; break;
113 case 0x51: s = "Set Tempo"; break;
114 case 0x54: s = "SMPTE Offset"; break;
115 case 0x58: s = "Time Signature"; break;
116 case 0x59: s = "Key Signature"; break;
117 case 0x74: s = "Sequencer-Specific1"; break;
118 case 0x7f: s = "Sequencer-Specific2"; break;
119 default:
120 break;
121 }
122 return QString(s);
123 }
124
125 //---------------------------------------------------------
126 // QString nameSysex
127 //---------------------------------------------------------
128
nameSysex(unsigned int len,const unsigned char * buf,MidiInstrument * instr)129 QString nameSysex(unsigned int len, const unsigned char* buf, MidiInstrument* instr)
130 {
131 QString s;
132 if(len == 0)
133 return s;
134
135 switch(buf[0]) {
136 case 0x00:
137 if(len < 3)
138 return s;
139 if (buf[1] == 0 && buf[2] == 0x41)
140 s = "Microsoft";
141 break;
142 case 0x01: s = "Sequential Circuits"; break;
143 case 0x02: s = "Big Briar"; break;
144 case 0x03: s = "Octave / Plateau"; break;
145 case 0x04: s = "Moog"; break;
146 case 0x05: s = "Passport Designs"; break;
147 case 0x06: s = "Lexicon"; break;
148 case 0x07: s = "Kurzweil"; break;
149 case 0x08: s = "Fender"; break;
150 case 0x09: s = "Gulbransen"; break;
151 case 0x0a: s = "Delta Labas"; break;
152 case 0x0b: s = "Sound Comp."; break;
153 case 0x0c: s = "General Electro"; break;
154 case 0x0d: s = "Techmar"; break;
155 case 0x0e: s = "Matthews Research"; break;
156 case 0x10: s = "Oberheim"; break;
157 case 0x11: s = "PAIA"; break;
158 case 0x12: s = "Simmons"; break;
159 case 0x13: s = "DigiDesign"; break;
160 case 0x14: s = "Fairlight"; break;
161 case 0x15: s = "JL Cooper"; break;
162 case 0x16: s = "Lowery"; break;
163 case 0x17: s = "Lin"; break;
164 case 0x18: s = "Emu"; break;
165 case 0x1b: s = "Peavy"; break;
166 case 0x20: s = "Bon Tempi"; break;
167 case 0x21: s = "S.I.E.L"; break;
168 case 0x23: s = "SyntheAxe"; break;
169 case 0x24: s = "Hohner"; break;
170 case 0x25: s = "Crumar"; break;
171 case 0x26: s = "Solton"; break;
172 case 0x27: s = "Jellinghaus Ms"; break;
173 case 0x28: s = "CTS"; break;
174 case 0x29: s = "PPG"; break;
175 case 0x2f: s = "Elka"; break;
176 case 0x36: s = "Cheetah"; break;
177 case 0x3e: s = "Waldorf"; break;
178 case 0x40: s = "Kawai"; break;
179 case 0x41: s = "Roland"; break;
180 case 0x42: s = "Korg"; break;
181 case 0x43: s = "Yamaha"; break;
182 case 0x44: s = "Casio"; break;
183 case 0x45: s = "Akai"; break;
184 case MUSE_SYNTH_SYSEX_MFG_ID: s = "MusE Soft Synth"; break;
185 case 0x7d: s = "Educational Use"; break;
186 case 0x7e: s = "Universal: Non Real Time"; break;
187 case 0x7f: s = "Universal: Real Time"; break;
188 default: s = "??"; break;
189 }
190
191 if(instr)
192 {
193 // Check for user-defined sysex in instrument...
194 foreach(const MusECore::SysEx* sx, instr->sysex())
195 {
196 if((int)len == sx->dataLen && memcmp(buf, sx->data, len) == 0)
197 return s + QString(": ") + sx->name;
198 }
199 }
200
201 //
202 // following messages should not show up in event list
203 // they are filtered while importing midi files
204 //
205 if ((len == gmOnMsgLen) && memcmp(buf, gmOnMsg, gmOnMsgLen) == 0)
206 s += ": GM-ON";
207 else if ((len == gm2OnMsgLen) && memcmp(buf, gm2OnMsg, gm2OnMsgLen) == 0)
208 s += ": GM2-ON";
209 else if ((len == gmOffMsgLen) && memcmp(buf, gmOffMsg, gmOffMsgLen) == 0)
210 s += ": GM-OFF";
211 else if ((len == gsOnMsgLen) && memcmp(buf, gsOnMsg, gsOnMsgLen) == 0)
212 s += ": GS-ON";
213 else if ((len == xgOnMsgLen) && memcmp(buf, xgOnMsg, xgOnMsgLen) == 0)
214 s += ": XG-ON";
215 return s;
216 }
217
218 //---------------------------------------------------------
219 // QString sysexComment
220 //---------------------------------------------------------
221
sysexComment(unsigned int len,const unsigned char * buf,MidiInstrument * instr)222 QString sysexComment(unsigned int len, const unsigned char* buf, MidiInstrument* instr)
223 {
224 QString s;
225 if(len == 0)
226 return s;
227
228 if(instr)
229 {
230 // Check for user-defined sysex in instrument...
231 foreach(const MusECore::SysEx* sx, instr->sysex())
232 {
233 if((int)len == sx->dataLen && memcmp(buf, sx->data, len) == 0)
234 return sx->comment;
235 }
236 }
237
238 // These are the common ones we know about so far...
239 if ((len == gmOnMsgLen) && memcmp(buf, gmOnMsg, gmOnMsgLen) == 0)
240 s = QObject::tr("Switch on General Midi Level 1 mode");
241 else if ((len == gm2OnMsgLen) && memcmp(buf, gm2OnMsg, gm2OnMsgLen) == 0)
242 s = QObject::tr("Switch on General Midi Level 2 mode");
243 else if ((len == gmOffMsgLen) && memcmp(buf, gmOffMsg, gmOffMsgLen) == 0)
244 s = QObject::tr("Switch off General Midi Level 1 or 2");
245 else if ((len == gsOnMsgLen) && memcmp(buf, gsOnMsg, gsOnMsgLen) == 0)
246 s = QObject::tr("Switch on Roland GS mode");
247 else if ((len == xgOnMsgLen) && memcmp(buf, xgOnMsg, xgOnMsgLen) == 0)
248 s = QObject::tr("Switch on Yamaha XG mode");
249 return s;
250 }
251
252 //---------------------------------------------------------
253 // buildMidiEventList
254 // TODO:
255 // parse data increment/decrement controller
256 // NRPN/RPN fine/course data 7/14 Bit
257 // must we set datah/datal to zero after change
258 // of NRPN/RPN register?
259 // generally: how to handle incomplete messages
260 //---------------------------------------------------------
261
buildMidiEventList(EventList * del,const MPEventList & el,MidiTrack * track,int div,bool addSysexMeta,bool doLoops)262 void buildMidiEventList(EventList* del, const MPEventList& el, MidiTrack* track,
263 int div, bool addSysexMeta, bool doLoops)
264 {
265 int hbank = 0xff;
266 int lbank = 0xff;
267 int rpnh = -1;
268 int rpnl = -1;
269 int datah = 0;
270 int datal = 0;
271 int dataType = 0; // 0 : disabled, 0x20000 : rpn, 0x30000 : nrpn
272
273 EventList mel;
274
275 MidiInstrument::NoteOffMode nom = MidiInstrument::NoteOffAll;
276 MidiPort* mp = 0;
277 MidiInstrument* minstr = 0;
278 const int port = track->outPort();
279 if(port >= 0 && port < MusECore::MIDI_PORTS)
280 {
281 mp = &MusEGlobal::midiPorts[port];
282 minstr = mp->instrument();
283 if(minstr)
284 nom = minstr->noteOffMode();
285 }
286
287 for (iMPEvent i = el.begin(); i != el.end(); ++i) {
288 MidiPlayEvent ev = *i;
289 if (!addSysexMeta && (ev.type() == ME_SYSEX || ev.type() == ME_META))
290 continue;
291 if (!(ev.type() == ME_SYSEX || ev.type() == ME_META
292 || ((ev.channel() == track->outChannel()) && (ev.port() == track->outPort()))))
293 continue;
294 unsigned tick = ev.time();
295
296 DEBUG_MIDI(stderr, "buildMidiEventList tick:%d dataA:%d dataB:%d\n",
297 ev.time(), ev.dataA(), ev.dataB());
298
299 if(doLoops)
300 {
301 if(tick >= MusEGlobal::song->lPos().tick() && tick < MusEGlobal::song->rPos().tick())
302 {
303 int loopn = ev.loopNum();
304 int loopc = MusEGlobal::audio->loopCount();
305 int cmode = MusEGlobal::song->cycleMode(); // CYCLE_NORMAL, CYCLE_MIX, CYCLE_REPLACE
306 // If we want REPLACE and the event was recorded in a previous loop,
307 // just ignore it. This will effectively ignore ALL previous loop events inside
308 // the left and right markers, regardless of where recording was started or stopped.
309 // We want to keep any loop 0 note-offs from notes which crossed over the left marker.
310 // To avoid more searching here, just keep ALL note-offs from loop 0, and let code below
311 // sort out and keep which ones had note-ons.
312 if(!(ev.isNoteOff() && loopn == 0))
313 {
314 if(cmode == Song::CYCLE_REPLACE && loopn < loopc)
315 continue;
316
317 // If we want NORMAL, same as REPLACE except keep all events from the previous loop
318 // from rec stop position to right marker (and beyond).
319 if(cmode == Song::CYCLE_NORMAL)
320 {
321 // Not sure of accuracy here. Adjust? Adjusted when used elsewhere?
322 unsigned endRec = MusEGlobal::audio->getEndRecordPos().tick();
323 if((tick < endRec && loopn < loopc) || (tick >= endRec && loopn < (loopc - 1)))
324 continue;
325 }
326 }
327 }
328 }
329
330 Event e;
331 switch(ev.type()) {
332 case ME_NOTEON:
333 e.setType(Note);
334
335 if (track->isDrumTrack()) {
336 int instr = track->map_drum_in(ev.dataA());
337 e.setPitch(instr);
338 }
339 else
340 e.setPitch(ev.dataA());
341
342 e.setVelo(ev.dataB());
343 e.setLenTick(0);
344 break;
345 case ME_NOTEOFF:
346 e.setType(Note);
347 if (track->isDrumTrack()) {
348 int instr = track->map_drum_in(ev.dataA());
349 e.setPitch(instr);
350 }
351 else
352 e.setPitch(ev.dataA());
353
354 e.setVelo(0);
355 e.setVeloOff(ev.dataB());
356 e.setLenTick(0);
357 break;
358 case ME_POLYAFTER:
359 e.setType(Controller);
360 e.setA((CTRL_POLYAFTER & ~0xff) | (ev.dataA() & 0x7f));
361 e.setB(ev.dataB());
362 break;
363
364 case ME_CONTROLLER:
365 {
366 int val = ev.dataB();
367 switch(ev.dataA()) {
368 case CTRL_HBANK:
369 hbank = val;
370 break;
371
372 case CTRL_LBANK:
373 lbank = val;
374 break;
375
376 case CTRL_HDATA:
377 datah = val;
378 // check if a CTRL_LDATA follows
379 // e.g. wie have a 14 bit controller:
380 {
381 iMPEvent ii = i;
382 ++ii;
383 bool found = false;
384 for (; ii != el.end(); ++ii) {
385 MidiPlayEvent ev = *ii;
386 if (ev.type() == ME_CONTROLLER) {
387 if (ev.dataA() == CTRL_LDATA) {
388 // handle later
389 found = true;
390 }
391 break;
392 }
393 }
394 if (!found) {
395 if (rpnh == -1 || rpnl == -1) {
396 fprintf(stderr, "parameter number not defined, data 0x%x\n", datah);
397 }
398 else {
399 int ctrl = dataType | (rpnh << 8) | rpnl;
400 e.setType(Controller);
401 e.setA(ctrl);
402 e.setB(datah);
403 }
404 }
405 }
406 break;
407
408 case CTRL_LDATA:
409 datal = val;
410
411 if (rpnh == -1 || rpnl == -1) {
412 fprintf(stderr, "parameter number not defined, data 0x%x 0x%x, tick %d, channel %d\n",
413 datah, datal, tick, track->outChannel());
414 break;
415 }
416 // assume that the sequence is always
417 // CTRL_HDATA - CTRL_LDATA
418 // eg. that LDATA is always send last
419
420 e.setType(Controller);
421 // 14 Bit RPN/NRPN
422 e.setA((dataType+0x30000) | (rpnh << 8) | rpnl);
423 e.setB((datah << 7) | datal);
424 break;
425
426 case CTRL_HNRPN:
427 rpnh = val;
428 dataType = 0x30000;
429 break;
430
431 case CTRL_LNRPN:
432 rpnl = val;
433 dataType = 0x30000;
434 break;
435
436 case CTRL_HRPN:
437 rpnh = val;
438 dataType = 0x20000;
439 break;
440
441 case CTRL_LRPN:
442 rpnl = val;
443 dataType = 0x20000;
444 break;
445
446 default:
447 e.setType(Controller);
448 int ctl = ev.dataA();
449 e.setA(ctl);
450
451 if(track->isDrumTrack())
452 {
453 // Is it a drum controller event, according to the track port's instrument?
454 MidiController *mc = MusEGlobal::midiPorts[track->outPort()].drumController(ctl);
455 if(mc)
456 // Store an index into the drum map.
457 e.setA((ctl & ~0xff) | track->map_drum_in(ctl & 0x7f));
458 }
459
460 e.setB(val);
461 break;
462 }
463 }
464 break;
465
466 case ME_PROGRAM:
467 e.setType(Controller);
468 e.setA(CTRL_PROGRAM);
469 e.setB((hbank << 16) | (lbank << 8) | ev.dataA());
470 break;
471
472 case ME_AFTERTOUCH:
473 e.setType(Controller);
474 e.setA(CTRL_AFTERTOUCH);
475 e.setB(ev.dataA());
476 break;
477
478 case ME_PITCHBEND:
479 e.setType(Controller);
480 e.setA(CTRL_PITCH);
481 e.setB(ev.dataA());
482 break;
483
484 case ME_SYSEX:
485 e.setType(Sysex);
486 e.setData(ev.constData(), ev.len());
487 break;
488
489 case ME_META:
490 {
491 const unsigned char* data = ev.constData();
492 switch (ev.dataA()) {
493 case ME_META_TEXT_1_COMMENT:
494 if (track->comment().isEmpty())
495 track->setComment(QString((const char*)data));
496 else
497 track->setComment(track->comment() + "\n" + QString((const char*)data));
498 break;
499 case ME_META_TEXT_3_TRACK_NAME: // Sequence-/TrackName
500 track->setName(QString((char*)data));
501 break;
502 case ME_META_TEXT_6_MARKER:
503 {
504 unsigned ltick = CALC_TICK(tick);
505 MusEGlobal::song->addMarker(QString((const char*)(data)), ltick, false);
506 }
507 break;
508 // Copyright is supposed to occur only at the beginning of the first track, but we don't
509 // specifically catch it yet during import, so let's just allow it 'wherever' for now.
510 case ME_META_TEXT_2_COPYRIGHT:
511 // Lyrics are allowed anywhere.
512 case ME_META_TEXT_5_LYRIC:
513 // Cue points are supposed to occur only in the first track, but we don't support them
514 // yet (need a list just like markers), so just allow them 'wherever' for now.
515 case ME_META_TEXT_7_CUE_POINT:
516 // Program name is allowed anywhere.
517 case ME_META_TEXT_8_PROGRAM_NAME:
518 // No documentation could be found for these, so just allow them 'wherever' for now.
519 case ME_META_TEXT_A:
520 case ME_META_TEXT_B:
521 case ME_META_TEXT_C:
522 case ME_META_TEXT_D:
523 case ME_META_TEXT_E:
524 {
525 e.setType(Meta);
526 e.setA(ev.dataA());
527 e.setData(ev.constData(), ev.len());
528 }
529 break;
530 // Instrument and device name metas are already handled by the midi importing code.
531 case ME_META_TEXT_4_INSTRUMENT_NAME:
532 case ME_META_TEXT_9_DEVICE_NAME:
533 break;
534
535 case ME_META_TEXT_F_TRACK_COMMENT:
536 track->setComment(QString((char*)data));
537 break;
538 case ME_META_SET_TEMPO:
539 {
540 unsigned tempo = data[2] + (data[1] << 8) + (data[0] <<16);
541 unsigned ltick = CALC_TICK(tick);
542 // FIXME: After ca 10 mins 32 bits will not be enough... This expression has to be changed/factorized or so in some "sane" way...
543 MusEGlobal::tempomap.addTempo(ltick, tempo);
544 }
545 break;
546 case ME_META_TIME_SIGNATURE:
547 {
548 int timesig_z = data[0];
549 int n = data[1];
550 int timesig_n = 1;
551 for (int i = 0; i < n; i++)
552 timesig_n *= 2;
553 int ltick = CALC_TICK(tick);
554 MusEGlobal::sigmap.add(ltick, MusECore::TimeSignature(timesig_z, timesig_n));
555 }
556 break;
557 case ME_META_KEY_SIGNATURE:
558 {
559 char kc = data[0];
560 bool minor = data[1];
561 key_enum key = KEY_SHARP_BEGIN;
562 switch(kc)
563 {
564 case -5:
565 key = KEY_DES;
566 break;
567 case -4:
568 key = KEY_AS;
569 break;
570 case -3:
571 key = KEY_ES;
572 break;
573 case -2:
574 key = KEY_BES;
575 break;
576 case -1:
577 key = KEY_F;
578 break;
579 case 0:
580 key = KEY_C;
581 break;
582 case 1:
583 key = KEY_G;
584 break;
585 case 2:
586 key = KEY_D;
587 break;
588 case 3:
589 key = KEY_A;
590 break;
591 case 4:
592 key = KEY_E;
593 break;
594 case 5:
595 key = KEY_B;
596 break;
597 default:
598 break;
599 }
600 if(key != KEY_SHARP_BEGIN)
601 {
602 unsigned ltick = CALC_TICK(tick);
603 MusEGlobal::keymap.addKey(ltick, key, minor);
604 }
605 }
606 break;
607 default:
608 fprintf(stderr, "buildMidiEventList: unknown Meta 0x%x %d unabsorbed, adding instead to track:%s\n",
609 ev.dataA(), ev.dataA(), track->name().toLatin1().constData());
610 e.setType(Meta);
611 e.setA(ev.dataA());
612 e.setData(ev.constData(), ev.len());
613 break;
614 }
615 }
616 break;
617 } // switch(ev.type()
618 if (!e.empty()) {
619 e.setTick(tick);
620
621 //-------------------------------------------
622 // Check for and prevent duplicate events
623 //-------------------------------------------
624
625 const int midi_evtype = ev.type();
626 const bool midi_noteoff = (midi_evtype == ME_NOTEOFF) || (midi_evtype == ME_NOTEON && ev.dataB() == 0);
627 const bool midi_noteon = midi_evtype == ME_NOTEON && ev.dataB() != 0;
628 const bool midi_controller = midi_evtype == ME_CONTROLLER;
629 bool noteon_found = false;
630 bool noteoff_found = false;
631 bool ctrlval_found = false;
632 //bool other_ctrlval_found = false;
633 if(i != el.begin())
634 {
635 iMPEvent k = i;
636 while(k != el.begin())
637 {
638 --k;
639 MidiPlayEvent k_ev = *k;
640 if(k_ev.channel() != ev.channel() || k_ev.port() != ev.port())
641 continue;
642 const int check_midi_evtype = k_ev.type();
643 const bool check_midi_noteoff = (check_midi_evtype == ME_NOTEOFF) || (check_midi_evtype == ME_NOTEON && k_ev.dataB() == 0);
644 const bool check_midi_noteon = check_midi_evtype == ME_NOTEON && k_ev.dataB() != 0;
645 const bool check_midi_controller = check_midi_evtype == ME_CONTROLLER;
646 if(midi_noteon || midi_noteoff)
647 {
648 if(ev.dataA() == k_ev.dataA()) // Note
649 {
650 if(check_midi_noteon)
651 {
652 // Check the instrument's note-off mode: If it does not support note-offs,
653 // don't bother doing duplicate note-on checks.
654 // This allows drum input triggers (no note offs at all), although it is awkward to
655 // first have to choose an output instrument with no note-off mode.
656 if(!midi_noteon || (nom != MidiInstrument::NoteOffNone))
657 noteon_found = true;
658 break;
659 }
660 if(check_midi_noteoff)
661 {
662 noteoff_found = true;
663 break;
664 }
665 }
666 }
667 else if(midi_controller)
668 {
669 if(ev.dataA() == k_ev.dataA()) // Controller number
670 {
671 if(check_midi_controller)
672 {
673 // All we can really do is prevent multiple events at the same time.
674 // We must allow multiple events at different times having the same value,
675 // since the sender may have wanted it that way (a 'flat' graph).
676 if(ev.time() == k_ev.time()) // Event time
677 ctrlval_found = true;
678 // Optimization: Do not allow multiple events at different times having the same value.
679 // Nice, but can't really discard these, sender may have wanted it that way (a 'flat' graph).
680 #if 0
681 if(ev.dataB() == k_ev.dataB()) // Controller value
682 ctrlval_found = true;
683 else
684 other_ctrlval_found = true;
685 #endif
686 break;
687 }
688 }
689 }
690 else
691 {
692 // TODO: Other types!
693 }
694 }
695 }
696 // Accept the event only if no duplicate was found. // TODO: Other types!
697 if((midi_noteon && !noteon_found) ||
698 (midi_noteoff && !noteoff_found) ||
699 //(midi_controller && (other_ctrlval_found || !ctrlval_found)))
700 (midi_controller && !ctrlval_found) ||
701 // Accept any other type of event.
702 (!midi_noteon && !midi_noteoff && !midi_controller) )
703 mel.add(e);
704 }
705 } // i != el.end()
706
707
708 //---------------------------------------------------
709 // read NoteOn events and remove corresponding NoteOffs
710 //---------------------------------------------------
711
712 for (iEvent i = mel.begin(); i != mel.end(); ++i) {
713 Event ev = i->second;
714 if (ev.isNote()) {
715 if (!ev.isNoteOff()) {
716
717 // If the event length is not zero, it means the event and its
718 // note on/off have already been taken care of. So ignore it.
719 if(ev.lenTick() != 0)
720 continue;
721
722 iEvent k;
723 for (k = mel.lower_bound(ev.tick()); k != mel.end(); ++k) {
724 Event event = k->second;
725 if (ev.isNoteOff(event)) {
726 int t = k->first - i->first;
727 if (t <= 0) {
728 if (MusEGlobal::debugMsg) {
729 fprintf(stderr, "Note len is (%d-%d)=%d, set to 1\n",
730 k->first, i->first, k->first - i->first);
731 ev.dump();
732 event.dump();
733 }
734 t = 1;
735 }
736 ev.setLenTick(t);
737 ev.setVeloOff(event.veloOff());
738 break;
739 }
740 }
741 if (k == mel.end()) {
742 fprintf(stderr, "-no note-off! %d pitch %d velo %d\n",
743 ev.tick(), ev.pitch(), ev.velo());
744 //
745 // switch off at end of measure
746 //
747 int endTick = MusEGlobal::song->roundUpBar(ev.tick()+1);
748 ev.setLenTick(endTick-ev.tick());
749 }
750 else {
751 if (k==i) {
752 //this will never happen, because i->second has to be a NOTE ON,
753 //while k has to be a NOTE OFF. but in case something changes:
754 fprintf(stderr, "ERROR: THIS SHOULD NEVER HAPPEN: k==i in midi.cpp:buildMidiEventList()\n");
755 }
756 else {
757 mel.erase(k);
758 }
759 i = mel.begin();
760 continue;
761 }
762 }
763 }
764 }
765
766 for (iEvent i = mel.begin(); i != mel.end(); ++i) {
767 Event ev = i->second;
768 if (ev.isNoteOff()) {
769 fprintf(stderr, "+extra note-off! %d pitch %d velo %d\n",
770 i->first, ev.pitch(), ev.velo());
771 continue;
772 }
773 int tick = CALC_TICK(ev.tick());
774 if (ev.isNote()) {
775 int lenTick = CALC_TICK(ev.lenTick());
776 ev.setLenTick(lenTick);
777 }
778 ev.setTick(tick);
779 del->add(ev);
780 }
781 }
782
783 } // namespace MusECore
784
785 namespace MusECore {
786
787 //---------------------------------------------------------
788 // midiPortsChanged
789 //---------------------------------------------------------
790
midiPortsChanged()791 void Audio::midiPortsChanged()
792 {
793 write(sigFd, "P", 1);
794 }
795
796 //---------------------------------------------------------
797 // sendLocalOff
798 // Can be called by any thread.
799 //---------------------------------------------------------
800
sendLocalOff()801 void Audio::sendLocalOff()
802 {
803 MidiPlayEvent ev;
804 ev.setTime(0); // Immediate processing. TODO Use curFrame?
805 ev.setType(MusECore::ME_CONTROLLER);
806 ev.setA(MusECore::CTRL_LOCAL_OFF);
807 ev.setB(0);
808 for (int k = 0; k < MusECore::MIDI_PORTS; ++k) {
809 for (int i = 0; i < MusECore::MUSE_MIDI_CHANNELS; ++i)
810 {
811 ev.setPort(k);
812 ev.setChannel(i);
813 // This is a 'trigger' event. Send to the device, but do not send to the
814 // midi port controllers because it leaves them in this state.
815 if(MusEGlobal::midiPorts[k].device())
816 MusEGlobal::midiPorts[k].device()->putEvent(ev, MidiDevice::NotLate);
817 }
818 }
819 }
820
821 //---------------------------------------------------------
822 // panic
823 // Can be called by any thread.
824 //---------------------------------------------------------
825
panic()826 void Audio::panic()
827 {
828 MidiPlayEvent ev;
829 ev.setTime(0); // Immediate processing. TODO Use curFrame?
830 ev.setType(MusECore::ME_CONTROLLER);
831 ev.setB(0);
832
833 // TODO Reset those controllers back to unknown!
834 for (int i = 0; i < MusECore::MIDI_PORTS; ++i) {
835 MusECore::MidiPort* port = &MusEGlobal::midiPorts[i];
836 for (int chan = 0; chan < MusECore::MUSE_MIDI_CHANNELS; ++chan) {
837 if (MusEGlobal::debugMsg)
838 fprintf(stderr, "send all sound of to midi port %d channel %d\n", i, chan);
839
840 ev.setPort(i);
841 ev.setChannel(chan);
842
843 ev.setA(MusECore::CTRL_ALL_SOUNDS_OFF);
844 // This is a 'trigger' event. Send to the device, but do not send to the
845 // midi port controllers because it leaves them in this state.
846 //port->putHwCtrlEvent(ev);
847 if(port->device())
848 port->device()->putEvent(ev, MidiDevice::NotLate);
849
850 ev.setA(MusECore::CTRL_RESET_ALL_CTRL);
851 // This is a 'trigger' event. Send to the device, but do not send to the
852 // midi port controllers because it leaves them in this state.
853 //port->putHwCtrlEvent(ev);
854 if(port->device())
855 port->device()->putEvent(ev, MidiDevice::NotLate);
856 }
857 }
858 }
859
860 //---------------------------------------------------------
861 // initDevices
862 // - called when instrument init sequences plus controller
863 // defaults should be checked and/or sent
864 // - called from arranger pulldown menu
865 //---------------------------------------------------------
866
initDevices(bool force)867 void Audio::initDevices(bool force)
868 {
869 for (int i = 0; i < MusECore::MIDI_PORTS; ++i) {
870 MusEGlobal::midiPorts[i].sendPendingInitializations(force);
871 }
872 }
873
874 //---------------------------------------------------------
875 // seekMidi
876 // Called from audio thread only.
877 //---------------------------------------------------------
878
seekMidi()879 void Audio::seekMidi()
880 {
881 MusECore::MetronomeSettings* metro_settings =
882 MusEGlobal::metroUseSongSettings ? &MusEGlobal::metroSongSettings : &MusEGlobal::metroGlobalSettings;
883
884 unsigned int pos = MusEGlobal::audio->tickPos();
885 const bool playing = isPlaying();
886
887 // Bit-wise channels that are used.
888 int used_ports[MusECore::MIDI_PORTS];
889 // Initialize the array.
890 for(int i = 0; i < MusECore::MIDI_PORTS; ++i)
891 used_ports[i] = 0;
892
893 // Find all used channels on all used ports.
894 // bool drum_found = false;
895 if(MusEGlobal::song->click() &&
896 metro_settings->clickPort < MusECore::MIDI_PORTS &&
897 metro_settings->clickChan < MusECore::MUSE_MIDI_CHANNELS)
898 used_ports[metro_settings->clickPort] |= (1 << metro_settings->clickChan);
899 MidiTrackList* tl = MusEGlobal::song->midis();
900 for(ciMidiTrack imt = tl->begin(); imt != tl->end(); ++imt)
901 {
902 MidiTrack* mt = *imt;
903
904 //------------------------------------------------------------
905 // While we are at it, flush out any track-related playback stuck notes
906 // (NOT 'live' notes) which were not put directly to the device
907 //------------------------------------------------------------
908 MPEventList& mel = mt->stuckNotes;
909 for(iMPEvent i = mel.begin(), i_next = i; i != mel.end(); i = i_next)
910 {
911 ++i_next;
912
913 MidiPlayEvent ev(*i);
914 const int ev_port = ev.port();
915 if(ev_port >= 0 && ev_port < MusECore::MIDI_PORTS)
916 {
917 MidiPort* mp = &MusEGlobal::midiPorts[ev_port];
918 ev.setTime(0); // Immediate processing. TODO Use curFrame?
919 if(mp->device())
920 mp->device()->putEvent(ev, MidiDevice::NotLate);
921 }
922 mel.erase(i);
923 }
924
925
926 #ifdef _USE_MIDI_TRACK_SINGLE_OUT_PORT_CHAN_
927
928 if(mt->isDrumTrack())
929 {
930 for(int i = 0; i < DRUM_MAPSIZE; ++i)
931 {
932 // Default to track port if -1 and track channel if -1.
933 int mport = mt->drummap()[i].port;
934 if(mport == -1)
935 mport = mt->outPort();
936 int mchan = mt->drummap()[i].channel;
937 if(mchan == -1)
938 mchan = mt->outChannel();
939 if(mport >= 0 && mport < MusECore::MIDI_PORTS && mchan >= 0 && mchan < MusECore::MUSE_MIDI_CHANNELS)
940 used_ports[mport] |= (1 << mchan);
941 }
942 }
943 else
944 {
945 const int mport = mt->outPort();
946 const int mchan = mt->outChannel();
947 if(mport >= 0 && mport < MusECore::MIDI_PORTS && mchan >= 0 && mchan < MusECore::MUSE_MIDI_CHANNELS)
948 used_ports[mport] |= (1 << mchan);
949 }
950
951 #else
952 MusECore::RouteList* rl = mt->outRoutes();
953 for(MusECore::ciRoute ir = rl->begin(); ir != rl->end(); ++ir)
954 {
955 switch(ir->type)
956 {
957 case MusECore::Route::MIDI_PORT_ROUTE:
958 {
959 if(mt->isDrumTrack())
960 {
961 for(int i = 0; i < DRUM_MAPSIZE; ++i)
962 {
963 // Default to track port if -1 and track channel if -1.
964 int mport = mt->drummap()[i].port;
965 if(mport == -1)
966 mport = mt->outPort();
967 int mchan = mt->drummap()[i].channel;
968 if(mchan == -1)
969 mchan = mt->outChannel();
970 if(mport >= 0 && mport < MIDI_PORTS && mchan >= 0 && mchan < MusECore::MUSE_MIDI_CHANNELS)
971 used_ports[mport] |= (1 << mchan);
972 }
973 }
974 else
975 {
976 const int mport = ir->midiPort;
977 const int mchan = ir->channel;
978 if(mport >= 0 && mport < MIDI_PORTS && mchan >= 0 && mchan < MusECore::MUSE_MIDI_CHANNELS)
979 used_ports[mport] |= (1 << mchan);
980 }
981 }
982 break;
983
984 case MusECore::Route::TRACK_ROUTE:
985 case MusECore::Route::JACK_ROUTE:
986 case MusECore::Route::MIDI_DEVICE_ROUTE:
987 break;
988 }
989 }
990 #endif
991 }
992
993 for(int i = 0; i < MusECore::MIDI_PORTS; ++i)
994 {
995 if(used_ports[i] == 0)
996 continue;
997
998 MidiPort* mp = &MusEGlobal::midiPorts[i];
999 MidiDevice* md = mp->device();
1000
1001 //---------------------------------------------------
1002 // Send STOP
1003 //---------------------------------------------------
1004
1005 // Don't send if external sync is on. The master, and our sync routing system will take care of that.
1006 if(!MusEGlobal::extSyncFlag)
1007 {
1008 if(mp->syncInfo().MRTOut())
1009 {
1010 // Shall we check for device write open flag to see if it's ok to send?...
1011 //if(!(rwFlags() & 0x1) || !(openFlags() & 1))
1012 //if(!(openFlags() & 1))
1013 // continue;
1014 mp->sendStop();
1015 }
1016 }
1017
1018 //---------------------------------------------------
1019 // If playing, clear all notes and flush out any
1020 // stuck notes which were put directly to the device
1021 //---------------------------------------------------
1022
1023 if(md && playing)
1024 md->handleSeek();
1025
1026 //---------------------------------------------------
1027 // reset sustain
1028 //---------------------------------------------------
1029
1030 if(md)
1031 {
1032 for(int ch = 0; ch < MusECore::MUSE_MIDI_CHANNELS; ++ch)
1033 {
1034 if(mp->hwCtrlState(ch, CTRL_SUSTAIN) == 127)
1035 {
1036 const MidiPlayEvent ev(0, i, ch, ME_CONTROLLER, CTRL_SUSTAIN, 0);
1037 md->putEvent(ev, MidiDevice::NotLate);
1038 }
1039 }
1040 }
1041
1042 MidiInstrument* instr = mp->instrument();
1043 MidiCtrlValListList* cll = mp->controller();
1044
1045 for(iMidiCtrlValList ivl = cll->begin(); ivl != cll->end(); ++ivl)
1046 {
1047 MidiCtrlValList* vl = ivl->second;
1048 int chan = ivl->first >> 24;
1049 if(!(used_ports[i] & (1 << chan))) // Channel not used in song?
1050 continue;
1051 int ctlnum = vl->num();
1052
1053 // Find the first non-muted value at the given tick...
1054 bool values_found = false;
1055 bool found_value = false;
1056
1057 iMidiCtrlVal imcv = vl->lower_bound(pos);
1058 if(imcv != vl->end() && imcv->first == pos)
1059 {
1060 for( ; imcv != vl->end() && imcv->first == pos; ++imcv)
1061 {
1062 const Part* p = imcv->second.part;
1063 if(!p)
1064 continue;
1065 // Ignore values that are outside of the part.
1066 if(pos < p->tick() || pos >= (p->tick() + p->lenTick()))
1067 continue;
1068 values_found = true;
1069 // Ignore if part or track is muted or off.
1070 if(p->mute())
1071 continue;
1072 const Track* track = p->track();
1073 if(track && (track->isMute() || track->off()))
1074 continue;
1075 found_value = true;
1076 break;
1077 }
1078 }
1079 else
1080 {
1081 while(imcv != vl->begin())
1082 {
1083 --imcv;
1084 const Part* p = imcv->second.part;
1085 if(!p)
1086 continue;
1087 // Ignore values that are outside of the part.
1088 unsigned t = imcv->first;
1089 if(t < p->tick() || t >= (p->tick() + p->lenTick()))
1090 continue;
1091 values_found = true;
1092 // Ignore if part or track is muted or off.
1093 if(p->mute())
1094 continue;
1095 const Track* track = p->track();
1096 if(track && (track->isMute() || track->off()))
1097 continue;
1098 found_value = true;
1099 break;
1100 }
1101 }
1102
1103 if(found_value)
1104 {
1105 int fin_port = i;
1106 MidiPort* fin_mp = mp;
1107 int fin_chan = chan;
1108 int fin_ctlnum = ctlnum;
1109 // Is it a drum controller event, according to the track port's instrument?
1110 if(mp->drumController(ctlnum))
1111 {
1112 if(const Part* p = imcv->second.part)
1113 {
1114 if(Track* t = p->track())
1115 {
1116 if(t->type() == MusECore::Track::DRUM)
1117 {
1118 MidiTrack* mt = static_cast<MidiTrack*>(t);
1119 int v_idx = ctlnum & 0x7f;
1120 fin_ctlnum = (ctlnum & ~0xff) | mt->drummap()[v_idx].anote;
1121 int map_port = mt->drummap()[v_idx].port;
1122 if(map_port != -1)
1123 {
1124 fin_port = map_port;
1125 fin_mp = &MusEGlobal::midiPorts[fin_port];
1126 }
1127 int map_chan = mt->drummap()[v_idx].channel;
1128 if(map_chan != -1)
1129 fin_chan = map_chan;
1130 }
1131 }
1132 }
1133 }
1134
1135 const MidiPlayEvent ev(0, fin_port, fin_chan, ME_CONTROLLER, fin_ctlnum, imcv->second.val);
1136 // This is the audio thread. Just set directly.
1137 fin_mp->setHwCtrlState(ev);
1138 // Don't bother sending any sustain values to the device, because we already
1139 // just sent out zero sustain values, above. Just set the hw state.
1140 // When play resumes, the correct values are sent again if necessary in Audio::startRolling().
1141 if(fin_ctlnum != CTRL_SUSTAIN && fin_mp->device())
1142 fin_mp->device()->putEvent(ev, MidiDevice::NotLate);
1143 }
1144
1145 // Either no value was found, or they were outside parts, or pos is in the unknown area before the first value.
1146 // Send instrument default initial values. NOT for syntis. Use midiState and/or initParams for that.
1147 //if((imcv == vl->end() || !done) && !MusEGlobal::song->record() && instr && !isSynti())
1148 // Hmm, without refinement we can only do this at position 0, due to possible 'skipped' values outside parts, above.
1149 if(instr && md && !md->isSynti() && !values_found &&
1150 MusEGlobal::config.midiSendCtlDefaults && !MusEGlobal::song->record() && pos == 0)
1151 {
1152 // NOTE: If this is a PROGRAM controller, this code is not as crazy as it looks.
1153 // (How can we ask for, and then set, an initial program when we are first asking
1154 // for the current program? Seems like a 'circular' conflict.)
1155 // Midnam does not contain a program controller, so the setHwCtrlState() below
1156 // has no effect on the current controller list since in midnam there's no
1157 // program controller which would make it patch-dependent. There is only our
1158 // instrument's global PROGRAM controller (does not care about channel or current patch).
1159 const int patch = mp->hwCtrlState(chan, CTRL_PROGRAM);
1160 const MidiController* mc = instr->findController(vl->num(), chan, patch);
1161 if(mc->initVal() != CTRL_VAL_UNKNOWN)
1162 {
1163 //fprintf(stderr, "Audio::seekMidi: !values_found: calling sendEvent: ctlnum:%d val:%d\n", ctlnum, mc->initVal() + mc->bias());
1164 // Use sendEvent to get the optimizations and limiting. No force sending. Note the addition of bias.
1165 const MidiPlayEvent ev(0, i, chan, ME_CONTROLLER, ctlnum, mc->initVal() + mc->bias());
1166 // This is the audio thread. Just set directly.
1167 mp->setHwCtrlState(ev);
1168 md->putEvent(ev, MidiDevice::NotLate);
1169 }
1170 }
1171
1172 //---------------------------------------------------
1173 // Send STOP and "set song position pointer"
1174 //---------------------------------------------------
1175
1176 // Don't send if external sync is on. The master, and our sync routing system will take care of that.
1177 if(!MusEGlobal::extSyncFlag)
1178 {
1179 if(mp->syncInfo().MRTOut())
1180 {
1181 int beat = (pos * 4) / MusEGlobal::config.division;
1182 mp->sendSongpos(beat);
1183 }
1184 }
1185 }
1186 }
1187 }
1188
1189 //---------------------------------------------------------
1190 // extClockHistoryTick2Frame
1191 // Convert tick to frame using the external clock history list.
1192 // The function takes a tick relative to zero (ie. relative to the first event in a processing batch).
1193 // The returned clock frames occurred during the previous audio cycle(s), so you may want to shift
1194 // the frames forward by one audio segment size for scheduling purposes.
1195 // CAUTION: There must be at least one valid clock in the history,
1196 // otherwise it returns zero. Don't feed this a tick
1197 // greater than or equal to the next tick, it will simply return
1198 // the very last frame, which is not very useful since
1199 // that will just bunch the events together at the last frame.
1200 //---------------------------------------------------------
1201
extClockHistoryTick2Frame(unsigned int tick) const1202 unsigned int Audio::extClockHistoryTick2Frame(unsigned int tick) const
1203 {
1204 if(_extClockHistorySize == 0)
1205 {
1206 fprintf(stderr, "Error: Audio::extClockTickToFrame(): empty list\n");
1207 return 0;
1208 }
1209
1210 const int div = MusEGlobal::config.division / 24;
1211 if(div == 0)
1212 return 0; // Prevent divide by zero.
1213
1214 int index = tick / div;
1215 if(index >= _extClockHistorySize)
1216 {
1217 fprintf(stderr, "Error: Audio::extClockTickToFrame(): index:%d >= size:%d\n", index, _extClockHistorySize);
1218 index = _extClockHistorySize - 1;
1219 }
1220
1221 // Divide the clock period by the division and interpolate for even better resolution.
1222 // FIXME: Darn, too bad we can't use this. It would work, but the previous cycle
1223 // has no knowledge of what to put at the end, and the current cycle
1224 // would end up lumping together events at the start which should have
1225 // been played at end of previous cycle.
1226 // const unsigned int subtick = tick % div;
1227 // const unsigned int frame = _extClockLastFrame + double(_extClockHistory[index] - _extClockLastFrame) * (double(subtick) / double(div));
1228 const unsigned int frame = _extClockHistory[index].frame();
1229
1230 return frame;
1231 }
1232
1233 //---------------------------------------------------------
1234 // extClockHistoryTick2Frame
1235 // Convert frame to tick using the external clock history list.
1236 // The function takes an absolute linearly increasing frame and returns a tick relative to zero
1237 // (ie. relative to the first event in a processing batch).
1238 // CAUTION: There must be at least one valid clock in the history,
1239 // otherwise it returns zero. Don't feed this a frame
1240 // greater than or equal to the next frame, it will simply return
1241 // the very last tick, which is not very useful since
1242 // that will just bunch the events together at the last tick.
1243 //---------------------------------------------------------
1244
extClockHistoryFrame2Tick(unsigned int frame) const1245 unsigned int Audio::extClockHistoryFrame2Tick(unsigned int frame) const
1246 {
1247 if(_extClockHistorySize == 0)
1248 {
1249 fprintf(stderr, "Error: Audio::extClockHistoryFrame2Tick(): empty list\n");
1250 return curTickPos;
1251 }
1252
1253 const unsigned int div = MusEGlobal::config.division / 24;
1254
1255 bool found = false;
1256 unsigned int val = 0;
1257
1258 for(int i = _extClockHistorySize - 1; i >= 0; --i)
1259 {
1260 DEBUG_MIDI(stderr, "Audio::extClockHistoryFrame2Tick(): frame:%u i:%d _extClockHistory[i]._frame:%u\n",
1261 frame, i, _extClockHistory[i].frame());
1262
1263 if(_extClockHistory[i].frame() <= frame)
1264 {
1265 if(!found)
1266 {
1267 found = true;
1268 int clocks = 0;
1269 unsigned int offset = curTickPos;
1270
1271 for(int k = i; k >= 0; --k)
1272 {
1273 if(_extClockHistory[k].isFirstClock())
1274 {
1275 if(_extClockHistory[k].externState() == ExtMidiClock::ExternStarted)
1276 offset = 0;
1277 }
1278
1279 if(!_extClockHistory[k].isPlaying())
1280 break;
1281
1282 if(k < i) // Ignore first clock.
1283 ++clocks;
1284 }
1285
1286 val = offset + clocks * div;
1287 }
1288 }
1289 }
1290 if(found)
1291 return val;
1292
1293 fprintf(stderr, "Error: Audio::extClockHistoryFrame2Tick(): frame:%u out of range. Returning zero. _extClockHistorySize:%u\n",
1294 frame, _extClockHistorySize);
1295
1296 // We don't know the state of the last clock, we can only assume it was playing.
1297 if(curTickPos >= div)
1298 return curTickPos - div;
1299
1300 return curTickPos;
1301 }
1302
1303 //---------------------------------------------------------
1304 // collectEvents
1305 // collect events for next audio segment
1306 //---------------------------------------------------------
1307
collectEvents(MusECore::MidiTrack * track,unsigned int cts,unsigned int nts,unsigned int frames,unsigned int latency_offset)1308 void Audio::collectEvents(MusECore::MidiTrack* track, unsigned int cts,
1309 unsigned int nts, unsigned int frames, unsigned int latency_offset)
1310 {
1311 DEBUG_MIDI_TIMING(stderr, "Audio::collectEvents: cts:%u nts:%u\n", cts, nts);
1312 const bool extsync = MusEGlobal::extSyncFlag;
1313 const int delay = track->delay;
1314 // If external sync is not on, we can take advantage of frame accuracy but
1315 // first we must allow the next tick position to be included in the search
1316 // even if it is equal to the current tick position.
1317 if((extsync && cts >= nts) ||
1318 (!extsync && cts > nts))
1319 return;
1320
1321 int port = track->outPort();
1322 int channel = track->outChannel();
1323 int defaultPort = port;
1324 MidiPort* mp = &MusEGlobal::midiPorts[port];
1325 MidiDevice* md = mp->device();
1326
1327 const unsigned int pos_fr = _pos.frame() + latency_offset;
1328 const unsigned int next_pos_fr = pos_fr + frames;
1329
1330 // at least one punch is set at this point
1331 const bool replaceMode = recording && track->recordFlag() && MusEGlobal::song->recMode() == MusEGlobal::song->REC_REPLACE;
1332 const bool punchboth = MusEGlobal::song->punchin() && MusEGlobal::song->punchout();
1333 const bool punchin = MusEGlobal::song->punchin() && !MusEGlobal::song->punchout();
1334 const bool punchout = MusEGlobal::song->punchout() && !MusEGlobal::song->punchin();
1335 const unsigned int rangeStart = MusEGlobal::song->lPos().tick();
1336 const unsigned int rangeEnd = MusEGlobal::song->rPos().tick();
1337
1338
1339 DEBUG_MIDI_TIMING(stderr, "Audio::collectEvents: pos_fr:%u next_pos_fr:%u\n", pos_fr, next_pos_fr);
1340
1341 PartList* pl = track->parts();
1342 for (iPart p = pl->begin(); p != pl->end(); ++p) {
1343 MusECore::MidiPart* part = (MusECore::MidiPart*)(p->second);
1344 // don't play muted parts
1345 if (part->mute())
1346 continue;
1347 const EventList& events = part->events();
1348 unsigned partTick = part->tick();
1349 unsigned partLen = part->lenTick();
1350 unsigned offset = delay + partTick;
1351 if (offset > nts)
1352 continue;
1353 unsigned stick = (offset > cts) ? 0 : cts - offset;
1354 unsigned etick = nts - offset;
1355 // Do not play events which are past the end of this part.
1356 if(etick > partLen)
1357 continue;
1358
1359 // The start and end tick are a rough range to make the loop faster instead of having
1360 // to iterate the whole list each time, comparing frames.
1361 // Use upper_bound because we need to include the 'next' last item because it may have a
1362 // fractional tick component that we would otherwise miss with lower_bound. The loop will
1363 // decide whether to process iterated items or not by precisely comparing frames.
1364 // We rely on the tempo value being 'stable' during the process period - that is
1365 // no user changes in-between cycles. We don't have that capability currently anyway -
1366 // to break the process up into chunks (like our controllers) depending on tempo frames,
1367 // our tempo map is not frame-accurate, only tick-accurate.
1368 ciEvent ie = events.lower_bound(stick);
1369 ciEvent iend = events.upper_bound(etick);
1370
1371 DEBUG_MIDI_TIMING(stderr, "Audio::collectEvents: part events stick:%u etick:%u\n", stick, etick);
1372
1373 for (; ie != iend; ++ie) {
1374 Event ev = ie->second;
1375 port = defaultPort; //Reset each loop
1376 //
1377 // don't play any meta events
1378 //
1379 if (ev.type() == Meta)
1380 continue;
1381 if (track->isDrumTrack()) {
1382 int instr = ev.pitch();
1383 // ignore muted drums
1384 if (ev.isNote() && track->drummap()[instr].mute)
1385 continue;
1386 }
1387
1388 if (replaceMode) {
1389 unsigned eventStart = ev.tick() + partTick;
1390 if (punchboth && (eventStart >= rangeStart && eventStart < rangeEnd))
1391 continue;
1392 else if (punchin && eventStart >= rangeStart)
1393 continue;
1394 else if (punchout && eventStart < rangeEnd)
1395 continue;
1396 }
1397
1398 unsigned tick = ev.tick() + offset;
1399
1400 DEBUG_MIDI_TIMING(stderr, "Audio::collectEvents: event tick:%u\n", tick);
1401
1402 //-----------------------------------------------------------------
1403 // Determining the playback scheduling frame from the event's tick:
1404 //-----------------------------------------------------------------
1405 unsigned frame;
1406 if(extsync)
1407 // If external sync is on, look up the scheduling frame from the tick,
1408 // in the external clock history list (which is cleared, re-composed, and processed each cycle).
1409 // The function takes a tick relative to zero (ie. relative to the first event in this batch).
1410 // The returned clock frame occurred during the previous audio cycle(s), so shift the frame
1411 // forward by one audio segment size.
1412 frame = extClockHistoryTick2Frame(tick - stick) + MusEGlobal::segmentSize;
1413 else
1414 {
1415 // If external sync is off, look up the scheduling frame from our tempo list
1416 // ie. normal playback.
1417 const unsigned int fr = MusEGlobal::tempomap.tick2frame(tick);
1418
1419 DEBUG_MIDI_TIMING(stderr, "Audio::collectEvents: event: frame:%u\n", fr);
1420
1421 // Take advantage of frame-accurate comparison ability here.
1422 // At some point, the event's frame time and the 'swept' current range of pos frame will intersect,
1423 // so all events should be accounted for.
1424 if(fr < pos_fr || fr >= next_pos_fr)
1425 {
1426 DEBUG_MIDI_TIMING(stderr, "Audio::collectEvents: Ignoring event\n");
1427 continue;
1428 }
1429
1430 frame = fr - pos_fr;
1431 frame += syncFrame;
1432 }
1433
1434 DEBUG_MIDI(stderr, "Audio::collectEvents: event: tick:%u final frame:%u\n", tick, frame);
1435
1436 switch (ev.type()) {
1437 case Note:
1438 {
1439 int len = ev.lenTick();
1440 int pitch = ev.pitch();
1441 int velo = ev.velo();
1442 int veloOff = ev.veloOff();
1443 if (track->isDrumTrack()) {
1444 // Map drum-notes to the drum-map values
1445 int instr = ev.pitch();
1446 pitch = track->drummap()[instr].anote;
1447 // Default to track port if -1 and track channel if -1.
1448 port = track->drummap()[instr].port; //This changes to non-default port
1449 if(port == -1)
1450 port = track->outPort();
1451 channel = track->drummap()[instr].channel;
1452 if(channel == -1)
1453 channel = track->outChannel();
1454 velo = int(double(velo) * (double(track->drummap()[instr].vol) / 100.0)) ;
1455 veloOff = int(double(veloOff) * (double(track->drummap()[instr].vol) / 100.0)) ;
1456 }
1457 else if (track->type() == Track::MIDI) {
1458 // transpose non drum notes
1459 pitch += (track->transposition + MusEGlobal::song->globalPitchShift());
1460 }
1461
1462 if (pitch > 127)
1463 pitch = 127;
1464 if (pitch < 0)
1465 pitch = 0;
1466
1467 // Apply track velocity and compression to both note-on and note-off velocity...
1468 velo += track->velocity;
1469 velo = (velo * track->compression) / 100;
1470 if (velo > 127)
1471 velo = 127;
1472 if (velo < 1) // no off event
1473 // Zero means zero. Should mean no note at all?
1474 //velo = 1;
1475 continue;
1476 veloOff += track->velocity;
1477 veloOff = (veloOff * track->compression) / 100;
1478 if (veloOff > 127)
1479 veloOff = 127;
1480 if (veloOff < 1)
1481 veloOff = 0;
1482
1483 len = (len * track->len) / 100;
1484 if (len <= 0) // don't allow zero length
1485 len = 1;
1486
1487 if (port == defaultPort) {
1488 if (md) {
1489 md->putEvent(
1490 MusECore::MidiPlayEvent(frame, port, channel, MusECore::ME_NOTEON, pitch, velo),
1491 MidiDevice::NotLate, MidiDevice::PlaybackBuffer);
1492 track->addStuckNote(MusECore::MidiPlayEvent(tick + len, port, channel,
1493 MusECore::ME_NOTEOFF, pitch, veloOff));
1494 }
1495 }
1496 else { //Handle events to different port than standard.
1497 MidiDevice* mdAlt = MusEGlobal::midiPorts[port].device();
1498 if (mdAlt) {
1499 mdAlt->putEvent(
1500 MusECore::MidiPlayEvent(frame, port, channel, MusECore::ME_NOTEON, pitch, velo),
1501 MidiDevice::NotLate, MidiDevice::PlaybackBuffer);
1502 track->addStuckNote(MusECore::MidiPlayEvent(tick + len, port, channel,
1503 MusECore::ME_NOTEOFF, pitch, veloOff));
1504 }
1505 }
1506
1507 if(velo > track->activity())
1508 track->setActivity(velo);
1509 }
1510 break;
1511
1512 case Controller:
1513 {
1514 if (track->isDrumTrack())
1515 {
1516 int ctl = ev.dataA();
1517 // Is it a drum controller event, according to the track port's instrument?
1518 MusECore::MidiController *mc = MusEGlobal::midiPorts[defaultPort].drumController(ctl);
1519 if(mc)
1520 {
1521 int instr = ctl & 0x7f;
1522 ctl &= ~0xff;
1523 int pitch = track->drummap()[instr].anote & 0x7f;
1524 // Default to track port if -1 and track channel if -1.
1525 port = track->drummap()[instr].port; //This changes to non-default port
1526 if(port == -1)
1527 port = track->outPort();
1528 channel = track->drummap()[instr].channel;
1529 if(channel == -1)
1530 channel = track->outChannel();
1531
1532 MusECore::MidiPlayEvent mpeAlt(frame, port, channel,
1533 MusECore::ME_CONTROLLER,
1534 ctl | pitch,
1535 ev.dataB());
1536
1537 MidiPort* mpAlt = &MusEGlobal::midiPorts[port];
1538 // TODO Maybe grab the flag from the 'Optimize Controllers' Global Setting,
1539 // which so far was meant for (N)RPN stuff. For now, just force it.
1540 // This is the audio thread. Just set directly.
1541 mpAlt->setHwCtrlState(mpeAlt);
1542 if(MidiDevice* mdAlt = mpAlt->device())
1543 mdAlt->putEvent(mpeAlt, MidiDevice::NotLate, MidiDevice::PlaybackBuffer);
1544
1545 break; // Break out.
1546 }
1547 }
1548
1549 MusECore::MidiPlayEvent mpe = ev.asMidiPlayEvent(frame, port, channel);
1550 // TODO Maybe grab the flag from the 'Optimize Controllers' Global Setting,
1551 // which so far was meant for (N)RPN stuff. For now, just force it.
1552 // This is the audio thread. Just set directly.
1553 mp->setHwCtrlState(mpe);
1554 if(md)
1555 md->putEvent(mpe, MidiDevice::NotLate, MidiDevice::PlaybackBuffer);
1556 }
1557 break;
1558
1559 default:
1560
1561 if(md)
1562 {
1563 md->putEvent(ev.asMidiPlayEvent(frame, port, channel),
1564 MidiDevice::NotLate, MidiDevice::PlaybackBuffer);
1565 }
1566 break;
1567 }
1568 }
1569 }
1570 }
1571
1572 //---------------------------------------------------------
1573 // processMidi
1574 // - collects midi events for current audio segment and
1575 // sends them to midi thread
1576 // - current audio segment position is (curTickPos, nextTickPos)
1577 // - called from midiseq thread,
1578 // executed in audio thread
1579 //---------------------------------------------------------
1580
processMidi(unsigned int frames)1581 void Audio::processMidi(unsigned int frames)
1582 {
1583 const bool extsync = MusEGlobal::extSyncFlag;
1584 const bool playing = isPlaying();
1585
1586 for (iMidiDevice id = MusEGlobal::midiDevices.begin(); id != MusEGlobal::midiDevices.end(); ++id)
1587 {
1588 MidiDevice* md = *id;
1589 int port = md->midiPort(); // Port should be same as event.port() from this device. Same idea event.channel().
1590
1591 // Process events sent by synthesizers (which in turn may have been passed by their GUI -> synth FIFOs).
1592 // Receive events sent from a synth's gui thread (which might be different than our gui thread) to the audio thread.
1593 if(md->isSynti())
1594 {
1595 SynthI* s = (SynthI*)md;
1596 while (s->eventsPending())
1597 {
1598 MidiRecordEvent ev = s->receiveEvent();
1599 // FIXME: This is for recording the events sent by GUI.
1600 // It never gets a chance to be processed since reading of
1601 // record FIFOs is done only by connected input ROUTES, below.
1602 // To be useful, the synth itself must be allowed to be chosen
1603 // as an input route, which is simple enough, but we currently don't
1604 // list synths as inputs for fear of too many INCOMPATIBLE messages
1605 // from DIFFERING synths. However, we could allow ONLY THIS synth
1606 // to be listed and therefore be automatically connected too, if desired.
1607 //md->recordEvent(ev);
1608 //
1609 // For now, instead of recording, here is the minimum that we must do:
1610
1611 // Intercept any special MusE system sysex messages. (This IS the system right here.)
1612 bool intercepted = false;
1613 const int type = ev.type();
1614 switch(type)
1615 {
1616 case ME_SYSEX:
1617 {
1618 const unsigned char* p = ev.constData();
1619 int n = ev.len();
1620 if(n >= 3)
1621 {
1622 if(p[0] == MUSE_SYNTH_SYSEX_MFG_ID)
1623 {
1624 if(p[1] == MUSE_SYSEX_SYSTEM_ID && p[2] == MUSE_SYSEX_SYSTEM_UPDATE_DRUM_MAPS_ID)
1625 {
1626 intercepted = true;
1627 if(port >= 0 && port < MusECore::MIDI_PORTS)
1628 MusEGlobal::midiPorts[port].updateDrumMaps();
1629 }
1630 }
1631 }
1632 }
1633 break;
1634
1635 default:
1636 break;
1637 }
1638
1639 // Update hardware state so knobs and boxes are updated. Optimize to avoid re-setting existing values.
1640 // Same code as in MidiPort::sendEvent()
1641 if(!intercepted && port != -1)
1642 // This is the audio thread. Just set directly.
1643 MusEGlobal::midiPorts[port].setHwCtrlState(MidiPlayEvent(ev));
1644 }
1645 }
1646
1647 // Take snapshots of the current sizes of the recording fifos,
1648 // because they may change while here in process, asynchronously.
1649 md->beforeProcess();
1650
1651 //
1652 // --------- Handle midi events for audio tracks -----------
1653 //
1654
1655 if(port < 0)
1656 continue;
1657
1658 for(int chan = 0; chan < MusECore::MUSE_MIDI_CHANNELS; ++chan)
1659 {
1660 MusECore::MidiRecFifo& rf = md->recordEvents(chan);
1661 int count = md->tmpRecordCount(chan);
1662 for(int i = 0; i < count; ++i)
1663 {
1664 const MusECore::MidiRecordEvent& event(rf.peek(i));
1665
1666 int etype = event.type();
1667 if(etype == MusECore::ME_CONTROLLER || etype == MusECore::ME_PITCHBEND || etype == MusECore::ME_PROGRAM)
1668 {
1669 int ctl, val;
1670 if(etype == MusECore::ME_CONTROLLER)
1671 {
1672 ctl = event.dataA();
1673 val = event.dataB();
1674 }
1675 else if(etype == MusECore::ME_PITCHBEND)
1676 {
1677 ctl = MusECore::CTRL_PITCH;
1678 val = event.dataA();
1679 }
1680 else //if(etype == MusECore::ME_PROGRAM)
1681 {
1682 ctl = MusECore::CTRL_PROGRAM;
1683 val = event.dataA();
1684 }
1685
1686 // Midi learn!
1687 MusEGlobal::midiLearnPort = port;
1688 MusEGlobal::midiLearnChan = chan;
1689 MusEGlobal::midiLearnCtrl = ctl;
1690
1691 // Send to audio tracks...
1692 for (MusECore::iTrack t = MusEGlobal::song->tracks()->begin(); t != MusEGlobal::song->tracks()->end(); ++t)
1693 {
1694 if((*t)->isMidiTrack())
1695 continue;
1696 MusECore::AudioTrack* track = static_cast<MusECore::AudioTrack*>(*t);
1697 MidiAudioCtrlMap* macm = track->controller()->midiControls();
1698 int h = macm->index_hash(port, chan, ctl);
1699 std::pair<ciMidiAudioCtrlMap, ciMidiAudioCtrlMap> range = macm->equal_range(h);
1700 for(ciMidiAudioCtrlMap imacm = range.first; imacm != range.second; ++imacm)
1701 {
1702 const MidiAudioCtrlStruct* macs = &imacm->second;
1703 int actrl = macs->audioCtrlId();
1704
1705 iCtrlList icl = track->controller()->find(actrl);
1706 if(icl == track->controller()->end())
1707 continue;
1708 CtrlList* cl = icl->second;
1709 double dval = midi2AudioCtrlValue(cl, macs, ctl, val);
1710
1711 // Time here needs to be frames always.
1712 unsigned int ev_t = event.time();
1713 unsigned int t = ev_t;
1714
1715 unsigned int pframe = _pos.frame();
1716 if(pframe > t) // Technically that's an error, shouldn't happen
1717 t = 0;
1718 else
1719 // Subtract the current audio position frame
1720 t -= pframe;
1721
1722 // Add the current running sync frame to make the control processing happy
1723 t += syncFrame;
1724 track->addScheduledControlEvent(actrl, dval, t);
1725
1726 // Rec automation...
1727
1728 // For the record time, if stopped we don't want the circular running position,
1729 // just the static one.
1730 unsigned int rec_t = playing ? ev_t : pframe;
1731
1732 if(!MusEGlobal::automation)
1733 continue;
1734 AutomationType at = track->automationType();
1735 // Unlike our built-in gui controls, there is not much choice here but to
1736 // just do this:
1737 if ( (at == AUTO_WRITE) ||
1738 (at == AUTO_READ && !playing) ||
1739 (at == AUTO_TOUCH) )
1740 track->enableController(actrl, false);
1741 if(playing)
1742 {
1743 if(at == AUTO_WRITE || at == AUTO_TOUCH)
1744 track->recEvents()->push_back(CtrlRecVal(rec_t, actrl, dval));
1745 }
1746 else
1747 {
1748 if(at == AUTO_WRITE)
1749 track->recEvents()->push_back(CtrlRecVal(rec_t, actrl, dval));
1750 else if(at == AUTO_TOUCH)
1751 // In touch mode and not playing. Send directly to controller list.
1752 // Add will replace if found.
1753 cl->add(rec_t, dval);
1754 }
1755 }
1756 }
1757 }
1758 }
1759 }
1760 }
1761
1762 MidiTrackList* mtl = MusEGlobal::song->midis();
1763 for (iMidiTrack t = mtl->begin(); t != mtl->end(); ++t)
1764 {
1765 MidiTrack* track = *t;
1766 const int t_port = track->outPort();
1767 const int t_channel = track->outChannel();
1768 MidiPort* mp = nullptr;
1769 if(t_port >= 0 && t_port < MusECore::MIDI_PORTS)
1770 mp = &MusEGlobal::midiPorts[t_port];
1771 MidiDevice* md = nullptr;
1772 if(mp)
1773 md = mp->device();
1774
1775 // only add track events if the track is unmuted and turned on
1776 if(!track->isMute() && !track->off())
1777 {
1778 // don't render existing events in replace mode (except when punch is active - to be filtered later)
1779 if (!(recording && track->recordFlag() && MusEGlobal::song->recMode() == MusEGlobal::song->REC_REPLACE
1780 && !MusEGlobal::song->punchin() && !MusEGlobal::song->punchout()))
1781 {
1782 if(playing)
1783 {
1784 unsigned int lat_offset = 0;
1785 unsigned int cur_tick = curTickPos;
1786 unsigned int next_tick = nextTickPos;
1787
1788 //--------------------------------------------------------------------
1789 // Account for the midi track's latency correction and/or compensation.
1790 //--------------------------------------------------------------------
1791 // TODO How to handle when external sync is on. For now, don't try to correct.
1792 if(MusEGlobal::config.enableLatencyCorrection && !extsync)
1793 {
1794 const TrackLatencyInfo& li = track->getLatencyInfo(false);
1795 // This value is negative for correction.
1796 const float mlat = li._sourceCorrectionValue;
1797 if((int)mlat < 0)
1798 {
1799 // Convert to a positive offset.
1800 const unsigned int l = (unsigned int)(-mlat);
1801 if(l > lat_offset)
1802 lat_offset = l;
1803 }
1804 if(lat_offset != 0)
1805 {
1806 Pos ppp(_pos.frame() + lat_offset, false);
1807 cur_tick = ppp.tick();
1808 ppp += frames;
1809 next_tick = ppp.tick();
1810 }
1811 }
1812
1813 collectEvents(track, cur_tick, next_tick, frames, lat_offset);
1814 }
1815 }
1816 }
1817
1818 //
1819 //----------midi recording
1820 //
1821 const bool track_rec_flag = track->recordFlag();
1822 // REMOVE Tim. monitor. Changed.
1823 // const bool track_rec_monitor = track->recMonitor(); // Separate monitor and record functions.
1824 const bool track_rec_monitor = track->isRecMonitored(); // Separate monitor and record functions.
1825
1826 if(track_rec_monitor || track_rec_flag)
1827 {
1828 MPEventList& rl = track->mpevents;
1829 RouteList* irl = track->inRoutes();
1830 for(ciRoute r = irl->begin(); r != irl->end(); ++r)
1831 {
1832 if(!r->isValid() || (r->type != Route::MIDI_PORT_ROUTE))
1833 continue;
1834 int devport = r->midiPort;
1835 if (devport == -1)
1836 continue;
1837 MidiDevice* dev = MusEGlobal::midiPorts[devport].device();
1838 if(!dev)
1839 continue;
1840
1841 #ifdef _USE_MIDI_ROUTE_PER_CHANNEL_
1842
1843 const int r_chan = r->channel;
1844 #else
1845 const int channelMask = r->channel;
1846 if(channelMask == -1 || channelMask == 0)
1847 continue;
1848 #endif // _USE_MIDI_ROUTE_PER_CHANNEL_
1849
1850 for(int channel = 0; channel < MusECore::MUSE_MIDI_CHANNELS; ++channel)
1851 {
1852
1853 #ifdef _USE_MIDI_ROUTE_PER_CHANNEL_
1854 if(r_chan != -1 && channel != r_chan)
1855 continue;
1856 #else // _USE_MIDI_ROUTE_PER_CHANNEL_
1857 if(!(channelMask & (1 << channel)))
1858 continue;
1859 #endif // _USE_MIDI_ROUTE_PER_CHANNEL_
1860
1861 if(!dev->sysexFIFOProcessed())
1862 {
1863 // Set to the sysex fifo at first.
1864 MidiRecFifo& rf = dev->recordEvents(MusECore::MUSE_MIDI_CHANNELS);
1865 // Get the frozen snapshot of the size.
1866 int count = dev->tmpRecordCount(MusECore::MUSE_MIDI_CHANNELS);
1867
1868 for(int i = 0; i < count; ++i)
1869 {
1870 MidiRecordEvent event(rf.peek(i));
1871 event.setPort(t_port);
1872 event.setChannel(t_channel);
1873 // don't echo controller changes back to software
1874 // synthesizer:
1875 if(md && track_rec_monitor)
1876 {
1877 // Do not echo synth events back to the same synth instance under any circumstances,
1878 // not even if monitor (echo) is on.
1879 if(!dev->isSynti() || dev != md)
1880 {
1881 // All recorded events arrived in the previous period. Shift into this period for playback.
1882 unsigned int et = event.time();
1883 // The events arrived in the previous period. Shift into this period for playback.
1884 // The events are already biased with the last frame time.
1885 unsigned int t = et + MusEGlobal::segmentSize;
1886 // Protection from slight errors in estimated frame time.
1887 if(t >= (syncFrame + MusEGlobal::segmentSize))
1888 {
1889 DEBUG_MIDI(stderr, "Error: Audio::processMidi(): sysex: t:%u >= syncFrame:%u + segmentSize:%u (==%u)\n",
1890 t, syncFrame, MusEGlobal::segmentSize, syncFrame + MusEGlobal::segmentSize);
1891
1892 t = syncFrame + (MusEGlobal::segmentSize - 1);
1893 }
1894 event.setTime(t);
1895 md->putEvent(event, MidiDevice::NotLate);
1896 event.setTime(et); // Restore for recording.
1897 }
1898 }
1899
1900 unsigned int et = event.time();
1901 // Make sure the event is recorded in units of ticks.
1902 if(extsync)
1903 {
1904 const unsigned int xt = extClockHistoryFrame2Tick(event.time());
1905 DEBUG_MIDI(stderr, "processMidi: event time:%d dataA:%d dataB:%d curTickPos:%u set time:%u\n",
1906 event.time(), event.dataA(), event.dataB(), curTickPos, xt);
1907
1908 event.setTime(xt);
1909 }
1910 else
1911 {
1912 // All recorded events arrived in the previous period. Shift into this period for record.
1913 unsigned int t = et + MusEGlobal::segmentSize;
1914 // Protection from slight errors in estimated frame time.
1915 if(t >= (syncFrame + MusEGlobal::segmentSize))
1916 {
1917 DEBUG_MIDI(stderr, "Error: Audio::processMidi(): record sysex: t:%u >= syncFrame:%u + segmentSize:%u (==%u)\n",
1918 t, syncFrame, MusEGlobal::segmentSize, syncFrame + MusEGlobal::segmentSize);
1919
1920 t = syncFrame + (MusEGlobal::segmentSize - 1);
1921 }
1922 // Be sure to allow for some (very) late events, such as
1923 // the first chunk's time in a multi-chunk sysex.
1924 const unsigned int a_fr = pos().frame() + t;
1925 const unsigned int fin_fr = syncFrame > a_fr ? 0 : a_fr - syncFrame;
1926 event.setTime(MusEGlobal::tempomap.frame2tick(fin_fr));
1927 }
1928
1929 // Is the transport recording, or, is it about to be from external sync?
1930 if((recording ||
1931 (MusEGlobal::song->record() && extsync && MusEGlobal::midiSyncContainer.isPlaying()))
1932 && track_rec_flag)
1933 rl.add(event);
1934
1935 event.setTime(et); // Restore.
1936 }
1937 dev->setSysexFIFOProcessed(true);
1938 }
1939
1940 MidiRecFifo& rf = dev->recordEvents(channel);
1941 int count = dev->tmpRecordCount(channel);
1942 for(int i = 0; i < count; ++i)
1943 {
1944 MidiRecordEvent event(rf.peek(i));
1945 int defaultPort = devport;
1946 int drumRecPitch=0; //prevent compiler warning: variable used without initialization
1947 MidiController *mc = nullptr;
1948 int ctl = 0;
1949 int prePitch = 0, preVelo = 0;
1950
1951 event.setPort(t_port);
1952 event.setChannel(t_channel);
1953
1954 if (event.isNote() || event.isNoteOff())
1955 {
1956 //
1957 // apply track values
1958 //
1959
1960 //Apply drum inkey:
1961 if (track->isDrumTrack())
1962 {
1963 int pitch = event.dataA();
1964 int dmindex = track->map_drum_in(pitch);
1965 //Map note that is played according to MusEGlobal::drumInmap
1966 drumRecPitch = track->drummap()[dmindex].enote;
1967 // Default to track port if -1 and track channel if -1.
1968 devport = track->drummap()[dmindex].port;
1969 if(devport == -1)
1970 devport = track->outPort();
1971 event.setPort(devport);
1972 int mapchan = track->drummap()[dmindex].channel;
1973 if(mapchan != -1)
1974 event.setChannel(mapchan);
1975 event.setA(track->drummap()[dmindex].anote);
1976
1977 if (MusEGlobal::config.newDrumRecordCondition & MusECore::DONT_REC_HIDDEN &&
1978 track->drummap()[dmindex].hide )
1979 continue; // skip that event, proceed with the next
1980
1981 if (MusEGlobal::config.newDrumRecordCondition & MusECore::DONT_REC_MUTED &&
1982 track->drummap()[dmindex].mute )
1983 continue; // skip that event, proceed with the next
1984 }
1985 else
1986 { //Track transpose if non-drum
1987 prePitch = event.dataA();
1988 int pitch = prePitch + track->transposition;
1989 if (pitch > 127)
1990 pitch = 127;
1991 if (pitch < 0)
1992 pitch = 0;
1993 event.setA(pitch);
1994 }
1995
1996 // Apply track velocity and compression to note-on AND note-off events.
1997 preVelo = event.dataB();
1998 int velo = preVelo + track->velocity;
1999 velo = (velo * track->compression) / 100;
2000 if (velo > 127)
2001 velo = 127;
2002 if (velo < 1)
2003 // Zero means zero. Should mean no note at all?
2004 //velo = 1;
2005 velo = 0; // Use zero as a marker to tell the playback (below) not to sound the note.
2006
2007 event.setB(velo);
2008 }
2009 else if(event.type() == MusECore::ME_CONTROLLER)
2010 {
2011 if (track->isDrumTrack()) //FINDMICHJETZT TEST
2012 {
2013 ctl = event.dataA();
2014 // Regardless of what port the event came from, is it a drum controller event
2015 // according to the track port's instrument?
2016 if(mp)
2017 mc = mp->drumController(ctl);
2018 if(mc)
2019 {
2020 int pitch = ctl & 0x7f; // pitch is now the incoming pitch
2021 ctl &= ~0xff;
2022 int dmindex = track->map_drum_in(pitch) & 0x7f;
2023 //Map note that is played according to drumInmap
2024 drumRecPitch = track->drummap()[dmindex].enote;
2025 // Default to track port if -1 and track channel if -1.
2026 devport = track->drummap()[dmindex].port;
2027 if(devport == -1)
2028 devport = track->outPort();
2029 event.setPort(devport);
2030 int mapchan = track->drummap()[dmindex].channel;
2031 if(mapchan != -1)
2032 event.setChannel(mapchan);
2033 event.setA(ctl | track->drummap()[dmindex].anote);
2034
2035 if (MusEGlobal::config.newDrumRecordCondition & MusECore::DONT_REC_HIDDEN &&
2036 track->drummap()[dmindex].hide )
2037 continue; // skip that event, proceed with the next
2038
2039 if (MusEGlobal::config.newDrumRecordCondition & MusECore::DONT_REC_MUTED &&
2040 track->drummap()[dmindex].mute )
2041 continue; // skip that event, proceed with the next
2042 }
2043 }
2044 }
2045
2046 // MusE uses a fixed clocks per quarternote of 24.
2047 // At standard 384 ticks per quarternote for example,
2048 // 384/24=16 for a division of 16 sub-frames (16 MusE 'ticks').
2049 // If ext sync, events are now time-stamped with last tick in MidiDevice::recordEvent(). p3.3.35
2050 // TODO: Tested, but record resolution not so good. Switch to wall clock based separate list in MidiDevice.
2051
2052 // don't echo controller changes back to software
2053 // synthesizer:
2054
2055 // Zero means zero. Should mean no note at all?
2056 // If the event is marked as a note with zero velocity (above), do not sound the note.
2057 if(!event.isNote() || event.dataB() != 0)
2058 {
2059
2060 // All recorded events arrived in previous period. Shift into this period for playback.
2061 // frameoffset needed to make process happy.
2062 unsigned int et = event.time();
2063 // The events arrived in the previous period. Shift into this period for playback.
2064 // The events are already biased with the last frame time.
2065 unsigned int t = et + MusEGlobal::segmentSize;
2066 // Protection from slight errors in estimated frame time.
2067 if(t >= (syncFrame + MusEGlobal::segmentSize))
2068 {
2069 DEBUG_MIDI(stderr, "Error: Audio::processMidi(): event: t:%u >= syncFrame:%u + segmentSize:%u (==%u)\n",
2070 t, syncFrame, MusEGlobal::segmentSize, syncFrame + MusEGlobal::segmentSize);
2071
2072 t = syncFrame + (MusEGlobal::segmentSize - 1);
2073 }
2074 event.setTime(t);
2075 // Check if we're outputting to another port than default:
2076 if (devport == defaultPort) {
2077 event.setPort(t_port);
2078 // REMOVE Tim. monitor. Changed.
2079 //if(md && track_rec_monitor && !track->off() && !track->isMute())
2080 if(md && track_rec_monitor)
2081 {
2082 // Do not echo synth events back to the same synth instance under any circumstances,
2083 // not even if monitor (echo) is on.
2084 if(!dev->isSynti() || dev != md)
2085 {
2086 MidiInstrument* minstr = MusEGlobal::midiPorts[t_port].instrument();
2087 const MidiInstrument::NoteOffMode nom = minstr->noteOffMode();
2088 // If the instrument has no note-off mode, do not use the stuck notes mechanism, send as is.
2089 // This allows drum input triggers (no note offs at all), although it is awkward to
2090 // first have to choose an output instrument with no note-off mode.
2091 if(nom == MidiInstrument::NoteOffNone)
2092 {
2093 if(event.isNoteOff())
2094 // Try to remove any corresponding stuck live note.
2095 track->removeStuckLiveNote(t_port, event.channel(), event.dataA());
2096 // md->addScheduledEvent(event);
2097 md->putEvent(event, MidiDevice::NotLate);
2098 }
2099 else if(event.isNoteOff())
2100 {
2101 // Try to remove any corresponding stuck live note.
2102 // Only if a stuck live note existed do we schedule the note off to play.
2103 if(track->removeStuckLiveNote(t_port, event.channel(), event.dataA()))
2104 // md->addScheduledEvent(event);
2105 md->putEvent(event, MidiDevice::NotLate);
2106 }
2107 else if(event.isNote())
2108 {
2109 // Check if a stuck live note exists on any track.
2110 ciMidiTrack it_other = mtl->begin();
2111 for( ; it_other != mtl->end(); ++it_other)
2112 {
2113 if((*it_other)->stuckLiveNoteExists(t_port, event.channel(), event.dataA()))
2114 break;
2115 }
2116 // Only if NO stuck live note existed do we schedule the note on to play.
2117 if(it_other == mtl->end())
2118 {
2119 if(track->addStuckLiveNote(t_port, event.channel(), event.dataA()))
2120 // md->addScheduledEvent(event);
2121 md->putEvent(event, MidiDevice::NotLate);
2122 }
2123 }
2124 else
2125 {
2126 // TODO Maybe grab the flag from the 'Optimize Controllers' Global Setting,
2127 // which so far was meant for (N)RPN stuff. For now, just force it.
2128 // This is the audio thread. Just set directly.
2129 MusEGlobal::midiPorts[t_port].setHwCtrlState(event);
2130 md->putEvent(event, MidiDevice::NotLate);
2131 }
2132 }
2133 }
2134 }
2135 else {
2136 MidiDevice* mdAlt = MusEGlobal::midiPorts[devport].device();
2137 // REMOVE Tim. monitor. Changed.
2138 //if(mdAlt && track_rec_monitor && !track->off() && !track->isMute())
2139 if(mdAlt && track_rec_monitor)
2140 {
2141 // Do not echo synth events back to the same synth instance under any circumstances,
2142 // not even if monitor (echo) is on.
2143 if(!dev->isSynti() || dev != mdAlt)
2144 {
2145 MidiInstrument* minstr = MusEGlobal::midiPorts[devport].instrument();
2146 MidiInstrument::NoteOffMode nom = minstr->noteOffMode();
2147 // If the instrument has no note-off mode, do not use the
2148 // stuck notes mechanism, just send as is.
2149 // If the instrument has no note-off mode, do not use the stuck notes mechanism, send as is.
2150 // This allows drum input triggers (no note offs at all), although it is awkward to
2151 // first have to choose an output instrument with no note-off mode.
2152 if(nom == MidiInstrument::NoteOffNone)
2153 {
2154 if(event.isNoteOff())
2155 // Try to remove any corresponding stuck live note.
2156 track->removeStuckLiveNote(event.port(), event.channel(), event.dataA());
2157 // mdAlt->addScheduledEvent(event);
2158 mdAlt->putEvent(event, MidiDevice::NotLate);
2159 }
2160 else if(event.isNoteOff())
2161 {
2162 // Try to remove any corresponding stuck live note.
2163 // Only if a stuck live note existed do we schedule the note off to play.
2164 if(track->removeStuckLiveNote(event.port(), event.channel(), event.dataA()))
2165 // mdAlt->addScheduledEvent(event);
2166 mdAlt->putEvent(event, MidiDevice::NotLate);
2167 }
2168 else if(event.isNote())
2169 {
2170 // Check if a stuck live note exists on any track.
2171 ciMidiTrack it_other = mtl->begin();
2172 for( ; it_other != mtl->end(); ++it_other)
2173 {
2174 if((*it_other)->stuckLiveNoteExists(event.port(), event.channel(), event.dataA()))
2175 break;
2176 }
2177 // Only if NO stuck live note existed do we schedule the note on to play.
2178 if(it_other == mtl->end())
2179 {
2180 if(track->addStuckLiveNote(event.port(), event.channel(), event.dataA()))
2181 mdAlt->putEvent(event, MidiDevice::NotLate);
2182 }
2183 }
2184 else
2185 {
2186 // TODO Maybe grab the flag from the 'Optimize Controllers' Global Setting,
2187 // which so far was meant for (N)RPN stuff. For now, just force it.
2188 // This is the audio thread. Just set directly.
2189 MusEGlobal::midiPorts[devport].setHwCtrlState(event);
2190 mdAlt->putEvent(event, MidiDevice::NotLate);
2191 }
2192 }
2193 }
2194 }
2195 event.setTime(et); // Restore for recording.
2196
2197 // Shall we activate meters even while rec echo is off? Sure, why not...
2198 if(event.isNote() && event.dataB() > track->activity())
2199 track->setActivity(event.dataB());
2200 }
2201
2202 // Is the transport recording, or, is it about to be from external sync?
2203 if((recording ||
2204 (MusEGlobal::song->record() && extsync && MusEGlobal::midiSyncContainer.isPlaying()))
2205 && track_rec_flag)
2206 {
2207 unsigned int et = event.time();
2208 // Make sure the event is recorded in units of ticks.
2209 if(extsync)
2210 {
2211 const unsigned int xt = extClockHistoryFrame2Tick(event.time());
2212 DEBUG_MIDI(stderr, "processMidi: event time:%d dataA:%d dataB:%d curTickPos:%u set time:%u\n",
2213 event.time(), event.dataA(), event.dataB(), curTickPos, xt);
2214
2215 event.setTime(xt);
2216 }
2217 else
2218 {
2219 // REMOVE Tim. latency. Removed. Oops, with ALSA this adds undesired shift forward!
2220 // // All recorded events arrived in the previous period. Shift into this period for record.
2221 // REMOVE Tim. latency. Changed. Oops, with ALSA this adds undesired shift forward!
2222 // And with Jack midi we currently already shift forward, in the input routine!
2223 // But I'm debating where to add the correction factor - I really need to add it here
2224 // (exactly like the WaveTrack recording correction) but a very simple fix would be
2225 // in the Jack midi input routine to replace the current fixed segSize correction
2226 // factor with the MidiDevice::_latencyInfo._outputLatency,
2227 // but that is wrong although it would work.
2228 // To add the correction here may be more complicated than the WaveTrack,
2229 // some things in the ALSA and Jack midi input routines depend on the event time
2230 // (like midi clock, other rt events).
2231 //
2232 //
2233 // unsigned int t = et + MusEGlobal::segmentSize;
2234 // // Protection from slight errors in estimated frame time.
2235 // if(t >= (syncFrame + MusEGlobal::segmentSize))
2236 // {
2237 // DEBUG_MIDI(stderr, "Error: Audio::processMidi(): record event: t:%u >= syncFrame:%u + segmentSize:%u (==%u)\n",
2238 // t, syncFrame, MusEGlobal::segmentSize, syncFrame + MusEGlobal::segmentSize);
2239 //
2240 // t = syncFrame + (MusEGlobal::segmentSize - 1);
2241 // }
2242 unsigned int t = et;
2243 // Protection from slight errors in estimated frame time.
2244 if(t >= syncFrame)
2245 {
2246 DEBUG_MIDI(stderr, "Error: Audio::processMidi(): record event: t:%u >= syncFrame:%u\n",
2247 t, syncFrame);
2248
2249 t = syncFrame - 1;
2250 }
2251
2252 // Be sure to allow for some (very) late events, such as
2253 // the first chunk's time in a multi-chunk sysex.
2254 const unsigned int a_fr = pos().frame() + t;
2255 const unsigned int fin_fr = syncFrame > a_fr ? 0 : a_fr - syncFrame;
2256 event.setTime(MusEGlobal::tempomap.frame2tick(fin_fr));
2257 }
2258
2259 // In these next steps, it is essential to set the recorded event's port
2260 // to the track port so buildMidiEventList will accept it. Even though
2261 // the port may have no device "<none>".
2262 //
2263 if (track->isDrumTrack())
2264 {
2265 // Is it a drum controller event?
2266 if(mc)
2267 {
2268 MusECore::MidiPlayEvent drumRecEvent = event;
2269 drumRecEvent.setA(ctl | drumRecPitch);
2270 // In this case, preVelo is simply the controller value.
2271 drumRecEvent.setB(preVelo);
2272 drumRecEvent.setPort(t_port); //rec-event to current port
2273 drumRecEvent.setChannel(t_channel); //rec-event to current channel
2274 track->mpevents.add(drumRecEvent);
2275 }
2276 else
2277 {
2278 MusECore::MidiPlayEvent drumRecEvent = event;
2279 drumRecEvent.setA(drumRecPitch);
2280 drumRecEvent.setB(preVelo);
2281 // Changed to 'port'. Events were not being recorded for a drum map entry pointing to a
2282 // different port. That must have been wrong - buildMidiEventList would ignore that. Tim.
2283 drumRecEvent.setPort(t_port); //rec-event to current port
2284 drumRecEvent.setChannel(t_channel); //rec-event to current channel
2285 track->mpevents.add(drumRecEvent);
2286 }
2287 }
2288 else
2289 {
2290 // Restore record-pitch to non-transposed value since we don't want the note transposed twice next
2291 MusECore::MidiPlayEvent recEvent = event;
2292 if (prePitch)
2293 recEvent.setA(prePitch);
2294 if (preVelo)
2295 recEvent.setB(preVelo);
2296 recEvent.setPort(t_port);
2297 recEvent.setChannel(t_channel);
2298
2299 track->mpevents.add(recEvent);
2300 }
2301 // Restore. Not required.
2302 //event.setTime(et);
2303 }
2304 }
2305 }
2306 }
2307 }
2308
2309 // Must be playing for valid nextTickPos, right? But wasn't checked in Audio::processMidi().
2310 // MusEGlobal::audio->isPlaying() might not be true during seek right now.
2311 //if(MusEGlobal::audio->isPlaying())
2312 //if(playing)
2313 //{
2314 ciMPEvent k;
2315 MidiDevice* mdev;
2316 int mport;
2317 // What is the current transport frame?
2318 const unsigned int pos_fr = _pos.frame();
2319 // What is the (theoretical) next transport frame?
2320 const unsigned int next_pos_fr = pos_fr + frames;
2321
2322 // If muted or off we want to send all playback note-offs immediately.
2323 if(track->isMute() || track->off())
2324 {
2325 //---------------------------------------------------
2326 // Send all track-related playback note-offs (NOT 'live' note-offs)
2327 // which were not put directly to the device
2328 //---------------------------------------------------
2329 MPEventList& mel = track->stuckNotes;
2330 if(!mel.empty())
2331 {
2332 for(k = mel.begin(); k != mel.end(); ++k)
2333 {
2334 MidiPlayEvent ev(*k);
2335 mport = ev.port();
2336 if(mport < 0)
2337 continue;
2338 mdev = MusEGlobal::midiPorts[mport].device();
2339 if(!mdev)
2340 continue;
2341 ev.setTime(0); // Mark for immediate delivery.
2342 //ev.setTime(MusEGlobal::audio->midiQueueTimeStamp(k->time()));
2343 mdev->putEvent(ev, MidiDevice::NotLate);
2344 }
2345 mel.clear();
2346 }
2347 }
2348 else
2349 // If not muted and not off, we want to schedule all playback note-offs normally.
2350 {
2351 //---------------------------------------------------
2352 // Schedule all track-related playback note-offs (NOT 'live' note-offs)
2353 // which were not put directly to the device
2354 // To save time this was put here instead of MidiDevice::processStuckNotes()
2355 //---------------------------------------------------
2356 MPEventList& mel = track->stuckNotes;
2357 if(!mel.empty())
2358 {
2359 for(k = mel.begin(); k != mel.end(); ++k)
2360 {
2361 MidiPlayEvent ev(*k);
2362 unsigned int off_tick = ev.time();
2363 // If external sync is not on, we can take advantage of frame accuracy but
2364 // first we must allow the next tick position to be included in the search
2365 // even if it is equal to the current tick position.
2366 if(extsync ? (off_tick >= nextTickPos) : (off_tick > nextTickPos))
2367 break;
2368 mport = ev.port();
2369 if(mport < 0)
2370 continue;
2371 mdev = MusEGlobal::midiPorts[mport].device();
2372 if(!mdev)
2373 continue;
2374
2375 unsigned int off_frame = 0;
2376 if(extsync)
2377 {
2378 if(off_tick < curTickPos)
2379 off_tick = curTickPos;
2380 off_frame = extClockHistoryTick2Frame(off_tick - curTickPos) + MusEGlobal::segmentSize;
2381 }
2382 else
2383 {
2384 // What is the exact transport frame that the event should be played at?
2385 const unsigned int fr = MusEGlobal::tempomap.tick2frame(off_tick);
2386 // Is the event frame outside of the current transport frame range?
2387 if(fr >= next_pos_fr)
2388 break;
2389 off_frame = (fr < pos_fr) ? 0 : fr - pos_fr;
2390 off_frame += syncFrame;
2391 }
2392 ev.setTime(off_frame);
2393
2394 // TODO: DECIDE: Hm, we don't want the device to miss any note offs.
2395 // So I guess schedule this as a user event rather than a playback event.
2396 mdev->putEvent(ev, MidiDevice::NotLate);
2397 }
2398 mel.erase(mel.begin(), k);
2399 }
2400 }
2401
2402 // If no monitor or off, or not rec-armed (or muted), we want to cancel all 'live' (rec) stuck notes immediately.
2403 // REMOVE Tim. monitor. Changed.
2404 //if(!track_rec_monitor || track->off() || track->isMute())
2405 if(!track_rec_monitor)
2406 {
2407 //------------------------------------------------------------
2408 // Send all track-related 'live' (rec) note-offs
2409 // which were not put directly to the device
2410 //------------------------------------------------------------
2411 MPEventList& mel = track->stuckLiveNotes;
2412 if(!mel.empty())
2413 {
2414 for(k = mel.begin(); k != mel.end(); ++k)
2415 {
2416 MidiPlayEvent ev(*k);
2417 mport = ev.port();
2418 if(mport < 0)
2419 continue;
2420 mdev = MusEGlobal::midiPorts[mport].device();
2421 if(!mdev)
2422 continue;
2423 ev.setTime(0); // Mark for immediate delivery.
2424 //ev.setTime(MusEGlobal::audio->midiQueueTimeStamp(k->time()));
2425 mdev->putEvent(ev, MidiDevice::NotLate);
2426 }
2427 mel.clear();
2428 }
2429 }
2430 //}
2431 }
2432
2433 //---------------------------------------------------
2434 // insert metronome clicks
2435 //---------------------------------------------------
2436
2437 // If in PRECOUNT state, process the precount events.
2438 processPrecount(frames);
2439
2440 // Since the latency for audio and midi may be different,
2441 // process the audio and midi metronomes separately.
2442 processAudioMetronome(frames);
2443 processMidiMetronome(frames);
2444
2445 // REMOVE Tim. clock. Added.
2446 // //---------------------------------------------------
2447 // // send midi clock output events
2448 // //---------------------------------------------------
2449 //
2450 // _clockOutputQueueSize = 0;
2451 // if(!extsync)
2452 // {
2453 // const unsigned curr_audio_frame = syncFrame;
2454 // const unsigned next_audio_frame = curr_audio_frame + frames;
2455 // // const uint64_t numer = (uint64_t)MusEGlobal::config.division * (uint64_t)MusEGlobal::tempomap.globalTempo() * 10000UL;
2456 // const uint64_t denom = (uint64_t)MusEGlobal::config.division * (uint64_t)MusEGlobal::tempomap.globalTempo() * 10000UL;
2457 // const unsigned int div = MusEGlobal::config.division/24;
2458 //
2459 // // // Do not round up here since (audio) frame resolution is higher than tick resolution.
2460 // // const unsigned int clock_tick = muse_multiply_64_div_64_to_64(numer, curr_audio_frame,
2461 // // (uint64_t)MusEGlobal::sampleRate * (uint64_t)MusEGlobal::tempomap.tempo(curTickPos));
2462 //
2463 // // unsigned int clock_tick_end;
2464 // // Is the transport moving?
2465 // if(playing)
2466 // {
2467 // // unsigned int delta_tick;
2468 // // // Did tick position wrap around?
2469 // // if(curTickPos > nextTickPos)
2470 // // delta_tick = curTickPos - nextTickPos;
2471 // // else
2472 // // delta_tick = nextTickPos - curTickPos;
2473 // // clock_tick_end = clock_tick + delta_tick;
2474 // }
2475 // else
2476 // {
2477 // // // Do not round up here since (audio) frame resolution is higher than tick resolution.
2478 // // clock_tick_end = muse_multiply_64_div_64_to_64(numer, next_audio_frame,
2479 // // (uint64_t)MusEGlobal::sampleRate * (uint64_t)MusEGlobal::tempomap.tempo(curTickPos));
2480 //
2481 // uint64_t div_remainder;
2482 // const uint64_t div_frames = muse_multiply_64_div_64_to_64(
2483 // (uint64_t)MusEGlobal::sampleRate * (uint64_t)MusEGlobal::tempomap.tempo(curTickPos), div,
2484 // denom, LargeIntRoundNone, &div_remainder);
2485 //
2486 // // Counter too far in future? Reset.
2487 // if(_clockOutputCounter >= curr_audio_frame && _clockOutputCounter - curr_audio_frame >= div_frames)
2488 // {
2489 // _clockOutputCounter = curr_audio_frame;
2490 // _clockOutputCounterRemainder = 0;
2491 // }
2492 // // Counter too far in past? Reset.
2493 // else if(_clockOutputCounter < curr_audio_frame)
2494 // {
2495 // _clockOutputCounter = curr_audio_frame;
2496 // _clockOutputCounterRemainder = 0;
2497 // }
2498 //
2499 // //const uint64_t curr_clock_out_count = _clockOutputCounter + div_frames + (_clockOutputCounterRemainder + div_remainder) / denom;
2500 // //uint64_t next_clock_out_frame = _clockOutputCounter + div_frames + (_clockOutputCounterRemainder + div_remainder) / denom;
2501 // uint64_t raccum;
2502 // //while(next_clock_out_frame <= next_audio_frame)
2503 // while(_clockOutputCounter < next_audio_frame)
2504 // {
2505 // if(_clockOutputQueueSize >= _clockOutputQueueCapacity)
2506 // break;
2507 //
2508 // //_clockOutputQueue[_clockOutputQueueSize] = _clockOutputCounter - curr_audio_frame;
2509 // _clockOutputQueue[_clockOutputQueueSize] = _clockOutputCounter;
2510 // ++_clockOutputQueueSize;
2511 // raccum = _clockOutputCounterRemainder + div_remainder;
2512 // _clockOutputCounter += div_frames + (raccum / denom);
2513 // _clockOutputCounterRemainder = raccum % denom;
2514 // }
2515 // //const uint64_t next_clock_out_count = _clockOutputCounter + div_frames + (_clockOutputCounterRemainder + div_remainder) / denom;
2516 //
2517 // //if(next_audio_frame >= next_clock_out_count)
2518 // //{
2519 //
2520 // //}
2521 // }
2522 //
2523 // // // Did clock_tick wrap around?
2524 // // if(_clockOutputCounter > clock_tick)
2525 // // _clockOutputCounter = clock_tick;
2526 // //
2527 // // //const unsigned int div = MusEGlobal::config.division/24;
2528 // // if(clock_tick_end >= _clockOutputCounter + div)
2529 // // {
2530 // // // This will always be at least 1.
2531 // // const unsigned int num_clocks = (clock_tick_end - _clockOutputCounter) / div;
2532 // // const unsigned int clk_frame_step = frames / num_clocks;
2533 // // const unsigned int clk_frame_step_rem = frames % num_clocks;
2534 // // unsigned int clk_frame_off;
2535 // // for(unsigned int c = 0; c < num_clocks; ++c)
2536 // // {
2537 // // if(c >= _clockOutputQueueCapacity)
2538 // // break;
2539 // // clk_frame_off = c * clk_frame_step + (c * clk_frame_step_rem) / num_clocks;
2540 // // }
2541 // //
2542 // // _clockOutputCounter = clock_tick_end;
2543 // // }
2544 // //
2545 // //
2546 // // unsigned cc, f;
2547 // // while(1)
2548 // // {
2549 // // cc = _clockOutputCounter + div;
2550 // // f = Pos(cc, true).frame();
2551 // // //if(f
2552 // // }
2553 // }
2554
2555 //
2556 // Play all midi events up to curFrame.
2557 //
2558 for(iMidiDevice id = MusEGlobal::midiDevices.begin(); id != MusEGlobal::midiDevices.end(); ++id)
2559 {
2560 MidiDevice* pl_md = *id;
2561 // const int pl_port = pl_md->midiPort();
2562
2563 // We are done with the 'frozen' recording fifos, remove the events.
2564 pl_md->afterProcess();
2565
2566 pl_md->processStuckNotes();
2567
2568 // REMOVE Tim. clock. Added.
2569 // While we are at it, to avoid the overhead of yet another device loop,
2570 // handle midi clock output here, for all device types.
2571 // if(!extsync && pl_port >= 0 && pl_port < MIDI_PORTS)
2572 // {
2573 // MidiPort* clk_mp = &MusEGlobal::midiPorts[pl_port];
2574 // // Clock out turned on?
2575 // if(clk_mp->syncInfo().MCOut())
2576 // {
2577 // for(unsigned int i = 0; i < _clockOutputQueueSize; ++i)
2578 // {
2579 // const MidiPlayEvent clk_ev(_clockOutputQueue[i], pl_port, 0, MusECore::ME_CLOCK, 0, 0);
2580 // pl_md->putEvent(clk_ev, MidiDevice::NotLate /*,MidiDevice::PlaybackBuffer*/);
2581 // }
2582 // }
2583 // }
2584
2585 // ALSA devices handled by another thread.
2586 const MidiDevice::MidiDeviceType typ = pl_md->deviceType();
2587 switch(typ)
2588 {
2589 case MidiDevice::ALSA_MIDI:
2590 break;
2591
2592 case MidiDevice::JACK_MIDI:
2593 case MidiDevice::SYNTH_MIDI:
2594 // The frame is not used by these devices but we pass it along anyway.
2595 // Only ALSA devices need the frame.
2596 pl_md->processMidi(syncFrame);
2597 break;
2598 }
2599 }
2600
2601 // Receive hardware state events sent from various threads to this audio thread.
2602 // Update hardware state so gui controls are updated.
2603 MusEGlobal::song->processIpcOutEventBuffers();
2604 }
2605
2606
2607 //---------------------------------------------------------
2608 // processPrecount
2609 //---------------------------------------------------------
2610
processPrecount(unsigned int frames)2611 void Audio::processPrecount(unsigned int frames)
2612 {
2613 //DEBUG_MIDI_METRONOME(stderr, "Audio::processPrecount: state:%d\n", state);
2614 if(state != PRECOUNT)
2615 return;
2616
2617 MusECore::MetronomeSettings* metro_settings =
2618 MusEGlobal::metroUseSongSettings ? &MusEGlobal::metroSongSettings : &MusEGlobal::metroGlobalSettings;
2619
2620 const unsigned int nextPrecountFramePos = _precountFramePos + frames;
2621
2622 DEBUG_MIDI_METRONOME(stderr, "Audio::processPrecount: precount: syncFrame:%u _pos.frame():%u"
2623 "_precountFramePos:%u precountMidiClickFrame:%u nextPrecountFramePos:%u clickno:%d\n",
2624 syncFrame, _pos.frame(), _precountFramePos, precountMidiClickFrame, nextPrecountFramePos, clickno);
2625
2626 MidiDevice* md = nullptr;
2627 if(metro_settings->midiClickFlag)
2628 md = MusEGlobal::midiPorts[metro_settings->clickPort].device();
2629
2630 AudioTickSound audioTickSound = MusECore::beatSound;
2631
2632 while(true)
2633 {
2634 const unsigned precount_click_frame = precountMidiClickFrame + (precountMidiClickFrameRemainder ? 1 :0);
2635 if(precount_click_frame >= nextPrecountFramePos)
2636 break;
2637 // Don't actually sound anything if we're just running out the time.
2638 // There will be times when _precountFramePos >= precountTotalFrames
2639 // and we must let it run out.
2640 if(_precountFramePos < precountTotalFrames)
2641 {
2642 if(MusEGlobal::song->click())
2643 {
2644 if ((clickno % clicksMeasure) == 0)
2645 audioTickSound = MusECore::measureSound;
2646 else
2647 audioTickSound = MusECore::beatSound;
2648
2649 // We need to shift ahead in time because Jack waits one more cycle,
2650 // unlike our own built-in transport which starts immediately.
2651 const unsigned int evtime = syncFrame + MusEGlobal::audioDevice->transportSyncToPlayDelay() +
2652 ((precount_click_frame < _precountFramePos) ? 0 : precount_click_frame - _precountFramePos);
2653
2654 MusECore::MidiPlayEvent ev(evtime, metro_settings->clickPort, metro_settings->clickChan,
2655 MusECore::ME_NOTEON, metro_settings->beatClickNote, metro_settings->beatClickVelo);
2656
2657 if (audioTickSound == MusECore::measureSound) {
2658 ev.setA(metro_settings->measureClickNote);
2659 ev.setB(metro_settings->measureClickVelo);
2660 }
2661 if (md) {
2662 MusECore::MidiPlayEvent evmidi = ev;
2663
2664 #ifdef DEBUG_MIDI_TIMING_DIFFS
2665 fprintf(stderr, "EVENT TIME DIFF:%u\n", ev.time() - _lastEvTime);
2666 _lastEvTime = ev.time();
2667 #endif
2668
2669 md->putEvent(evmidi, MidiDevice::NotLate, MidiDevice::PlaybackBuffer);
2670 // Internal midi paths are now all note off aware. Driver handles note offs. Convert.
2671 // Ticksynth has been modified too.
2672 evmidi.setType(MusECore::ME_NOTEOFF);
2673 evmidi.setB(0);
2674 evmidi.setTime(ev.time() + MusEGlobal::tempomap.ticks2frames(10, curTickPos));
2675
2676 // The precount CANNOT use the stuck notes mechanism because the stuck notes
2677 // mechanism wants ticks not frames, and it later compares those ticks
2678 // with nextTickPos and converts them into frames using midiQueueTimeStamp(),
2679 // which is not a valid mechanism during precount!
2680 // Therefore we have no choice but to directly schedule a note-off.
2681 // Since it is important that they not be missed, schedule these as userBuffer events.
2682 // Should be OK, it's unlikely that the note-off would be missed unless the user could
2683 // somehow seek during precount or something. (The userBuffer tries not to miss anything.)
2684 // The idea behind the stuck notes mechanism was that it converts to frames
2685 // only at scheduling time so that if the user might change the tempo while
2686 // playing a song, the note-off times will be properly adjusted.
2687 // But this precount mechanism CANNOT honour any tempo changes anyway because
2688 // we must know the total required precount frames BEFOREHAND so that it can be aligned
2689 // with the metronome clicks properly. Thus negating any possible tempo change support.
2690 //md->addStuckNote(evmidi);
2691 md->putEvent(evmidi, MidiDevice::NotLate, MidiDevice::UserBuffer);
2692 }
2693 if (metro_settings->audioClickFlag) {
2694 ev.setA(audioTickSound);
2695 DEBUG_MIDI_METRONOME(stderr, "Audio::processMidi: precount: metronome->putEvent\n");
2696 metronome->putEvent(ev, MidiDevice::NotLate, MidiDevice::PlaybackBuffer);
2697 // Built-in metronome synth does not use stuck notes...
2698 }
2699 }
2700 }
2701
2702 precountMidiClickFrame += framesBeat;
2703
2704 precountMidiClickFrameRemainder += framesBeatRemainder;
2705 if(precountMidiClickFrameRemainder >= framesBeatDivisor)
2706 {
2707 precountMidiClickFrame++;
2708 precountMidiClickFrameRemainder -= framesBeatDivisor;
2709 }
2710
2711 ++clickno;
2712 }
2713
2714 _precountFramePos += frames;
2715 }
2716
2717 //---------------------------------------------------------
2718 // processAudioMetronome
2719 //---------------------------------------------------------
2720
processMidiMetronome(unsigned int frames)2721 void Audio::processMidiMetronome(unsigned int frames)
2722 {
2723 const MusECore::MetronomeSettings* metro_settings =
2724 MusEGlobal::metroUseSongSettings ? &MusEGlobal::metroSongSettings : &MusEGlobal::metroGlobalSettings;
2725
2726 const bool extsync = MusEGlobal::extSyncFlag;
2727 const bool playing = isPlaying();
2728
2729 // Should the metronome be muted after precount?
2730 const bool precount_mute_metronome = metro_settings->precountEnableFlag
2731 && MusEGlobal::song->click()
2732 && !extsync
2733 && ((!MusEGlobal::song->record() && metro_settings->precountOnPlay) || MusEGlobal::song->record())
2734 && metro_settings->precountMuteMetronome;
2735
2736 MidiDevice* md = 0;
2737 if (metro_settings->midiClickFlag && !precount_mute_metronome)
2738 md = MusEGlobal::midiPorts[metro_settings->clickPort].device();
2739
2740 if (playing)
2741 {
2742 int bar, beat, z, n;
2743 unsigned tick;
2744 AudioTickSound audioTickSound = MusECore::beatSound;
2745 const MusECore::MetroAccents* accents;
2746 int accents_sz;
2747
2748 unsigned int lat_offset_midi = 0;
2749 unsigned int cur_tick_midi = curTickPos;
2750 unsigned int next_tick_midi = nextTickPos;
2751
2752 //--------------------------------------------------------------------
2753 // Account for the metronome's latency correction and/or compensation.
2754 //--------------------------------------------------------------------
2755 // TODO How to handle when external sync is on. For now, don't try to correct.
2756 if(MusEGlobal::config.enableLatencyCorrection && !extsync)
2757 {
2758 if(metro_settings->midiClickFlag)
2759 {
2760 const TrackLatencyInfo& li = metronome->getLatencyInfoMidi(false /*playback*/, false);
2761 // This value is negative for correction.
2762 const float mlat = li._sourceCorrectionValue;
2763 if((int)mlat < 0)
2764 {
2765 // Convert to a positive offset.
2766 const unsigned int l = (unsigned int)(-mlat);
2767 if(l > lat_offset_midi)
2768 lat_offset_midi = l;
2769 }
2770 if(lat_offset_midi != 0)
2771 {
2772 Pos ppp(_pos.frame() + lat_offset_midi, false);
2773 cur_tick_midi = ppp.tick();
2774 ppp += frames;
2775 next_tick_midi = ppp.tick();
2776 }
2777 }
2778 }
2779
2780 // What is the current transport frame, adjusted?
2781 const unsigned int pos_fr_midi = _pos.frame() + lat_offset_midi;
2782 // What is the (theoretical) next transport frame?
2783 const unsigned int next_pos_fr_midi = pos_fr_midi + frames;
2784
2785 // If external sync is not on, we can take advantage of frame accuracy but
2786 // first we must allow the next tick position to be included in the search
2787 // even if it is equal to the current tick position.
2788 while (extsync ? (midiClick < next_tick_midi) : (midiClick <= next_tick_midi))
2789 {
2790 bool do_play = true;
2791 unsigned int evtime = 0;
2792 if(extsync)
2793 {
2794 if(midiClick < cur_tick_midi)
2795 midiClick = cur_tick_midi;
2796 evtime = extClockHistoryTick2Frame(midiClick - cur_tick_midi) + MusEGlobal::segmentSize;
2797 }
2798 else
2799 {
2800 // What is the exact transport frame that the midiClick should be played at?
2801 const unsigned int fr = MusEGlobal::tempomap.tick2frame(midiClick);
2802 // Is the midiClick frame outside of the current transport frame range?
2803 if(fr < pos_fr_midi || fr >= next_pos_fr_midi)
2804 {
2805 // Break out of the loop if midiClick equals nextTickPos.
2806 if(midiClick == next_tick_midi)
2807 break;
2808 // Continue on, but do not play any notes.
2809 do_play = false;
2810 }
2811 evtime = fr - pos_fr_midi;
2812 evtime += syncFrame;
2813 }
2814
2815 DEBUG_MIDI_METRONOME(stderr,
2816 "Audio::processMidiMetronome: playing: syncFrame:%u _pos.frame():%u midiClick:%u next_tick_midi:%u clickno:%d\n",
2817 syncFrame, _pos.frame(), midiClick, next_tick_midi, clickno);
2818
2819 MusEGlobal::sigmap.tickValues(midiClick, &bar, &beat, &tick);
2820 MusEGlobal::sigmap.timesig(midiClick, z, n);
2821 // How many ticks per beat?
2822 const int ticks_beat = MusEGlobal::sigmap.ticks_beat(n);
2823
2824 if (do_play && MusEGlobal::song->click()
2825 && (metro_settings->midiClickFlag)
2826 && !precount_mute_metronome) {
2827
2828 if (tick == 0 && beat == 0) {
2829 audioTickSound = MusECore::measureSound;
2830 if (MusEGlobal::debugMsg)
2831 fprintf(stderr, "meas: midiClick %d nextPos %d bar %d beat %d tick %d z %d n %d ticks_beat %d\n",
2832 midiClick, next_tick_midi, bar, beat, tick, z, n, ticks_beat);
2833 }
2834 else if (tick == unsigned(ticks_beat - (ticks_beat/(n*2)))) {
2835 audioTickSound = MusECore::accent2Sound;
2836 if (MusEGlobal::debugMsg)
2837 fprintf(stderr, "acc2: midiClick %d nextPos %d bar %d beat %d tick %d z %d n %d ticks_beat %d\n",
2838 midiClick, next_tick_midi, bar, beat, tick, z, n, ticks_beat);
2839 }
2840 else if (tick == unsigned(ticks_beat - (ticks_beat/n))) {
2841 audioTickSound = MusECore::accent1Sound;
2842 if (MusEGlobal::debugMsg)
2843 fprintf(stderr, "acc1: midiClick %d nextPos %d bar %d beat %d tick %d z %d n %d ticks_beat %d\n",
2844 midiClick, next_tick_midi, bar, beat, tick, z, n, ticks_beat);
2845 } else {
2846 if (MusEGlobal::debugMsg)
2847 fprintf(stderr, "beat: midiClick %d nextPos %d bar %d beat %d tick %d z %d n %d div %d\n",
2848 midiClick, next_tick_midi, bar, beat, tick, z, n, ticks_beat);
2849 }
2850
2851 MusECore::MidiPlayEvent ev(evtime, metro_settings->clickPort, metro_settings->clickChan,
2852 MusECore::ME_NOTEON, metro_settings->beatClickNote, metro_settings->beatClickVelo);
2853 if (audioTickSound == MusECore::measureSound) {
2854 ev.setA(metro_settings->measureClickNote);
2855 ev.setB(metro_settings->measureClickVelo);
2856 }
2857 if (audioTickSound == MusECore::accent1Sound) {
2858 ev.setA(metro_settings->accentClick1);
2859 ev.setB(metro_settings->accentClick1Velo);
2860 }
2861 if (audioTickSound == MusECore::accent2Sound) {
2862 ev.setA(metro_settings->accentClick2);
2863 ev.setB(metro_settings->accentClick2Velo);
2864 }
2865
2866 // Should the metronome be played after precount?
2867 if(!precount_mute_metronome)
2868 {
2869 // Don't bother sending to midi out if velocity is zero.
2870 if (metro_settings->midiClickFlag && md && ev.dataB() > 0) {
2871 MusECore::MidiPlayEvent evmidi = ev;
2872
2873 #ifdef DEBUG_MIDI_TIMING_DIFFS
2874 fprintf(stderr, "EVENT TIME DIFF:%u\n", evmidi.time() - _lastEvTime);
2875 _lastEvTime = evmidi.time();
2876 #endif
2877
2878 md->putEvent(evmidi, MidiDevice::NotLate, MidiDevice::PlaybackBuffer);
2879 // Internal midi paths are now all note off aware. Driver handles note offs. Convert.
2880 // Ticksynth has been modified too.
2881 evmidi.setType(MusECore::ME_NOTEOFF);
2882 evmidi.setB(0);
2883 evmidi.setTime(midiClick+10);
2884 md->addStuckNote(evmidi);
2885 }
2886 }
2887 }
2888
2889 const int beat_mod = (beat + 1) % z;
2890
2891 MetroAccent::AccentTypes_t acc_types = MetroAccent::NoAccent;
2892 if(metro_settings->metroAccentsMap)
2893 {
2894 MusECore::MetroAccentsMap::const_iterator imap = metro_settings->metroAccentsMap->find(z);
2895 if(imap != metro_settings->metroAccentsMap->cend())
2896 {
2897 const MusECore::MetroAccentsStruct& mas = imap->second;
2898 accents = &mas._accents;
2899 accents_sz = accents->size();
2900 if(beat_mod < accents_sz)
2901 acc_types = accents->at(beat_mod)._accentType;
2902 }
2903 }
2904
2905 // State machine to select next midiClick position.
2906 if (metro_settings->clickSamples == MetronomeSettings::newSamples) {
2907 if (tick == 0) {// ON key
2908 if(acc_types & MetroAccent::Accent1)
2909 {
2910 // Cue an accent 1. (This part 'triggers' an accent sequence to begin
2911 // which automatically cues accent 2 if required then a normal beat, as shown below.)
2912 midiClick = MusEGlobal::sigmap.bar2tick(bar, beat, ticks_beat - ((ticks_beat/n)));
2913 }
2914 else if(acc_types & MetroAccent::Accent2)
2915 {
2916 // Cue accent 2.
2917 midiClick = MusEGlobal::sigmap.bar2tick(bar, beat, ticks_beat - (ticks_beat/(n*2)));
2918 }
2919 else
2920 {
2921 // Cue a normal beat.
2922 midiClick = MusEGlobal::sigmap.bar2tick(bar, beat+1, 0);
2923 }
2924 }
2925 else if (tick >= unsigned(ticks_beat - (ticks_beat/(n*2)))) { // second accent tick
2926 // Finished accent 2. Cue a normal beat.
2927 midiClick = MusEGlobal::sigmap.bar2tick(bar, beat+1, 0);
2928 }
2929 else if (tick < unsigned(ticks_beat - ((ticks_beat/(n*2))))) { // first accent tick
2930 if(acc_types & MetroAccent::Accent2)
2931 // Finished accent 1. Cue accent 2.
2932 midiClick = MusEGlobal::sigmap.bar2tick(bar, beat, ticks_beat - (ticks_beat/(n*2)));
2933 else
2934 // Finished accent 1. Cue a normal beat.
2935 midiClick = MusEGlobal::sigmap.bar2tick(bar, beat+1, 0);
2936 }
2937 }
2938 else
2939 {
2940 midiClick = MusEGlobal::sigmap.bar2tick(bar, beat+1, 0);
2941 }
2942 }
2943 }
2944 }
2945
2946 //---------------------------------------------------------
2947 // processAudioMetronome
2948 //---------------------------------------------------------
2949
processAudioMetronome(unsigned int frames)2950 void Audio::processAudioMetronome(unsigned int frames)
2951 {
2952 const MusECore::MetronomeSettings* metro_settings =
2953 MusEGlobal::metroUseSongSettings ? &MusEGlobal::metroSongSettings : &MusEGlobal::metroGlobalSettings;
2954
2955 const bool extsync = MusEGlobal::extSyncFlag;
2956 const bool playing = isPlaying();
2957
2958 // Should the metronome be muted after precount?
2959 const bool precount_mute_metronome = metro_settings->precountEnableFlag
2960 && MusEGlobal::song->click()
2961 && !extsync
2962 && ((!MusEGlobal::song->record() && metro_settings->precountOnPlay) || MusEGlobal::song->record())
2963 && metro_settings->precountMuteMetronome;
2964
2965 if (playing)
2966 {
2967 int bar, beat, z, n;
2968 unsigned tick;
2969 AudioTickSound audioTickSound = MusECore::beatSound;
2970 const MusECore::MetroAccents* accents;
2971 int accents_sz;
2972
2973 unsigned int lat_offset = 0;
2974 unsigned int cur_tick = curTickPos;
2975 unsigned int next_tick = nextTickPos;
2976
2977 //--------------------------------------------------------------------
2978 // Account for the metronome's latency correction and/or compensation.
2979 //--------------------------------------------------------------------
2980 // TODO How to handle when external sync is on. For now, don't try to correct.
2981 if(MusEGlobal::config.enableLatencyCorrection && !extsync)
2982 {
2983 if(metro_settings->audioClickFlag)
2984 {
2985 const TrackLatencyInfo& li = metronome->getLatencyInfo(false);
2986 // This value is negative for correction.
2987 const float mlat = li._sourceCorrectionValue;
2988 if((int)mlat < 0)
2989 {
2990 // Convert to a positive offset.
2991 const unsigned int l = (unsigned int)(-mlat);
2992 if(l > lat_offset)
2993 lat_offset = l;
2994 }
2995 if(lat_offset != 0)
2996 {
2997 Pos ppp(_pos.frame() + lat_offset, false);
2998 cur_tick = ppp.tick();
2999 ppp += frames;
3000 next_tick = ppp.tick();
3001 }
3002 }
3003 }
3004
3005 // What is the current transport frame, adjusted?
3006 const unsigned int pos_fr = _pos.frame() + lat_offset;
3007 // What is the (theoretical) next transport frame?
3008 const unsigned int next_pos_fr = pos_fr + frames;
3009
3010 // If external sync is not on, we can take advantage of frame accuracy but
3011 // first we must allow the next tick position to be included in the search
3012 // even if it is equal to the current tick position.
3013 while (extsync ? (audioClick < next_tick) : (audioClick <= next_tick))
3014 {
3015 bool do_play = true;
3016 unsigned int evtime = 0;
3017 if(extsync)
3018 {
3019 if(audioClick < cur_tick)
3020 audioClick = cur_tick;
3021 evtime = extClockHistoryTick2Frame(audioClick - cur_tick) + MusEGlobal::segmentSize;
3022 }
3023 else
3024 {
3025 // What is the exact transport frame that the click should be played at?
3026 const unsigned int fr = MusEGlobal::tempomap.tick2frame(audioClick);
3027 // Is the click frame outside of the current transport frame range?
3028 if(fr < pos_fr || fr >= next_pos_fr)
3029 {
3030 // Break out of the loop if midiClick equals nextTickPos.
3031 if(audioClick == next_tick)
3032 break;
3033 // Continue on, but do not play any notes.
3034 do_play = false;
3035 }
3036 evtime = fr - pos_fr;
3037 evtime += syncFrame;
3038 }
3039
3040 DEBUG_MIDI_METRONOME(stderr,
3041 "Audio::processAudioMetronome: playing: syncFrame:%u _pos.frame():%u audioClick:%u next_tick:%u clickno:%d\n",
3042 syncFrame, _pos.frame(), audioClick, next_tick, clickno);
3043
3044 MusEGlobal::sigmap.tickValues(audioClick, &bar, &beat, &tick);
3045 MusEGlobal::sigmap.timesig(audioClick, z, n);
3046 // How many ticks per beat?
3047 const int ticks_beat = MusEGlobal::sigmap.ticks_beat(n);
3048
3049 if (do_play && MusEGlobal::song->click()
3050 && (metro_settings->audioClickFlag)
3051 && !precount_mute_metronome) {
3052
3053 if (tick == 0 && beat == 0) {
3054 audioTickSound = MusECore::measureSound;
3055 if (MusEGlobal::debugMsg)
3056 fprintf(stderr, "meas: audioClick %d next_tick %d bar %d beat %d tick %d z %d n %d ticks_beat %d\n",
3057 audioClick, next_tick, bar, beat, tick, z, n, ticks_beat);
3058 }
3059 else if (tick == unsigned(ticks_beat - (ticks_beat/(n*2)))) {
3060 audioTickSound = MusECore::accent2Sound;
3061 if (MusEGlobal::debugMsg)
3062 fprintf(stderr, "acc2: audioClick %d next_tick %d bar %d beat %d tick %d z %d n %d ticks_beat %d\n",
3063 audioClick, next_tick, bar, beat, tick, z, n, ticks_beat);
3064 }
3065 else if (tick == unsigned(ticks_beat - (ticks_beat/n))) {
3066 audioTickSound = MusECore::accent1Sound;
3067 if (MusEGlobal::debugMsg)
3068 fprintf(stderr, "acc1: audioClick %d next_tick %d bar %d beat %d tick %d z %d n %d ticks_beat %d\n",
3069 audioClick, next_tick, bar, beat, tick, z, n, ticks_beat);
3070 } else {
3071 if (MusEGlobal::debugMsg)
3072 fprintf(stderr, "beat: audioClick %d next_tick %d bar %d beat %d tick %d z %d n %d div %d\n",
3073 audioClick, next_tick, bar, beat, tick, z, n, ticks_beat);
3074 }
3075
3076 // Should the metronome be played after precount?
3077 if(!precount_mute_metronome)
3078 {
3079 if (metro_settings->audioClickFlag) {
3080 MusECore::MidiPlayEvent ev(evtime, 0, 0,
3081 MusECore::ME_NOTEON, audioTickSound, 0);
3082 DEBUG_MIDI_METRONOME(stderr, "Audio::processAudioMetronome: playing: metronome->putEvent\n");
3083 metronome->putEvent(ev, MidiDevice::NotLate, MidiDevice::PlaybackBuffer);
3084 // Built-in metronome synth does not use stuck notes...
3085 }
3086 }
3087 }
3088
3089 const int beat_mod = (beat + 1) % z;
3090
3091 MetroAccent::AccentTypes_t acc_types = MetroAccent::NoAccent;
3092 if(metro_settings->metroAccentsMap)
3093 {
3094 MusECore::MetroAccentsMap::const_iterator imap = metro_settings->metroAccentsMap->find(z);
3095 if(imap != metro_settings->metroAccentsMap->cend())
3096 {
3097 const MusECore::MetroAccentsStruct& mas = imap->second;
3098 accents = &mas._accents;
3099 accents_sz = accents->size();
3100 if(beat_mod < accents_sz)
3101 acc_types = accents->at(beat_mod)._accentType;
3102 }
3103 }
3104
3105 // State machine to select next midiClick position.
3106 if (metro_settings->clickSamples == MetronomeSettings::newSamples) {
3107 if (tick == 0) {// ON key
3108 if(acc_types & MetroAccent::Accent1)
3109 {
3110 // Cue an accent 1. (This part 'triggers' an accent sequence to begin
3111 // which automatically cues accent 2 if required then a normal beat, as shown below.)
3112 audioClick = MusEGlobal::sigmap.bar2tick(bar, beat, ticks_beat - ((ticks_beat/n)));
3113 }
3114 else if(acc_types & MetroAccent::Accent2)
3115 {
3116 // Cue accent 2.
3117 audioClick = MusEGlobal::sigmap.bar2tick(bar, beat, ticks_beat - (ticks_beat/(n*2)));
3118 }
3119 else
3120 {
3121 // Cue a normal beat.
3122 audioClick = MusEGlobal::sigmap.bar2tick(bar, beat+1, 0);
3123 }
3124 }
3125 else if (tick >= unsigned(ticks_beat - (ticks_beat/(n*2)))) { // second accent tick
3126 // Finished accent 2. Cue a normal beat.
3127 audioClick = MusEGlobal::sigmap.bar2tick(bar, beat+1, 0);
3128 }
3129 else if (tick < unsigned(ticks_beat - ((ticks_beat/(n*2))))) { // first accent tick
3130 if(acc_types & MetroAccent::Accent2)
3131 // Finished accent 1. Cue accent 2.
3132 audioClick = MusEGlobal::sigmap.bar2tick(bar, beat, ticks_beat - (ticks_beat/(n*2)));
3133 else
3134 // Finished accent 1. Cue a normal beat.
3135 audioClick = MusEGlobal::sigmap.bar2tick(bar, beat+1, 0);
3136 }
3137 }
3138 else
3139 {
3140 audioClick = MusEGlobal::sigmap.bar2tick(bar, beat+1, 0);
3141 }
3142 }
3143 }
3144 }
3145
3146
3147 } // namespace MusECore
3148