1 //=============================================================================
2 // MuseScore
3 // Music Composition & Notation
4 //
5 // Copyright (C) 2011 Werner Schweer
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2
9 // as published by the Free Software Foundation and appearing in
10 // the file LICENCE.GPL
11 //=============================================================================
12
13 #include "importgtp.h"
14
15 #include <libmscore/score.h>
16 #include <libmscore/measurebase.h>
17 #include <libmscore/text.h>
18 #include <libmscore/box.h>
19 #include <libmscore/staff.h>
20 #include <libmscore/part.h>
21 #include <libmscore/measure.h>
22 #include <libmscore/timesig.h>
23 #include <libmscore/tremolo.h>
24 #include <libmscore/rest.h>
25 #include <libmscore/chord.h>
26 #include <libmscore/note.h>
27 #include <libmscore/stringdata.h>
28 #include <libmscore/clef.h>
29 #include <libmscore/lyrics.h>
30 #include <libmscore/tempotext.h>
31 #include <libmscore/glissando.h>
32 #include <libmscore/slur.h>
33 #include <libmscore/tie.h>
34 #include <libmscore/tuplet.h>
35 #include <libmscore/barline.h>
36 #include <libmscore/excerpt.h>
37 #include <libmscore/stafftype.h>
38 #include <libmscore/bracket.h>
39 #include <libmscore/articulation.h>
40 #include <libmscore/keysig.h>
41 #include <libmscore/harmony.h>
42 #include <libmscore/bend.h>
43 #include <libmscore/tremolobar.h>
44 #include <libmscore/segment.h>
45 #include <libmscore/rehearsalmark.h>
46 #include <libmscore/dynamic.h>
47 #include <libmscore/arpeggio.h>
48 #include <libmscore/volta.h>
49 #include <libmscore/instrtemplate.h>
50 #include <libmscore/fingering.h>
51 #include <libmscore/notedot.h>
52 #include <libmscore/stafftext.h>
53 #include <libmscore/sym.h>
54 #include <libmscore/chordline.h>
55
56
57 namespace Ms {
58
59 //---------------------------------------------------------
60 // readInfo
61 //---------------------------------------------------------
62
readInfo()63 void GuitarPro5::readInfo()
64 {
65 title = readDelphiString();
66 subtitle = readDelphiString();
67 artist = readDelphiString();
68 album = readDelphiString();
69 composer = readDelphiString();
70 readDelphiString();
71 QString copyright = readDelphiString();
72 if (!copyright.isEmpty())
73 score->setMetaTag("copyright", QString("%1").arg(copyright));
74
75 transcriber = readDelphiString();
76 instructions = readDelphiString();
77 int n = readInt();
78 for (int i = 0; i < n; ++i)
79 comments.append(readDelphiString());
80 }
81
82 //---------------------------------------------------------
83 // readBeatEffects
84 //---------------------------------------------------------
85
readBeatEffects(int track,Segment * segment)86 int GuitarPro5::readBeatEffects(int track, Segment* segment)
87 {
88 int effects = 0;
89
90 uchar fxBits1 = readUChar();
91 uchar fxBits2 = readUChar();
92 if (fxBits1 & BEAT_FADE)
93 effects = 4; // fade in
94 if (fxBits1 & BEAT_EFFECT) {
95 int k = readUChar();
96 effects = k + effects * 100;// &effects;
97 }
98 if (fxBits1 & BEAT_VIBRATO_TREMOLO) {
99 effects = 7 + effects * 100;
100 }
101 if (fxBits2 & BEAT_TREMOLO)
102 readTremoloBar(track, segment); // readBend();
103 if (fxBits2 & 0x01) { // Rasgueado effect
104 StaffText* st = new StaffText(score);
105 st->setXmlText("rasg.");
106 st->setParent(segment);
107 st->setTrack(track);
108 score->addElement(st);
109 }
110 if (fxBits1 & BEAT_ARPEGGIO) {
111 int strokeup = readUChar(); // up stroke length
112 int strokedown = readUChar(); // down stroke length
113
114 Arpeggio* a = new Arpeggio(score);
115 // representation is different in guitar pro 5 - the up/down order below is correct
116 if (strokeup > 0) {
117 a->setArpeggioType(ArpeggioType::UP_STRAIGHT);
118 }
119 else if (strokedown > 0) {
120 a->setArpeggioType(ArpeggioType::DOWN_STRAIGHT);
121 }
122 else {
123 delete a;
124 a = 0;
125 }
126 if (a) {
127 ChordRest* cr = new Chord(score);
128 cr->setTrack(track);
129 cr->add(a);
130 segment->add(cr);
131 }
132 }
133 if (fxBits2 & BEAT_STROKE_DIR) {
134 effects = readChar(); // stroke pick direction
135 effects += 4; //1 or 2 for effects becomes 4 or 5
136 }
137 return effects;
138 }
139
140 //---------------------------------------------------------
141 // readPageSetup
142 //---------------------------------------------------------
143
readPageSetup()144 void GuitarPro5::readPageSetup()
145 {
146 skip(version > 500 ? 49 : 30);
147 for (int i = 0; i < 11; ++i) {
148 skip(4);
149 readBytePascalString();
150 }
151 }
152
153 //---------------------------------------------------------
154 // readBeat
155 //---------------------------------------------------------
156
readBeat(const Fraction & tick,int voice,Measure * measure,int staffIdx,Tuplet ** tuplets,bool)157 Fraction GuitarPro5::readBeat(const Fraction& tick, int voice, Measure* measure, int staffIdx, Tuplet** tuplets,
158 bool /*mixChange*/)
159 {
160 uchar beatBits = readUChar();
161 bool dotted = beatBits & BEAT_DOTTED;
162
163 slide = -1;
164 int track = staffIdx * VOICES + voice;
165 if (slides.contains(track))
166 slide = slides.take(track);
167
168 int pause = -1;
169 if (beatBits & BEAT_PAUSE)
170 pause = readUChar();
171
172 // readDuration
173 int len = readChar();
174 int tuple = 0;
175 if (beatBits & BEAT_TUPLET)
176 tuple = readInt();
177
178 Segment* segment = measure->getSegment(SegmentType::ChordRest, tick);
179 if (beatBits & BEAT_CHORD) {
180 int numStrings = score->staff(staffIdx)->part()->instrument()->stringData()->strings();
181 skip(17);
182 #if 0
183 uchar header = readUChar(); //1
184 uchar sharp = readUChar(); //2
185 skip(3); //5
186 char root = readChar(); //6
187 uchar chordtype = readUChar();//7
188 uchar nines = readUChar();//8
189 int bass = readInt();//12
190 int aug = readInt(); //16
191 char add = readChar(); //17
192 #endif
193 QString name;
194 {
195 /*auto len =*/ readUChar();
196 char c[21];
197 f->read(c, 21);
198 // if (len > 20)
199 // skip(len - 20);
200 //skip(len - 20);
201 c[20] = 0;
202 name = c;
203 }
204 //QString name = readPascalString(21);
205 skip(4);
206 // no header to be read in the GP5 format - default to true.
207 readChord(segment, staffIdx * VOICES, numStrings, name, true);
208 skip(32);
209 }
210 Lyrics* lyrics = 0;
211 QString free_text;
212 if (beatBits & BEAT_LYRICS) {
213 //free_text = readDelphiString();
214 QString qs = readDelphiString();
215 std::string txt = qs.toUtf8().constData();
216 txt.erase(std::remove_if(txt.begin(), txt.end(), [](char c) {return c == '_'; }), txt.end());
217 // auto pos = txt.find('-');
218 auto buffer = txt;
219 txt.resize(0);
220 const char* c = buffer.c_str();
221 while (*c) {
222 if (*c == ' ') {
223 while (*c == ' ')
224 ++c;
225 if (*c == '-') {
226 txt += '-';
227 ++c;
228 while (*c == ' ')
229 ++c;
230 }
231 else if (*c)
232 txt += '-';
233 }
234 else
235 txt += *(c++);
236 }
237 if (gpLyrics.lyrics.size() == 0 || (gpLyrics.lyrics.size() == 1 && gpLyrics.lyrics[0].isEmpty())) {
238 // gpLyrics.lyrics.resize(0);
239 gpLyrics.lyrics.clear();
240 gpLyrics.fromBeat = _beat_counter;
241 gpLyrics.lyricTrack = track;
242 }
243 while (txt.size() && txt[txt.size() - 1] == '-')
244 txt.resize(txt.size() - 1);
245 // gpLyrics.lyrics.append(txt);
246 gpLyrics.lyrics.append(QString::fromUtf8(txt.data(), int(txt.size())));
247 gpLyrics.segments.push_back(segment);
248 }
249 #if 0
250 gpLyrics.beatCounter++;
251 if (false && gpLyrics.beatCounter >= gpLyrics.fromBeat && gpLyrics.lyricTrack == staffIdx+1) {
252 int index = gpLyrics.beatCounter - gpLyrics.fromBeat;
253 if (index < gpLyrics.lyrics.size()) {
254 lyrics = new Lyrics(score);
255 lyrics->setPlainText(gpLyrics.lyrics[index]);
256 }
257 }
258 #endif
259 int beatEffects = 0;
260 if (beatBits & BEAT_EFFECTS)
261 beatEffects = readBeatEffects(track, segment);
262 last_segment = segment;
263 if (beatBits & BEAT_MIX_CHANGE)
264 readMixChange(measure);
265
266 int strings = readUChar(); // used strings mask
267
268 Fraction l = len2fraction(len);
269
270 // Some beat effects could add a Chord before this
271 ChordRest* cr = segment->cr(track);
272 if (voice != 0 && pause == 0 && strings == 0)
273 cr = 0;
274 else {
275 if (strings == 0) {
276 if (cr) {
277 segment->remove(cr);
278 delete cr;
279 cr = 0;
280 }
281 cr = new Rest(score);
282 }
283 else {
284 if (!cr)
285 cr = new Chord(score);
286 }
287 cr->setParent(segment);
288 cr->setTrack(track);
289
290 TDuration d(l);
291 d.setDots(dotted ? 1 : 0);
292
293 if (dotted)
294 l = l + (l * Fraction(1,2));
295
296 if (tuple) {
297 Tuplet* tuplet = tuplets[staffIdx * 2 + voice];
298 if ((tuplet == 0) || (tuplet->elementsDuration() == tuplet->baseLen().fraction() * tuplet->ratio().numerator())) {
299 tuplet = new Tuplet(score);
300 tuplet->setTick(tick);
301 // int track = staffIdx * 2 + voice;
302 tuplets[staffIdx * 2 + voice] = tuplet;
303 tuplet->setTrack(cr->track());
304 setTuplet(tuplet, tuple);
305 tuplet->setParent(measure);
306 }
307 tuplet->setTrack(cr->track());
308 tuplet->setBaseLen(l);
309 tuplet->setTicks(l * tuplet->ratio().denominator());
310 cr->setTuplet(tuplet);
311 tuplet->add(cr);
312 }
313
314 cr->setTicks(l);
315 if (cr->isRest() && (pause == 0 || l >= measure->ticks())) {
316 cr->setDurationType(TDuration::DurationType::V_MEASURE);
317 cr->setTicks(measure->ticks());
318 }
319 else
320 cr->setDurationType(d);
321
322 if (!segment->cr(track))
323 segment->add(cr);
324
325 Staff* staff = cr->staff();
326 int numStrings = staff->part()->instrument()->stringData()->strings();
327 bool hasSlur = false;
328 Note* _note{ nullptr };
329 std::vector<Note*> delnote;
330 for (int i = 6; i >= 0; --i) {
331 if (strings & (1 << i) && ((6-i) < numStrings)) {
332 Note* note = new Note(score);
333 _note = note;
334 if (dotted) {
335 // there is at most one dotted note in this guitar pro version
336 NoteDot* dot = new NoteDot(score);
337 dot->setParent(note);
338 dot->setTrack(track); // needed to know the staff it belongs to (and detect tablature)
339 dot->setVisible(true);
340 note->add(dot);
341 }
342 toChord(cr)->add(note);
343
344 hasSlur = (readNote(6-i, note) || hasSlur);
345 if (slideList.size() && slideList.back() == nullptr) {
346 slideList.back() = note;
347 hasSlur = true;
348 }
349 if (note->fret() == -20) {
350 delnote.push_back(note);
351 #if 0
352 Chord* chord = toChord(cr);
353 chord->remove(note);
354 delete note;
355 if (chord->notes().empty()) {
356 chord->segment()->remove(chord);
357 delete chord;
358 cr = nullptr;
359 }
360 #endif
361 }
362 else
363 note->setTpcFromPitch();
364 }
365 }
366 if (delnote.size()) {
367 Chord* chord = toChord(cr);
368 for (auto n : delnote) {
369 chord->remove(n);
370 delete n;
371 }
372 if (chord->notes().empty()) {
373 if (chord->tuplet())
374 chord->tuplet()->remove(chord);
375 chord->segment()->remove(chord);
376 delete chord;
377 cr = nullptr;
378 }
379 delnote.clear();
380 }
381 createSlur(hasSlur, staffIdx, cr);
382 if (lyrics)
383 cr->add(lyrics);
384 if (free_text.length() && _note) {
385 addTextToNote(free_text, Align::CENTER, _note);
386 }
387
388 }
389 int rr = readChar();
390 if (cr && cr->isChord()) {
391 Chord* chord = toChord(cr);
392 do {
393 applyBeatEffects(chord, beatEffects % 100);
394 } while (beatEffects /= 100);
395 if (rr == ARPEGGIO_DOWN)
396 chord->setStemDirection(Direction::DOWN);
397 else if (rr == ARPEGGIO_UP)
398 chord->setStemDirection(Direction::UP);
399 }
400 int r = readChar();
401 if (r & 0x8) {
402 int rrr = readChar();
403 qDebug(" 3beat read 0x%02x", rrr);
404 }
405 if (cr && cr->isChord()) {
406 if (toChord(cr)->notes().size() == 0) {
407 segment->remove(cr);
408 delete cr;
409 cr = 0;
410 }
411 else if (slide > 0)
412 createSlide(slide, cr, staffIdx);
413 }
414 restsForEmptyBeats(segment, measure, cr, l, track, tick);
415 return cr ? cr->actualTicks() : measure->ticks();
416 }
417
418 //---------------------------------------------------------
419 // readMeasure
420 //---------------------------------------------------------
421
readMeasure(Measure * measure,int staffIdx,Tuplet ** tuplets,bool mixChange)422 void GuitarPro5::readMeasure(Measure* measure, int staffIdx, Tuplet** tuplets, bool mixChange)
423 {
424 for (int voice = 0; voice < 2; ++voice) {
425 Fraction measureLen = { 0,1 };
426 Fraction tick = measure->tick();
427 int beats = readInt();
428 if (beats > 100)
429 return;
430 for (int beat = 0; beat < beats; ++beat) {
431 Fraction ticks = readBeat(tick, voice, measure, staffIdx, tuplets, mixChange);
432 ++_beat_counter;
433 tick += ticks;
434 measureLen += ticks;
435 }
436 if (measureLen < measure->ticks()) {
437 score->setRest(tick, staffIdx * VOICES + voice, measure->ticks() - measureLen, false, nullptr, false);
438 }
439 }
440 }
441
442 //---------------------------------------------------------
443 // readMixChange
444 //---------------------------------------------------------
445
readMixChange(Measure * measure)446 bool GuitarPro5::readMixChange(Measure* measure)
447 {
448 /*char patch =*/ readChar();
449 skip(16);
450 signed char volume = readChar();
451 signed char pan = readChar();
452 signed char chorus = readChar();
453 signed char reverb = readChar();
454 signed char phase = readChar();
455 signed char tremolo = readChar();
456 readDelphiString(); // tempo name
457
458 int temp = readInt();
459 bool editedTempo = false;
460 if (volume >= 0)
461 readChar();
462 if (pan >= 0)
463 readChar();
464 if (chorus >= 0)
465 readChar();
466 if (reverb >= 0)
467 readChar();
468 //qDebug("read reverb: %d", reverb);
469 if (phase >= 0)
470 readChar();
471 if (tremolo >= 0)
472 readChar();
473 if (temp >= 0) {
474 if (last_segment) {
475 score->setTempo(last_segment->tick(), double(temp) / 60.0);
476 last_segment = nullptr;
477 }
478 if (temp != previousTempo) {
479 previousTempo = temp;
480 setTempo(temp, measure);
481 editedTempo = true;
482 }
483 readChar();
484 if (version > 500)
485 readChar();
486 }
487 readChar();
488 readChar();
489 if (version > 500) {
490 readDelphiString();
491 readDelphiString();
492 }
493 return editedTempo;
494 }
495
496 //---------------------------------------------------------
497 // readTracks
498 //---------------------------------------------------------
499
readTracks()500 bool GuitarPro5::readTracks()
501 {
502 for (int i = 0; i < staves; ++i) {
503 int tuning[GP_MAX_STRING_NUMBER];
504 Staff* staff = score->staff(i);
505 Part* part = staff->part();
506
507 uchar c = readUChar(); // simulations bitmask
508 if (c & 0x2) { // 12 stringed guitar
509 }
510 if (c & 0x4) { // banjo track
511 }
512 if (i == 0 || version == 500)
513 skip(1);
514 QString name = readPascalString(40);
515
516 int strings = readInt();
517 if (strings <= 0 || strings > GP_MAX_STRING_NUMBER)
518 return false;
519 for (int j = 0; j < strings; ++j) {
520 tuning[j] = readInt();
521 }
522 for (int j = strings; j < GP_MAX_STRING_NUMBER; ++j)
523 readInt();
524 int midiPort = readInt() -1;
525 int midiChannel = readInt() - 1;
526 /*int midiChannel2 =*/ readInt(); // -1
527
528 int frets = readInt();
529 int capo = readInt();
530 /*int color =*/ readInt();
531
532 skip(version > 500 ? 49 : 44);
533 if (version > 500) {
534 // british stack clean / amp tone
535 readDelphiString();
536 readDelphiString();
537 }
538 std::vector<int> tuning2(strings);
539 //int tuning2[strings];
540 for (int k = 0; k < strings; ++k)
541 tuning2[strings-k-1] = tuning[k];
542 StringData stringData(frets, strings, &tuning2[0]);
543 createTuningString(strings, &tuning2[0]);
544 Instrument* instr = part->instrument();
545 instr->setStringData(stringData);
546 instr->setSingleNoteDynamics(false);
547 part->setPartName(name);
548 part->setPlainLongName(name);
549
550 //
551 // determine clef
552 //
553 int patch = channelDefaults[midiChannel].patch;
554 ClefType clefId = ClefType::G;
555 if (midiChannel == GP_DEFAULT_PERCUSSION_CHANNEL) {
556 clefId = ClefType::PERC;
557 // instr->setUseDrumset(DrumsetKind::GUITAR_PRO);
558 instr->setDrumset(gpDrumset);
559 staff->setStaffType(Fraction(0,1), *StaffType::preset(StaffTypes::PERC_DEFAULT));
560 }
561 else
562 clefId = defaultClef(patch);
563 Measure* measure = score->firstMeasure();
564 Clef* clef = new Clef(score);
565 clef->setClefType(clefId);
566 clef->setTrack(i * VOICES);
567 Segment* segment = measure->getSegment(SegmentType::HeaderClef, Fraction(0,1));
568 segment->add(clef);
569
570 if (capo > 0) {
571 Segment* s = measure->getSegment(SegmentType::ChordRest, measure->tick());
572 StaffText* st = new StaffText(score);
573 st->setPlainText(QString("Capo. fret ") + QString::number(capo));
574 st->setTrack(i * VOICES);
575 s->add(st);
576 }
577
578 Channel* ch = instr->channel(0);
579 if (midiChannel == GP_DEFAULT_PERCUSSION_CHANNEL) {
580 ch->setProgram(0);
581 ch->setBank(128);
582 }
583 else {
584 ch->setProgram(patch);
585 ch->setBank(0);
586 }
587 ch->setVolume(channelDefaults[midiChannel].volume);
588 ch->setPan(channelDefaults[midiChannel].pan);
589 ch->setChorus(channelDefaults[midiChannel].chorus);
590 ch->setReverb(channelDefaults[midiChannel].reverb);
591 staff->part()->setMidiChannel(midiChannel, midiPort);
592
593 //qDebug("default2: %d", channelDefaults[i].reverb);
594 // missing: phase, tremolo
595 }
596 skip(version == 500 ? 2 : 1);
597
598 return true;
599 }
600
601 //---------------------------------------------------------
602 // readMeasures
603 //---------------------------------------------------------
604
readMeasures(int)605 void GuitarPro5::readMeasures(int /*startingTempo*/)
606 {
607 Measure* measure = score->firstMeasure();
608 bool mixChange = false;
609 for (int bar = 0; bar < measures; ++bar, measure = measure->nextMeasure()) {
610 const GpBar& gpbar = bars[bar];
611
612 if (!gpbar.marker.isEmpty()) {
613 RehearsalMark* s = new RehearsalMark(score);
614 s->setPlainText(gpbar.marker.trimmed());
615 s->setTrack(0);
616 Segment* segment = measure->getSegment(SegmentType::ChordRest, measure->tick());
617 segment->add(s);
618 }
619
620 std::vector<Tuplet*> tuplets(staves * 2);
621 //Tuplet* tuplets[staves * 2]; // two voices
622 for (int track = 0; track < staves*2; ++track)
623 tuplets[track] = 0;
624
625 for (int staffIdx = 0; staffIdx < staves; ++staffIdx) {
626 _beat_counter = 0;
627 readMeasure(measure, staffIdx, &tuplets[0], mixChange);
628 if (!(((bar == (measures-1)) && (staffIdx == (staves-1))))) {
629 /*int a = */ readChar();
630 // qDebug(" ======skip %02x", a);
631 }
632 }
633 if (bar == 1 && !mixChange)
634 setTempo(tempo, score->firstMeasure());
635 }
636
637 if (gpLyrics.segments.size()) {
638 auto size = std::min(int(gpLyrics.segments.size()), int(gpLyrics.lyrics.size()));
639 for (int i = 0; i < size; ++i) {
640 std::string str = gpLyrics.lyrics[i].toUtf8().constData();
641 auto seg = gpLyrics.segments[i];
642 auto mes = seg->measure();
643 while (str.size() && seg && seg->segmentType() == SegmentType::ChordRest) {
644 auto cr = seg->cr(gpLyrics.lyricTrack);
645 if (cr) {
646 if (str[0] != '-') {
647 auto lyr = new Lyrics(score);
648
649 std::string text;
650 auto pos = str.find('-');
651 auto pos2 = str.find('\n');
652 if (pos2 < pos)
653 pos = pos2;
654 if (pos != std::string::npos) {
655 const char* c = &str.c_str()[pos + 1];
656 if (*c == 0) {
657 pos = std::string::npos;
658 text = str;
659 }
660 else {
661 text = str.substr(0, pos);
662 str = str.substr(pos + 1);
663 }
664 }
665 else
666 text = str;
667 if (pos == std::string::npos)
668 str.resize(0);
669 lyr->setPlainText(QString::fromUtf8(text.data(), int(text.size())));
670 cr->add(lyr);
671 }
672 else {
673 str = str.substr(1);
674 }
675 }
676 seg = seg->next();
677 if (!seg) {
678 mes = mes->nextMeasure();
679 if (!mes)
680 break;
681 seg = mes->first();
682 }
683 }
684 }
685 }
686 else {
687 int counter = 0;
688 // int index = 0;
689 //TODO-ws ??? gpLyrics.lyricTrack -= 1;
690 auto mes = score->firstMeasure();
691 auto beg = mes->first();
692
693 do {
694 if (beg->isChordRestType() && beg->cr(gpLyrics.lyricTrack)) {
695 ChordRest* cr = beg->cr(gpLyrics.lyricTrack);
696 ++counter;
697 if (!cr->isChord())
698 continue;
699 bool is_tied = false;
700 Chord* chord = toChord(cr);
701 for (auto n : chord->notes()) {
702 if (n->tiedNotes().size() > 1 && n->tiedNotes()[0] != n) {
703 is_tied = true;
704 break;
705 }
706 }
707 if (is_tied)
708 continue;
709 #if 0 // TODO-ws
710 if (counter >= gpLyrics.fromBeat) {
711 if (gpLyrics.lyrics[index][0] != '-') {
712 auto lyr = new Lyrics(score);
713
714 std::string text;
715 auto pos = gpLyrics.lyrics[index].find('-');
716 auto pos2 = gpLyrics.lyrics[index].find('\n');
717 if (pos2 < pos)
718 pos = pos2;
719 if (pos != std::string::npos) {
720 const char* c = &gpLyrics.lyrics[index].c_str()[pos + 1];
721 if (*c == 0) {
722 pos = std::string::npos;
723 text = gpLyrics.lyrics[index];
724 }
725 else {
726 text = gpLyrics.lyrics[index].substr(0, pos);
727 auto str = gpLyrics.lyrics[index].substr(pos + 1);
728 gpLyrics.lyrics[index] = str;
729 if (str.length())
730 gpLyrics.lyrics[index][0] = str[0];
731 }
732 }
733 else
734 text = gpLyrics.lyrics[index];
735 if (pos == std::string::npos)
736 ++index;
737 lyr->setPlainText(text);
738 cr->add(lyr);
739 if (index >= gpLyrics.lyrics.size())
740 break;
741 }
742 else {
743 //TODO: Need studio new release, bug here
744 std::string s = &gpLyrics.lyrics[index].c_str()[1];
745 gpLyrics.lyrics[index] = s;
746 if (s.length())
747 gpLyrics.lyrics[index][0] = s[0];
748 }
749 }
750 #endif
751 }
752 } while ((beg = beg->next()) || ((mes = toMeasure(mes->next())) && (beg = mes->first())));
753 }
754 }
755
756 //---------------------------------------------------------
757 // read
758 //---------------------------------------------------------
759
read(QFile * fp)760 bool GuitarPro5::read(QFile* fp)
761 {
762 f = fp;
763
764 readInfo();
765 readLyrics();
766 readPageSetup();
767
768 previousDynamic = -1;
769 previousTempo = -1;
770 //previousDynamic = new int [staves * VOICES];
771 // initialise the dynamics to 0
772 //for (int i = 0; i < staves * VOICES; i++)
773 // previousDynamic[i] = 0;
774
775 tempo = readInt();
776 if (version > 500)
777 skip(1);
778
779 key = readInt();
780 /* int octave =*/ readChar(); // octave
781
782 readChannels();
783
784 std::vector<unsigned int> articulations;
785 articulations.resize(19);
786 {
787 unsigned int r; unsigned char x;
788 for (int i = 0; i < 19; ++i) {
789 x = readUChar();
790 r = x;
791 x = readUChar();
792 r += x << 8;
793
794 articulations[i] = r;
795 }
796 }
797
798 //skip(42);
799 skip(4);
800
801 measures = readInt();
802 staves = readInt();
803
804 for (int str = 0; str < 7; ++str) {
805 for (int staff = 0; staff < staves; ++staff)
806 dead_end[{staff, str}] = true;
807 }
808
809 slurs = new Slur*[staves];
810 for (int i = 0; i < staves; ++i)
811 slurs[i] = 0;
812
813 int tnumerator = 4;
814 int tdenominator = 4;
815 for (int i = 0; i < measures; ++i) {
816 if (i > 0)
817 skip(1);
818 GpBar bar;
819 uchar barBits = readUChar();
820 if (barBits & SCORE_TIMESIG_NUMERATOR)
821 tnumerator = readUChar();
822 if (barBits & SCORE_TIMESIG_DENOMINATOR)
823 tdenominator = readUChar();
824 if (barBits & SCORE_REPEAT_START)
825 bar.repeatFlags = bar.repeatFlags | Repeat::START;
826 if (barBits & SCORE_REPEAT_END) { // number of repeats
827 bar.repeatFlags = bar.repeatFlags |Repeat::END;
828 bar.repeats = readUChar();
829 }
830 if (barBits & SCORE_MARKER) {
831 bar.marker = readDelphiString(); // new section?
832 /*int color =*/ readInt(); // color?
833 }
834 if (barBits & SCORE_VOLTA) { // a volta
835 uchar voltaNumber = readUChar();
836 while (voltaNumber > 0) {
837 // voltas are represented as flags
838 bar.volta.voltaType = GP_VOLTA_FLAGS;
839 bar.volta.voltaInfo.append(voltaNumber & 1);
840 voltaNumber >>= 1;
841 }
842 }
843 if (barBits & SCORE_KEYSIG) {
844 int currentKey = readUChar();
845 /* key signatures are specified as
846 * 1# = 1, 2# = 2, ..., 7# = 7
847 * 1b = 255, 2b = 254, ... 7b = 249 */
848 bar.keysig = currentKey <= 7 ? currentKey : -256+currentKey;
849 readUChar(); // specified major/minor mode
850 }
851 if (barBits & SCORE_DOUBLE_BAR)
852 bar.barLine = BarLineType::DOUBLE;
853 if (barBits & 0x3) {
854 skip(4);
855 }
856 if ((barBits & 0x10) == 0) {
857 skip(1);
858 }
859
860 readChar(); // triple feel (none, 8, 16)
861 bar.timesig = Fraction(tnumerator, tdenominator);
862 bars.append(bar);
863 }
864
865 //
866 // create a part for every staff
867 //
868 for (int staffIdx = 0; staffIdx < staves; ++staffIdx) {
869 Part* part = new Part(score);
870 Staff* s = new Staff(score);
871 s->setPart(part);
872 part->insertStaff(s, -1);
873 score->staves().push_back(s);
874 score->appendPart(part);
875 }
876
877 createMeasures();
878 if (!readTracks()) {
879 return false;
880 }
881 readMeasures(tempo);
882 for (auto n : slideList) {
883 // Note* next = nullptr;
884 auto segment = n->chord()->segment();
885 auto measure = segment->measure();
886 while ((segment = segment->next1(SegmentType::ChordRest)) || ((measure = measure->nextMeasure() ) && (segment = measure->first()))) {
887 if (segment->segmentType() != SegmentType::ChordRest)
888 continue;
889 bool br = false;
890 ChordRest* cr = toChordRest(segment->cr(n->track()));
891 if (cr && cr->isChord()) {
892 Chord* c = toChord(cr);
893 for (auto nt : c->notes()) {
894 if (nt->string() == n->string()) {
895 for (auto e : nt->el())
896 if (e->isChordLine()) {
897 ChordLine* cl = toChordLine(e);
898 if (cl->chordLineType() == ChordLineType::PLOP || cl->chordLineType() == ChordLineType::SCOOP) {
899 br = true;
900 break;
901 }
902 }
903 if (br)
904 break;
905 Glissando* s = new Glissando(score);
906 s->setAnchor(Spanner::Anchor::NOTE);
907 s->setStartElement(n);
908 s->setTick(n->chord()->segment()->tick());
909 s->setTrack(n->track());
910 s->setParent(n);
911 s->setGlissandoType(GlissandoType::STRAIGHT);
912 s->setEndElement(nt);
913 s->setTick2(nt->chord()->segment()->tick());
914 s->setTrack2(n->track());
915 score->addElement(s);
916 br = true;
917 break;
918 }
919 }
920 }
921 if (br)
922 break;
923 }
924 }
925
926 std::map<int, int> counter;
927 for (int i = 0; i < 19; ++i) {
928 if (articulations[i] != 0xFFFF) {
929 Measure* measure = toMeasure(score->measure(articulations[i] - 1));
930 if (i < 4) {
931 Segment* segment = measure->getSegment(SegmentType::BarLine, measure->tick());
932 Symbol* sym = new Symbol(score);
933 if (i == 0)
934 sym->setSym(SymId::coda);
935 else if (i == 1) {
936 #if 0
937 sym->setSym(SymId::coda);
938 Symbol* s2 = new Symbol(score);
939 s2->setSym(SymId::coda);
940 s2->setXoffset(5.5f);
941 auto iter = counter.find(articulations[i]);
942 if (iter != counter.end())
943 s2->setElYOffset(-7.0f * iter->second);
944 s2->setParent(measure);
945 s2->setTrack(0);
946 segment->add(s2);
947 #endif
948 sym->setSym(SymId::codaSquare);
949 }
950 else if (i == 2)
951 sym->setSym(SymId::segno);
952 else {
953 #if 0
954 sym->setSym(SymId::segno);
955 Symbol* s2 = new Symbol(score);
956 s2->setSym(SymId::segno);
957 s2->setXoffset(5.5f);
958 auto iter = counter.find(articulations[i]);
959 if (iter != counter.end())
960 s2->setElYOffset(-7.0f * iter->second);
961 s2->setParent(measure);
962 s2->setTrack(0);
963 segment->add(s2);
964 #endif
965 sym->setSym(SymId::segnoSerpent2);
966 }
967
968
969 sym->setParent(measure);
970 sym->setTrack(0);
971 segment->add(sym);
972 auto iter = counter.find(articulations[i]);
973 if (iter == counter.end())
974 counter[articulations[i]] = 1;
975 else {
976 //TODO-ws sym->setElYOffset(-7.0f * counter[articulations[i]]);
977 counter[articulations[i]] += 1;
978 }
979 }
980 else {
981 Segment* s = measure->getSegment(SegmentType::KeySig, measure->tick());
982 StaffText* st = new StaffText(score);
983 static constexpr char text[][22] = {
984 "fine", "Da Capo", "D.C. al Coda", "D.C. al Double Coda",
985 "D.C. al Fine", "Da Segno", "D.S. al Coda", "D.S. al Double Coda",
986 "D.S. al Fine", "Da Segno Segno", "D.S.S. al Coda", "D.S.S. al Double Coda",
987 "D.S.S. al Fine", "Da Coda", "Da Double Coda"
988 };
989 st->setPlainText(text[i - 4]);
990 st->setParent(s);
991 st->setTrack(0);
992 //TODO-ws st->_measureEnd = true;
993 auto iter = counter.find(articulations[i]);
994 if (iter == counter.end())
995 counter[articulations[i]] = 1;
996 else {
997 //TODO-ws st->setElYOffset(-7.0f * counter[articulations[i]]);
998 counter[articulations[i]] += 1;
999 }
1000 score->addElement(st);
1001 }
1002 }
1003 }
1004 return true;
1005 }
1006
1007 //---------------------------------------------------------
1008 // readNoteEffects
1009 //---------------------------------------------------------
1010
readNoteEffects(Note * note)1011 bool GuitarPro5::readNoteEffects(Note* note)
1012 {
1013 uchar modMask1 = readUChar();
1014 uchar modMask2 = readUChar();
1015 bool slur = false;
1016
1017 if (modMask1 & EFFECT_BEND) {
1018 readBend(note);
1019 }
1020 if (modMask1 & EFFECT_HAMMER) {
1021 slur = true;
1022 #if 0
1023 Symbol* s = new Symbol(score);
1024 s->setSym(SymId::articLaissezVibrerBelow);
1025 s->setParent(note);
1026 note->add(s);
1027 #endif
1028 }
1029 if (modMask1 & EFFECT_LET_RING)
1030 addLetRing(note);
1031 //note->setLetRing(true);
1032
1033 if (modMask1 & EFFECT_GRACE) {
1034 int fret = readUChar(); // grace fret
1035 /*int dynamic =*/ readUChar(); // grace dynamic
1036 int transition = readUChar(); // grace transition
1037 /*int duration =*/ readUChar(); // grace duration
1038 int gflags = readUChar();
1039
1040 NoteType note_type = NoteType::ACCIACCATURA;
1041
1042 if (gflags & NOTE_APPOGIATURA) //on beat
1043 note_type = NoteType::APPOGGIATURA;
1044
1045 #if 0
1046 int grace_len = MScore::division/8;
1047 if (duration == 1)
1048 grace_len = MScore::division/8; //32th
1049 else if (duration == 2)
1050 grace_len = MScore::division/6; //24th
1051 else if (duration == 3)
1052 grace_len = MScore::division/4; //16th
1053 Note* gn = new Note(score);
1054
1055 if (gflags & EFFECT_GHOST) {
1056 gn->setHeadGroup(NoteHead::Group::HEAD_CROSS);
1057 gn->setGhost(true);
1058 }
1059 gn->setFret(fret);
1060 gn->setString(note->string());
1061 #endif
1062 int grace_pitch = note->staff()->part()->instrument()->stringData()->getPitch(note->string(), fret, nullptr, Fraction(0,1));
1063 #if 0
1064 gn->setPitch(grace_pitch);
1065 gn->setTpcFromPitch();
1066
1067 Chord* gc = new Chord(score);
1068 gc->setTrack(note->chord()->track());
1069 gc->add(gn);
1070 gc->setParent(note->chord());
1071
1072 TDuration d;
1073 d.setVal(grace_len);
1074 if (grace_len == MScore::division/6)
1075 d.setDots(1);
1076 gc->setDurationType(d);
1077 gc->setTicks(d.fraction());
1078 gc->setNoteType(note_type);
1079 gc->setMag(note->chord()->staff()->mag(0) * score->styleD(Sid::graceNoteMag));
1080 note->chord()->add(gc);
1081 addDynamic(gn, dynamic);
1082 #endif
1083 auto gnote = score->setGraceNote(note->chord(), grace_pitch, note_type, MScore::division / 2);
1084 gnote->setString(note->string());
1085 auto sd = note->part()->instrument()->stringData();
1086 gnote->setFret(grace_pitch - sd->stringList().at(sd->stringList().size() - note->string() - 1).pitch);
1087 if (transition == 0) {
1088 // no transition
1089 }
1090 else if (transition == 1) {
1091 }
1092 else if (transition == 3) {
1093 Slur* slur1 = new Slur(score);
1094 slur1->setAnchor(Spanner::Anchor::CHORD);
1095 slur1->setStartElement(gnote->chord());
1096 slur1->setEndElement(note->chord());
1097 slur1->setParent(0);
1098 slur1->setTrack(note->staffIdx());
1099 slur1->setTrack2(note->staffIdx());
1100 slur1->setTick(gnote->chord()->tick());
1101 slur1->setTick2(note->chord()->tick());
1102 //TODO-ws note->chord()->has_slur = true;
1103 score->addElement(slur1);
1104 //TODO: Add a 'slide' guitar effect when implemented
1105 //note->setSlideNote(gn);
1106 }
1107 #if 0
1108 else if (transition == 2 && note->fret()>=0 && note->fret()<=255 && note->fret()!=gn->fret()) {
1109 QList<PitchValue> points;
1110 points.append(PitchValue(0,0, false));
1111 points.append(PitchValue(60,(note->fret()-gn->fret())*100, false));
1112
1113 Bend* b = new Bend(note->score());
1114 b->setPoints(points);
1115 b->setTrack(gn->track());
1116 gn->add(b);
1117 }
1118 else if (transition == 3) {
1119 // TODO:
1120 // major: replace with a 'hammer-on' guitar effect when implemented
1121 // minor: make slurs for parts
1122
1123 ChordRest* cr1 = toChord(gc);
1124 ChordRest* cr2 = toChord(note->chord());
1125
1126 Slur* slur = new Slur(score);
1127 slur->setAnchor(Spanner::Anchor::CHORD);
1128 slur->setStartElement(cr1);
1129 slur->setEndElement(cr2);
1130 slur->setTick(cr1->tick());
1131 slur->setTick2(cr2->tick());
1132 slur->setTrack(cr1->track());
1133 slur->setTrack2(cr2->track());
1134 // this case specifies only two-note slurs, don't set a parent
1135 score->undoAddElement(slur);
1136 }
1137 #endif
1138 }
1139 if (modMask2 & EFFECT_STACATTO) {
1140 Chord* chord = note->chord();
1141 Articulation* a = new Articulation(chord->score());
1142 a->setSymId(SymId::articStaccatoAbove);
1143 bool add = true;
1144 for (auto a1 : chord->articulations()) {
1145 if (a1->symId() == SymId::articStaccatoAbove) {
1146 add = false;
1147 break;
1148 }
1149 }
1150 if (add)
1151 chord->add(a);
1152 }
1153 if (modMask2 & EFFECT_PALM_MUTE)
1154 addPalmMute(note);
1155 //note->setPalmMute(true);
1156
1157 if (modMask2 & EFFECT_TREMOLO) { // tremolo picking length
1158 int tremoloDivision = readUChar();
1159 Chord* chord = note->chord();
1160 Tremolo* t = new Tremolo(score);
1161 if (tremoloDivision == 1) {
1162 t->setTremoloType(TremoloType::R8);
1163 chord->add(t);
1164 }
1165 else if (tremoloDivision == 2) {
1166 t->setTremoloType(TremoloType::R16);
1167 chord->add(t);
1168 }
1169 else if (tremoloDivision == 3) {
1170 t->setTremoloType(TremoloType::R32);
1171 chord->add(t);
1172 }
1173 else
1174 qDebug("Unknown tremolo value");
1175 }
1176 // bool skip = false;
1177 if (modMask2 & EFFECT_SLIDE) {
1178 int slideKind = readUChar();
1179 if (slideKind & SLIDE_OUT_DOWN) {
1180 slideKind &= ~SLIDE_OUT_DOWN;
1181 ChordLine* cl = new ChordLine(score);
1182 cl->setChordLineType(ChordLineType::FALL);
1183 cl->setStraight(true);
1184 note->add(cl);
1185 // skip = true;
1186 }
1187 // slide out upwards (doit)
1188 if (slideKind & SLIDE_OUT_UP) {
1189 slideKind &= ~SLIDE_OUT_UP;
1190 ChordLine* cl = new ChordLine(score);
1191 cl->setChordLineType(ChordLineType::DOIT);
1192 cl->setStraight(true);
1193 note->add(cl);
1194 // skip = true;
1195 }
1196 // slide in from below (plop)
1197 if (slideKind & SLIDE_IN_BELOW) {
1198 slideKind &= ~SLIDE_IN_BELOW;
1199 ChordLine* cl = new ChordLine(score);
1200 cl->setChordLineType(ChordLineType::PLOP);
1201 cl->setStraight(true);
1202 note->add(cl);
1203 // skip = true;
1204 }
1205 // slide in from above (scoop)
1206 if (slideKind & SLIDE_IN_ABOVE) {
1207 slideKind &= ~SLIDE_IN_ABOVE;
1208 ChordLine* cl = new ChordLine(score);
1209 cl->setChordLineType(ChordLineType::SCOOP);
1210 cl->setStraight(true);
1211 note->add(cl);
1212 // skip = true;
1213 }
1214
1215 if (false && !slideList.empty() && slideList.back()->chord()->segment() != note->chord()->segment()) {
1216 Note* start = slideList.front();
1217 slideList.pop_front();
1218 bool skip = false;
1219 for (auto e : start->el()) {
1220 if (e->isChordLine())
1221 skip = true;
1222 }
1223 if (!skip) {
1224 Glissando* s = new Glissando(score);
1225 s->setAnchor(Spanner::Anchor::NOTE);
1226 s->setStartElement(start);
1227 s->setTick(start->chord()->segment()->tick());
1228 s->setTrack(start->staffIdx());
1229 s->setParent(start);
1230 s->setGlissandoType(GlissandoType::STRAIGHT);
1231 s->setEndElement(note);
1232 s->setTick2(note->chord()->segment()->tick());
1233 s->setTrack2(note->staffIdx());
1234 score->addElement(s);
1235 }
1236 }
1237 if (slideKind & LEGATO_SLIDE) {
1238 slideKind &= ~LEGATO_SLIDE;
1239 slideList.push_back(nullptr);
1240 createSlur(true, note->staffIdx(), note->chord());
1241 }
1242 if (slideKind & SHIFT_SLIDE) {
1243 slideKind &= ~SHIFT_SLIDE;
1244 slideList.push_back(note);
1245 }
1246 #if 0
1247 if (slideKind)
1248 int k = 1;
1249 if (slideKind > 4)
1250 int k = 1;
1251 // if slide >= 4 then we are not dealing with legato slide nor shift slide
1252 if (slideKind >= 4)
1253 slide = slideKind;
1254 else
1255 slides[note->chord()->track()] = slideKind;
1256 #endif
1257 }
1258
1259 if (modMask2 & EFFECT_ARTIFICIAL_HARMONIC) {
1260 int type = readArtificialHarmonic();
1261 if (type == 2) {
1262 auto harmNote = readUChar();
1263 /*auto sharp =*/ readChar();
1264 auto octave = readUChar();
1265
1266 auto harmonicNote = new Note(score);
1267 //TODO-ws harmonicNote->setHarmonic(true);
1268 note->chord()->add(harmonicNote);
1269 auto staff = note->staff();
1270 // int string = staff->part()->instrument()->stringData()->strings() - 1 - note->string();
1271 int fret = note->fret();
1272 switch (harmNote) {
1273 case 0: fret += 24; break;
1274 case 2: fret += 34; break;
1275 case 4: fret += 38; break;
1276 case 5: fret += 12; break;
1277 case 7: fret += 32; break;
1278 case 9: fret += 28; break;
1279 default: fret += octave * 12;
1280 }
1281 harmonicNote->setString(note->string());
1282 harmonicNote->setFret(fret);
1283 harmonicNote->setPitch(staff->part()->instrument()->stringData()->getPitch(note->string(), fret, nullptr, Fraction(0,1)));
1284 harmonicNote->setTpcFromPitch();
1285 addTextToNote("A.H.", Align::CENTER, harmonicNote);
1286 }
1287 if (type == 1 || type == 4 || type == 5) {
1288 //TextStyle textStyle;
1289 //textStyle.setAlign(Align::CENTER);
1290 //addTextToNote("N.H.", textStyle, note);
1291 //TODO-ws note->setHarmonic(true);
1292 }
1293 }
1294
1295 if (modMask2 & 0x40)
1296 addVibrato(note);
1297
1298 if (modMask2 & EFFECT_TRILL) {
1299 //TODO-ws note->setTrillFret(readUChar()); // trill fret
1300 readUChar(); // trill fret
1301
1302 int period = readUChar(); // trill length
1303
1304 // add the trill articulation to the note
1305 Articulation* art = new Articulation(note->score());
1306 art->setSymId(SymId::ornamentTrill);
1307 if (!note->score()->addArticulation(note, art))
1308 delete art;
1309
1310 switch(period) {
1311 case 1: // 16
1312 break;
1313 case 2: // 32
1314 break;
1315 case 3: // 64
1316 break;
1317 default:
1318 qDebug("unknown trill period %d", period);
1319 break;
1320 }
1321 }
1322 return slur;
1323 }
1324
1325 //---------------------------------------------------------
1326 // readNote
1327 //---------------------------------------------------------
1328
readNote(int string,Note * note)1329 bool GuitarPro5::readNote(int string, Note* note)
1330 {
1331 uchar noteBits = readUChar();
1332 //
1333 // noteBits:
1334 // 7 - Right hand or left hand fingering;
1335 // 6 - Accentuated note
1336 // 5 - Note type (rest, empty note, normal note);
1337 // 4 - note dynamic;
1338 // 3 - Presence of effects linked to the note;
1339 // 2 - Ghost note;
1340 // 1 - Dotted note; ?
1341 // 0 - Time-independent duration
1342
1343 if (noteBits & NOTE_GHOST) {
1344 note->setHeadGroup(NoteHead::Group::HEAD_CROSS);
1345 note->setGhost(true);
1346 }
1347
1348 bool tieNote = false;
1349
1350 if (noteBits & NOTE_DEAD) {
1351 uchar noteType = readUChar();
1352 if (noteType == 1) {} //standard note
1353 else if (noteType == 2) {
1354 tieNote = true;
1355 }
1356 else if (noteType == 3) { // dead notes
1357 note->setHeadGroup(NoteHead::Group::HEAD_CROSS);
1358 note->setGhost(true);
1359 }
1360 else
1361 qDebug("unknown note type: %d", noteType);
1362 }
1363
1364 if (noteBits & NOTE_DYNAMIC) { // velocity
1365 int d = readChar();
1366 if (previousDynamic != d) {
1367 previousDynamic = d;
1368 addDynamic(note, d);
1369 }
1370 }
1371
1372 int fretNumber = 0;
1373 if (noteBits & NOTE_FRET) {
1374 fretNumber = readChar();
1375 }
1376
1377 if (noteBits & NOTE_FINGERING) {
1378 int leftFinger = readUChar();
1379 int rightFinger = readUChar();
1380 Fingering* fi = new Fingering(score);
1381 QString finger;
1382 // if there is a valid left hand fingering
1383 if (leftFinger < 5) {
1384 if (leftFinger == 0)
1385 finger = "T";
1386 else if (leftFinger == 1)
1387 finger = "1";
1388 else if (leftFinger == 2)
1389 finger = "2";
1390 else if (leftFinger == 3)
1391 finger = "3";
1392 else if (leftFinger == 4)
1393 finger = "4";
1394 }
1395 else {
1396 if (rightFinger == 0)
1397 finger = "T";
1398 else if (rightFinger == 1)
1399 finger = "I";
1400 else if (rightFinger == 2)
1401 finger = "M";
1402 else if (rightFinger == 3)
1403 finger = "A";
1404 else if (rightFinger == 4)
1405 finger = "O";
1406 }
1407 fi->setPlainText(finger);
1408 note->add(fi);
1409 fi->reset();
1410 }
1411
1412 if (noteBits & 0x1) // Time independent duration
1413 skip(8);
1414
1415 // check if a note is supposed to be accented, and give it the marcato type
1416 if (noteBits & NOTE_MARCATO) {
1417 Articulation* art = new Articulation(note->score());
1418 art->setSymId(SymId::articMarcatoAbove);
1419 if (!note->score()->addArticulation(note, art))
1420 delete art;
1421 }
1422
1423 // check if a note is supposed to be accented, and give it the sforzato type
1424 if (noteBits & NOTE_SFORZATO) {
1425 Articulation* art = new Articulation(note->score());
1426 art->setSymId(SymId::articAccentAbove);
1427 note->add(art);
1428 // if (!note->score()->addArticulation(note, art))
1429 // delete art;
1430 }
1431
1432 readUChar(); //skip
1433
1434 Staff* staff = note->staff();
1435 if (fretNumber == 255 || fretNumber < 0) {
1436 fretNumber = 0;
1437 note->setHeadGroup(NoteHead::Group::HEAD_CROSS);
1438 note->setGhost(true);
1439 }
1440 int pitch = staff->part()->instrument()->stringData()->getPitch(string, fretNumber, nullptr, Fraction(0,1));
1441 note->setFret(fretNumber);
1442 note->setString(string);
1443 note->setPitch(pitch);
1444
1445 // This function uses string and fret number, so it should be set before this
1446 bool slur = false;
1447 if (noteBits & NOTE_SLUR) {
1448 slur = readNoteEffects(note);
1449 }
1450
1451 if (tieNote) {
1452 auto staffIdx = note->staffIdx();
1453 if (dead_end[{staffIdx, string}]) {
1454 note->setFret(-20);
1455 return false;
1456 }
1457 if (slurs[staffIdx]) {
1458 score->removeSpanner(slurs[staffIdx]);
1459 delete slurs[staffIdx];
1460 slurs[staffIdx] = 0;
1461 }
1462 bool found = false;
1463 Chord* chord = note->chord();
1464 Segment* segment = chord->segment()->prev1(SegmentType::ChordRest);
1465 int track = note->track();
1466 std::vector<ChordRest*> chords;
1467 Note* true_note = nullptr;
1468 while (segment) {
1469 Element* e = segment->element(track);
1470 if (e) {
1471 if (e->isChord()) {
1472 Chord* chord2 = toChord(e);
1473 foreach (Note* note2, chord2->notes()) {
1474 if (note2->string() == string) {
1475 if (chords.empty()) {
1476 Tie* tie = new Tie(score);
1477 tie->setEndNote(note);
1478 note2->add(tie);
1479 }
1480 note->setFret(note2->fret());
1481 note->setPitch(note2->pitch());
1482 true_note = note2;
1483 found = true;
1484 break;
1485 }
1486 }
1487 }
1488 if (found)
1489 break;
1490 else {
1491 if (e)
1492 chords.push_back(toChordRest(e));
1493 }
1494 }
1495 segment = segment->prev1(SegmentType::ChordRest);
1496 }
1497 if (true_note && chords.size()) {
1498 Note* end_note = note;
1499 for (unsigned int i = 0; i < chords.size(); ++i) {
1500 Chord* chord1 = nullptr;
1501 auto cr = chords.at(i);
1502 if (cr->isChord())
1503 chord1 = toChord(cr);
1504 else {
1505 auto rest = toRest(cr);
1506 auto dur = rest->ticks();
1507 auto dut = rest->durationType();
1508 auto seg = rest->segment();
1509 seg->remove(rest);
1510 auto tuplet = rest->tuplet();
1511 if (tuplet)
1512 tuplet->remove(rest);
1513 delete rest;
1514 chord1 = new Chord(score);
1515 chord1->setTrack(note->track());
1516 chord1->setTicks(dur);
1517 chord1->setDurationType(dut);
1518 seg->add(chord1);
1519 if (tuplet)
1520 tuplet->add(chord1);
1521 }
1522
1523 Note* note2 = new Note(score);
1524 note2->setString(true_note->string());
1525 note2->setFret(true_note->fret());
1526 note2->setPitch(true_note->pitch());
1527 note2->setTpcFromPitch();
1528 chord1->setNoteType(true_note->noteType());
1529 chord1->add(note2);
1530 Tie* tie = new Tie(score);
1531 tie->setEndNote(end_note);
1532 //TODO-ws end_note->setHarmonic(true_note->harmonic());
1533 end_note = note2;
1534 note2->add(tie);
1535 }
1536 Tie* tie = new Tie(score);
1537 tie->setEndNote(end_note);
1538 //TODO-ws end_note->setHarmonic(true_note->harmonic());
1539 true_note->add(tie);
1540 }
1541 if (!found) {
1542 note->setFret(-20);
1543 dead_end[{staffIdx, string}] = true;
1544 qDebug("tied note not found, pitch %d fret %d string %d", note->pitch(), note->fret(), note->string());
1545 return false;
1546 }
1547 }
1548 dead_end[{note->staffIdx(), string}] = false;
1549 return slur;
1550 }
1551
1552 //---------------------------------------------------------
1553 // readArtificialHarmonic
1554 //---------------------------------------------------------
1555
readArtificialHarmonic()1556 int GuitarPro5::readArtificialHarmonic()
1557 {
1558 int type = readChar();
1559 switch(type) {
1560 case 1: // natural
1561 break;
1562 case 2: // artificial
1563 //skip(3);
1564 break;
1565 case 3: // tapped
1566 skip(1);
1567 break;
1568 case 4: // pinch
1569 break;
1570 case 5: // semi
1571 break;
1572 }
1573 return type;
1574 }
1575
1576 }
1577