diff --git a/Sources/VLLayout.cpp b/Sources/VLLayout.cpp index 5e7f908..d2747f9 100644 --- a/Sources/VLLayout.cpp +++ b/Sources/VLLayout.cpp @@ -5,7 +5,7 @@ // // (MN) Matthias Neeracher // -// Copyright © 2007 Matthias Neeracher +// Copyright © 2007-2011 Matthias Neeracher // #include "VLLayout.h" @@ -77,17 +77,17 @@ float VLLayout::MeasurePosition(int measure) const return 0.0f; } -float VLLayout::NotePosition(int measure, VLFraction at) const +float VLLayout::NotePosition(VLLocation at) const { for (int sys=0; sys(size()); } float MeasurePosition(int measure) const; - float NotePosition(int measure, VLFraction at) const; + float NotePosition(VLLocation at) const; }; class VLFontHandler { diff --git a/Sources/VLMIDIWriter.cpp b/Sources/VLMIDIWriter.cpp index 2910993..69ecba9 100644 --- a/Sources/VLMIDIWriter.cpp +++ b/Sources/VLMIDIWriter.cpp @@ -35,40 +35,40 @@ void VLMIDIWriter::Visit(VLSong & song) void VLMIDIWriter::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas) { + const VLLocation kStartOfMeasure = {m, VLFraction(0)}; if (fVolta.size() <= m) fVolta.push_back(0); fTime = p.fTime; - fMeasure = m; fStanza = ++fVolta[m]; if (!fChordTime) fChordTime = fNoteTime = fCountIn*fTime.fNum; - fAt = 0; + fAt = kStartOfMeasure; VisitChords(meas); - fAt = 0; + fAt = kStartOfMeasure; VisitNotes(meas, p, false); } void VLMIDIWriter::VisitNote(VLLyricsNote & n) { if (!(n.fTied & VLNote::kTiedWithPrev)) { - VLMIDIUserEvent event = {12, n.fPitch, fStanza, fMeasure, n.fVisual, fAt}; + VLMIDIUserEvent event = {12, n.fPitch, fStanza, n.fVisual, fAt}; MusicTrackNewUserEvent(fTrack, fNoteTime, reinterpret_cast(&event)); } - fAt += n.fDuration; + fAt.fAt = fAt.fAt+n.fDuration; fNoteTime += n.fDuration * (float)fTime.fDenom; } void VLMIDIWriter::VisitChord(VLChord & c) { if (c.fPitch != VLNote::kNoPitch) { - VLMIDIUserEvent event = {12, 0, fStanza, fMeasure, 0, fAt}; + VLMIDIUserEvent event = {12, 0, fStanza, 0, fAt}; MusicTrackNewUserEvent(fTrack, fChordTime, reinterpret_cast(&event)); } - fAt += c.fDuration; + fAt.fAt = fAt.fAt+c.fDuration; fChordTime += c.fDuration * (float)fTime.fDenom; } diff --git a/Sources/VLMIDIWriter.h b/Sources/VLMIDIWriter.h index a1dbde3..b8fbd16 100644 --- a/Sources/VLMIDIWriter.h +++ b/Sources/VLMIDIWriter.h @@ -16,9 +16,8 @@ struct VLMIDIUserEvent { uint32_t fLength; int8_t fPitch; // 0 -> Chord uint8_t fStanza; - int16_t fMeasure; - uint32_t fVisual; - VLFract fAt; + uint16_t fVisual; + VLLocation fAt; }; class VLMIDIWriter: public VLSongVisitor { @@ -34,11 +33,10 @@ private: MusicSequence fMusic; size_t fCountIn; MusicTrack fTrack; - size_t fMeasure; size_t fStanza; MusicTimeStamp fChordTime; MusicTimeStamp fNoteTime; - VLFraction fAt; + VLLocation fAt; VLFraction fTime; std::vector fVolta; }; diff --git a/Sources/VLModel.cpp b/Sources/VLModel.cpp index 7622cca..7dabbd2 100644 --- a/Sources/VLModel.cpp +++ b/Sources/VLModel.cpp @@ -109,7 +109,7 @@ std::string VLNote::Name(uint16_t accidental) const void VLNote::MakeRepresentable() { - if (fDuration > 1) + if (fDuration > VLFraction(1)) fDuration = 1; fVisual = kWhole | (fVisual & kAccidentalsMask); VLFraction part(1,1); @@ -251,7 +251,7 @@ void VLMeasure::DecomposeNotes(const VLProperties & prop, VLNoteList & decompose // Don't paint ourselves into a corner by leaving a non-representable // remainder. // - if (p.fDuration != c.fDuration && (c.fDuration-p.fDuration) % kMinDuration != 0) { + if (p.fDuration != c.fDuration && (c.fDuration-p.fDuration) % kMinDuration != VLFraction(0)) { r += kMinDuration; p.fDuration = c.fDuration-r; continue; @@ -296,7 +296,7 @@ void VLMeasure::DecomposeNotes(const VLProperties & prop, VLNoteList & decompose if (at.fDenom == 3 || at.fDenom > 4) { // // Break up notes not starting on quarter beat - // - Never cross middle of measure + // - Never cross middle of at.fMeasure // VLFraction middle; if (prop.fTime.fNum & 1) // Treat 5/4 as 3+2, not 2+3 @@ -324,8 +324,8 @@ void VLMeasure::DecomposeNotes(const VLProperties & prop, VLNoteList & decompose VLFraction sw24(1,24); VLFraction grid4(1, 4); VLFraction grid8(1, 8); - if ((p.fDuration == sw6 && (at % grid4 == 0)) - || (swing16 && p.fDuration == sw12 && (at % grid8 == 0)) + if ((p.fDuration == sw6 && !(at % grid4)) + || (swing16 && p.fDuration == sw12 && !(at % grid8)) ) { if (p.fDuration == c.fDuration && n2!=e && n->fDuration == p.fDuration && n2->fDuration >= p.fDuration @@ -337,8 +337,8 @@ void VLMeasure::DecomposeNotes(const VLProperties & prop, VLNoteList & decompose // p.fVisual = (p.fVisual+1) & ~VLNote::kTupletMask; } - } else if ((p.fDuration == sw12 && ((at+p.fDuration) % grid4 == 0)) - || (swing16 && p.fDuration == sw24 && ((at+p.fDuration) % grid8 == 0)) + } else if ((p.fDuration == sw12 && !((at+p.fDuration) % grid4)) + || (swing16 && p.fDuration == sw24 && !((at+p.fDuration) % grid8)) ) { // // Second swing note (8th triplet -> 8th) @@ -346,7 +346,7 @@ void VLMeasure::DecomposeNotes(const VLProperties & prop, VLNoteList & decompose if (!prevTriplets) p.fVisual &= ~VLNote::kTupletMask; } else if ((p.fDuration > kMinDuration) && - ((at % p.fDuration != 0) + ((at % p.fDuration != VLFraction(0)) || (p.fDuration != c.fDuration && 2*p.fDuration != c.fDuration) || (n!=e && n->fDuration != c.fDuration @@ -379,7 +379,7 @@ void VLMeasure::DecomposeNotes(const VLProperties & prop, VLNoteList & decompose p.fDuration = c.fDuration; p.fTied |= VLNote::kTiedWithPrev; p.fLyrics.clear(); - } while (c.fDuration > 0); + } while (c.fDuration > VLFraction(0)); i = n; } } @@ -499,21 +499,21 @@ void VLSong::clear() // // Deal with chords - a bit simpler // -void VLSong::AddChord(VLChord chord, size_t measure, VLFraction at) +void VLSong::AddChord(VLChord chord, VLLocation at) { // // Always keep an empty measure in reserve // - while (measure+1 >= fMeasures.size()) + while (at.fMeasure+1 >= fMeasures.size()) AddMeasure(); - VLChordList::iterator i = fMeasures[measure].fChords.begin(); + VLChordList::iterator i = fMeasures[at.fMeasure].fChords.begin(); VLFraction t(0); for (;;) { VLFraction tEnd = t+i->fDuration; - if (tEnd > at) { - if (t == at) { + if (tEnd > at.fAt) { + if (t == at.fAt) { // // Exact match, replace current // @@ -523,9 +523,9 @@ void VLSong::AddChord(VLChord chord, size_t measure, VLFraction at) // // Overlap, split current // - chord.fDuration = tEnd-at; - i->fDuration = at-t; - fMeasures[measure].fChords.insert(++i, chord); + chord.fDuration = tEnd-at.fAt; + i->fDuration = at.fAt-t; + fMeasures[at.fMeasure].fChords.insert(++i, chord); } break; // Exit here } @@ -534,24 +534,24 @@ void VLSong::AddChord(VLChord chord, size_t measure, VLFraction at) } } -void VLSong::DelChord(size_t measure, VLFraction at) +void VLSong::DelChord(VLLocation at) { - VLChordList::iterator i = fMeasures[measure].fChords.begin(); + VLChordList::iterator i = fMeasures[at.fMeasure].fChords.begin(); VLFraction t(0); for (;;) { - if (t == at) { + if (t == at.fAt) { // // Found it. Extend previous or make rest // - if (i != fMeasures[measure].fChords.begin()) { + if (i != fMeasures[at.fMeasure].fChords.begin()) { // // Extend previous // VLChordList::iterator j = i; --j; j->fDuration += i->fDuration; - fMeasures[measure].fChords.erase(i); + fMeasures[at.fMeasure].fChords.erase(i); } else { // // Turn into rest @@ -561,7 +561,7 @@ void VLSong::DelChord(size_t measure, VLFraction at) break; } VLFraction tEnd = t+i->fDuration; - if (tEnd > at) + if (tEnd > at.fAt) break; // Past the point, quit t = tEnd; ++i; @@ -569,17 +569,17 @@ void VLSong::DelChord(size_t measure, VLFraction at) // // Trim excess empty measures // - if (measure == fMeasures.size()-2 && fMeasures[measure].IsEmpty()) + if (at.fMeasure == fMeasures.size()-2 && fMeasures[at.fMeasure].IsEmpty()) fMeasures.pop_back(); } -uint8_t & FirstTie(VLMeasure & measure) +static uint8_t & FirstTie(VLMeasure & measure) { VLNoteList::iterator i = measure.fMelody.begin(); return i->fTied; } -uint8_t & LastTie(VLMeasure & measure) +static uint8_t & LastTie(VLMeasure & measure) { VLNoteList::iterator i = measure.fMelody.end(); --i; @@ -589,25 +589,25 @@ uint8_t & LastTie(VLMeasure & measure) // // Dealing with notes is similar, but we also have to handle ties // -void VLSong::AddNote(VLLyricsNote note, size_t measure, VLFraction at) +void VLSong::AddNote(VLLyricsNote note, VLLocation at) { // // Sanity check on accidentals // - note.fVisual = VLPitchAccidental(note.fPitch, note.fVisual, Properties(measure).fKey); + note.fVisual = VLPitchAccidental(note.fPitch, note.fVisual, Properties(at.fMeasure).fKey); // // Always keep an empty measure in reserve // - while (measure+1 >= fMeasures.size()) + while (at.fMeasure+1 >= fMeasures.size()) AddMeasure(); - VLNoteList::iterator i = fMeasures[measure].fMelody.begin(); + VLNoteList::iterator i = fMeasures[at.fMeasure].fMelody.begin(); VLFraction t(0); for (;;) { VLFraction tEnd = t+i->fDuration; - if (tEnd > at) { - if (t == at) { + if (tEnd > at.fAt) { + if (t == at.fAt) { // // Exact match, replace current // @@ -617,11 +617,11 @@ void VLSong::AddNote(VLLyricsNote note, size_t measure, VLFraction at) // if (i->fTied & VLNote::kTiedWithPrev) { i->fTied &= ~VLNote::kTiedWithPrev; - LastTie(fMeasures[measure-1]) &= ~VLNote::kTiedWithNext; + LastTie(fMeasures[at.fMeasure-1]) &= ~VLNote::kTiedWithNext; } if (i->fTied & VLNote::kTiedWithNext) { VLNoteList::iterator j = i; - for (size_t tiedMeas = measure+1; j->fTied & VLNote::kTiedWithNext;++tiedMeas) { + for (size_t tiedMeas = at.fMeasure+1; j->fTied & VLNote::kTiedWithNext;++tiedMeas) { j = fMeasures[tiedMeas].fMelody.begin(); j->fPitch = note.fPitch; j->fVisual= note.fVisual; @@ -639,28 +639,28 @@ void VLSong::AddNote(VLLyricsNote note, size_t measure, VLFraction at) // // Overlap, split current // - note.fDuration = tEnd-at; - i->fDuration = at-t; - i = fMeasures[measure].fMelody.insert(++i, note); + note.fDuration = tEnd-at.fAt; + i->fDuration = at.fAt-t; + i = fMeasures[at.fMeasure].fMelody.insert(++i, note); } if (i->fPitch == VLNote::kNoPitch) { // // Merge with adjacent rests // - if (i != fMeasures[measure].fMelody.begin()) { + if (i != fMeasures[at.fMeasure].fMelody.begin()) { VLNoteList::iterator j = i; --j; if (j->fPitch == VLNote::kNoPitch) { j->fDuration += i->fDuration; - fMeasures[measure].fMelody.erase(i); + fMeasures[at.fMeasure].fMelody.erase(i); i = j; } } VLNoteList::iterator j = i; ++j; - if (j != fMeasures[measure].fMelody.end() && j->fPitch == VLNote::kNoPitch) { + if (j != fMeasures[at.fMeasure].fMelody.end() && j->fPitch == VLNote::kNoPitch) { i->fDuration += j->fDuration; - fMeasures[measure].fMelody.erase(j); + fMeasures[at.fMeasure].fMelody.erase(j); } } break; // Exit here @@ -670,8 +670,8 @@ void VLSong::AddNote(VLLyricsNote note, size_t measure, VLFraction at) } i->fTied = 0; if (note.fTied & VLNote::kTiedWithPrev) // kTiedWithNext is NEVER user set - if (measure && i == fMeasures[measure].fMelody.begin()) { - VLNoteList::iterator j = fMeasures[measure-1].fMelody.end(); + if (at.fMeasure && i == fMeasures[at.fMeasure].fMelody.begin()) { + VLNoteList::iterator j = fMeasures[at.fMeasure-1].fMelody.end(); --j; if (j->fPitch == i->fPitch) { j->fTied |= VLNote::kTiedWithNext; @@ -680,40 +680,40 @@ void VLSong::AddNote(VLLyricsNote note, size_t measure, VLFraction at) } } -void VLSong::DelNote(size_t measure, VLFraction at) +void VLSong::DelNote(VLLocation at) { - VLNoteList::iterator i = fMeasures[measure].fMelody.begin(); + VLNoteList::iterator i = fMeasures[at.fMeasure].fMelody.begin(); VLFraction t(0); for (;;) { - if (t == at) { + if (t == at.fAt) { // // Found it. Break ties. // if (i->fTied & VLNote::kTiedWithNext) - FirstTie(fMeasures[measure+1]) &= ~VLNote::kTiedWithPrev; + FirstTie(fMeasures[at.fMeasure+1]) &= ~VLNote::kTiedWithPrev; if (i->fTied & VLNote::kTiedWithPrev) - LastTie(fMeasures[measure-1]) &= ~VLNote::kTiedWithNext; + LastTie(fMeasures[at.fMeasure-1]) &= ~VLNote::kTiedWithNext; // // Extend previous or make rest // - if (i != fMeasures[measure].fMelody.begin()) { + if (i != fMeasures[at.fMeasure].fMelody.begin()) { // // Extend previous // VLNoteList::iterator j = i; --j; j->fDuration += i->fDuration; - fMeasures[measure].fMelody.erase(i); + fMeasures[at.fMeasure].fMelody.erase(i); } else { // // Merge with next if it's a rest, otherwise, just turn into rest // VLNoteList::iterator j = i; ++j; - if (j != fMeasures[measure].fMelody.end() && j->fPitch == VLNote::kNoPitch) { + if (j != fMeasures[at.fMeasure].fMelody.end() && j->fPitch == VLNote::kNoPitch) { i->fDuration += j->fDuration; - fMeasures[measure].fMelody.erase(j); + fMeasures[at.fMeasure].fMelody.erase(j); } i->fPitch = VLNote::kNoPitch; i->fTied = 0; @@ -721,7 +721,7 @@ void VLSong::DelNote(size_t measure, VLFraction at) break; } VLFraction tEnd = t+i->fDuration; - if (tEnd > at) + if (tEnd > at.fAt) break; // Past the point, quit t = tEnd; ++i; @@ -729,19 +729,19 @@ void VLSong::DelNote(size_t measure, VLFraction at) // // Trim excess empty measures // - if (measure == fMeasures.size()-2 && fMeasures[measure].IsEmpty()) + if (at.fMeasure == fMeasures.size()-2 && fMeasures[at.fMeasure].IsEmpty()) fMeasures.pop_back(); } -VLNote VLSong::ExtendNote(size_t measure, VLFraction at) +VLNote VLSong::ExtendNote(VLLocation at) { - VLNoteList::iterator i = fMeasures[measure].fMelody.begin(); - VLNoteList::iterator end= fMeasures[measure].fMelody.end(); + VLNoteList::iterator i = fMeasures[at.fMeasure].fMelody.begin(); + VLNoteList::iterator end= fMeasures[at.fMeasure].fMelody.end(); if (i==end) return VLNote(); // Empty song, do nothing - for (VLFraction t(0); i != end && t+i->fDuration <= at; ++i) + for (VLFraction t(0); i != end && t+i->fDuration <= at.fAt; ++i) t += i->fDuration; if (i == end) @@ -752,17 +752,17 @@ VLNote VLSong::ExtendNote(size_t measure, VLFraction at) for (;;) { VLNoteList::iterator j=i; ++j; - if (j != fMeasures[measure].fMelody.end()) { + if (j != fMeasures[at.fMeasure].fMelody.end()) { // // Extend across next note/rest // i->fDuration += j->fDuration; - fMeasures[measure].fMelody.erase(j); - } else if (++measure < fMeasures.size()) { + fMeasures[at.fMeasure].fMelody.erase(j); + } else if (++at.fMeasure < fMeasures.size()) { // // Extend into next measure // - VLNoteList::iterator k = fMeasures[measure].fMelody.begin(); + VLNoteList::iterator k = fMeasures[at.fMeasure].fMelody.begin(); if (k->fTied & VLNote::kTiedWithPrev) { // // Already extended, extend further @@ -783,10 +783,10 @@ VLNote VLSong::ExtendNote(size_t measure, VLFraction at) if (!wasTied) break; i = k; - k = fMeasures[++measure].fMelody.begin(); + k = fMeasures[++at.fMeasure].fMelody.begin(); } } - if (measure+1 == fMeasures.size()) + if (at.fMeasure+1 == fMeasures.size()) AddMeasure(); } break; @@ -1220,23 +1220,23 @@ size_t VLSong::CountBotLedgers() const return 0; } -bool VLSong::FindWord(size_t stanza, size_t & measure, VLFraction & at) +bool VLSong::FindWord(size_t stanza, VLLocation & at) { - at += VLFraction(1,64); - return PrevWord(stanza, measure, at); + at.fAt = at.fAt+VLFraction(1,64); + return PrevWord(stanza, at); } -bool VLSong::PrevWord(size_t stanza, size_t & measure, VLFraction & at) +bool VLSong::PrevWord(size_t stanza, VLLocation & at) { do { - VLMeasure & meas = fMeasures[measure]; - VLNoteList::iterator note = fMeasures[measure].fMelody.begin(); - VLNoteList::iterator end = fMeasures[measure].fMelody.end(); + VLMeasure & meas = fMeasures[at.fMeasure]; + VLNoteList::iterator note = fMeasures[at.fMeasure].fMelody.begin(); + VLNoteList::iterator end = fMeasures[at.fMeasure].fMelody.end(); bool hasWord = false; VLFraction word(0); VLFraction now(0); - while (note != meas.fMelody.end() && now < at) { + while (note != meas.fMelody.end() && now < at.fAt) { if (!(note->fTied & VLNote::kTiedWithPrev) && note->fPitch != VLNote::kNoPitch ) @@ -1250,37 +1250,37 @@ bool VLSong::PrevWord(size_t stanza, size_t & measure, VLFraction & at) ++note; } if (hasWord) { - at = word; + at.fAt = word; return true; } else { - at = fProperties[meas.fPropIdx].fTime; + at.fAt = fProperties[meas.fPropIdx].fTime; } - } while (measure-- > 0); + } while (at.fMeasure-- > 0); - measure = 0; + at.fMeasure = 0; return false; } -bool VLSong::NextWord(size_t stanza, size_t & measure, VLFraction & at) +bool VLSong::NextWord(size_t stanza, VLLocation & at) { bool firstMeasure = true; do { - VLMeasure & meas = fMeasures[measure]; - VLNoteList::iterator note = fMeasures[measure].fMelody.begin(); - VLNoteList::iterator end = fMeasures[measure].fMelody.end(); + VLMeasure & meas = fMeasures[at.fMeasure]; + VLNoteList::iterator note = fMeasures[at.fMeasure].fMelody.begin(); + VLNoteList::iterator end = fMeasures[at.fMeasure].fMelody.end(); VLFraction now(0); while (note != meas.fMelody.end()) { if (!(note->fTied & VLNote::kTiedWithPrev) && note->fPitch != VLNote::kNoPitch - && (!firstMeasure || now>at) + && (!firstMeasure || now>at.fAt) ) if (note->fLyrics.size() < stanza || !(note->fLyrics[stanza-1].fKind & VLSyllable::kHasPrev) ) { - at = now; + at.fAt = now; return true; } @@ -1288,23 +1288,23 @@ bool VLSong::NextWord(size_t stanza, size_t & measure, VLFraction & at) ++note; } firstMeasure = false; - } while (++measure < fMeasures.size()); + } while (++at.fMeasure < fMeasures.size()); return false; } -std::string VLSong::GetWord(size_t stanza, size_t measure, VLFraction at) +std::string VLSong::GetWord(size_t stanza, VLLocation at) { std::string word; - while (measure < fMeasures.size()) { - VLMeasure & meas = fMeasures[measure]; + while (at.fMeasure < fMeasures.size()) { + VLMeasure & meas = fMeasures[at.fMeasure]; VLNoteList::iterator note = meas.fMelody.begin(); VLNoteList::iterator end = meas.fMelody.end(); VLFraction now(0); while (note != end) { - if (now >= at && note->fPitch != VLNote::kNoPitch + if (now >= at.fAt && note->fPitch != VLNote::kNoPitch && !(note->fTied & VLNote::kTiedWithPrev) ) { if (word.size()) @@ -1319,19 +1319,19 @@ std::string VLSong::GetWord(size_t stanza, size_t measure, VLFraction at) now += note->fDuration; ++note; } - at = 0; - ++measure; + at.fAt = VLFraction(0); + ++at.fMeasure; } return word; } -void VLSong::SetWord(size_t stanza, size_t measure, VLFraction at, std::string word, size_t * nextMeas, VLFract * nextAt) +void VLSong::SetWord(size_t stanza, VLLocation at, std::string word, VLLocation * nextAt) { // // Always keep an empty measure in reserve // - while (measure+1 >= fMeasures.size()) + while (at.fMeasure+1 >= fMeasures.size()) AddMeasure(); uint8_t kind = 0; @@ -1342,9 +1342,9 @@ void VLSong::SetWord(size_t stanza, size_t measure, VLFraction at, std::string w } state = kFindFirst; do { - VLMeasure & meas = fMeasures[measure]; - VLNoteList::iterator note = fMeasures[measure].fMelody.begin(); - VLNoteList::iterator end = fMeasures[measure].fMelody.end(); + VLMeasure & meas = fMeasures[at.fMeasure]; + VLNoteList::iterator note = fMeasures[at.fMeasure].fMelody.begin(); + VLNoteList::iterator end = fMeasures[at.fMeasure].fMelody.end(); VLFraction now(0); while (note != meas.fMelody.end()) { @@ -1353,7 +1353,7 @@ void VLSong::SetWord(size_t stanza, size_t measure, VLFraction at, std::string w ) switch (state) { case kFindFirst: - if (now < at) + if (now < at.fAt) break; // Not yet there, skip this note state = kOverwrite; // Fall through @@ -1402,13 +1402,10 @@ void VLSong::SetWord(size_t stanza, size_t measure, VLFraction at, std::string w kind &= ~VLSyllable::kHasPrev; break; } case kCleanup: - if (nextMeas) { - *nextMeas = measure; - nextMeas = 0; - } if (nextAt) { - *nextAt = now; - nextAt = 0; + nextAt->fMeasure = at.fMeasure; + nextAt->fAt = now; + nextAt = 0; } // // Delete all subsequent syllables with kHasPrev set @@ -1424,12 +1421,12 @@ void VLSong::SetWord(size_t stanza, size_t measure, VLFraction at, std::string w now += note->fDuration; ++note; } - at = 0; - } while (++measure < fMeasures.size()); - if (nextMeas) - *nextMeas = 0; - if (nextAt) - *nextAt = VLFraction(0); + at.fAt = VLFraction(0); + } while (++at.fMeasure < fMeasures.size()); + if (nextAt) { + nextAt->fMeasure = 0; + nextAt->fAt = VLFraction(0); + } } void VLSong::AddRepeat(size_t beginMeasure, size_t endMeasure, int times) @@ -1937,7 +1934,7 @@ void VLSong::PasteMeasures(size_t beginMeasure, const VLSong & measures, int mod if (endProp > beginProp && fProperties[propAt] == endProp[-1]) --endProp; } - int postOffset = endProp - beginProp; + ptrdiff_t postOffset = endProp - beginProp; fProperties.insert(fProperties.begin()+propAt, beginProp, endProp); fMeasures.insert(fMeasures.begin()+beginMeasure, diff --git a/Sources/VLModel.h b/Sources/VLModel.h index 4fecec9..b3e94cd 100644 --- a/Sources/VLModel.h +++ b/Sources/VLModel.h @@ -65,36 +65,83 @@ inline VLFraction operator%(VLFraction one, VLFraction other) return one %= other; } -inline bool operator==(VLFraction one, VLFraction other) +inline bool operator!(VLFract fract) +{ + return !fract.fNum; +} + +inline bool operator==(VLFract one, VLFract other) { return one.fNum*other.fDenom == other.fNum*one.fDenom; } -inline bool operator!=(VLFraction one, VLFraction other) +inline bool operator!=(VLFract one, VLFract other) { return one.fNum*other.fDenom != other.fNum*one.fDenom; } -inline bool operator<(VLFraction one, VLFraction other) +inline bool operator<(VLFract one, VLFract other) { return one.fNum*other.fDenom < other.fNum*one.fDenom; } -inline bool operator>(VLFraction one, VLFraction other) +inline bool operator>(VLFract one, VLFract other) { return one.fNum*other.fDenom > other.fNum*one.fDenom; } -inline bool operator<=(VLFraction one, VLFraction other) +inline bool operator<=(VLFract one, VLFract other) { return one.fNum*other.fDenom <= other.fNum*one.fDenom; } -inline bool operator>=(VLFraction one, VLFraction other) +inline bool operator>=(VLFract one, VLFract other) { return one.fNum*other.fDenom >= other.fNum*one.fDenom; } +#pragma mark - +#pragma mark struct VLLocation + +struct VLLocation { + uint32_t fMeasure; + VLFract fAt; +}; + +inline bool operator==(const VLLocation & one, const VLLocation & other) +{ + return one.fMeasure == other.fMeasure && one.fAt == other.fAt; +} + +inline bool operator!=(const VLLocation & one, const VLLocation & other) +{ + return one.fMeasure != other.fMeasure || one.fAt != other.fAt; +} + +inline bool operator<(const VLLocation & one, const VLLocation & other) +{ + return one.fMeasure < other.fMeasure + || (one.fMeasure == other.fMeasure && one.fAt < other.fAt); +} + +inline bool operator<=(const VLLocation & one, const VLLocation & other) +{ + return one.fMeasure < other.fMeasure + || (one.fMeasure == other.fMeasure && one.fAt <= other.fAt); +} + +inline bool operator>(const VLLocation & one, const VLLocation & other) +{ + return one.fMeasure > other.fMeasure + || (one.fMeasure == other.fMeasure && one.fAt > other.fAt); +} + +inline bool operator>=(const VLLocation & one, const VLLocation & other) +{ + return one.fMeasure > other.fMeasure + || (one.fMeasure == other.fMeasure && one.fAt >= other.fAt); +} + #pragma mark - #pragma mark class VLNote @@ -324,8 +371,8 @@ public: VLPropertyList fProperties; VLMeasureList fMeasures; VLRepeatList fRepeats; - int8_t fGoToCoda; - int8_t fCoda; + int16_t fGoToCoda; + int16_t fCoda; // // Iterate over measures in performance order @@ -367,11 +414,11 @@ public: iterator begin() { return iterator(*this, false); } iterator end() { return iterator(*this, true); } - void AddChord(VLChord chord, size_t measure, VLFraction at); - void AddNote(VLLyricsNote note, size_t measure, VLFraction at); - void DelChord(size_t measure, VLFraction at); - void DelNote(size_t measure, VLFraction at); - VLNote ExtendNote(size_t measure, VLFraction at); + void AddChord(VLChord chord, VLLocation at); + void AddNote(VLLyricsNote note, VLLocation at); + void DelChord(VLLocation at); + void DelNote(VLLocation at); + VLNote ExtendNote(VLLocation at); void AddRepeat(size_t beginMeasure, size_t endMeasure, int times); void DelRepeat(size_t beginMeasure, size_t endMeasure); void AddEnding(size_t beginMeasure, size_t endMeasure, size_t volta); @@ -391,12 +438,12 @@ public: void ChangeDivisions(int section, int newDivisions); void ChangeTime(int section, VLFraction newTime); - bool FindWord(size_t stanza, size_t & measure, VLFraction & at); - bool PrevWord(size_t stanza, size_t & measure, VLFraction & at); - bool NextWord(size_t stanza, size_t & measure, VLFraction & at); - std::string GetWord(size_t stanza, size_t measure, VLFraction at); - void SetWord(size_t stanza, size_t measure, VLFraction at, std::string word, - size_t * nextMeas=0, VLFract * nextAt=0); + bool FindWord(size_t stanza, VLLocation & at); + bool PrevWord(size_t stanza, VLLocation & at); + bool NextWord(size_t stanza, VLLocation & at); + std::string GetWord(size_t stanza, VLLocation at); + void SetWord(size_t stanza, VLLocation at, std::string word, + VLLocation * nextAt=0); enum { kInsert, diff --git a/Sources/VLPListDocument.mm b/Sources/VLPListDocument.mm index 21df73c..b95f1d3 100644 --- a/Sources/VLPListDocument.mm +++ b/Sources/VLPListDocument.mm @@ -96,7 +96,7 @@ void VLPlistVisitor::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas) NSMutableDictionary * md = [NSMutableDictionary dictionaryWithObjectsAndKeys: - [NSNumber numberWithInt:m], @"measure", + [NSNumber numberWithUnsignedInt:m], @"measure", [NSNumber numberWithInt:meas.fPropIdx], @"properties", fNotes, @"melody", fChords, @"chords", nil]; @@ -112,7 +112,7 @@ void VLPlistVisitor::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas) [md setObject: [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:!last], @"last", - [NSNumber numberWithInt:volta], @"volta", + [NSNumber numberWithUnsignedInt:volta], @"volta", nil] forKey: @"begin-ending"]; if (fSong->DoesEndRepeat(m+1, ×)) @@ -124,7 +124,7 @@ void VLPlistVisitor::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas) [md setObject: [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:!last], @"last", - [NSNumber numberWithInt:volta], @"volta", + [NSNumber numberWithUnsignedInt:volta], @"volta", nil] forKey: @"end-ending"]; if (fSong->fGoToCoda == m+1) @@ -305,9 +305,9 @@ enum { - (void)readMelody:(NSArray *)melody inMeasure:(size_t)measNo onsets:(int *)onsets lyrics:(uint8_t *)prevKind { - VLFraction at(0); - int lastOnset = 0; - VLFraction tiedStart(0); + VLLocation at = {measNo, VLFraction(0)}; + int lastOnset = 0; + VLLocation tiedStart = {measNo, VLFraction(0)}; VLLyricsNote tiedNote; for (NSEnumerator * ne = [melody objectEnumerator]; @@ -328,13 +328,13 @@ enum { [[ndict objectForKey:@"normalNotes"] intValue]); if ([[ndict objectForKey:@"tied"] intValue] & VLNote::kTiedWithPrev) { - if (at != 0) { + if (at.fAt != VLFraction(0)) { // // Extend preceding note // tiedNote.fDuration += note.fDuration; - song->DelNote(measNo, tiedStart); - song->AddNote(tiedNote, measNo, tiedStart); + song->DelNote(tiedStart); + song->AddNote(tiedNote, tiedStart); goto advanceAt; } else { @@ -376,10 +376,10 @@ enum { tiedStart = at; tiedNote = note; - song->AddNote(note, measNo, at); + song->AddNote(note, at); if (!(note.fTied & VLNote::kTiedWithPrev)) { - VLFraction inQuarter = at % VLFraction(1,4); + VLFraction inQuarter = at.fAt % VLFraction(1,4); int onset = inQuarter.fNum * 48 / inQuarter.fDenom; ++onsets[onset]; switch (onset) { @@ -398,13 +398,13 @@ enum { } } advanceAt: - at += note.fDuration; + at.fAt = at.fAt + note.fDuration; } } - (void)readChords:(NSArray *)chords inMeasure:(size_t)measNo { - VLFraction at(0); + VLLocation at = {measNo, VLFraction(0)}; for (NSEnumerator * ce = [chords objectEnumerator]; NSDictionary * cdict = [ce nextObject]; @@ -420,9 +420,9 @@ advanceAt: chord.fRootAccidental = [[cdict objectForKey:@"rootvisual"] intValue]; chord.fSteps = [[cdict objectForKey:@"steps"] intValue]; - song->AddChord(chord, measNo, at); + song->AddChord(chord, at); - at += chord.fDuration; + at.fAt = at.fAt + chord.fDuration; } } diff --git a/Sources/VLSheetView.h b/Sources/VLSheetView.h index 438ebe5..2e929b1 100644 --- a/Sources/VLSheetView.h +++ b/Sources/VLSheetView.h @@ -81,8 +81,7 @@ enum VLCursorVisual { NSPoint fLastNoteCenter; NSTrackingRectTag fCursorTracking; VLRegion fCursorRegion; - int fCursorMeasure; - VLFract fCursorAt; + VLLocation fCursorLocation; int fCursorVertPos; uint16_t fCursorVisual; size_t fCursorStanza; @@ -95,10 +94,8 @@ enum VLCursorVisual { size_t fVolta; size_t fVoltaOK; VLLayout * fLayout; - int fHighlightStartMeasure; - VLFract fHighlightStartAt; - int fHighlightEndMeasure; - VLFract fHighlightEndAt; + VLLocation fHighlightStart; + VLLocation fHighlightEnd; size_t fHighlightStanza; VLKeyValueUndo * fUndo; @@ -138,7 +135,7 @@ enum VLCursorVisual { - (float) noteYInSection:(int)section withPitch:(int)pitch; - (VLMusicElement)accidentalForVisual:(uint16_t)visual; - (float) noteYInMeasure:(int)measure withGrid:(int)vertPos; -- (float) noteXInMeasure:(int)measure at:(VLFraction)at; +- (float) noteXAt:(VLLocation)at; - (void) needsRecalculation; - (void) scrollMeasureToVisible:(int)measure; diff --git a/Sources/VLSheetView.mm b/Sources/VLSheetView.mm index 47a721a..108cd55 100644 --- a/Sources/VLSheetView.mm +++ b/Sources/VLSheetView.mm @@ -233,9 +233,9 @@ static float sFlatPos[] = { + [self noteYInGrid:vertPos]; } -- (float) noteXInMeasure:(int)measure at:(VLFraction)at +- (float) noteXAt:(VLLocation)at { - return fLayout->NotePosition(measure, at); + return fLayout->NotePosition(at); } - (void) scrollMeasureToVisible:(int)measure @@ -764,9 +764,9 @@ const float kSemiFloor = -1.0f*kLineH; if (measure < 0 || measure > kLayout.NumMeasures()) return fCursorRegion = kRegionNowhere; - fCursorMeasure = measure+fLayout->FirstMeasure(system); + fCursorLocation.fMeasure = measure+fLayout->FirstMeasure(system); - if (fCursorMeasure > [self song]->fMeasures.size()) + if (fCursorLocation.fMeasure > [self song]->fMeasures.size()) return fCursorRegion = kRegionNowhere; else return fCursorRegion = kRegionMeasure; @@ -780,18 +780,18 @@ const float kSemiFloor = -1.0f*kLineH; loc.x -= group*(kLayout.DivPerGroup()+1)*kNoteW; int div = static_cast(roundf(loc.x / kNoteW))-1; div = std::min(std::max(div, 0), kLayout.DivPerGroup()-1); - fCursorMeasure = measure+fLayout->FirstMeasure(system); - if (fCursorMeasure > [self song]->fMeasures.size()) + fCursorLocation.fMeasure = measure+fLayout->FirstMeasure(system); + if (fCursorLocation.fMeasure > [self song]->fMeasures.size()) return fCursorRegion = kRegionNowhere; - fCursorAt = VLFraction(div+group*kLayout.DivPerGroup(), 4*song->Properties(fCursorMeasure).fDivisions); + fCursorLocation.fAt = VLFraction(div+group*kLayout.DivPerGroup(), 4*song->Properties(fCursorLocation.fMeasure).fDivisions); if (loc.y >= kSystemBaseline+kChordY) { // // Chord, round to quarters // - int scale = fCursorAt.fDenom / 4; - fCursorAt = VLFraction(fCursorAt.fNum / scale, 4); + int scale = fCursorLocation.fAt.fDenom / 4; + fCursorLocation.fAt = VLFraction(fCursorLocation.fAt.fNum / scale, 4); return fCursorRegion = kRegionChord; } else if (loc.y < kSystemBaseline+kLyricsY) { fCursorStanza = static_cast((kSystemBaseline+kLyricsY-loc.y) / kLyricsH) @@ -855,7 +855,7 @@ const float kSemiFloor = -1.0f*kLineH; break; case kRegionLyrics: if (extend && [[self editTarget] canExtendSelection:kRegionLyrics]) { - [[self editTarget] extendSelection:fCursorMeasure at:fCursorAt]; + [[self editTarget] extendSelection:fCursorLocation]; } else { fSelEnd = -1; [self editLyrics]; @@ -881,7 +881,7 @@ const float kSemiFloor = -1.0f*kLineH; if (prevRegion == kRegionMeasure) [self adjustSelection:event]; else if ([[self editTarget] canExtendSelection:[self findRegionForEvent:event]]) - [[self editTarget] extendSelection:fCursorMeasure at:fCursorAt]; + [[self editTarget] extendSelection:fCursorLocation]; } - (void) keyDown:(NSEvent *)event diff --git a/Sources/VLSheetViewChords.h b/Sources/VLSheetViewChords.h index 152f2e8..6ebdd3f 100644 --- a/Sources/VLSheetViewChords.h +++ b/Sources/VLSheetViewChords.h @@ -13,14 +13,12 @@ @interface VLChordEditable : VLEditable { VLSheetView * fView; VLSong * fSong; - int fMeasure; - VLFract fAt; + VLLocation fSelection; } - (VLChordEditable *)initWithView:(VLSheetView *)view song:(VLSong *)song - measure:(int)measure - at:(VLFract)at; + at:(VLLocation)at; - (NSString *) stringValue; - (void) setStringValue:(NSString*)val; - (BOOL) validValue:(NSString*)val; @@ -34,7 +32,7 @@ - (void) editChord; - (void) drawChordsForSystem:(int)system; -- (void) highlightChordInMeasure:(int)measure at:(VLFraction)at; +- (void) highlightChord:(VLLocation)at; @end diff --git a/Sources/VLSheetViewChords.mm b/Sources/VLSheetViewChords.mm index b39b1d3..ab6e9a0 100644 --- a/Sources/VLSheetViewChords.mm +++ b/Sources/VLSheetViewChords.mm @@ -61,14 +61,12 @@ std::string NormalizeName(NSString* rawName) - (VLChordEditable *)initWithView:(VLSheetView *)view song:(VLSong *)song - measure:(int)measure - at:(VLFract)at; + at:(VLLocation)at; { - self = [super init]; - fView = view; - fSong = song; - fMeasure= measure; - fAt = at; + self = [super init]; + fView = view; + fSong = song; + fSelection = at; [fView setNeedsDisplay: YES]; @@ -77,23 +75,23 @@ std::string NormalizeName(NSString* rawName) - (NSString *) stringValue { - if (fMeasure >= fSong->CountMeasures()) + if (fSelection.fMeasure >= fSong->CountMeasures()) return @""; - const VLMeasure measure = fSong->fMeasures[fMeasure]; + const VLMeasure measure = fSong->fMeasures[fSelection.fMeasure]; const VLChordList & chords = measure.fChords; VLFraction at(0); for (VLChordList::const_iterator chord = chords.begin(); - chord != chords.end() && at <= fAt; + chord != chords.end() && at <= fSelection.fAt; ++chord ) { - if (at == fAt && chord->fPitch != VLNote::kNoPitch) { + if (at == fSelection.fAt && chord->fPitch != VLNote::kNoPitch) { // // Found it! // VLSoundOut::Instance()->PlayChord(*chord); - const VLProperties & prop = fSong->Properties(fMeasure); + const VLProperties & prop = fSong->Properties(fSelection.fMeasure); std::string name, ext, root; chord->Name(name, ext, root, prop.fKey > 0); @@ -114,14 +112,14 @@ std::string NormalizeName(NSString* rawName) std::string chordName = NormalizeName(val); if (!chordName.size()) { [[fView document] willChangeSong]; - fSong->DelChord(fMeasure, fAt); + fSong->DelChord(fSelection); [[fView document] didChangeSong]; } else { VLChord chord(chordName); VLSoundOut::Instance()->PlayChord(chord); [[fView document] willChangeSong]; - fSong->AddChord(chord, fMeasure, fAt); + fSong->AddChord(chord, fSelection); [[fView document] didChangeSong]; } } @@ -144,29 +142,29 @@ std::string NormalizeName(NSString* rawName) { const VLProperties & prop = fSong->fProperties.front(); - fAt = fAt+VLFraction(1,4); - if (fAt >= prop.fTime) { - fAt = VLFraction(0,4); - fMeasure = (fMeasure+1) % fSong->CountMeasures(); - [fView scrollMeasureToVisible:fMeasure]; + fSelection.fAt = fSelection.fAt+VLFraction(1,4); + if (fSelection.fAt >= prop.fTime) { + fSelection.fAt = VLFraction(0,4); + fSelection.fMeasure = (fSelection.fMeasure+1) % fSong->CountMeasures(); + [fView scrollMeasureToVisible:fSelection.fMeasure]; } } - (void) moveToPrev { - if (fAt < VLFraction(1,4)) { - const VLProperties & prop = fSong->fProperties.front(); - fAt = prop.fTime - VLFraction(1,4); - fMeasure = - (fMeasure+fSong->CountMeasures()-1) % fSong->CountMeasures(); - [fView scrollMeasureToVisible:fMeasure]; + if (fSelection.fAt < VLFraction(1,4)) { + const VLProperties & prop = fSong->fProperties.front(); + fSelection.fAt = prop.fTime - VLFraction(1,4); + fSelection.fMeasure = + (fSelection.fMeasure+fSong->CountMeasures()-1) % fSong->CountMeasures(); + [fView scrollMeasureToVisible:fSelection.fMeasure]; } else - fAt = fAt-VLFraction(1,4); + fSelection.fAt = fSelection.fAt-VLFraction(1,4); } - (void) highlightCursor { - [fView highlightChordInMeasure:fMeasure at:fAt]; + [fView highlightChord:fSelection]; } @end @@ -231,16 +229,16 @@ std::string NormalizeName(NSString* rawName) break; const VLMeasure measure = song->fMeasures[measIdx]; const VLChordList & chords = measure.fChords; - VLFraction at(0); + VLLocation at = {measIdx, VLFraction(0)}; for (VLChordList::const_iterator chord = chords.begin(); chord != chords.end(); ++chord ) { NSAttributedString * chordName = [self stringWithChord:*chord]; NSPoint chordLoc = - NSMakePoint([self noteXInMeasure:measIdx at:at], kSystemY+kChordY); + NSMakePoint([self noteXAt:at], kSystemY+kChordY); [chordName drawAtPoint:chordLoc]; - at += chord->fDuration; + at.fAt = at.fAt+chord->fDuration; } } } @@ -251,18 +249,17 @@ std::string NormalizeName(NSString* rawName) [[VLChordEditable alloc] initWithView:self song:[self song] - measure:fCursorMeasure - at:fCursorAt]; + at:fCursorLocation]; [self setEditTarget:e]; [fFieldEditor selectText:self]; } -- (void) highlightChordInMeasure:(int)measure at:(VLFraction)at +- (void) highlightChord:(VLLocation)at { const VLProperties & prop = [self song]->fProperties.front(); - const float kSystemY = [self systemY:fLayout->SystemForMeasure(measure)]; + const float kSystemY = [self systemY:fLayout->SystemForMeasure(at.fMeasure)]; NSRect r = - NSMakeRect([self noteXInMeasure:measure at:at]-kNoteW*0.5f, + NSMakeRect([self noteXAt:at]-kNoteW*0.5f, kSystemY+kChordY, prop.fDivisions*kNoteW, kChordH); [[NSColor colorWithCalibratedWhite:0.8f alpha:1.0f] setFill]; NSRectFillUsingOperation(r, NSCompositePlusDarker); diff --git a/Sources/VLSheetViewLyrics.h b/Sources/VLSheetViewLyrics.h index ce71680..ef4cb26 100644 --- a/Sources/VLSheetViewLyrics.h +++ b/Sources/VLSheetViewLyrics.h @@ -14,20 +14,16 @@ VLSheetView * fView; VLSong * fSong; size_t fStanza; - size_t fMeasure; - VLFract fAt; - size_t fAnchorMeas; - VLFract fAnchorAt; - size_t fNextMeas; - VLFract fNextAt; + VLLocation fSelection; + VLLocation fAnchor; + VLLocation fNext; NSString * fText; } - (VLLyricsEditable *)initWithView:(VLSheetView *)view song:(VLSong *)song stanza:(int)stanza - measure:(int)measure - at:(VLFract)at; + at:(VLLocation)at; - (NSString *) stringValue; - (void) setStringValue:(NSString*)val; - (BOOL) validValue:(NSString*)val; @@ -41,9 +37,8 @@ - (void) editLyrics; - (void) drawLyricsForSystem:(int)system stanza:(size_t)stanza; -- (void) highlightLyricsInStanza:(size_t)stanza measure:(int)measure at:(VLFraction)at; -- (void) highlightTextInStanza:(size_t)stanza startMeasure:(int)startMeasure at:(VLFraction)startAt - endMeasure:(int)endMeasure at:(VLFraction)endAt; +- (void) highlightLyricsInStanza:(size_t)stanza at:(VLLocation)at; +- (void) highlightTextInStanza:(size_t)stanza start:(VLLocation)start end:(VLLocation)end; @end diff --git a/Sources/VLSheetViewLyrics.mm b/Sources/VLSheetViewLyrics.mm index bfa604d..aae2767 100644 --- a/Sources/VLSheetViewLyrics.mm +++ b/Sources/VLSheetViewLyrics.mm @@ -20,35 +20,28 @@ - (void)highlightWord { - size_t endMeas = fMeasure; - VLFraction endAt = fAt; - if (!fSong->NextWord(fStanza, endMeas, endAt)) - endMeas = 1000; - [fView highlightTextInStanza:fStanza startMeasure:fMeasure at:fAt endMeasure:endMeas at:endAt]; - std::string word = fSong->GetWord(fStanza, fMeasure, fAt); + VLLocation end = fSelection; + if (!fSong->NextWord(fStanza, end)) + end.fMeasure = 1000; + [fView highlightTextInStanza:fStanza start:fSelection end:end]; + std::string word = fSong->GetWord(fStanza, fSelection); fText = [[NSString alloc] initWithUTF8String:word.c_str()]; } - (VLLyricsEditable *)initWithView:(VLSheetView *)view song:(VLSong *)song stanza:(int)stanza - measure:(int)measure - at:(VLFract)at + at:(VLLocation)at { self = [super init]; fView = view; fSong = song; fStanza = stanza; - fMeasure = measure; - fAt = at; - fAnchorMeas = measure; - fAnchorAt = at; - fNextMeas = fMeasure; - fNextAt = fAt; + fSelection = at; + fAnchor = at; + fNext = at; - VLFraction At = fAt; - fSong->FindWord(fStanza, fMeasure, At); - fAt = At; + fSong->FindWord(fStanza, fSelection); [self highlightWord]; return self; @@ -67,7 +60,7 @@ - (void) setStringValue:(NSString *)val { [[fView document] willChangeSong]; - fSong->SetWord(fStanza, fMeasure, fAt, val ? [val UTF8String] : "", &fNextMeas, &fNextAt); + fSong->SetWord(fStanza, fSelection, val ? [val UTF8String] : "", &fNext); [[fView document] didChangeSong]; } @@ -78,46 +71,38 @@ - (void) moveToNext { - if (fNextMeas != fMeasure || fNextAt != fAt) { - fMeasure = fNextMeas; - VLFraction at = fNextAt; - fSong->FindWord(fStanza, fMeasure, at); - fAt = at; + if (fNext != fSelection) { + fSelection = fNext; + fSong->FindWord(fStanza, fSelection); } else { - VLFraction at = fAt; - if (!fSong->NextWord(fStanza, fMeasure, at)) { - fMeasure = 0; - at = 0; - fSong->FindWord(fStanza, fMeasure, at); + if (!fSong->NextWord(fStanza, fSelection)) { + fSelection.fMeasure = 0; + fSelection.fAt = VLFraction(0); + fSong->FindWord(fStanza, fSelection); } - fAt = at; } - fNextMeas = fMeasure; - fNextAt = fAt; + fNext = fSelection; [self highlightWord]; - [fView scrollMeasureToVisible:fMeasure]; + [fView scrollMeasureToVisible:fSelection.fMeasure]; } - (void) moveToPrev { - VLFraction at = fAt; - if (!fSong->PrevWord(fStanza, fMeasure, at)) { - fMeasure = fSong->CountMeasures()-1; - at = fSong->Properties(fMeasure).fTime; - fSong->PrevWord(fStanza, fMeasure, at); + if (!fSong->PrevWord(fStanza, fSelection)) { + fSelection.fMeasure = fSong->CountMeasures()-1; + fSelection.fAt = fSong->Properties(fSelection.fMeasure).fTime; + fSong->PrevWord(fStanza, fSelection); } - fAt = at; - fNextMeas = fMeasure; - fNextAt = fAt; + fNext = fSelection; [self highlightWord]; - [fView scrollMeasureToVisible:fMeasure]; + [fView scrollMeasureToVisible:fSelection.fMeasure]; } - (void) highlightCursor { - std::string word = fSong->GetWord(fStanza, fMeasure, fAt); + std::string word = fSong->GetWord(fStanza, fSelection); if (!word.size()) - [fView highlightLyricsInStanza:fStanza measure:fMeasure at:fAt]; + [fView highlightLyricsInStanza:fStanza at:fSelection]; } - (BOOL)canExtendSelection:(VLRegion)region @@ -125,40 +110,33 @@ return region == kRegionLyrics; } -- (void)extendSelection:(size_t)measure at:(VLFract)At +- (void)extendSelection:(VLLocation)at { - VLFraction at = At; - if (!fSong->FindWord(fStanza, measure, at)) + if (!fSong->FindWord(fStanza, at)) return; - if (measure < fAnchorMeas || (measure==fAnchorMeas && at < fAnchorAt)) { + if (at < fAnchor) { // // Backward from anchor // - fMeasure = measure; - fAt = at; - measure = fAnchorMeas; - at = fAnchorAt; + fSelection = at; + at = fAnchor; } else { // // Forward from anchor // - fMeasure = fAnchorMeas; - at = fAnchorAt; - fSong->FindWord(fStanza, fMeasure, at); - fAt = at; - at = At; + fSelection = fAnchor; + fSong->FindWord(fStanza, fSelection); } - if (!fSong->NextWord(fStanza, measure, at)) - measure = 1000; - [fView highlightTextInStanza:fStanza startMeasure:fMeasure at:fAt endMeasure:measure at:at]; + if (!fSong->NextWord(fStanza, at)) + at.fMeasure = 1000; + [fView highlightTextInStanza:fStanza start:fSelection end:at]; std::string text; - size_t textMeas = fMeasure; - VLFraction textAt = fAt; - while (textMeas < measure || (textMeas == measure && textAt < at)) { + VLLocation textAt = fSelection; + while (textAt < at) { if (text.size()) text += ' '; - text += fSong->GetWord(fStanza, textMeas, textAt); - fSong->NextWord(fStanza, textMeas, textAt); + text += fSong->GetWord(fStanza, textAt); + fSong->NextWord(fStanza, textAt); } [fText release]; fText = [[NSString alloc] initWithUTF8String:text.c_str()]; @@ -236,7 +214,7 @@ float VLCocoaFontHandler::Width(const char * utf8Text) break; const VLMeasure measure = song->fMeasures[measIdx]; const VLNoteList & notes = measure.fMelody; - VLFraction at(0); + VLLocation at = {measIdx, VLFraction(0)}; for (VLNoteList::const_iterator note = notes.begin(); note != notes.end(); ++note @@ -247,18 +225,15 @@ float VLCocoaFontHandler::Width(const char * utf8Text) ; } else { bool highlight = stanza == fHighlightStanza - && (measIdx > fHighlightStartMeasure - || (measIdx == fHighlightStartMeasure && at >= fHighlightStartAt)) - && (measIdx < fHighlightEndMeasure - || (measIdx == fHighlightEndMeasure && at < fHighlightEndAt)); + && at >= fHighlightStart && at < fHighlightEnd; if (highlight && !sHighlightColor) sHighlightColor = [[self textBackgroundColorForSystem:system] shadowWithLevel:0.2]; text.AddSyllable(note->fLyrics[stanza-1], - [self noteXInMeasure:measIdx at:at], + [self noteXAt:at], highlight); } - at += note->fDuration; + at.fAt = at.fAt+note->fDuration; } } @@ -273,30 +248,26 @@ float VLCocoaFontHandler::Width(const char * utf8Text) initWithView:self song:[self song] stanza:fCursorStanza - measure:fCursorMeasure - at:fCursorAt]; + at:fCursorLocation]; [self setEditTarget:e]; [fFieldEditor selectText:self]; } -- (void) highlightLyricsInStanza:(size_t)stanza measure:(int)measure at:(VLFraction)at +- (void) highlightLyricsInStanza:(size_t)stanza at:(VLLocation)at { - const float kSystemY = [self systemY:fLayout->SystemForMeasure(measure)]; + const float kSystemY = [self systemY:fLayout->SystemForMeasure(at.fMeasure)]; NSRect r = - NSMakeRect([self noteXInMeasure:measure at:at]-kNoteW*0.5f, + NSMakeRect([self noteXAt:at]-kNoteW*0.5f, kSystemY+kLyricsY-stanza*kLyricsH, kNoteW, kLyricsH); [[NSColor colorWithCalibratedWhite:0.8f alpha:1.0f] setFill]; NSRectFillUsingOperation(r, NSCompositePlusDarker); } -- (void) highlightTextInStanza:(size_t)stanza startMeasure:(int)startMeasure at:(VLFraction)startAt - endMeasure:(int)endMeasure at:(VLFraction)endAt +- (void) highlightTextInStanza:(size_t)stanza start:(VLLocation)start end:(VLLocation)end { - fHighlightStanza = stanza; - fHighlightStartMeasure = startMeasure; - fHighlightStartAt = startAt; - fHighlightEndMeasure = endMeasure; - fHighlightEndAt = endAt; + fHighlightStanza = stanza; + fHighlightStart = start; + fHighlightEnd = end; [self setNeedsDisplay:YES]; } diff --git a/Sources/VLSheetViewNotes.h b/Sources/VLSheetViewNotes.h index 3b1a4cf..6924c66 100644 --- a/Sources/VLSheetViewNotes.h +++ b/Sources/VLSheetViewNotes.h @@ -14,7 +14,7 @@ - (void) drawNotesForSystem:(int)system; - (void) addNoteAtCursor; -- (void) drawNoteCursor:(int)vertPos inMeasure:(size_t)measure at:(VLFract)at visual:(uint16_t)visual; +- (void) drawNoteCursor:(int)vertPos at:(VLLocation)at visual:(uint16_t)visual; @end diff --git a/Sources/VLSheetViewNotes.mm b/Sources/VLSheetViewNotes.mm index bb38df7..f9dc884 100644 --- a/Sources/VLSheetViewNotes.mm +++ b/Sources/VLSheetViewNotes.mm @@ -21,20 +21,20 @@ - (void) addNoteAtCursor { - if (fCursorMeasure > -1 && fCursorVertPos != kCursorNoPitch) { + if (fCursorLocation.fMeasure > -1 && fCursorVertPos != kCursorNoPitch) { [[self document] willChangeSong]; if (fCursorVisual == kCursorExtend) { - VLNote oldNote = [self song]->ExtendNote(fCursorMeasure, fCursorAt); + VLNote oldNote = [self song]->ExtendNote(fCursorLocation); VLSoundOut::Instance()->PlayNote(oldNote); } else if (fClickMode == 'k') { - [self song]->DelNote(fCursorMeasure, fCursorAt); + [self song]->DelNote(fCursorLocation); } else { int pitch = VLNote::kNoPitch; if (fClickMode == ' ') pitch = VLGridToPitch(fCursorVertPos, fCursorVisual, - [self song]->Properties(fCursorMeasure).fKey); + [self song]->Properties(fCursorLocation.fMeasure).fKey); VLNote newNote(1, pitch, fCursorVisual & ~kCursorFlagsMask); - [self song]->AddNote(VLLyricsNote(newNote), fCursorMeasure, fCursorAt); + [self song]->AddNote(VLLyricsNote(newNote), fCursorLocation); VLSoundOut::Instance()->PlayNote(newNote); } fClickMode = ' '; @@ -68,7 +68,7 @@ [self drawLedgerLines:[self gridInSection:section withPitch:pitch visual:visual] at:p]; } -- (void) drawNoteCursor:(int)vertPos inMeasure:(size_t)measure at:(VLFract)at +- (void) drawNoteCursor:(int)vertPos at:(VLLocation)at visual:(uint16_t)visual mode:(char)mode { int cursorX; @@ -76,24 +76,24 @@ VLMusicElement cursorElt; VLMusicElement accidental = mode ? [self accidentalForVisual:visual] : kMusicNothing; - cursorX = [self noteXInMeasure:measure at:at]; + cursorX = [self noteXAt:at]; if (visual == kCursorExtend) { - cursorY = [self noteYInMeasure:measure withGrid:vertPos]; + cursorY = [self noteYInMeasure:at.fMeasure withGrid:vertPos]; cursorElt = kMusicExtendCursor; } else { switch (mode) { default: - cursorY = [self noteYInMeasure:measure withGrid:vertPos] - kNoteY; + cursorY = [self noteYInMeasure:at.fMeasure withGrid:vertPos] - kNoteY; [self drawLedgerLines:vertPos at:NSMakePoint(cursorX, - [self systemY:fLayout->SystemForMeasure(measure)])]; + [self systemY:fLayout->SystemForMeasure(at.fMeasure)])]; cursorElt = kMusicNoteCursor; break; case 'r': - cursorY = [self noteYInMeasure:measure withGrid:3]; + cursorY = [self noteYInMeasure:at.fMeasure withGrid:3]; cursorElt = kMusicRestCursor; break; case 'k': - cursorY = [self noteYInMeasure:measure withGrid:vertPos] - kNoteY; + cursorY = [self noteYInMeasure:at.fMeasure withGrid:vertPos] - kNoteY; cursorElt = kMusicKillCursor; break; } @@ -135,15 +135,14 @@ } } -- (void) drawNoteCursor:(int)vertPos inMeasure:(size_t)measure at:(VLFract)at visual:(uint16_t)visual +- (void) drawNoteCursor:(int)vertPos at:(VLLocation)at visual:(uint16_t)visual { - [self drawNoteCursor:vertPos inMeasure:measure at:at visual:visual mode:0]; + [self drawNoteCursor:vertPos at:at visual:visual mode:0]; } - (void) drawNoteCursor { - [self drawNoteCursor:fCursorVertPos inMeasure:fCursorMeasure at:fCursorAt - visual:fCursorVisual mode:fClickMode]; + [self drawNoteCursor:fCursorVertPos at:fCursorLocation visual:fCursorVisual mode:fClickMode]; } - (void) drawNote:(int)visual at:(NSPoint)p @@ -337,7 +336,7 @@ const VLMeasure & measure = song->fMeasures[measIdx]; VLNoteList melody; measure.DecomposeNotes(kProp, melody); - VLFraction at(0); + VLLocation at = {measIdx, VLFraction(0)}; float tupletStartX; float tupletEndX; CGFloat tupletY; @@ -356,11 +355,11 @@ if (pitch != VLNote::kNoPitch) { [self drawLedgerLinesInSection:measure.fPropIdx withPitch:pitch visual:note->fVisual - at:NSMakePoint([self noteXInMeasure:measIdx at:at], + at:NSMakePoint([self noteXAt:at], kSystemY)]; uint16_t visual = VLPitchAccidental(note->fPitch, note->fVisual, kProp.fKey); pos = - NSMakePoint([self noteXInMeasure:measIdx at:at], + NSMakePoint([self noteXAt:at], kSystemY+[self noteYInSection:measure.fPropIdx withPitch:pitch visual:&visual]); int step = [self gridInSection:measure.fPropIdx @@ -370,7 +369,7 @@ accidental:[self accidentalForVisual:filterVisuals(step, visual)] tied:tied]; } else { - pos = NSMakePoint([self noteXInMeasure:measIdx at:at], + pos = NSMakePoint([self noteXAt:at], kSystemY+[self noteYInSection:measure.fPropIdx withPitch:65]); [self drawRest:note->fVisual & VLNote::kNoteHeadMask at: pos]; } @@ -403,12 +402,12 @@ inTuplet = 0; } - at += note->fDuration; + at.fAt = at.fAt+note->fDuration; } if (inTuplet) [self drawTuplet:tuplet bracketFrom:tupletStartX to:tupletEndX atY:tupletY]; } - if (fCursorRegion == kRegionNote && fLayout->SystemForMeasure(fCursorMeasure) == system) + if (fCursorRegion == kRegionNote && fLayout->SystemForMeasure(fCursorLocation.fMeasure) == system) [self drawNoteCursor]; } diff --git a/Sources/VLSheetViewSelection.mm b/Sources/VLSheetViewSelection.mm index 4b4a036..0815e6e 100644 --- a/Sources/VLSheetViewSelection.mm +++ b/Sources/VLSheetViewSelection.mm @@ -21,12 +21,10 @@ @interface VLPlaybackEditable : VLEditable { VLSheetView * fView; size_t fStanza; - size_t fNoteMeasure; - VLFract fNoteAt; + VLLocation fNote; int fNoteVert; uint16_t fNoteVisual; - size_t fChordMeasure; - VLFract fChordAt; + VLLocation fChord; } - (VLPlaybackEditable *)initWithView:(VLSheetView *)view; @@ -42,8 +40,8 @@ { fView = view; fStanza = 1; - fNoteMeasure = 0x80000000; - fChordMeasure = 0x80000000; + fNote.fMeasure = 0x80000000; + fChord.fMeasure = 0x80000000; return self; } @@ -51,31 +49,29 @@ - (void) userEvent:(const VLMIDIUserEvent *) event { if (event->fPitch) { - fNoteMeasure = event->fMeasure; - fNoteAt = event->fAt; + fNote = event->fAt; fNoteVisual = event->fVisual & VLNote::kAccidentalsMask; if (event->fPitch == VLNote::kNoPitch) fNoteVert = kCursorNoPitch; else - fNoteVert = VLPitchToGrid(event->fPitch, fNoteVisual, [fView song]->Properties(fNoteMeasure).fKey); + fNoteVert = VLPitchToGrid(event->fPitch, fNoteVisual, [fView song]->Properties(fNote.fMeasure).fKey); fStanza = event->fStanza; - VLFraction endAt= fNoteAt+VLFraction(1,128); - [fView highlightTextInStanza:fStanza startMeasure:fNoteMeasure at:fNoteAt - endMeasure:fNoteMeasure at:endAt]; + VLLocation end = fNote; + end.fAt = end.fAt+VLFraction(1,128); + [fView highlightTextInStanza:fStanza start:fNote end:end]; } else { - fChordMeasure = event->fMeasure; - fChordAt = event->fAt; + fChord = event->fAt; } - [fView scrollMeasureToVisible:event->fMeasure+1]; + [fView scrollMeasureToVisible:event->fAt.fMeasure+1]; [fView setNeedsDisplay:YES]; } - (void) highlightCursor { - if (fNoteMeasure != 0x80000000 && fNoteVert != kCursorNoPitch) - [fView drawNoteCursor:fNoteVert inMeasure:fNoteMeasure at:fNoteAt visual:fNoteVisual]; - if (fChordMeasure != 0x80000000) - [fView highlightChordInMeasure:fChordMeasure at:fChordAt]; + if (fNote.fMeasure != 0x80000000 && fNoteVert != kCursorNoPitch) + [fView drawNoteCursor:fNoteVert at:fNote visual:fNoteVisual]; + if (fChord.fMeasure != 0x80000000) + [fView highlightChord:fChord]; } - (BOOL) hidden @@ -120,12 +116,12 @@ VLSequenceCallback( - (void)editSelection:(BOOL)extend { if (extend && fSelEnd > -1) { - if (fCursorMeasure > fSelEnd) - fSelEnd = fCursorMeasure; - else if (fCursorMeasure < fSelStart) - fSelStart = fCursorMeasure; + if (fCursorLocation.fMeasure > fSelEnd) + fSelEnd = fCursorLocation.fMeasure; + else if (fCursorLocation.fMeasure < fSelStart) + fSelStart = fCursorLocation.fMeasure; } else { - fSelStart = fSelEnd = fSelAnchor = fCursorMeasure; + fSelStart = fSelEnd = fSelAnchor = fCursorLocation.fMeasure; } [self updateMenus]; [self setNeedsDisplay:YES]; @@ -137,21 +133,21 @@ VLSequenceCallback( case kRegionNote: case kRegionChord: case kRegionLyrics: - if (fCursorAt.fNum > 0 && fCursorMeasure >= fSelAnchor) - ++fCursorMeasure; + if (fCursorLocation.fAt.fNum > 0 && fCursorLocation.fMeasure >= fSelAnchor) + ++fCursorLocation.fMeasure; // // Fall through // case kRegionMeasure: - fCursorMeasure = - std::max(0, std::min(fCursorMeasure, [self song]->CountMeasures())); - if (fCursorMeasure >= fSelAnchor) { + fCursorLocation.fMeasure = + std::max(0, std::min(fCursorLocation.fMeasure, [self song]->CountMeasures())); + if (fCursorLocation.fMeasure >= fSelAnchor) { fSelStart = fSelAnchor; - fSelEnd = fCursorMeasure; + fSelEnd = fCursorLocation.fMeasure; [self updateMenus]; [self setNeedsDisplay:YES]; } else { - fSelStart = fCursorMeasure; + fSelStart = fCursorLocation.fMeasure; fSelEnd = fSelAnchor; [self updateMenus]; [self setNeedsDisplay:YES]; diff --git a/Sources/VLSheetWindow.h b/Sources/VLSheetWindow.h index f8957be..7b1a685 100644 --- a/Sources/VLSheetWindow.h +++ b/Sources/VLSheetWindow.h @@ -23,7 +23,7 @@ - (void) moveToPrev; - (void) highlightCursor; - (BOOL) canExtendSelection:(VLRegion)region; -- (void) extendSelection:(size_t)measure at:(VLFract)at; +- (void) extendSelection:(VLLocation)at; - (BOOL) hidden; @end diff --git a/Sources/VLSheetWindow.mm b/Sources/VLSheetWindow.mm index a6b1086..d9c09a1 100644 --- a/Sources/VLSheetWindow.mm +++ b/Sources/VLSheetWindow.mm @@ -49,7 +49,7 @@ return NO; } -- (void)extendSelection:(size_t)measure at:(VLFract)at +- (void)extendSelection:(VLLocation)at { } @@ -132,14 +132,14 @@ - (IBAction) togglePlayElements:(id)sender { - [[self document] setPlayElements:[[self document] playElements] ^ [sender tag]]; + [[self document] setPlayElements:[[self document] playElements] ^ (int)[sender tag]]; } - (BOOL) validateUserInterfaceItem:(id )item { if ([item action] == @selector(togglePlayElements:)) { NSMenuItem * menuItem = (NSMenuItem *)item; - if (int tag = [item tag]) + if (NSInteger tag = [item tag]) [menuItem setState:([[self document] playElements] & tag) != 0]; } else if ([item action] == @selector(playStop:)) { NSMenuItem * menuItem = [(NSObject *)item isKindOfClass:[NSMenuItem class]] ? (NSMenuItem *)item : nil;