1 #include "importptb.h"
2 #include "assert.h"
3
4 #include <libmscore/part.h>
5 #include <libmscore/staff.h>
6 #include <libmscore/measure.h>
7 #include <libmscore/symbol.h>
8 #include <libmscore/tie.h>
9 #include <libmscore/bend.h>
10 #include <libmscore/timesig.h>
11 #include <libmscore/sym.h>
12 #include <libmscore/articulation.h>
13 #include <libmscore/tuplet.h>
14 #include <libmscore/instrument.h>
15 #include <libmscore/clef.h>
16 #include <libmscore/rest.h>
17 #include <libmscore/stafftext.h>
18 #include <libmscore/chord.h>
19 #include <libmscore/tempotext.h>
20 #include <libmscore/excerpt.h>
21 #include <libmscore/rehearsalmark.h>
22 #include <libmscore/bracketItem.h>
23 #include <libmscore/box.h>
24 #include <libmscore/palmmute.h>
25
26 namespace Ms {
27
readBoolean()28 bool PowerTab::readBoolean()
29 {
30 return readUChar() != 0;
31 }
32
readUChar()33 unsigned char PowerTab::readUChar()
34 {
35 unsigned char byte;
36 _file->read((char*)&byte, 1);
37 return byte;
38 }
39
readShort()40 unsigned short PowerTab::readShort()
41 {
42 uint16_t val;
43 _file->read((char*)&val, 2);
44 return val;
45 }
46
readChar()47 char PowerTab::readChar()
48 {
49 char byte;
50 _file->read(&byte, 1);
51 return byte;
52 }
53
54
readInt()55 int PowerTab::readInt()
56 {
57 int32_t val;
58 _file->read((char*)&val, 4);
59 return val;
60 }
61
readString(int length)62 std::string PowerTab::readString(int length)
63 {
64 if (length == -1) {
65 length = readUChar();
66 if (length == 0xFF)
67 length = readShort();
68 }
69 char* p = new char[length];
70 _file->read(p, length);
71
72 std::string s(p, length);
73 delete[] p;
74 return s;
75 }
76
readVersion()77 bool PowerTab::readVersion()
78 {
79 std::string version = readString(4);
80 version += std::string("-") + std::to_string(readShort());
81 return version == "ptab-4";
82 }
83
skip(int len)84 void PowerTab::skip(int len /* = 1 */)
85 {
86 for (int i = 0; i < len; ++i)
87 readChar();
88 }
89
readSongInfo(ptSongInfo & info)90 void PowerTab::readSongInfo(ptSongInfo& info)
91 {
92 auto classification = readChar();
93 info.classification = classification;
94 if (classification == 0) {
95 skip(1);
96 info.name = readString();
97 info.interpret = readString();
98
99 auto releaseType = readChar();
100
101 switch (releaseType) {
102 case 0: {
103 /*auto albumType =*/ readChar();
104 info.album = readString();
105 info.year = readShort();
106 info.liverecording = readChar() != 0;
107 break;
108 }
109 case 1: {
110 info.album = readString();
111 info.liverecording = readChar() != 0;
112 break;
113 }
114 case 2: {
115 info.album = readString();
116 info.day = readShort();
117 info.month = readShort();
118 info.year = readShort();
119 break;
120 }
121 default:
122 assert(0);
123 }
124
125 if (readChar() == 0) {
126 info.author = readString();
127 info.lyricist = readString();
128 }
129
130 info.arrenger = readString();
131 info.guitarTranscriber = readString();
132 info.bassTranscriber = readString();
133 info.copyright = readString();
134
135 info.lyrics = readString();
136
137 info.guitarInstructions = readString();
138 info.bassInstructions = readString();
139
140 }
141 else if (classification == 1) {
142 info.name = readString();
143 info.album = readString();
144 info.style = readShort();
145 info.level = readUChar();
146 info.author = readString();
147 info.instructions = readString();
148 info.copyright = readString();
149 }
150 }
151
readHeaderItems()152 int PowerTab::readHeaderItems()
153 {
154 int itemCount = readShort();
155 if (itemCount != 0) {
156 int header = readShort();
157 if (header == 0xFFFF) {
158 if (readShort() != 1) {
159 return -1;
160 }
161 auto str = readString(readShort()); //section title
162 }
163 }
164 return itemCount;
165 }
166
readTrackInfo(ptTrack & info)167 void PowerTab::readTrackInfo(ptTrack& info)
168 {
169 TrackInfo tr;
170
171 tr.number = readUChar();
172 tr.name = readString();
173 tr.instrument = readUChar();
174 tr.volume = readUChar();
175 tr.balance = readUChar();
176 tr.reverb = readUChar();
177 tr.chorus = readUChar();
178 tr.tremolo = readUChar();
179 tr.phaser = readUChar();
180 tr.capo = readUChar();
181 tr.tuningName = readString();
182 tr.offset = readUChar();
183
184 int ln = readUChar();
185 for (int i = 0; i < ln; ++i)
186 tr.strings.push_back(readUChar());
187 info.infos.push_back(tr);
188 }
189
readChord(ptTrack & info)190 void PowerTab::readChord(ptTrack& info)
191 {
192 ptChord ch;
193 ch.key = readShort(); //chord key
194 ch.formula = readUChar();
195 ch.modification = readShort(); //Chord Modification
196 ch.extra = readUChar();
197 ch.top_fret = readUChar();
198 auto stringCount = readUChar();
199 for (int i = 0; i < stringCount; ++i) {
200 ch.frets.push_back(readUChar()); // fret
201 }
202 if (info.diagramMap.find({ {ch.key, ch.formula, ch.modification} }) == info.diagramMap.end())
203 info.diagramMap[ { {ch.key, ch.formula, ch.modification} }] = ch;
204 else {
205 auto a1 = info.diagramMap[ { {ch.key, ch.formula, ch.modification} }];
206 auto a2 = ch;
207
208 //?? int k = 1;
209 }
210 }
211
readFontSettings()212 void PowerTab::readFontSettings()
213 {
214 readString(); //font name
215 readInt(); // point size
216 readInt(); // weight
217 readBoolean(); //italic
218 readBoolean(); //underline
219 readBoolean(); //strikeout
220 readInt(); //color
221 }
222
readFloatingText()223 void PowerTab::readFloatingText()
224 {
225 readString(); //text
226 //rect :
227 readInt(); // left
228 readInt(); // top
229 readInt(); // right
230 readInt(); // bottom
231
232 readUChar();
233 readFontSettings();
234 }
235
readDynamic()236 void PowerTab::readDynamic()
237 {
238 readShort();
239 readUChar();
240 readUChar();
241 readShort();
242 }
243
readKeySignature()244 void PowerTab::readKeySignature()
245 {
246 readUChar();
247 }
248
readRehearsalSign(ptSection & sec)249 void PowerTab::readRehearsalSign(ptSection& sec)
250 {
251 auto c = readChar();
252 auto str = readString();
253 if (str.size()) {
254 sec.partName = str;
255 sec.partMarker = c;
256 }
257 }
258
readChordText(ptSection & sec)259 void PowerTab::readChordText(ptSection& sec)
260 {
261 ptChordText cht;
262 cht.position = readUChar();
263 cht.key = readShort();
264 cht.formula = readUChar();
265 cht.formula_mod = readShort();
266 cht.extra = readUChar();
267 //sec.chordTextMap.push_back(cht);
268 sec.chordTextMap.insert({ cht.position, cht });
269 }
270
readRhytmSlash(ptSection & sec)271 void PowerTab::readRhytmSlash(ptSection& sec)
272 {
273 stRhytmSlash rs;
274 rs.position = readUChar();
275 auto beaming = readUChar();
276 auto data = readInt();
277 auto duration = (data & 0xE00000) >> 21;
278 switch (duration) {
279 case 0:
280 rs.duration = 1;
281 break;
282 case 1:
283 rs.duration = 2;
284 break;
285 case 2:
286 rs.duration = 4;
287 break;
288 case 3:
289 rs.duration = 8;
290 break;
291 case 4:
292 rs.duration = 16;
293 }
294
295 rs.triplet = beaming & (0x20 | 0x40);
296 rs.tripletend = beaming & 0x80;
297
298 rs.dotted = data & 0x01;
299 rs.doubleDotted = data & 0x02;
300
301 rs.is_rest = data & 0x04;
302
303 sec.rhytm.emplace_back(rs);
304 }
305
readGuitarIn(ptTrack & info)306 void PowerTab::readGuitarIn(ptTrack& info)
307 {
308 ptGuitarIn gin;
309 gin.section = readShort();
310 gin.staff = readUChar() + staffInc;
311 gin.position = readUChar();
312 gin.rhytmSlash = readUChar();
313 gin.trackinfo = readUChar();
314 info.guitar_ins.push_back(gin);
315 //info.getSection(section).getPosition(position).addComponent(new ptGuitarIn(staff, inf));
316 }
317
readTempoMarker(ptTrack & info)318 void PowerTab::readTempoMarker(ptTrack& info)
319 {
320 auto section = readShort();
321 /*auto position =*/ readUChar();
322 auto tempo = readShort();
323 /*auto data =*/ readShort();
324 readString(); //description
325
326 #if 0 // TODO-ws
327 int tripletFeel = 0;
328 if (data & 0x01) {
329 tripletFeel = 8;
330 }
331 else if (data & 0x02) {
332 tripletFeel = 16;
333 }
334 #endif
335 if (tempo > 0) {
336 info.getSection(section).tempo = tempo;//.getPosition(position).addComponent(new ptTempo(tempo));
337 }
338 }
339
readSectionSymbol(ptTrack & info)340 void PowerTab::readSectionSymbol(ptTrack& info)
341 {
342 int section = readShort();
343 int position = readUChar();
344 int data = readInt();
345
346 int endNumber = data >> 16;
347 info.getSection(section).getPosition(position).addComponent(new ptSymbol(endNumber));
348 }
349
readTimeSignature(ptBar * bar)350 void PowerTab::readTimeSignature(ptBar* bar)
351 {
352 skip(3);
353 int data = readUChar();
354 readUChar(); // measure pulses
355
356 bar->numerator = ((data - (data % 8)) / 8) + 1;
357 bar->denominator = pow(2, data % 8);
358 }
359
readBarLine(ptSection & sec)360 void PowerTab::readBarLine(ptSection& sec)
361 {
362 auto bar = new ptBar();
363 /*int position =*/ readUChar();
364 auto b_type = readUChar();
365
366 bar->repeatStart = (b_type >> 5) == 3;
367 bar->repeatClose = (b_type >> 5) == 4 ? b_type - 128 : 0;
368
369 bar->measureNo = sec.number;
370
371 readKeySignature();
372 readTimeSignature(bar);
373 readRehearsalSign(sec);
374 //sec.getPosition(position).addComponent(bar);
375 sec.bars.push_back(std::shared_ptr<ptBar>(bar));
376 /*if (bars.empty() || ( bars.back()->measureNo < bar->measureNo ))
377 bars.push_back(bar);*/
378 }
379
readStaff(int staff,ptSection & sec)380 void PowerTab::readStaff(int staff, ptSection& sec)
381 {
382 skip(5);
383 for (int voice = 0; voice < 2; ++voice) {
384 int itemCount = readHeaderItems();
385 for (int i = 0; i < itemCount; ++i) {
386 readPosition(staff, voice, sec);
387 if (i < itemCount - 1) {
388 readShort();
389 }
390 }
391 }
392 }
393
readNote(ptBeat * beat)394 void PowerTab::readNote(ptBeat* beat)
395 {
396 ptNote note;
397 auto position = readUChar();
398 auto simpleData = readShort();
399 auto symboCount = readUChar();
400 for (int i = 0; i < symboCount; ++i) {
401 skip(2);
402 auto data3 = readUChar();
403 auto data4 = readUChar();
404 note.bend = data4 == 101 ? data3 / 16 + 1 : 0;
405 note.slide = data4 == 100 ? data3 + 1 : 0;
406 }
407 note.value = position & 0x1F;
408 note.str = ((position & 0xE0) >> 5);
409 note.tied = simpleData & 0x01;
410 note.dead = simpleData & 0x02;
411 note.hammer = simpleData & 0x08;
412 beat->notes.emplace_back(note);
413 }
414
readPosition(int staff,int voice,ptSection & sec)415 void PowerTab::readPosition(int staff, int voice, ptSection& sec)
416 {
417 auto position = readUChar();
418
419 ptBeat* beat{ nullptr };
420 bool add = false;
421 if (voice == 0 || sec.beats[staff].empty()) {
422 beat = new ptBeat(staff, voice);
423 beat->position = position;
424 add = true;
425 }
426 else {
427 auto pos = sec.beats[staff].begin();
428 auto end = sec.beats[staff].end();
429 while (pos != end && pos->get()->position < position) {
430 ++pos;
431 }
432 if (pos == end) {
433 beat = new ptBeat(staff, voice);
434 beat->position = position;
435 add = true;
436 }
437 else if (pos->get()->position == position) {
438 beat = pos->get();
439 }
440 else {
441 beat = new ptBeat(staff, voice);
442 beat->position = position;
443 sec.beats[staff].insert(pos, std::shared_ptr<ptBeat>(beat));
444 }
445 }
446 auto beaming = readUChar();
447 beaming = (((int)beaming - 128 < 0) ? beaming : beaming - 128);
448
449 readUChar();
450
451 auto data1 = readUChar();
452 auto data2 = readUChar(); //32 - palm mute, 4 - accent, 2 - staccato
453 auto data3 = readUChar();
454 auto durationValue = readUChar();
455
456 int multiBarRest = 1;
457 auto complexCount = readUChar();
458 for (int i = 0; i < complexCount; ++i) {
459 auto count = readShort();
460 readUChar();
461 auto type = readUChar();
462 if (type & 0x08) {
463 multiBarRest = count;
464 }
465 }
466
467 auto itemCount = readHeaderItems();
468 for (int i = 0; i < itemCount; ++i) {
469 readNote(beat);
470 if ( i < itemCount - 1) {
471 readShort();
472 }
473 }
474 curTrack->infos[staff].notes_count += itemCount;
475 beat->mmrest = (itemCount == 0) ? multiBarRest : 1;
476 beat->vibrato = (( (data1 & 0x08) != 0) || ( (data1 & 0x10) != 0 ));
477 beat->grace = (data3 & 0x01) != 0;
478 beat->tuplet = (data3 & 0x20) != 0;
479
480 if (beat->duration != 0) {
481 durationValue = std::max((int)durationValue, beat->duration);
482 }
483
484 beat->duration = durationValue;//beat->duration == 0 ? durationValue : std::min(beat->duration, (int)durationValue);
485 beat->dotted = (data1 & 0x01);
486 beat->doubleDotted = (data1 & 0x02);
487 beat->arpegioUp = (data1 & 0x20);
488 beat->arpegioDown = (data1 & 0x40);
489 beat->enters = ((beaming - (beaming % 8)) / 8) + 1;
490 beat->times = (beaming % 8) + 1;
491 beat->isRest = (data1 & 0x04);
492 beat->palmMute = data2 & 0x20;
493 beat->accent = data2 & 0x04;
494 beat->staccato = data2 & 0x02;
495
496 for (int i = int(sec.beats.size()); i < staff + 1; ++i) {
497 sec.beats.push_back({});
498 }
499 if (add) {
500 sec.beats[staff].push_back(std::shared_ptr<ptBeat>(beat));
501 }
502 //sec.getPosition(position).addComponent(beat);
503 }
504
getStaffMap(ptSection & sec)505 std::vector<int> PowerTab::getStaffMap(ptSection& sec)
506 {
507 std::vector<int> result;
508 std::vector<int> slash;
509 if (!staffInc && curTrack->guitar_ins.size()) {
510 auto first = curTrack->guitar_ins.front();
511 while (first.section == sec.number) {
512 if (first.trackinfo) {
513 for (unsigned int i = 0; i < curTrack->infos.size(); ++i) {
514 if ((1 << i) & first.trackinfo) {
515 result.push_back(i);
516 }
517 }
518 }
519
520 if (first.rhytmSlash) {
521 for (unsigned int i = 0; i < curTrack->infos.size(); ++i) {
522 if ((i << 1) & first.rhytmSlash) {
523 slash.push_back(-1 - i);
524 }
525 }
526 }
527
528 curTrack->guitar_ins.pop_front();
529 if (curTrack->guitar_ins.empty()) break;
530 first = curTrack->guitar_ins.front();
531 }
532 }
533
534 if (result.empty() || int(result.size()) < sec.staves) {
535 result.clear();
536 if (int(lastStaffMap.size()) < sec.staves) {
537 for (int i = 0; i < sec.staves; ++i) {
538 result.push_back(i + staffInc);
539 }
540 }
541 else {
542 result = lastStaffMap;
543 }
544 }
545
546 for (auto i : slash) {
547 result.push_back(i);
548 }
549
550 lastStaffMap = result;
551 return result;
552 }
553
554 //---------------------------------------------------------
555 // addPalmMate
556 //---------------------------------------------------------
557
addPalmMute(Chord * chord)558 void PowerTab::addPalmMute(Chord* chord)
559 {
560 int track = chord->track();
561 while (int(_palmMutes.size()) < track + 1)
562 _palmMutes.push_back(0);
563
564 if (_palmMutes[track]) {
565 PalmMute* pm = _palmMutes[track];
566 Chord* lastChord = toChord(pm->endCR());
567 if (lastChord == chord)
568 return;
569 //
570 // extend the current palm mute or start a new one
571 //
572 Fraction tick = chord->segment()->tick();
573 if (pm->tick2() < tick)
574 _palmMutes[track] = 0;
575 else {
576 pm->setTick2(chord->tick() + chord->actualTicks());
577 pm->setEndElement(chord);
578 }
579
580 }
581 if (!_palmMutes[track]) {
582 PalmMute* pm = new PalmMute(score);
583 _palmMutes[track] = pm;
584 Segment* segment = chord->segment();
585 Fraction tick = segment->tick();
586
587 pm->setTick(tick);
588 pm->setTick2(tick + chord->actualTicks());
589 pm->setTrack(track);
590 pm->setTrack2(track);
591 pm->setStartElement(chord);
592 pm->setEndElement(chord);
593 score->addElement(pm);
594 }
595 }
596
fillMeasure(tBeatList & elist,Measure * measure,int staff,std::vector<Note * > & tiedNotes)597 void PowerTab::fillMeasure(tBeatList& elist, Measure* measure, int staff, std::vector<Note*>& tiedNotes)
598 {
599 Tuplet* tuple = nullptr;
600 int tupleBeatCounter{ 0 };
601 Fraction tick = measure->tick();
602 Fraction endtick = measure->endTick();
603 Chord* hammer{ nullptr };
604
605 while (elist.size() && tick < endtick) {
606 auto beat = elist.front().get();
607 auto segment = measure->getSegment(SegmentType::ChordRest, tick);
608 Fraction l(1, beat->duration);
609 int dots = beat->dotted ? (beat->doubleDotted ? 2 : 1) : (beat->doubleDotted ? 2 : 0);
610 switch (dots) {
611 case 1:
612 l = l + (l * Fraction(1,2));
613 break;
614 case 2:
615 l = l + (l * Fraction(3,4));
616 break;
617 }
618
619 TDuration d(l);
620 d.setDots(dots);
621
622 if (beat->tuplet || tupleBeatCounter) {
623 Fraction nt = (l * Fraction(1,3) * Fraction(2,1));
624 tick += nt;
625 }
626 else {
627 tick += l;
628 }
629 ChordRest* cr;
630 if (beat->notes.empty()) {
631 auto rest = new Rest(score);
632 cr = rest;
633 rest->setTrack(staff * VOICES);
634 rest->setTicks(l);
635 rest->setDurationType(d);
636 segment->add(rest);
637
638 }
639 else {
640 Chord* chord = new Chord(score);
641 cr = chord;
642 chord->setTrack(staff * VOICES);
643 chord->setTicks(l);
644 chord->setDurationType(d);
645 segment->add(chord);
646
647 if (beat->palmMute)
648 addPalmMute(chord);
649 if (beat->accent) {
650 auto accent = new Articulation(score);
651 accent->setSymId(SymId::articAccentAbove);
652 chord->add(accent);
653 }
654 if (beat->staccato) {
655 auto st = new Articulation(score);
656 st->setSymId(SymId::articStaccatoAbove);
657 chord->add(st);
658 }
659 bool has_hammer = false;
660 for (const auto &n : beat->notes) {
661 auto note = new Note(score);
662 chord->add(note);
663 if (n.dead) {
664 note->setHeadGroup(NoteHead::Group::HEAD_CROSS);
665 note->setGhost(true);
666 }
667
668 if (n.hammer) {
669 has_hammer = true;
670 }
671
672 if (n.tied && tiedNotes[n.str]) {
673 Tie* tie = new Tie(score);
674 tie->setEndNote(note);
675 tiedNotes[n.str]->add(tie);
676 }
677
678 if (n.bend) {
679 Bend* bend = new Bend(score);
680 //TODO-ws bend->setNote(note);
681 bend->points().append(PitchValue(0, n.bend * 25 - 12));
682 bend->points().append(PitchValue(50, 0));
683 note->add(bend);
684 }
685
686 if (false && n.slide) {
687 Text* st = new Text(score, Tid::HARMONY_A);
688 st->setXmlText(QString("SLIDE %1").arg(n.slide));
689 st->setTrack(staff * VOICES);
690 chord->notes().front()->add(st);
691 }
692
693 tiedNotes[n.str] = note;
694 note->setFret(n.value);
695 note->setString(n.str);
696 const StringData* sd = score->staff(staff)->part()->instrument()->stringData();
697 int k = int(curTrack->infos[staff].strings.size()) - n.str - 1;
698 int pitch = sd->stringList().at(k).pitch + n.value; //getPitch(n.str, n.value, 0);
699 note->setPitch(pitch);
700 note->setTpcFromPitch();
701 }
702
703 if (hammer) {
704 auto cr1 = hammer;
705 auto cr2 = chord;
706 hammer = nullptr;
707
708 Slur* slur = new Slur(score);
709 slur->setStartElement(cr1);
710 slur->setEndElement(cr2);
711 slur->setTick(cr1->tick());
712 slur->setTick2(tick);
713 slur->setTrack(staff * VOICES);
714 slur->setTrack2(staff * VOICES);
715 score->addElement(slur);
716
717 Text* st = new Text(score, Tid::HARMONY_A);
718 st->setXmlText("H");
719 st->setTrack(staff * VOICES);
720 cr1->notes().front()->add(st);
721 }
722 if (has_hammer) {
723 hammer = chord;
724 }
725 }
726
727 if (tupleBeatCounter && tuple) {
728 tupleBeatCounter--;
729 cr->setTuplet(tuple);
730 tuple->add(cr);
731 }
732
733 if (beat->tuplet && !tuple) {
734 tuple = new Tuplet(score);
735 tuple->setParent(measure);
736 tuple->setTrack(cr->track());
737 tuple->setBaseLen(l);
738 tuple->setRatio(Fraction(3, 2));
739 tuple->setTicks(l * tuple->ratio().denominator());
740 cr->setTuplet(tuple);
741 tuple->add(cr);
742 tupleBeatCounter = 2;
743 }
744 elist.pop_front();
745 }
746
747 if (tick == measure->tick()) {
748 auto rest = new Rest(score);
749 rest->setTrack(staff * VOICES);
750 auto ts = measure->timesig();
751 rest->setTicks(ts);
752 rest->setDurationType(TDuration(ts));
753 measure->getSegment(SegmentType::ChordRest, tick)->add(rest);
754 }
755
756 }
757
addToScore(ptSection & sec)758 void PowerTab::addToScore(ptSection& sec)
759 {
760 cur_section = &sec;
761 Fraction tick = score->lastMeasure() ? score->lastMeasure()->endTick() : Fraction(0,1);
762
763 Fraction lastTS(-1, -1);
764 bool firstMeasure = true;
765 if (score->lastMeasure()) {
766 lastTS = score->lastMeasure()->timesig();
767 firstMeasure = false;
768 }
769 if (firstMeasure) {
770 //int lastStaff = sec.staffMap.back() + 1;
771 for (int i = 0; i < staves; ++i) {
772 Part* part = new Part(score);
773 Staff* s = new Staff(score);
774 s->setPart(part);
775 part->insertStaff(s, -1);
776 auto info = &curTrack->infos[i];
777 std::string ss = info->name;
778 part->setPartName(QString::fromUtf8(ss.data(), int(ss.size())));
779 part->setPlainLongName(QString::fromUtf8(ss.data(), int(ss.size())));
780
781 std::vector<int> reverseStr;
782 for (auto it = info->strings.rbegin(); it != info->strings.rend(); ++it)
783 reverseStr.push_back(*it);
784 StringData stringData(32, int(info->strings.size()), reverseStr.data());
785 part->instrument()->setStringData(stringData);
786
787 part->setMidiProgram(info->instrument);
788
789 score->staves().push_back(s);
790 score->appendPart(part);
791 }
792 }
793 auto bar1 = sec.bars.front();
794 while (bar1->denominator == 0) {
795 if (sec.bars.size() == 1)
796 break;
797 sec.bars.pop_front();
798 bar1 = sec.bars.front();
799 }
800 if (bar1->denominator == 0) {
801 bar1->denominator = 4;
802 bar1->numerator = 4;
803 }
804 auto measure = createMeasure(bar1.get(), tick);
805 if (repeatCount) {
806 measure->setRepeatEnd(true);
807 measure->setRepeatCount(repeatCount);
808 }
809 repeatCount = bar1->repeatClose;
810 if (bar1->repeatStart) {
811 measure->setRepeatStart(true);
812 }
813 if (sec.bars.size() > 1) {
814 sec.bars.pop_front();
815 }
816 if (sec.tempo) {
817 TempoText* tt = new TempoText(score);
818 tt->setTempo(double(sec.tempo) / 60.0f);
819 tt->setXmlText(QString("<sym>metNoteQuarterUp</sym> = %1").arg(sec.tempo));
820 tt->setTrack(0);
821 Segment* segment = measure->getSegment(SegmentType::ChordRest, measure->tick());
822 segment->add(tt);
823 score->setTempo(measure->tick(), tt->tempo());
824 }
825 if (!sec.partName.empty() && lastPart != sec.partMarker) {
826 lastPart = sec.partMarker;
827 RehearsalMark* t = new RehearsalMark(score);
828 t->setFrameType(FrameType::SQUARE);
829 t->setPlainText(QString(sec.partMarker));
830 t->setTrack(0);
831 auto seg = measure->getSegment(SegmentType::ChordRest, measure->tick());
832 seg->add(t);
833
834 t = new RehearsalMark(score);
835 t->setFrameType(FrameType::NO_FRAME);
836 t->setPlainText(QString::fromUtf8(sec.partName.data(), int(sec.partName.size())));
837 t->setOffset(QPointF(10.0, 0.0));
838 t->setTrack(0);
839 seg->add(t);
840 }
841 if (firstMeasure) {
842 for (int staffIdx = 0; staffIdx < staves; ++staffIdx) {
843 int keysig = staffIdx >= staffInc ? 0 : 1; // Can be parsed int beat section
844 KeySig* t = new KeySig(score);
845 t->setKey(Key(keysig));
846 t->setTrack(staffIdx * VOICES);
847 Segment* s = measure->getSegment(SegmentType::KeySig, tick);
848 s->add(t);
849
850 ClefType clefId = staffIdx >= staffInc ? ClefType::F8_VB : ClefType::G15_MB;
851 auto clef = new Clef(score);
852 clef->setTrack(staffIdx * VOICES);
853 clef->setClefType(clefId);
854 s = measure->getSegment(SegmentType::HeaderClef, Fraction(0,1));
855 s->add(clef);
856 }
857
858 }
859
860 std::vector<std::vector<Note*>> tiedNotes(staves);
861 for (auto& nvec : tiedNotes) {
862 nvec.resize(10);
863 memset(nvec.data(), 0, sizeof(Note*) * 10);
864 }
865 //std::vector<tBeatList>
866 while (true) {
867 bool empty = true;
868 while (int(sec.beats.size()) < staves) {
869 sec.beats.push_back({});
870 }
871 for (unsigned int i = 0; i < sec.beats.size(); ++i) {
872 fillMeasure(sec.beats[i], measure, i, tiedNotes[i]);
873 if (sec.beats[i].size() && i < unsigned(staffInc))
874 empty = false;
875 }
876 if (lastTS != measure->timesig()) {
877 lastTS = measure->timesig();
878 for (int staffIdx = 0; staffIdx < staves; ++staffIdx) {
879 Staff* staff = score->staff(staffIdx);
880 auto staffType = staff->staffType(Fraction(0,1));
881 if (staffType->genTimesig()) {
882 auto t = new TimeSig(score);
883 t->setTrack(staffIdx * VOICES);
884 t->setSig(lastTS);
885 Segment* s = measure->getSegment(SegmentType::TimeSig, measure->tick());
886 s->add(t);
887 }
888 }
889 }
890 if (empty) {
891 break;
892 }
893 auto bar = sec.bars.front();
894 while (bar->denominator == 0) {
895 if (sec.bars.size() == 1)
896 break;
897 sec.bars.pop_front();
898 bar = sec.bars.front();
899 }
900 if (bar->denominator == 0) {
901 bar->denominator = measure->timesig().denominator();
902 bar->numerator = measure->timesig().numerator();
903 }
904 measure = createMeasure(bar.get(), measure->endTick());
905 if (repeatCount) {
906 measure->setRepeatEnd(true);
907 measure->setRepeatCount(repeatCount);
908 }
909 repeatCount = bar->repeatClose;
910 if (bar->repeatStart) {
911 measure->setRepeatStart(true);
912 }
913 if (sec.bars.size() > 2) {
914 sec.bars.pop_front();
915 }
916 }
917 if (sec.bars.size()) {
918 auto bar = sec.bars.back();
919 if (bar->repeatStart) {
920 measure->setRepeatStart(true);
921 }
922 if (bar->repeatClose) {
923 measure->setRepeatEnd(true);
924 measure->setRepeatCount(bar->repeatClose);
925 }
926 sec.bars.clear();
927 }
928
929 }
930
copyTracks(ptTrack * track)931 void PowerTab::ptSection::copyTracks(ptTrack* track)
932 {
933 //if not found GuitarIn in section or all tracks are read -> return
934 if (staves == int(staffMap.size())) {
935 return;
936 }
937
938 auto signature = chordTextMap.begin();
939 for (unsigned index = 0; index < staffMap.size(); ++index) {
940 auto staff = (staffMap[index] + 1) * -1;
941 if (staff < 0) {
942 continue;
943 }
944
945 for (const auto &rt : rhytm) {
946 auto newSig = chordTextMap.find(rt.position);
947 if (newSig != chordTextMap.end()) {
948 signature = newSig;
949 }
950
951 ptBeat* beat = new ptBeat(staff, 0);
952 beat->position = rt.position;
953 beat->duration = rt.duration;
954 beat->dotted = rt.dotted;
955 beat->doubleDotted = rt.doubleDotted;
956 beat->isRest = rt.is_rest;
957 beat->tuplet = rt.triplet;
958 if (!rt.is_rest) {
959 auto diagram = track->diagramMap.find({ {signature->second.key, signature->second.formula, signature->second.formula_mod} });
960 for (unsigned int string = 0; string < diagram->second.frets.size(); ++string) {
961 int fret = diagram->second.frets[string];
962 if (fret >= 0xFE) {
963 continue;
964 }
965 ptNote note;
966 note.value = fret;
967 note.str = string;
968 if (fret == 0xFE) {
969 note.dead = true;
970 note.value = 0;
971 }
972 beat->notes.emplace_back(note);
973 }
974 }
975 while (int(beats.size()) <= staff) {
976 beats.push_back({});
977 }
978 beats[staff].push_back(std::shared_ptr<ptBeat>(beat));
979 }
980 }
981 }
982
readSection(ptSection & sec)983 void PowerTab::readSection(ptSection& sec)
984 {
985 //rect:
986 readInt(); // left
987 readInt(); // top
988 readInt(); // right
989 readInt(); // bottom
990
991 auto lastBarData = readUChar();
992
993 skip(4); //spacing from staff
994
995 readBarLine(sec);
996
997 int itemCount = readHeaderItems();
998 for (int i = 0; i < itemCount; ++i) {
999 readDirection(sec);
1000 if (i < itemCount - 1) {
1001 readShort();
1002 }
1003 }
1004 //ChordText section
1005 itemCount = readHeaderItems();
1006 for (int i = 0; i < itemCount; ++i) {
1007 readChordText(sec);
1008 if (i < itemCount - 1) {
1009 readShort();
1010 }
1011 }
1012 //RhytmSlash
1013 itemCount = readHeaderItems();
1014 for (int i = 0; i < itemCount; ++i) {
1015 readRhytmSlash(sec);
1016 if (i < itemCount - 1)
1017 readShort();
1018 }
1019 // Staff
1020 sec.staves = readHeaderItems();
1021 sec.staffMap = getStaffMap(sec);
1022 for (int i = 0; i < sec.staves; ++i) {
1023 int staff = sec.staffMap[i];
1024 readStaff(staff, sec);
1025 if (i < sec.staves - 1) {
1026 readShort();
1027 }
1028 }
1029 sec.copyTracks(curTrack);
1030 // MusicBar section
1031 itemCount = readHeaderItems();
1032 for (int i = 0; i < itemCount; ++i) {
1033 readBarLine(sec);
1034 if (i < itemCount - 1) {
1035 readShort();
1036 }
1037 }
1038
1039 auto bar = new ptBar();
1040 bar->repeatClose = (lastBarData >> 5 == 4) ? lastBarData - 128 : 0;
1041 sec.bars.push_back(std::shared_ptr<ptBar>(bar));
1042 //sec.getPosition(sec.getNextPositionNumber()).addComponent(bar);
1043 }
1044
readDirection(ptSection & sec)1045 void PowerTab::readDirection(ptSection& sec)
1046 {
1047 int position = readUChar();
1048 int symbolCount = readUChar();
1049 for (int i = 0; i < symbolCount; ++i) {
1050 unsigned int data = readShort();
1051 sec.getPosition(position).addComponent(new ptDirection((data >> 8), ((data & 0xC0) >> 6), (data & 0x1F)));
1052 }
1053 }
1054
readDataInstruments(ptTrack & info)1055 void PowerTab::readDataInstruments(ptTrack& info)
1056 {
1057 curTrack = &info;
1058 //Guitar section
1059 auto itemCount = readHeaderItems();
1060 for (int i = 0; i < itemCount; ++i) {
1061 readTrackInfo(info);
1062 if (i < itemCount - 1) {
1063 readShort();
1064 }
1065 }
1066 // Chord Diagram Section
1067 itemCount = readHeaderItems();
1068 for (int i = 0; i < itemCount; ++i) {
1069 readChord(info);
1070 if (i < itemCount - 1) {
1071 readShort();
1072 }
1073 }
1074 //Floating Text section
1075 itemCount = readHeaderItems();
1076 for (int i = 0; i < itemCount; ++i) {
1077 readFloatingText();
1078 if (i < itemCount - 1) {
1079 readShort();
1080 }
1081 }
1082 // GuitarIn section
1083 itemCount = readHeaderItems();
1084 for (int i = 0; i < itemCount; ++i) {
1085 readGuitarIn(info);
1086 if (i < itemCount - 1) {
1087 readShort();
1088 }
1089 }
1090 // Tempo marker
1091 itemCount = readHeaderItems();
1092 for (int i = 0; i < itemCount; ++i) {
1093 readTempoMarker(info);
1094 if (i < itemCount - 1) {
1095 readShort();
1096 }
1097 }
1098 //Dynamic section
1099 itemCount = readHeaderItems();
1100 for (int i = 0; i < itemCount; ++i) {
1101 readDynamic();
1102 if (i < itemCount - 1) {
1103 readShort();
1104 }
1105 }
1106 //Symbol section
1107 itemCount = readHeaderItems();
1108 for (int i = 0; i < itemCount; ++i) {
1109 readSectionSymbol(info);
1110 if (i < itemCount - 1) {
1111 readShort();
1112 }
1113 }
1114 //Section section
1115 itemCount = readHeaderItems();
1116 for (int i = 0; i < itemCount; ++i) {
1117 readSection(info.getSection(i));
1118 if (i < itemCount - 1) {
1119 readShort();
1120 }
1121 }
1122 }
1123
crTS(int strings,int tuning[])1124 std::string crTS(int strings, int tuning[])
1125 {
1126 const static char* tune[] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
1127 std::vector<int> pitch;
1128 for (int i = 0; i < strings; ++i) {
1129 pitch.push_back(tuning[i]);
1130 }
1131 std::string t;
1132 for (auto i : pitch) {
1133 t += tune[i % 12];
1134 t += " ";
1135 }
1136 return t;
1137 }
1138
1139
createMeasure(ptBar * bar,const Fraction & tick)1140 Measure* PowerTab::createMeasure(ptBar* bar, const Fraction& tick)
1141 {
1142 auto measure = new Measure(score);
1143 Fraction nts(bar->numerator, bar->denominator);
1144
1145 measure->setTick(tick);
1146 measure->setTimesig(nts);
1147 measure->setTicks(nts);
1148
1149 score->measures()->add(measure);
1150
1151 return measure;
1152 }
1153
getSection(int ind)1154 PowerTab::ptSection& PowerTab::ptTrack::getSection(int ind)
1155 {
1156 for (int i = (int)sections.size(); i < ind + 1; ++i) {
1157 sections.push_back(ptSection(i));
1158 }
1159 return sections[ind];
1160 }
1161
ptSection(int num)1162 PowerTab::ptSection::ptSection(int num)
1163 {
1164 number = num;
1165 }
1166
getPosition(int pos)1167 PowerTab::ptPosition& PowerTab::ptSection::getPosition(int pos)
1168 {
1169 unsigned int i = 0;
1170 while ( i < positions.size() ) {
1171 auto& p = positions[i];
1172 if (p.position == pos) {
1173 return p;
1174 }
1175 ++i;
1176 }
1177 ptPosition p;
1178 p.position = pos;
1179 positions.emplace_back(p);
1180 return positions.back();
1181 }
1182
getNextPositionNumber()1183 int PowerTab::ptSection::getNextPositionNumber()
1184 {
1185 int next = 0;
1186 unsigned int k = 0;
1187 while (k < positions.size()) {
1188 auto p = positions[k];
1189 next = std::max(next, p.position + 1);
1190 ++k;
1191 }
1192 return next;
1193 }
1194
addComponent(ptComponent * c)1195 void PowerTab::ptPosition::addComponent(ptComponent* c)
1196 {
1197 components.push_back(std::shared_ptr<ptComponent>(c));
1198 }
1199
1200
1201 //---------------------------------------------------------
1202 // read
1203 //---------------------------------------------------------
1204
read()1205 Score::FileError PowerTab::read()
1206 {
1207 if (!readVersion())
1208 return Score::FileError::FILE_BAD_FORMAT;
1209 ptSong song;
1210
1211 readSongInfo(song.info);
1212 readDataInstruments(song.track1);
1213 staffInc = int(song.track1.infos.size());
1214 lastStaffMap.clear();
1215 readDataInstruments(song.track1);
1216
1217 staves = int(song.track1.infos.size());
1218
1219 std::vector<tBeatList> parts(staves);
1220 for (int i = staffInc; i < staves; ++i) {
1221 for (auto& sec : song.track1.sections) {
1222 while (int(sec.beats.size()) < staves)
1223 sec.beats.push_back({});
1224 parts[i].insert(parts[i].end(), sec.beats[i].begin(), sec.beats[i].end());
1225 sec.beats[i].clear();
1226 }
1227 }
1228
1229 for (auto& sec : song.track1.sections) {
1230 for (int i = 0; i < staves; ++i) {
1231 if (parts[i].size()) {
1232 sec.beats[i].insert(sec.beats[i].begin(), parts[i].begin(), parts[i].end());
1233 parts[i].clear();
1234 }
1235 }
1236 addToScore(sec);
1237 for (int i = 0; i < staves; ++i)
1238 parts[i] = sec.beats[i];
1239 }
1240
1241 score->style().set(Sid::ArpeggioHiddenInStdIfTab, true);
1242
1243 MeasureBase* m;
1244 if (!score->measures()->first()) {
1245 m = new VBox(score);
1246 m->setTick(Fraction(0,1));
1247 score->addMeasure(m, 0);
1248 }
1249 else {
1250 m = score->measures()->first();
1251 if (!m->isVBox()) {
1252 MeasureBase* mb = new VBox(score);
1253 mb->setTick(Fraction(0,1));
1254 score->addMeasure(mb, m);
1255 m = mb;
1256 }
1257 }
1258 // create title
1259 std::string name = song.info.name;
1260 if (!name.empty()) {
1261 Text* s = new Text(score, Tid::TITLE);
1262 s->setPlainText(QString::fromUtf8(name.data(), int(name.size())));
1263 m->add(s);
1264 }
1265
1266 // static const char* tune[] = { "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B" };
1267 int id = 0;
1268 for (Part* part : score->parts()) {
1269 QMultiMap<int, int> tracks;
1270 Score* pscore = new Score(score);
1271
1272 //TODO-ws pscore->tuning.clear();
1273 auto& info = song.track1.infos[id++];
1274 for (auto it = info.strings.rbegin(); it != info.strings.rend(); ++it) {
1275 //TODO-ws pscore->tuning += tune[*it % 12];
1276 // pscore->tuning += " ";
1277 }
1278
1279
1280 //TODO-ws pscore->showLyrics = score->showLyrics;
1281 pscore->style().set(Sid::createMultiMeasureRests, false);
1282 pscore->style().set(Sid::ArpeggioHiddenInStdIfTab, true);
1283
1284 QList<int> stavesMap;
1285 Part* p = new Part(pscore);
1286 p->setInstrument(*part->instrument());
1287
1288 Staff* staff = part->staves()->front();
1289
1290 Staff* s = new Staff(pscore);
1291 s->setPart(p);
1292 const StaffType* st = staff->staffType(Fraction(0,1));
1293 s->setStaffType(Fraction(0,1), *st);
1294
1295 s->linkTo(staff);
1296 p->staves()->append(s);
1297 pscore->staves().append(s);
1298 stavesMap.append(staff->idx());
1299 for (int i = staff->idx() * VOICES, j = 0; i < staff->idx() * VOICES + VOICES; i++, j++)
1300 tracks.insert(i, j);
1301
1302 Excerpt* excerpt = new Excerpt(score);
1303 excerpt->setTracks(tracks);
1304 excerpt->setPartScore(pscore);
1305 //title?
1306 excerpt->setTitle(part->instrument()->longNames()[0].name());
1307 pscore->setExcerpt(excerpt);
1308 excerpt->parts().append(part);
1309 score->excerpts().append(excerpt);
1310
1311 Excerpt::cloneStaves(score, pscore, stavesMap, tracks);
1312
1313 if (staff->part()->instrument()->stringData()->strings() > 0
1314 && part->staves()->front()->staffType(Fraction(0,1))->group() == StaffGroup::STANDARD) {
1315 p->setStaves(2);
1316 Staff* s1 = p->staff(1);
1317
1318 int lines = staff->part()->instrument()->stringData()->strings();
1319 StaffTypes sts = StaffTypes::TAB_DEFAULT;
1320 if (lines == 4)
1321 sts = StaffTypes::TAB_4COMMON;
1322 StaffType st1 = *StaffType::preset(sts);
1323 s1->setStaffType(Fraction(0,1), st1);
1324 s1->setLines(Fraction(0,1), lines);
1325 Excerpt::cloneStaff(s, s1);
1326 BracketItem* bi = new BracketItem(pscore, BracketType::NORMAL, 2);
1327 p->staves()->front()->addBracket(bi);
1328 }
1329 pscore->appendPart(p);
1330
1331 //
1332 // create excerpt title
1333 //
1334 MeasureBase* measure = pscore->first();
1335 if (!measure || (measure->type() != ElementType::VBOX)) {
1336 MeasureBase* mb = new VBox(pscore);
1337 mb->setTick(Fraction(0,1));
1338 pscore->addMeasure(mb, measure);
1339 measure = mb;
1340 }
1341 Text* txt = new Text(pscore, Tid::INSTRUMENT_EXCERPT);
1342 txt->setPlainText(part->longName());
1343 measure->add(txt);
1344
1345 pscore->setPlaylistDirty();
1346 pscore->setLayoutAll();
1347 pscore->addLayoutFlags(LayoutFlag::FIX_PITCH_VELO);
1348 pscore->doLayout();
1349 }
1350 return Score::FileError::FILE_NO_ERROR;
1351 }
1352
1353 }
1354