From 9d198f5ceced10945f86d72f719cfadd2b6c02b1 Mon Sep 17 00:00:00 2001 From: Matthias Neeracher Date: Wed, 31 Aug 2011 04:02:37 +0200 Subject: [PATCH] Revamp tuplet model --- Sources/VLLilypondWriter.cpp | 7 ++-- Sources/VLModel.cpp | 16 +++++---- Sources/VLModel.h | 16 +++++---- Sources/VLPListDocument.mm | 2 ++ Sources/VLSheetViewInternal.h | 2 +- Sources/VLSheetViewNotes.mm | 63 ++++++++++++++++++++++------------- 6 files changed, 65 insertions(+), 41 deletions(-) diff --git a/Sources/VLLilypondWriter.cpp b/Sources/VLLilypondWriter.cpp index 6fc1417..6a55303 100644 --- a/Sources/VLLilypondWriter.cpp +++ b/Sources/VLLilypondWriter.cpp @@ -261,9 +261,10 @@ void VLLilypondWriter::VisitNote(VLLyricsNote & n) && n.fPitch == fPrevNote.fPitch ) strcpy(duration, "."); - else if (n.fVisual & VLNote::kTriplet) - sprintf(duration, "%s\\times 2/3 { %s%d%s }", - space, nm.c_str(), kValue[n.fVisual & VLNote::kNoteHeadMask], tie); + else if (n.fVisual & VLNote::kTupletMask) + sprintf(duration, "%s\\times %d/%d { %s%d%s }", + space, VLNote::TupletDenom(n.fVisual), VLNote::TupletNum(n.fVisual), + nm.c_str(), kValue[n.fVisual & VLNote::kNoteHeadMask], tie); else sprintf(duration, "%s%s%d%s", space, nm.c_str(), kValue[n.fVisual & VLNote::kNoteHeadMask], tie); diff --git a/Sources/VLModel.cpp b/Sources/VLModel.cpp index 8d76d74..9a658af 100644 --- a/Sources/VLModel.cpp +++ b/Sources/VLModel.cpp @@ -314,7 +314,7 @@ void VLMeasure::DecomposeNotes(const VLProperties & prop, VLNoteList & decompose p.AlignToGrid(inBeat, kQuarterDur); // Align all others } checkTriplets: - if (p.fVisual & VLNote::kTriplet) { + if ((p.fVisual & VLNote::kTupletMask) == VLNote::kTriplet) { // // Distinguish swing 8ths/16ths from triplets // @@ -335,7 +335,7 @@ void VLMeasure::DecomposeNotes(const VLProperties & prop, VLNoteList & decompose // // First swing note (4th triplet -> 8th) // - p.fVisual = (p.fVisual+1) & ~VLNote::kTriplet; + 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)) @@ -344,7 +344,7 @@ void VLMeasure::DecomposeNotes(const VLProperties & prop, VLNoteList & decompose // Second swing note (8th triplet -> 8th) // if (!prevTriplets) - p.fVisual &= ~VLNote::kTriplet; + p.fVisual &= ~VLNote::kTupletMask; } else if ((p.fDuration > kMinDuration) && ((at % p.fDuration != 0) || (p.fDuration != c.fDuration @@ -357,11 +357,11 @@ void VLMeasure::DecomposeNotes(const VLProperties & prop, VLNoteList & decompose // Get rid of awkward triplets // p.fDuration *= VLFraction(3,4); - p.fVisual = (p.fVisual+1) & ~VLNote::kTriplet; + p.fVisual = (p.fVisual+1) & ~VLNote::kTupletMask; } } haveDuration: - if (p.fVisual & VLNote::kTriplet) + if ((p.fVisual & VLNote::kTupletMask) == VLNote::kTriplet) if ((prevTriplets = (prevTriplets+1)%3)) { prevTripDur = p.fDuration; prevVisual = p.fVisual; @@ -554,8 +554,7 @@ void VLSong::AddNote(VLLyricsNote note, size_t measure, VLFraction at) // // Sanity check on accidentals // - note.fVisual = (note.fVisual & ~VLNote::kAccidentalsMask) - | VLPitchAccidental(note.fPitch, note.fVisual, Properties(measure).fKey); + note.fVisual = VLPitchAccidental(note.fPitch, note.fVisual, Properties(measure).fKey); // // Always keep an empty measure in reserve // @@ -2080,6 +2079,9 @@ std::string VLSong::PrimaryGroove() const return bestGroove; } +#pragma mark - +#pragma mark class VLSongVisitor + //////////////////////// VLSongVisitor //////////////////////////////// VLSongVisitor::~VLSongVisitor() diff --git a/Sources/VLModel.h b/Sources/VLModel.h index 1a349da..d3ccae3 100644 --- a/Sources/VLModel.h +++ b/Sources/VLModel.h @@ -132,20 +132,22 @@ struct VLNote { kWantSharp = 0x10, kWant2Sharp = 0x20, - kPreferSharps = 0x30, // kWantSharp | kWant2Sharp + kPreferSharps = 0x30, // kWantSharp | kWant2Sharp kWantFlat = 0x40, kWant2Flat = 0x80, - kPreferFlats = 0xC0, // kWantFlat | kWant2Flat - kWantNatural = 0x50, // kWantSharp | kWantFlat - kNaturalOrSharp = 0x70, // kPreferSharps| kWantFlat - kNaturalOrFlat = 0xD0, // kPreferFlats | kWantSharp + kPreferFlats = 0xC0, // kWantFlat | kWant2Flat + kWantNatural = 0x50, // kWantSharp | kWantFlat + kNaturalOrSharp = 0x70, // kPreferSharps| kWantFlat + kNaturalOrFlat = 0xD0, // kPreferFlats | kWantSharp kAccidentalsMask= 0x00F0, - kTriplet = 0x300, + kTriplet = 0x3200, - kTupletMask = 0x0F00 + kTupletMask = 0xFF00 }; + static int TupletNum(uint16_t visual) { return visual >> 12; } + static int TupletDenom(uint16_t visual) { return (visual >> 8) & 0x0F; } VLNote(VLFraction dur=0, int pitch=kNoPitch, uint16_t visual=0); VLNote(std::string name); std::string Name(uint16_t accidentals=0) const; diff --git a/Sources/VLPListDocument.mm b/Sources/VLPListDocument.mm index ed9e766..3e6da11 100644 --- a/Sources/VLPListDocument.mm +++ b/Sources/VLPListDocument.mm @@ -542,6 +542,8 @@ advanceAt: [filterTask release]; if ([error length]) { + [contents writeToFile:@"/var/tmp/VocalEaselFilterInput" atomically:NO]; + [error writeToFile:@"/var/tmp/VocalEaselFilterError" atomically:NO]; NSString * errStr = [[[NSString alloc] initWithData:error encoding:NSUTF8StringEncoding] autorelease]; [NSException raise:NSInvalidArgumentException diff --git a/Sources/VLSheetViewInternal.h b/Sources/VLSheetViewInternal.h index 5babf0f..5b50797 100644 --- a/Sources/VLSheetViewInternal.h +++ b/Sources/VLSheetViewInternal.h @@ -10,7 +10,7 @@ const float kLineX = 5.0; const float kLineH = 10.0; -const float kTripletH = 5.0; +const float kTupletH = 5.0; #define kSystemBaseline ((fNumBotLedgers+1)*kLineH+fNumStanzas*kLyricsH) #define kSystemAscent ((fNumTopLedgers+7)*kLineH+kChordH) #define kSystemH (kSystemBaseline+kSystemAscent) diff --git a/Sources/VLSheetViewNotes.mm b/Sources/VLSheetViewNotes.mm index 4c8c2c3..ebd7ca7 100644 --- a/Sources/VLSheetViewNotes.mm +++ b/Sources/VLSheetViewNotes.mm @@ -296,7 +296,7 @@ operation: NSCompositeSourceOver]; } -- (void) drawTripletBracketFrom:(int)startX to:(int)endX atY:(int)y +- (void) drawTuplet:(uint16_t)tuplet bracketFrom:(int)startX to:(int)endX atY:(int)y { static NSDictionary * sTripletFont = nil; if (!sTripletFont) @@ -308,13 +308,15 @@ NSBezierPath * bz = [NSBezierPath bezierPath]; - [bz moveToPoint: NSMakePoint(startX, y-kTripletH)]; + [bz moveToPoint: NSMakePoint(startX, y-kTupletH)]; [bz lineToPoint: NSMakePoint(startX, y)]; [bz lineToPoint: NSMakePoint(endX, y)]; - [bz lineToPoint: NSMakePoint(endX, y-kTripletH)]; + [bz lineToPoint: NSMakePoint(endX, y-kTupletH)]; [bz stroke]; - [@"3" drawAtPoint: NSMakePoint((startX+endX)*0.5f, y+kTripletH) + NSString * tupletText = tuplet == VLNote::kTriplet ? @"3" + : [NSString stringWithFormat:@"%d:%d", VLNote::TupletNum(tuplet), VLNote::TupletDenom(tuplet)]; + [tupletText drawAtPoint: NSMakePoint((startX+endX)*0.5f, y+kTupletH) withAttributes: sTripletFont]; } @@ -326,11 +328,6 @@ const VLSystemLayout & kLayout = (*fLayout)[system]; const CGFloat kSystemY = [self systemY:system]; - float tripletStartX; - float tripletEndX; - CGFloat tripletY; - bool hasTriplets = false; - for (int m = 0; mfVisual & VLNote::kNoteHeadMask at: pos]; } - if (note->fVisual & VLNote::kTriplet) { - tripletEndX = pos.x+kNoteW*0.5f; - if (hasTriplets) { - tripletY = std::max(tripletY, pos.y+kLineH); - } else { - tripletY = std::max(kSystemY+5.0f*kLineH, pos.y+kLineH); - tripletStartX = pos.x-kNoteW*0.5f; - hasTriplets = true; + if (uint16_t newTuplet = note->fVisual & VLNote::kTupletMask) { + tupletEndX = pos.x+kNoteW*0.5f; + if (inTuplet && newTuplet == tuplet) { + tupletY = std::max(tupletY, pos.y+kLineH); + } else { + if (inTuplet) + [self drawTuplet:tuplet bracketFrom:tupletStartX to:tupletEndX atY:tupletY]; + tupletY = std::max(kSystemY+5.0f*kLineH, pos.y+kLineH); + tupletStartX = pos.x-kNoteW*0.5f; + tuplet = newTuplet; + tupletDur = 0; } - } else if (hasTriplets) { - [self drawTripletBracketFrom:tripletStartX to:tripletEndX atY:tripletY]; - hasTriplets = false; + ++inTuplet; + tupletDur += note->fDuration / VLNote::TupletDenom(tuplet); + if (tuplet == VLNote::kTriplet ? (tupletDur.fNum == 1 && !(tupletDur.fDenom & (tupletDur.fDenom-1))) + : inTuplet == VLNote::TupletNum(tuplet) + ) { + // + // Tuplet adds up to power of two fraction + // + [self drawTuplet:tuplet bracketFrom:tupletStartX to:tupletEndX atY:tupletY]; + inTuplet = 0; + } + } else if (++inTuplet) { + [self drawTuplet:tuplet bracketFrom:tupletStartX to:tupletEndX atY:tupletY]; + inTuplet = 0; } at += note->fDuration; } - } - if (hasTriplets) { - [self drawTripletBracketFrom:tripletStartX to:tripletEndX atY:tripletY]; + if (inTuplet) + [self drawTuplet:tuplet bracketFrom:tupletStartX to:tupletEndX atY:tupletY]; } if (fCursorRegion == kRegionNote && fLayout->SystemForMeasure(fCursorMeasure) == system) [self drawNoteCursor];