void ConvertGtp::readSongAttributes() { QString s; Q_UINT8 num; currentStage = QString("readSongAttributes: song->info"); song->info["TITLE"] = readDelphiString(); song->info["SUBTITLE"] = readDelphiString(); song->info["ARTIST"] = readDelphiString(); song->info["ALBUM"] = readDelphiString(); if (versionMajor >= 5) song->info["LYRICIST"] = readDelphiString(); song->info["COMPOSER"] = readDelphiString(); song->info["COPYRIGHT"] = readDelphiString(); song->info["TRANSCRIBER"] = readDelphiString(); song->info["INSTRUCTIONS"] = readDelphiString(); // Notice lines currentStage = QString("readSongAttributes: notice lines"); song->info["COMMENTS"] = ""; int n = readDelphiInteger(); for (int i = 0; i < n; i++) song->info["COMMENTS"] += readDelphiString() + "\n"; if (versionMajor <= 4) { currentStage = QString("readSongAttributes: shuffle rhythm feel"); (*stream) >> num; // GREYFIX: Shuffle rhythm feel }
bool GuitarPro5::readMixChange(Measure* measure) { /*char patch =*/ readChar(); skip(16); char volume = readChar(); char pan = readChar(); char chorus = readChar(); char reverb = readChar(); char phase = readChar(); char tremolo = readChar(); readDelphiString(); // tempo name int tempo = readInt(); bool editedTempo = false; if (volume >= 0) readChar(); if (pan >= 0) readChar(); if (chorus >= 0) readChar(); if (reverb >= 0) readChar(); //qDebug("read reverb: %d", reverb); if (phase >= 0) readChar(); if (tremolo >= 0) readChar(); if (tempo >= 0) { if (tempo != previousTempo) { previousTempo = tempo; setTempo(tempo, measure); editedTempo = true; } readChar(); if (version > 500) readChar(); } readChar(); skip(1); if (version > 500) { readDelphiString(); readDelphiString(); } return editedTempo; }
void ConvertGtp::readSongAttributes() { string s; char num; currentStage = string("readSongAttributes: song->info"); song->info["TITLE"] = readDelphiString(); song->info["SUBTITLE"] = readDelphiString(); song->info["ARTIST"] = readDelphiString(); song->info["ALBUM"] = readDelphiString(); song->info["COMPOSER"] = readDelphiString(); song->info["COPYRIGHT"] = readDelphiString(); song->info["TRANSCRIBER"] = readDelphiString(); song->info["INSTRUCTIONS"] = readDelphiString(); // Notice lines currentStage = string("readSongAttributes: notice lines"); song->info["COMMENTS"] = ""; int n = readDelphiInteger(); for (int i = 0; i < n; i++) song->info["COMMENTS"] += readDelphiString() + "\n"; currentStage = string("readSongAttributes: shuffle rhythm feel"); num = readChar(); // GREYFIX: Shuffle rhythm feel if (versionMajor >= 4) { currentStage = string("readSongAttributes: lyrics"); // Lyrics num = readDelphiInteger(); // GREYFIX: Lyric track number start for (int i = 0; i < LYRIC_LINES_MAX_NUMBER; i++) { num = readDelphiInteger(); // GREYFIX: Start from bar readWordPascalString(); // GREYFIX: Lyric line } } currentStage = string("readSongAttributes: tempo"); song->tempo = readDelphiInteger(); // Tempo //osg::notify(osg::INFO) << "tempo: " << song->tempo << "\n"; int oct = -1; if (versionMajor >= 4) { num = readChar(); // GREYFIX: key oct = readDelphiInteger(); // GREYFIX: octave } else { readDelphiInteger(); // GREYFIX: key } }
void ConvertGtp::readTabs() { char beat_bitmask, strings, num; char length, volume, pan, chorus, reverb, phase, tremolo; int x; currentStage = string("readTabs"); vector<TabTrack>::iterator trk = song->t.begin(); for (int tr = 0; tr < numTracks; tr++) { trk->b.resize(numBars); trk->c.resize(0); trk++; } for (int j = 0; j < numBars; j++) { for (trk = song->t.begin(); trk != song->t.end(); trk++) { int numBeats = readDelphiInteger(); //osg::notify(osg::INFO) << "TRACK " << tr << ", BAR " << j << ", numBeats " << numBeats << " (position: " << stream.tellg() << ")\n"; if (numBeats < 0 || (strongChecks && numBeats > 128)) throw string("Track %1, bar %2, insane number of beats: %3"); x = trk->c.size(); trk->c.resize(trk->c.size() + numBeats); trk->b[j].time1 = bars[j].time1; trk->b[j].time2 = bars[j].time2; trk->b[j].keysig = bars[j].keysig; trk->b[j].start = x; trk->b[j].notes = numBeats; trk->b[j].tempo = -1; trk->b[j].begin = bars[j].begin; trk->b[j].end = bars[j].end; for (int k = 0; k < numBeats; k++) { trk->c[x].flags = 0; beat_bitmask = readChar(); // beat bitmask if (beat_bitmask & 0x01) // dotted column trk->c[x].flags |= FLAG_DOT; if (beat_bitmask & 0x40) { num = readChar(); // GREYFIX: pause_kind } // Guitar Pro 4 beat lengths are as following: // -2 = 1 => 480 3-l = 5 2^(3-l)*15 // -1 = 1/2 => 240 4 // 0 = 1/4 => 120 3 // 1 = 1/8 => 60 2 // 2 = 1/16 => 30 ... etc 1 // 3 = 1/32 => 15 0 length = readChar(); // length //osg::notify(osg::INFO) << "beat_bitmask: " << (int) beat_bitmask << "; length: " << length << "\n"; float len = 1.0f / (1 << (2 + length)); trk->c[x].l = len; if (beat_bitmask & 0x20) { int tuple = readDelphiInteger(); //osg::notify(osg::INFO) << "Tuple: " << tuple << "\n"; // GREYFIX: t for tuples if (!(tuple == 3 || (tuple >= 5 && tuple <= 7) || (tuple >= 9 && tuple <= 13))) throw string("Insane tuple t: %1"); } if (beat_bitmask & 0x02) // Chord diagram { readChord(trk, x); } if (beat_bitmask & 0x04) { readDelphiString(); } // GREYFIX: column-wide effects if (beat_bitmask & 0x08) { readColumnEffects(trk, x); } if (beat_bitmask & 0x10) { // mixer variations num = readChar(); // GREYFIX: new MIDI patch volume = readChar(); // GREYFIX: new pan = readChar(); // GREYFIX: new chorus = readChar(); // GREYFIX: new reverb = readChar(); // GREYFIX: new phase = readChar(); // GREYFIX: new tremolo = readChar(); // GREYFIX: new int tempo = readDelphiInteger(); // GREYFIX: new tempo trk->b[j].tempo = tempo; // GREYFIX: transitions if (volume != -1) num = readChar(); if (pan != -1) num = readChar(); if (chorus != -1) num = readChar(); if (reverb != -1) num = readChar(); if (tremolo != -1) num = readChar(); if (tempo != -1) num = readChar(); if (versionMajor >= 4) { num = readChar(); // bitmask: what should be applied to all tracks } } strings = readChar(); // used strings mask for (int y = STRING_MAX_NUMBER - 1; y >= 0; y--) { trk->c[x].e[y] = 0; trk->c[x].a[y] = NULL_NOTE; if (strings & (1 << (y + STRING_MAX_NUMBER - trk->strings))) readNote(trk, x, y); } // Dump column string tmp = ""; for (int y = 0; y <= trk->strings; y++) { if (trk->c[x].a[y] == NULL_NOTE) { tmp += "."; } else { tmp += '0' + trk->c[x].a[y]; } } //osg::notify(osg::INFO) << "[" << tmp << "]\n"; x++; } } } }
void ConvertGtp::readBarProperties() { char bar_bitmask, num; int time1 = 4; int time2 = 4; int keysig = 0; string text = ""; bars.resize(numBars); currentStage = string("readBarProperties"); //osg::notify(osg::INFO) << "readBarProperties(): start\n"; for (int i = 0; i < numBars; i++) { bool begin = false; int end = 0; bar_bitmask = readChar(); // bar property bitmask if (bar_bitmask != 0) ;//osg::notify(osg::INFO) << "BAR #" << i << " - flags " << (int) bar_bitmask << "\n"; // GREYFIX: new_time_numerator if (bar_bitmask & 0x01) { num = readChar(); time1 = num; //osg::notify(osg::INFO) << "new time1 signature: " << time1 << ":" << time2 << "\n"; } // GREYFIX: new_time_denominator if (bar_bitmask & 0x02) { num = readChar(); time2 = num; //osg::notify(osg::INFO) << "new time2 signature: " << time1 << ":" << time2 << "\n"; } // GREYFIX: begin repeat if (bar_bitmask & 0x04) { begin = true; //osg::notify(osg::INFO) << "begin repeat\n"; } // GREYFIX: number_of_repeats if (bar_bitmask & 0x08) { num = readChar(); end = num; //osg::notify(osg::INFO) << "end repeat " << (int) num << "x\n"; } // GREYFIX: alternative_ending_to if (bar_bitmask & 0x10) { num = readChar(); //osg::notify(osg::INFO) << "alternative ending to " << (int) num << "\n"; } // GREYFIX: new section if (bar_bitmask & 0x20) { text = readDelphiString(); readDelphiInteger(); // color? //osg::notify(osg::INFO) << "new section: " << text << "\n"; } if (bar_bitmask & 0x40) { num = readChar(); // GREYFIX: alterations_number keysig = num; num = readChar(); // GREYFIX: minor //osg::notify(osg::INFO) << "new key signature (" << keysig << ", " << num << ")\n"; } // GREYFIX: double bar if (bar_bitmask & 0x80) { //osg::notify(osg::INFO) << "double bar\n"; } bars[i].start = 0; bars[i].time1 = time1; bars[i].time2 = time1; bars[i].keysig = keysig; bars[i].section = text; bars[i].begin = begin; bars[i].end = end; } //osg::notify(osg::INFO) << "readBarProperties(): end\n"; }
void GuitarPro5::read(QFile* fp) { f = fp; readInfo(); readLyrics(); readPageSetup(); previousDynamic = -1; previousTempo = -1; //previousDynamic = new int [staves * VOICES]; // initialise the dynamics to 0 //for (int i = 0; i < staves * VOICES; i++) // previousDynamic[i] = 0; tempo = readInt(); if (version > 500) skip(1); key = readInt(); /* int octave =*/ readChar(); // octave readChannels(); skip(42); measures = readInt(); staves = readInt(); slurs = new Slur*[staves]; for (int i = 0; i < staves; ++i) slurs[i] = 0; int tnumerator = 4; int tdenominator = 4; for (int i = 0; i < measures; ++i) { if (i > 0) skip(1); GpBar bar; uchar barBits = readUChar(); if (barBits & SCORE_TIMESIG_NUMERATOR) tnumerator = readUChar(); if (barBits & SCORE_TIMESIG_DENOMINATOR) tdenominator = readUChar(); if (barBits & SCORE_REPEAT_START) bar.repeatFlags = bar.repeatFlags | Repeat::START; if (barBits & SCORE_REPEAT_END) { // number of repeats bar.repeatFlags = bar.repeatFlags |Repeat::END; bar.repeats = readUChar(); } if (barBits & SCORE_MARKER) { bar.marker = readDelphiString(); // new section? /*int color =*/ readInt(); // color? } if (barBits & SCORE_VOLTA) { // a volta uchar voltaNumber = readUChar(); while (voltaNumber > 0) { // voltas are represented as flags bar.volta.voltaType = GP_VOLTA_FLAGS; bar.volta.voltaInfo.append(voltaNumber & 1); voltaNumber >>= 1; } } if (barBits & SCORE_KEYSIG) { int currentKey = readUChar(); /* key signatures are specified as * 1# = 1, 2# = 2, ..., 7# = 7 * 1b = 255, 2b = 254, ... 7b = 249 */ bar.keysig = currentKey <= 7 ? currentKey : -256+currentKey; readUChar(); // specified major/minor mode } if (barBits & SCORE_DOUBLE_BAR) bar.barLine = BarLineType::DOUBLE; if (barBits & 0x3) skip(4); if ((barBits & 0x10) == 0) skip(1); readChar(); // triple feel (none, 8, 16) bar.timesig = Fraction(tnumerator, tdenominator); bars.append(bar); }
void GuitarPro5::readTracks() { for (int i = 0; i < staves; ++i) { int tuning[GP_MAX_STRING_NUMBER]; Staff* staff = score->staff(i); Part* part = staff->part(); uchar c = readUChar(); // simulations bitmask if (c & 0x2) { // 12 stringed guitar } if (c & 0x4) { // banjo track } if (i == 0 || version == 500) skip(1); QString name = readPascalString(40); int strings = readInt(); if (strings <= 0 || strings > GP_MAX_STRING_NUMBER) throw GuitarProError::GP_BAD_NUMBER_OF_STRINGS ; for (int j = 0; j < strings; ++j) { tuning[j] = readInt(); } for (int j = strings; j < GP_MAX_STRING_NUMBER; ++j) readInt(); /*int midiPort =*/ readInt(); // -1 int midiChannel = readInt() - 1; /*int midiChannel2 =*/ readInt(); // -1 int frets = readInt(); int capo = readInt(); /*int color =*/ readInt(); skip(version > 500 ? 49 : 44); if (version > 500) { // british stack clean / amp tone readDelphiString(); readDelphiString(); } int tuning2[strings]; for (int k = 0; k < strings; ++k) tuning2[strings-k-1] = tuning[k]; StringData stringData(frets, strings, tuning2); Instrument* instr = part->instr(); instr->setStringData(stringData); part->setPartName(name); part->setLongName(name); instr->setTranspose(Interval(capo)); // // determine clef // int patch = channelDefaults[midiChannel].patch; ClefType clefId = ClefType::G; if (midiChannel == GP_DEFAULT_PERCUSSION_CHANNEL) { clefId = ClefType::PERC; // instr->setUseDrumset(DrumsetKind::GUITAR_PRO); instr->setDrumset(gpDrumset); staff->setStaffType(StaffType::preset(StaffTypes::PERC_DEFAULT)); } else if (patch >= 24 && patch < 32) clefId = ClefType::G3; else if (patch >= 32 && patch < 40) clefId = ClefType::F8; Measure* measure = score->firstMeasure(); Clef* clef = new Clef(score); clef->setClefType(clefId); clef->setTrack(i * VOICES); Segment* segment = measure->getSegment(Segment::Type::Clef, 0); segment->add(clef); Channel& ch = instr->channel(0); if (midiChannel == GP_DEFAULT_PERCUSSION_CHANNEL) { ch.program = 0; ch.bank = 128; } else { ch.program = patch; ch.bank = 0; } ch.volume = channelDefaults[midiChannel].volume; ch.pan = channelDefaults[midiChannel].pan; ch.chorus = channelDefaults[midiChannel].chorus; ch.reverb = channelDefaults[midiChannel].reverb; //qDebug("default2: %d", channelDefaults[i].reverb); // missing: phase, tremolo ch.updateInitList(); } skip(version == 500 ? 2 : 1); }
int GuitarPro5::readBeat(int tick, int voice, Measure* measure, int staffIdx, Tuplet** tuplets, bool /*mixChange*/) { uchar beatBits = readUChar(); bool dotted = beatBits & BEAT_DOTTED; slide = -1; int track = staffIdx * VOICES + voice; if (slides.contains(track)) slide = slides.take(track); int pause = -1; if (beatBits & BEAT_PAUSE) pause = readUChar(); // readDuration int len = readChar(); int tuple = 0; if (beatBits & BEAT_TUPLET) tuple = readInt(); Segment* segment = measure->getSegment(Segment::Type::ChordRest, tick); if (beatBits & BEAT_CHORD) { int numStrings = score->staff(staffIdx)->part()->instr()->stringData()->strings(); skip(17); QString name = readPascalString(21); skip(4); // no header to be read in the GP5 format - default to true. readChord(segment, staffIdx * VOICES, numStrings, name, true); skip(32); } Lyrics* lyrics = 0; if (beatBits & BEAT_LYRICS) { QString txt = readDelphiString(); lyrics = new Lyrics(score); lyrics->setText(txt); } gpLyrics.beatCounter++; if (gpLyrics.beatCounter >= gpLyrics.fromBeat && gpLyrics.lyricTrack == staffIdx+1) { int index = gpLyrics.beatCounter - gpLyrics.fromBeat; if (index < gpLyrics.lyrics.size()) { lyrics = new Lyrics(score); lyrics->setText(gpLyrics.lyrics[index]); } } int beatEffects = 0; if (beatBits & BEAT_EFFECTS) beatEffects = readBeatEffects(track, segment); if (beatBits & BEAT_MIX_CHANGE) readMixChange(measure); int strings = readUChar(); // used strings mask Fraction l = len2fraction(len); // Some beat effects could add a Chord before this ChordRest* cr = segment->cr(track); if (voice != 0 && pause == 0 && strings == 0) cr = 0; else { if (strings == 0) { if (cr) { segment->remove(cr); delete cr; cr = 0; } cr = new Rest(score); } else { if (!cr) cr = new Chord(score); } cr->setTrack(track); TDuration d(l); d.setDots(dotted ? 1 : 0); if (dotted) l = l + (l/2); if (tuple) { Tuplet* tuplet = tuplets[staffIdx * 2 + voice]; if ((tuplet == 0) || (tuplet->elementsDuration() == tuplet->baseLen().fraction() * tuplet->ratio().numerator())) { tuplet = new Tuplet(score); // int track = staffIdx * 2 + voice; tuplets[staffIdx * 2 + voice] = tuplet; tuplet->setTrack(cr->track()); setTuplet(tuplet, tuple); tuplet->setParent(measure); } tuplet->setTrack(cr->track()); tuplet->setBaseLen(l); tuplet->setDuration(l * tuplet->ratio().denominator()); cr->setTuplet(tuplet); tuplet->add(cr); } cr->setDuration(l); if (cr->type() == Element::Type::REST && (pause == 0 || l == measure->len())) cr->setDurationType(TDuration::DurationType::V_MEASURE); else cr->setDurationType(d); if(!segment->cr(track)) segment->add(cr); Staff* staff = cr->staff(); int numStrings = staff->part()->instr()->stringData()->strings(); bool hasSlur = false; for (int i = 6; i >= 0; --i) { if (strings & (1 << i) && ((6-i) < numStrings)) { Note* note = new Note(score); if (dotted) { // there is at most one dotted note in this guitar pro version NoteDot* dot = new NoteDot(score); dot->setIdx(0); dot->setParent(note); dot->setTrack(track); // needed to know the staff it belongs to (and detect tablature) dot->setVisible(true); note->add(dot); } static_cast<Chord*>(cr)->add(note); hasSlur = readNote(6-i, note); note->setTpcFromPitch(); } } createSlur(hasSlur, staffIdx, cr); if (lyrics) cr->add(lyrics); } int rr = readChar(); if (cr && (cr->type() == Element::Type::CHORD)) { Chord* chord = static_cast<Chord*>(cr); applyBeatEffects(chord, beatEffects); if (rr == ARPEGGIO_DOWN) chord->setStemDirection(MScore::Direction::DOWN); else if (rr == ARPEGGIO_UP) chord->setStemDirection(MScore::Direction::UP); } int r = readChar(); if (r & 0x8) { int rrr = readChar(); qDebug(" 3beat read 0x%02x", rrr); } if (cr && (cr->type() == Element::Type::CHORD) && slide > 0) createSlide(slide, cr, staffIdx); restsForEmptyBeats(segment, measure, cr, l, track, tick); return cr ? cr->actualTicks() : measure->ticks(); }