1 /*-
2 * Copyright (c) 2010-2021 Hans Petter Selasky. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26 #include "midipp_decode.h"
27
28 #include "midipp_buttonmap.h"
29 #include "midipp_chords.h"
30 #include "midipp_mainwindow.h"
31 #include "midipp_scores.h"
32 #include "midipp_button.h"
33 #include "midipp_element.h"
34 #include "midipp_groupbox.h"
35 #include "midipp_instrument.h"
36
37 Q_DECL_EXPORT const QString
MppKeyStr(int key)38 MppKeyStr(int key)
39 {
40 int rem = MPP_BAND_REM(key, MPP_MAX_BANDS);
41 int off;
42 int sub;
43 int oct;
44
45 off = rem / MPP_BAND_STEP_12;
46 sub = rem % MPP_BAND_STEP_12;
47 oct = (key - rem) / MPP_MAX_BANDS;
48
49 if (sub != 0) {
50 const char *off_map[12] = {
51 "C%1.%2", "D%1B.%2", "D%1.%2", "E%1B.%2",
52 "E%1.%2", "F%1.%2", "G%1B.%2", "G%1.%2",
53 "A%1B.%2", "A%1.%2", "H%1B.%2", "H%1.%2"
54 };
55 sub = MPP_SUBDIV_REM_BITREV(sub);
56 return (QString(off_map[off]).arg(oct).arg(sub));
57 } else {
58 const char *off_map[12] = {
59 "C%1", "D%1B", "D%1", "E%1B",
60 "E%1", "F%1", "G%1B", "G%1",
61 "A%1B", "A%1", "H%1B", "H%1"
62 };
63 return (QString(off_map[off]).arg(oct));
64 }
65 }
66
67 Q_DECL_EXPORT const QString
MppKeyStrNoOctave(int key)68 MppKeyStrNoOctave(int key)
69 {
70 int rem = MPP_BAND_REM(key, MPP_MAX_BANDS);
71 int off;
72 int sub;
73
74 off = rem / MPP_BAND_STEP_12;
75 sub = rem % MPP_BAND_STEP_12;
76
77 if (sub != 0) {
78 const char *off_map[12] = {
79 "C.%1", "Db.%1", "D.%1", "Eb.%1",
80 "E.%1", "F.%1", "Gb.%1", "G.%1",
81 "Ab.%1", "A.%1", "Hb.%1", "H.%1"
82 };
83 sub = MPP_SUBDIV_REM_BITREV(sub);
84 return (QString(off_map[off]).arg(sub));
85 } else {
86 const char *off_map[12] = {
87 "C", "Db", "D", "Eb",
88 "E", "F", "Gb", "G",
89 "Ab", "A", "Hb", "H"
90 };
91 return (QString(off_map[off]));
92 }
93 }
94
95 Q_DECL_EXPORT const QString
MppBitsToString(const MppChord_t & mask,int off)96 MppBitsToString(const MppChord_t &mask, int off)
97 {
98 QString temp;
99 int x;
100
101 for (x = 0; x != MPP_MAX_CHORD_BANDS; x++) {
102 if (mask.test(x) == 0)
103 continue;
104 temp += MppKeyStrNoOctave((x * MPP_BAND_STEP_CHORD) + off);
105 temp += " ";
106 }
107 return (temp);
108 }
109
110 void
MppScoreVariantInit(void)111 MppScoreVariantInit(void)
112 {
113 const int rk = 0;
114 MppChord_t mask;
115 QString str;
116 uint32_t x;
117 uint32_t y;
118 uint32_t z;
119
120 Mpp.VariantList += QString("\n/* Unique chords having two keys */\n\n");
121
122 for (z = 0, x = MPP_BAND_STEP_12; x != MPP_MAX_BANDS; x += MPP_BAND_STEP_12) {
123 mask.zero();
124 mask.set(0);
125 mask.set(x / MPP_BAND_STEP_CHORD);
126
127 if (MppFindChordRoot(mask) != mask)
128 continue;
129
130 MppChordToStringGeneric(mask, rk, rk, 0, MPP_BAND_STEP_12, str);
131 if (str.isEmpty())
132 str = " ";
133 else
134 z++;
135
136 Mpp.VariantList += str;
137 Mpp.VariantList += " = ";
138 Mpp.VariantList += MppBitsToString(mask, rk);
139 Mpp.VariantList += "\n";
140 }
141
142 Mpp.VariantList += QString("\n/* Total number of variants is %1 */\n\n").arg(z);
143 Mpp.VariantList += QString("/* Unique chords having three keys */\n\n");
144
145 for (z = 0, x = MPP_BAND_STEP_12; x != MPP_MAX_BANDS; x += MPP_BAND_STEP_12) {
146 for (y = x + MPP_BAND_STEP_12; y != MPP_MAX_BANDS; y += MPP_BAND_STEP_12) {
147 mask.zero();
148 mask.set(0);
149 mask.set(x / MPP_BAND_STEP_CHORD);
150 mask.set(y / MPP_BAND_STEP_CHORD);
151
152 if (MppFindChordRoot(mask) != mask)
153 continue;
154
155 MppChordToStringGeneric(mask, rk, rk, 0, MPP_BAND_STEP_12, str);
156 if (str.isEmpty())
157 str = " ";
158 else
159 z++;
160 Mpp.VariantList += str;
161 Mpp.VariantList += " = ";
162 Mpp.VariantList += MppBitsToString(mask, rk);
163 Mpp.VariantList += "\n";
164 }
165 }
166
167 Mpp.VariantList += QString("\n/* Total number of variants is %1 */\n\n").arg(z);
168
169 Mpp.VariantList += QString("/* List of supported keys */\n\n");
170
171 for (x = 0; x != MPP_MAX_CHORD_BANDS; x++) {
172 Mpp.VariantList += MppKeyStr(x * MPP_BAND_STEP_CHORD);
173 Mpp.VariantList += QString(" /* %1 of %2 */\n").arg(x + 1)
174 .arg(MPP_MAX_CHORD_BANDS);
175 }
176
177 /* Key adjustment table for K5.1 effect */
178 Mpp.KeyAdjust[4] = round((MPP_MAX_BANDS * log(1.0 + 1.0 / 4.0) / log(2.0)) - (MPP_BAND_STEP_12 * 4));
179 Mpp.KeyAdjust[5] = round((MPP_MAX_BANDS * log(1.0 + 1.0 / 3.0) / log(2.0)) - (MPP_BAND_STEP_12 * 5));
180 Mpp.KeyAdjust[7] = round((MPP_MAX_BANDS * log(1.0 + 1.0 / 2.0) / log(2.0)) - (MPP_BAND_STEP_12 * 7));
181
182 Mpp.KeyAdjust[1] = Mpp.KeyAdjust[5] - Mpp.KeyAdjust[4];
183 Mpp.KeyAdjust[2] = Mpp.KeyAdjust[7] - Mpp.KeyAdjust[5];
184 Mpp.KeyAdjust[3] = Mpp.KeyAdjust[7] - Mpp.KeyAdjust[4];
185
186 Mpp.KeyAdjust[6] = Mpp.KeyAdjust[7] - Mpp.KeyAdjust[1];
187
188 Mpp.KeyAdjust[8] = -Mpp.KeyAdjust[4];
189 Mpp.KeyAdjust[9] = -Mpp.KeyAdjust[3];
190 Mpp.KeyAdjust[10] = -Mpp.KeyAdjust[2];
191 Mpp.KeyAdjust[11] = -Mpp.KeyAdjust[1];
192 }
193
194 static void
MppInitArray(const uint16_t * src,MppChord_t * dst,uint8_t n)195 MppInitArray(const uint16_t *src, MppChord_t *dst, uint8_t n)
196 {
197 while (n--) {
198 dst[n].zero();
199 for (uint8_t x = 0; x != 12; x++) {
200 if ((src[n] >> x) & 1)
201 dst[n].set((MPP_BAND_STEP_12 / MPP_BAND_STEP_CHORD) * x);
202 }
203 }
204 }
205
206 static int
MppCommonKeys(const MppChord_t & pa,const MppChord_t & pb,int a_key,int b_key)207 MppCommonKeys(const MppChord_t & pa, const MppChord_t & pb, int a_key, int b_key)
208 {
209 MppChord_t temp = pb;
210 int key = ((12 + a_key - b_key) % 12) *
211 (MPP_BAND_STEP_12 / MPP_BAND_STEP_CHORD);
212
213 while (key--) {
214 if (temp.test(0)) {
215 temp.tog(0);
216 temp.tog(MPP_MAX_CHORD_BANDS);
217 }
218 temp.shr();
219 }
220
221 temp &= pa;
222 return (temp.order());
223 }
224
MppDecodeCircle(MppDecodeTab * _ptab)225 MppDecodeCircle :: MppDecodeCircle(MppDecodeTab *_ptab)
226 {
227 static const uint16_t circle[NMAX] = { 0x91, 0x89, 0x249 };
228 ptab = _ptab;
229
230 MppInitArray(circle, mask, NMAX);
231
232 memset(r_press, 0, sizeof(r_press));
233 memset(r_key, 0, sizeof(r_key));
234 memset(r_mask, 0, sizeof(r_mask));
235
236 setMinimumSize(128,128);
237 }
238
~MppDecodeCircle()239 MppDecodeCircle :: ~MppDecodeCircle()
240 {
241 }
242
243 void
mousePressEvent(QMouseEvent * event)244 MppDecodeCircle :: mousePressEvent(QMouseEvent *event)
245 {
246 QPoint p = event->pos();
247
248 for (uint8_t x = 0; x != NMAX; x++) {
249 for (uint8_t y = 0; y != 12; y++) {
250 if (r_press[x][y].contains(p) == 0)
251 continue;
252 ptab->chord_key -= ptab->chord_key % MPP_MAX_BANDS;
253 ptab->chord_key += MPP_BAND_STEP_12 * r_key[x][y];
254 ptab->chord_bass = ptab->chord_key % MPP_MAX_BANDS;
255 ptab->chord_mask = r_mask[x][y];
256 ptab->chord_step = MPP_BAND_STEP_12;
257 ptab->handle_refresh();
258 ptab->handle_play_press();
259 return;
260 }
261 }
262 }
263
264 void
mouseReleaseEvent(QMouseEvent * event)265 MppDecodeCircle :: mouseReleaseEvent(QMouseEvent *event)
266 {
267 QPoint p = event->pos();
268
269 for (uint8_t x = 0; x != NMAX; x++) {
270 for (uint8_t y = 0; y != 12; y++) {
271 if (r_press[x][y].contains(p) == 0)
272 continue;
273 ptab->handle_play_release();
274 }
275 }
276 }
277
278 void
paintEvent(QPaintEvent * event)279 MppDecodeCircle :: paintEvent(QPaintEvent *event)
280 {
281 QPainter paint(this);
282 int w = width();
283 int h = height();
284 int r;
285 qreal step;
286 uint8_t x;
287 uint8_t y;
288 uint8_t z;
289 int found_key;
290 uint32_t rols;
291 MppChord_t footprint;
292
293 paint.fillRect(QRectF(0,0,w,h), Mpp.ColorWhite);
294 paint.setRenderHints(QPainter::Antialiasing, 1);
295
296 memset(r_press, 0, sizeof(r_press));
297 memset(r_key, 0, sizeof(r_key));
298 memset(r_mask, 0, sizeof(r_mask));
299
300 footprint = MppFindChordRoot(ptab->chord_mask, &rols);
301 found_key = (ptab->chord_key +
302 (rols * MPP_BAND_STEP_CHORD)) % MPP_MAX_BANDS;
303 found_key /= MPP_BAND_STEP_12;
304
305 r = (w > h) ? h : w;
306 step = r / (2 * (NMAX + 2));
307
308 QFont fnt[NMAX];
309
310 fnt[0].setPixelSize(step / 1.5);
311 fnt[1].setPixelSize(step / 2.5);
312 fnt[2].setPixelSize(step / 3.5);
313
314 for (x = 0; x != NMAX; x++) {
315 const qreal radius = (NMAX + 2 - x) * step - step / 2.0;
316
317 paint.setPen(QPen(Mpp.ColorBlack, 2));
318 paint.setBrush(QBrush());
319
320 paint.drawEllipse(QRectF(w / 2.0 - radius,
321 h / 2.0 - radius,
322 2.0*radius, 2.0*radius));
323
324 for (y = z = 0; y != 12; y++) {
325 const double phase = 2.0 * M_PI * (double)y / 12.0;
326 const qreal xp = radius * cos(phase) + w / 2.0;
327 const qreal yp = radius * sin(phase) + h / 2.0;
328
329 r_press[x][y] = QRect(xp - step / 2.0,
330 yp - step / 2.0,
331 step, step);
332 switch (x) {
333 case 1:
334 r_key[x][y] = (z + 9) % 12;
335 break;
336 default:
337 r_key[x][y] = z;
338 break;
339 }
340 r_mask[x][y] = mask[x];
341
342 z += 7;
343 z %= 12;
344 }
345 }
346
347 for (x = 0; x != NMAX; x++) {
348 paint.setFont(fnt[x]);
349
350 for (y = 0; y != 12; y++) {
351 QColor bg;
352 QColor fg;
353
354 switch (MppCommonKeys(r_mask[x][y], footprint,
355 r_key[x][y], found_key)) {
356 case 4:
357 case 3:
358 bg = Mpp.ColorWhite;
359 fg = Mpp.ColorBlack;
360 break;
361 case 2:
362 bg = Mpp.ColorLight;
363 fg = Mpp.ColorWhite;
364 break;
365 case 1:
366 bg = Mpp.ColorGrey;
367 fg = Mpp.ColorWhite;
368 break;
369 default:
370 bg = Mpp.ColorBlack;
371 fg = Mpp.ColorWhite;
372 break;
373 }
374 paint.setPen(QPen(bg, 0));
375 paint.setBrush(bg);
376
377 paint.drawEllipse(r_press[x][y]);
378
379 paint.setPen(QPen(fg, 0));
380 paint.setBrush(fg);
381
382 QString suffix;
383
384 switch (x) {
385 case 1:
386 suffix = "m";
387 break;
388 case 2:
389 suffix = "°7";
390 break;
391 default:
392 break;
393 }
394
395 paint.drawText(r_press[x][y],
396 Qt::AlignCenter | Qt::TextSingleLine,
397 MppKeyStrNoOctave(r_key[x][y] * MPP_BAND_STEP_12) + suffix);
398 }
399 }
400 }
401
402 uint8_t
parseScoreChord(MppChordElement * pinfo)403 MppDecodeTab :: parseScoreChord(MppChordElement *pinfo)
404 {
405 QString out;
406 uint32_t is_sharp;
407 uint32_t any = 0;
408 uint32_t key = 0;
409 uint32_t bass;
410 MppChord_t footprint;
411
412 if (pinfo->chord != 0)
413 is_sharp = (pinfo->chord->txt.indexOf('#') > -1);
414 else
415 is_sharp = 0;
416
417 footprint.zero();
418
419 for (int x = 0; x != MPP_MAX_CHORD_BANDS; x++) {
420 if (pinfo->stats[x] == 0)
421 continue;
422 footprint.set(x);
423 any = 1;
424 }
425 if (!any)
426 return (1); /* not found */
427
428 while (footprint.test(0) == 0) {
429 footprint.shr();
430 key += MPP_BAND_STEP_CHORD;
431 }
432
433 bass = MPP_BAND_REM(pinfo->key_base, MPP_MAX_BANDS);
434
435 MppChordToStringGeneric(footprint, key, bass, is_sharp, MPP_BAND_STEP_CHORD, out);
436
437 if (out.isEmpty())
438 return (1); /* not found */
439
440 chord_key = key;
441 chord_bass = bass;
442 chord_sharp = is_sharp;
443 chord_mask = footprint;
444
445 MPP_BLOCKED(lin_edit,setText(out));
446
447 handle_align(pinfo->key_max + 1);
448 handle_refresh();
449
450 return (0);
451 }
452
MppDecodeTab(MppMainWindow * _mw)453 MppDecodeTab :: MppDecodeTab(MppMainWindow *_mw)
454 : QWidget()
455 {
456
457 chord_key = 5 * 12 * MPP_BAND_STEP_12; /* C5 */
458 chord_bass = 0; /* C */
459 chord_sharp = 0;
460 chord_step = MPP_BAND_STEP_12;
461 chord_mask.zero();
462 chord_mask.set(0);
463 chord_mask.set((MPP_BAND_STEP_12 / MPP_BAND_STEP_CHORD) * 4);
464 chord_mask.set((MPP_BAND_STEP_12 / MPP_BAND_STEP_CHORD) * 7);
465 delta_v = 0;
466
467 mw = _mw;
468
469 gl = new QGridLayout(this);
470
471 gb = new MppGroupBox(tr("Chord Selector"));
472
473 gl->setRowStretch(1,1);
474 gl->setColumnStretch(0,1);
475
476 lin_edit = new QLineEdit(QString("C"));
477 lin_edit->setMaxLength(256);
478
479 lin_out = new QLineEdit();
480 lin_out->setMaxLength(256);
481
482 but_map_volume = new MppButtonMap("Key volume\0"
483 "MAX\0"
484 "63\0"
485 "31\0"
486 "15\0"
487 "7\0", 5, 5);
488 but_map_volume->setSelection(4);
489
490 but_map_view = new MppButtonMap("View selection\0"
491 "View-A\0"
492 "View-B\0", 2, 2);
493
494 #if MPP_MAX_VIEWS != 2
495 #error "Please update code above"
496 #endif
497 but_insert = new QPushButton(tr("&Insert"));
498 but_rol_up = new QPushButton(tr("Rotate\n&up"));
499 but_rol_down = new QPushButton(tr("Rotate\nd&own"));
500 but_mod_up = new QPushButton(tr("&Next\nvariant"));
501 but_mod_down = new QPushButton(tr("Pre&vious\nvariant"));
502 but_step_up_half = new QPushButton(tr("Step up\n12 scale"));
503 but_step_down_half = new QPushButton(tr("Step down\n12 scale"));
504 but_step_up_one = new QPushButton(tr("Step up\n192 scale"));
505 but_step_down_one = new QPushButton(tr("Step down\n192 scale"));
506 but_round_12 = new QPushButton(tr("Round to 12 scale"));
507 but_play = new QPushButton(tr("&Play"));
508
509 connect(but_play, SIGNAL(pressed()), this, SLOT(handle_play_press()));
510 connect(but_play, SIGNAL(released()), this, SLOT(handle_play_release()));
511
512 connect(but_insert, SIGNAL(released()), this, SLOT(handle_insert()));
513
514 connect(but_rol_up, SIGNAL(pressed()), this, SLOT(handle_rol_up()));
515 connect(but_rol_up, SIGNAL(released()), this, SLOT(handle_play_release()));
516 connect(but_rol_down, SIGNAL(pressed()), this, SLOT(handle_rol_down()));
517 connect(but_rol_down, SIGNAL(released()), this, SLOT(handle_play_release()));
518
519 connect(but_mod_up, SIGNAL(pressed()), this, SLOT(handle_mod_up()));
520 connect(but_mod_up, SIGNAL(released()), this, SLOT(handle_play_release()));
521 connect(but_mod_down, SIGNAL(pressed()), this, SLOT(handle_mod_down()));
522 connect(but_mod_down, SIGNAL(released()), this, SLOT(handle_play_release()));
523
524 connect(but_step_up_half, SIGNAL(pressed()), this, SLOT(handle_step_up_half()));
525 connect(but_step_up_half, SIGNAL(released()), this, SLOT(handle_play_release()));
526 connect(but_step_down_half, SIGNAL(pressed()), this, SLOT(handle_step_down_half()));
527 connect(but_step_down_half, SIGNAL(released()), this, SLOT(handle_play_release()));
528
529 connect(but_step_up_one, SIGNAL(pressed()), this, SLOT(handle_step_up_one()));
530 connect(but_step_up_one, SIGNAL(released()), this, SLOT(handle_play_release()));
531 connect(but_step_down_one, SIGNAL(pressed()), this, SLOT(handle_step_down_one()));
532 connect(but_step_down_one, SIGNAL(released()), this, SLOT(handle_play_release()));
533
534 connect(but_round_12, SIGNAL(pressed()), this, SLOT(handle_round_12()));
535 connect(but_round_12, SIGNAL(released()), this, SLOT(handle_play_release()));
536
537 connect(lin_edit, SIGNAL(textChanged(const QString &)), this, SLOT(handle_parse()));
538
539 gb->addWidget(
540 new QLabel(tr("[CDEFGABH][#b][...][/CDEFGABH[#b]]")),
541 0,0,1,4, Qt::AlignHCenter|Qt::AlignVCenter);
542
543 gb->addWidget(but_rol_down, 2,0,1,1);
544 gb->addWidget(but_rol_up, 2,1,1,1);
545
546 gb->addWidget(but_mod_down, 2,2,1,1);
547 gb->addWidget(but_mod_up, 2,3,1,1);
548
549 gb->addWidget(but_step_down_half, 3,0,1,1);
550 gb->addWidget(but_step_up_half, 3,1,1,1);
551 gb->addWidget(but_step_down_one, 3,2,1,1);
552 gb->addWidget(but_step_up_one, 3,3,1,1);
553
554 gb->addWidget(but_round_12, 4,0,1,2);
555
556 gb->addWidget(lin_edit, 5,0,1,4);
557 gb->addWidget(lin_out, 6,0,1,4);
558
559 gb->addWidget(but_map_volume, 7,0,1,4);
560 gb->addWidget(but_map_view, 8,0,1,4);
561
562 gb->addWidget(but_insert, 9, 2, 1, 2);
563 gb->addWidget(but_play, 9, 0, 1, 2);
564
565 gb_gen = new MppGroupBox(tr("Chord Scratch Area"));
566 gl->addWidget(gb_gen, 1,0,1,1);
567
568 editor = new MppDecodeEditor(_mw);
569 editor->setTabChangesFocus(true);
570
571 gb_gen->addWidget(editor, 0,0,1,1);
572
573 gb_dc = new MppGroupBox(tr("Circle of fifths"));
574 wi_dc = new MppDecodeCircle(this);
575 gb_dc->addWidget(wi_dc, 0,0,1,1);
576
577 split = new QSplitter();
578 #if defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR)
579 split->setHandleWidth(32);
580 #else
581 split->setHandleWidth(16);
582 #endif
583 split->addWidget(gb);
584 split->addWidget(gb_dc);
585
586 gl->addWidget(split, 0,0,1,1);
587
588 handle_parse();
589
590 but_insert->setFocus();
591
592 reset_state();
593
594 connect(this, SIGNAL(key_pressed(int)),
595 this, SLOT(handle_key_pressed(int)));
596 connect(this, SIGNAL(key_released(int)),
597 this, SLOT(handle_key_released(int)));
598 connect(this, SIGNAL(sustain_pedal(int)),
599 this, SLOT(handle_sustain_pedal(int)));
600 }
601
602 void
handle_play_press()603 MppDecodeTab :: handle_play_press()
604 {
605 MppScoreMain *sm = mw->scores_main[but_map_view->currSelection];
606 uint8_t vel = (127 >> but_map_volume->currSelection);
607 int key_bass;
608
609 mw->atomic_lock();
610 key_bass = chord_key - MPP_BAND_REM(chord_key, MPP_MAX_BANDS) + chord_bass;
611 if (key_bass >= chord_key)
612 key_bass -= 2 * MPP_MAX_BANDS;
613 else
614 key_bass -= 1 * MPP_MAX_BANDS;
615
616 mw->output_key(MPP_DEFAULT_TRACK(sm->unit), sm->synthChannel, key_bass, vel, 0, 0);
617 mw->output_key(MPP_DEFAULT_TRACK(sm->unit), sm->synthChannel, key_bass + MPP_MAX_BANDS, vel, 0, 0);
618
619 for (int x = 0; x != MPP_MAX_CHORD_BANDS; x++) {
620 if (chord_mask.test(x)) {
621 mw->output_key(MPP_DEFAULT_TRACK(sm->unit),
622 sm->synthChannel, chord_key + (x * MPP_BAND_STEP_CHORD), vel, 0, 0);
623 }
624 }
625 mw->atomic_unlock();
626 }
627
628 void
handle_play_release()629 MppDecodeTab :: handle_play_release()
630 {
631 MppScoreMain *sm = mw->scores_main[but_map_view->currSelection];
632 int key_bass;
633
634 mw->atomic_lock();
635 key_bass = chord_key - MPP_BAND_REM(chord_key, MPP_MAX_BANDS) + chord_bass;
636 if (key_bass >= chord_key)
637 key_bass -= 2 * MPP_MAX_BANDS;
638 else
639 key_bass -= 1 * MPP_MAX_BANDS;
640
641 mw->output_key(MPP_DEFAULT_TRACK(sm->unit), sm->synthChannel, key_bass, 0, 0, 0);
642 mw->output_key(MPP_DEFAULT_TRACK(sm->unit), sm->synthChannel, key_bass + MPP_MAX_BANDS, 0, 0, 0);
643
644 for (int x = 0; x != MPP_MAX_CHORD_BANDS; x++) {
645 if (chord_mask.test(x)) {
646 mw->output_key(MPP_DEFAULT_TRACK(sm->unit),
647 sm->synthChannel, chord_key + (x * MPP_BAND_STEP_CHORD), 0, 0, 0);
648 }
649 }
650 mw->atomic_unlock();
651 }
652
653 void
handle_insert()654 MppDecodeTab :: handle_insert()
655 {
656 QPlainTextEdit *qedit = mw->currEditor();
657 if (qedit == 0)
658 return;
659
660 QTextCursor cursor(qedit->textCursor());
661 MppChordElement info;
662 MppElement *ptr;
663 MppHead temp;
664 int row;
665
666 temp += qedit->toPlainText();
667 temp.flush();
668
669 row = cursor.blockNumber();
670
671 cursor.beginEditBlock();
672
673 /* check if the chord is valid */
674 if (temp.getChord(row, &info) != 0) {
675 if (info.chord != 0) {
676 info.chord->txt = QChar('(') + lin_edit->text().trimmed() + QChar(')');
677
678 cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor, 1);
679 cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, info.chord->line);
680 cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::MoveAnchor, 1);
681 cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor, 1);
682 cursor.removeSelectedText();
683 cursor.insertText(temp.toPlain(info.chord->line).replace("\n", ""));
684 }
685 if (info.start != 0) {
686 for (ptr = info.start; ptr != info.stop;
687 ptr = TAILQ_NEXT(ptr, entry)) {
688 ptr->type = MPP_T_UNKNOWN;
689 ptr->txt = "";
690 }
691
692 info.start->txt = getText();
693
694 cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor, 1);
695 cursor.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, row);
696 cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::MoveAnchor, 1);
697 cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor, 1);
698 cursor.removeSelectedText();
699 cursor.insertText(temp.toPlain(info.start->line).replace("\n", ""));
700 }
701 } else {
702 cursor.removeSelectedText();
703 cursor.insertText(getText() + QChar('\n'));
704 }
705 cursor.endEditBlock();
706
707 mw->handle_compile();
708 }
709
710 void
handle_align(int key)711 MppDecodeTab :: handle_align(int key)
712 {
713 if (key < (2 * MPP_MAX_BANDS) ||
714 key > (128 * MPP_BAND_STEP_12 - MPP_MAX_BANDS))
715 return;
716
717 chord_key = key - MPP_BAND_REM(key, MPP_MAX_BANDS) +
718 MPP_MAX_BANDS + MPP_BAND_REM(chord_key, MPP_MAX_BANDS);
719
720 for (int x = MPP_MAX_CHORD_BANDS; x--; ) {
721 if (chord_mask.test(x) == 0)
722 continue;
723 if ((chord_key + (x * MPP_BAND_STEP_CHORD)) < key)
724 break;
725 int rols = 0;
726 MppRolUpChord(chord_mask, rols);
727 chord_key -= rols * MPP_BAND_STEP_CHORD;
728 x = MPP_MAX_CHORD_BANDS;
729 }
730 }
731
732 void
handle_rol_up()733 MppDecodeTab :: handle_rol_up()
734 {
735 int rols;
736
737 if (chord_key > (128 * MPP_BAND_STEP_12 - MPP_MAX_BANDS))
738 return;
739 handle_play_release();
740 rols = 0;
741 MppRolDownChord(chord_mask, rols);
742 chord_key += rols * MPP_BAND_STEP_CHORD;
743 handle_refresh();
744 handle_play_press();
745 }
746
747 void
handle_rol_down()748 MppDecodeTab :: handle_rol_down()
749 {
750 int rols;
751
752 if (chord_key < 2 * MPP_MAX_BANDS)
753 return;
754 handle_play_release();
755 rols = 0;
756 MppRolUpChord(chord_mask, rols);
757 chord_key -= rols * MPP_BAND_STEP_CHORD;
758 handle_refresh();
759 handle_play_press();
760 }
761
762 void
handle_mod_up()763 MppDecodeTab :: handle_mod_up()
764 {
765 uint32_t rols;
766 handle_play_release();
767 chord_mask = MppFindChordRoot(chord_mask, &rols);
768 chord_key += rols * MPP_BAND_STEP_CHORD;
769 MppNextChordRoot(chord_mask,
770 chord_step / MPP_BAND_STEP_CHORD);
771 handle_refresh();
772 handle_play_press();
773 }
774
775 void
handle_mod_down()776 MppDecodeTab :: handle_mod_down()
777 {
778 uint32_t rols;
779 handle_play_release();
780 chord_mask = MppFindChordRoot(chord_mask, &rols);
781 chord_key += rols * MPP_BAND_STEP_CHORD;
782 MppPrevChordRoot(chord_mask,
783 chord_step / MPP_BAND_STEP_CHORD);
784 handle_refresh();
785 handle_play_press();
786 }
787
788 void
handle_step_up_half()789 MppDecodeTab :: handle_step_up_half()
790 {
791 handle_play_release();
792 if (chord_key < (128 * MPP_BAND_STEP_12)) {
793 chord_key += MPP_BAND_STEP_12;
794 chord_bass += MPP_BAND_STEP_12;
795 chord_bass %= MPP_MAX_BANDS;
796 handle_refresh();
797 }
798 handle_play_press();
799 }
800
801 void
handle_step_down_half()802 MppDecodeTab :: handle_step_down_half()
803 {
804 handle_play_release();
805 if (chord_key >= (25 * MPP_BAND_STEP_12)) {
806 chord_key -= MPP_BAND_STEP_12;
807 chord_bass += 11 * MPP_BAND_STEP_12;
808 chord_bass %= MPP_MAX_BANDS;
809 handle_refresh();
810 }
811 handle_play_press();
812 }
813
814 void
handle_step_up_one()815 MppDecodeTab :: handle_step_up_one()
816 {
817 handle_play_release();
818 if (chord_key < (128 * MPP_BAND_STEP_12)) {
819 chord_key += MPP_BAND_STEP_CHORD;
820 chord_bass += MPP_BAND_STEP_CHORD;
821 chord_bass %= MPP_MAX_BANDS;
822 handle_refresh();
823 }
824 handle_play_press();
825 }
826
827 void
handle_step_down_one()828 MppDecodeTab :: handle_step_down_one()
829 {
830 handle_play_release();
831 if (chord_key >= (24 * MPP_BAND_STEP_12 + 1)) {
832 chord_key -= MPP_BAND_STEP_CHORD;
833 chord_bass += MPP_MAX_BANDS - MPP_BAND_STEP_CHORD;
834 chord_bass %= MPP_MAX_BANDS;
835 handle_refresh();
836 }
837 handle_play_press();
838 }
839
840 void
handle_round_12()841 MppDecodeTab :: handle_round_12()
842 {
843 handle_play_release();
844 round(MPP_BAND_STEP_12);
845 handle_play_press();
846 }
847
848 void
round(int value)849 MppDecodeTab :: round(int value)
850 {
851 int x,y,mod;
852
853 if (value < 1)
854 return;
855
856 mod = (value / MPP_BAND_STEP_CHORD);
857
858 chord_step = value;
859
860 chord_key += value / 2;
861 chord_key -= chord_key % value;
862
863 chord_bass += value / 2;
864 chord_bass -= chord_bass % value;
865 chord_bass %= MPP_MAX_BANDS;
866
867 if (mod > 0) {
868 for (x = 0; x != MPP_MAX_CHORD_BANDS; x++) {
869 if (chord_mask.test(x) == 0 || (x % mod) == 0)
870 continue;
871
872 y = x + (mod / 2);
873 y -= (y % mod);
874 y %= MPP_MAX_CHORD_BANDS;
875
876 chord_mask.clr(x);
877 chord_mask.set(y);
878 }
879 }
880 handle_refresh();
881 }
882
883 void
handle_refresh()884 MppDecodeTab :: handle_refresh()
885 {
886 QString out_key;
887 QString str;
888 int key_bass;
889
890 key_bass = chord_key -
891 MPP_BAND_REM(chord_key, MPP_MAX_BANDS) +
892 chord_bass;
893
894 if (key_bass >= chord_key)
895 key_bass -= 2 * MPP_MAX_BANDS;
896 else
897 key_bass -= 1 * MPP_MAX_BANDS;
898
899 MppChordToStringGeneric(chord_mask, chord_key, key_bass,
900 chord_sharp, MPP_BAND_STEP_CHORD, str);
901
902 out_key += MppKeyStr(key_bass);
903 out_key += " ";
904 out_key += MppKeyStr(key_bass + MPP_MAX_BANDS);
905 out_key += " ";
906
907 for (int x = 0; x != MPP_MAX_CHORD_BANDS; x++) {
908 if (chord_mask.test(x) == 0)
909 continue;
910 out_key += MppKeyStr((x * MPP_BAND_STEP_CHORD) + chord_key);
911 out_key += " ";
912 }
913
914 if (str.isEmpty() == 0) {
915 out_key += "/* ";
916 out_key += str;
917 out_key += " */";
918 }
919
920 MPP_BLOCKED(lin_edit,setText(str));
921 MPP_BLOCKED(lin_out,setText(out_key));
922
923 wi_dc->update();
924 }
925
926 void
handle_parse()927 MppDecodeTab :: handle_parse()
928 {
929 QString out_key;
930 MppChord_t mask;
931 int key_bass;
932 uint32_t rem;
933 uint32_t bass;
934
935 QString chord = lin_edit->text().trimmed();
936 if (chord.isEmpty())
937 goto error;
938
939 MppStringToChordGeneric(mask, rem, bass, MPP_BAND_STEP_CHORD, chord);
940 chord_sharp = (chord.indexOf('#') > -1);
941
942 if (mask.test(0) == 0)
943 goto error;
944
945 chord_bass = MPP_BAND_REM(bass, MPP_MAX_BANDS);
946 chord_key = chord_key -
947 MPP_BAND_REM(chord_key, MPP_MAX_BANDS) +
948 rem;
949 chord_mask = mask;
950
951 key_bass = chord_key -
952 MPP_BAND_REM(chord_key, MPP_MAX_BANDS) +
953 chord_bass;
954
955 if (key_bass >= chord_key)
956 key_bass -= 2 * MPP_MAX_BANDS;
957 else
958 key_bass -= 1 * MPP_MAX_BANDS;
959
960 out_key += MppKeyStr(key_bass);
961 out_key += " ";
962 out_key += MppKeyStr(key_bass + MPP_MAX_BANDS);
963 out_key += " ";
964
965 for (int x = 0; x != MPP_MAX_CHORD_BANDS; x++) {
966 if (chord_mask.test(x) == 0)
967 continue;
968 out_key += MppKeyStr((x * MPP_BAND_STEP_CHORD) + chord_key);
969 out_key += " ";
970 }
971
972 out_key += "/* ";
973 out_key += chord;
974 out_key += " */";
975
976 lin_out->setText(out_key);
977
978 goto done;
979 error:
980 chord_mask.zero();
981 chord_mask.set(0);
982 lin_out->setText("/* ERROR */");
983 done:
984 wi_dc->update();
985 }
986
987 QString
getText()988 MppDecodeTab :: getText()
989 {
990 return (lin_out->text());
991 }
992
993 void
setText(QString str)994 MppDecodeTab :: setText(QString str)
995 {
996 MPP_BLOCKED(lin_edit,setText(str));
997 handle_parse();
998 }
999
1000 void
keyPressEvent(QKeyEvent * event)1001 MppDecodeTab :: keyPressEvent(QKeyEvent *event)
1002 {
1003 switch (event->key()) {
1004 case Qt::Key_Up:
1005 handle_mod_up();
1006 break;
1007 case Qt::Key_Down:
1008 handle_mod_down();
1009 break;
1010 default:
1011 break;
1012 }
1013 }
1014
1015 void
keyReleaseEvent(QKeyEvent * event)1016 MppDecodeTab :: keyReleaseEvent(QKeyEvent *event)
1017 {
1018 switch (event->key()) {
1019 case Qt::Key_Up:
1020 handle_play_release();
1021 break;
1022 case Qt::Key_Down:
1023 handle_play_release();
1024 break;
1025 default:
1026 break;
1027 }
1028 }
1029
1030 void
reset_state()1031 MppDecodeTab :: reset_state()
1032 {
1033 memset(key_bitmap, 0, sizeof(key_bitmap));
1034 sustain = 0;
1035 stable = 0;
1036 }
1037
1038 void
watchdog()1039 MppDecodeTab :: watchdog()
1040 {
1041 constexpr unsigned stride = MPP_BAND_STEP_12 / MPP_BAND_STEP_CHORD;
1042 MppChordElement info = {};
1043 unsigned int x;
1044 int key;
1045 bool any_new = false;
1046 bool pressed = false;
1047
1048 for (x = 0; x != 128; x++) {
1049 if (!(key_bitmap[x] & BIT_PRESSED)) {
1050 if (key_bitmap[x] & BIT_CACHED)
1051 any_new = true;
1052 key_bitmap[x] &= ~BIT_CACHED;
1053 continue;
1054 }
1055 if (!(key_bitmap[x] & BIT_CACHED)) {
1056 key_bitmap[x] |= BIT_CACHED;
1057 any_new = true;
1058 }
1059 key = x * MPP_BAND_STEP_12;
1060 if (pressed == false)
1061 info.key_base = key;
1062 if (info.key_max < key)
1063 info.key_max = key;
1064 pressed = true;
1065 info.stats[(x * stride) % MPP_MAX_CHORD_BANDS]++;
1066 }
1067
1068 if (any_new || !pressed) {
1069 stable = 0;
1070 return;
1071 } else {
1072 switch (stable) {
1073 case 0:
1074 stable = 1;
1075 return;
1076 case 1:
1077 stable = 2;
1078 break;
1079 default:
1080 return;
1081 }
1082 }
1083
1084 if (parseScoreChord(&info) != 0)
1085 return;
1086
1087 if (mw->scoreRecordOn == 2)
1088 mw->mbm_score_record->setSelection(0);
1089
1090 QPlainTextEdit *ped = mw->currEditor();
1091 if (ped == 0)
1092 return;
1093
1094 QTextCursor cursor;
1095
1096 cursor = QTextCursor(ped->textCursor());
1097 cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::MoveAnchor, 1);
1098 cursor.beginEditBlock();
1099 cursor.insertText(getText() + QChar('\n'));
1100 cursor.endEditBlock();
1101
1102 ped->setTextCursor(cursor);
1103 }
1104
1105 void
handle_key_pressed(int key)1106 MppDecodeTab :: handle_key_pressed(int key)
1107 {
1108 key /= MPP_BAND_STEP_12;
1109 if (key < 0 || key > 127)
1110 return;
1111 key_bitmap[key] |= BIT_PRESSED;
1112 key_bitmap[key] &= ~BIT_RELEASED;
1113 }
1114
1115 void
handle_key_released(int key)1116 MppDecodeTab :: handle_key_released(int key)
1117 {
1118 key /= MPP_BAND_STEP_12;
1119 if (key < 0 || key > 127)
1120 return;
1121 key_bitmap[key] |= BIT_RELEASED;
1122 if (sustain == 0)
1123 key_bitmap[key] &= ~BIT_PRESSED;
1124 }
1125
1126 void
handle_sustain_pedal(int level)1127 MppDecodeTab :: handle_sustain_pedal(int level)
1128 {
1129 if (sustain == (level >= 64))
1130 return;
1131 sustain = (level >= 64);
1132 if (sustain != 0)
1133 return;
1134 for (unsigned x = 0; x != 128; x++) {
1135 if (key_bitmap[x] & BIT_RELEASED)
1136 key_bitmap[x] &= ~BIT_PRESSED;
1137 }
1138 }
1139
1140 void
mouseDoubleClickEvent(QMouseEvent * e)1141 MppDecodeEditor :: mouseDoubleClickEvent(QMouseEvent *e)
1142 {
1143 MppHead temp;
1144 MppChordElement info;
1145 QTextCursor cursor(textCursor());
1146 int row;
1147
1148 cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::MoveAnchor, 1);
1149 cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor, 1);
1150
1151 /* check if the line is empty */
1152 if (cursor.selectedText().simplified().size() == 0)
1153 return;
1154
1155 row = cursor.blockNumber();
1156
1157 temp += toPlainText();
1158 temp.flush();
1159
1160 /* check if the chord is valid */
1161 if (temp.getChord(row, &info) != 0)
1162 mw->tab_chord_gl->parseScoreChord(&info);
1163
1164 setTextCursor(cursor);
1165 }
1166