Implement note extensions

This commit is contained in:
Matthias Neeracher 2007-04-22 02:59:52 +00:00
parent 920abba112
commit 1d3fc9e22b
6 changed files with 199 additions and 25 deletions

View File

@ -0,0 +1,97 @@
%!PS-Adobe-3.0 EPSF-3.0
%%BoundingBox: -1 -215.5 566.742 180
%%Pages: 0
%%Title: noteheads.s0triangle from feta26
%%Creator: FontForge
%%Author: Matthias Neeracher
%%CreationDate: 19:50 21-4-2007
%%EndComments
%%BeginPreview: 73 51 4 51
%0027ADC6000000000000000000000000000000000000000000000000000000000000000000
%07FFFFFFD50000000000000000000000000000000000000000000000000000000000000000
%1FFFFFFFFFC500000000000000000000000000000000000000000000000000000000000000
%1FFFFFFFFFFFD6000000000000000000000000000000000000000000000000000000000000
%06FFFFFFFFFFFFE81000000000000000000000000000000000000000000000000000000000
%007FFFFFFFFFFFFFFA40000000000000000000000000000000000000000000000000000000
%0009FFFFFFFFFFFFFFFD710000000000000000000000000000000000000000000000000000
%0000CFFFFFFFFFFFFFFFFFA500000000000000000000000000000000000000000000000000
%00002EFFFFFFFFFFFFFFFFFFE9400000000000000000000000000000000000000000000000
%000006FFFFFFFFFFFFFFFFFFFFFEA510000000000000000000000000000000000000000000
%000000BFFFFFFFFFFFFFFFFFFFFFFFFB730000000000000000000000000000000000000000
%0000002FFFFFFFFFFFFFFFFFFFFFFFFFFFEA62000000000000000000000000000000000000
%00000008FFFFFFFFF9DFFFFFFFFFFFFFFFFFFFEB7410000000000000000000000000000000
%00000001EFFFFFFFF7038DFFFFFFFFFFFFFFFFFFFFFDA85310000000000000000000000000
%000000007FFFFFFFFD000038DFFFFFFFFFFFFFFFFFFFFFFFFDB97542000000000000000000
%000000001EFFFFFFFF600000027BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEDCBA998877653000
%0000000008FFFFFFFFD000000000149CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC20
%0000000001FFFFFFFFF4000000000000159CFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0
%0000000000AFFFFFFFFA0000000000000000148BEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0
%00000000005FFFFFFFFF100000000000000000000257ADFFFFFFFFFFFFFFFFFFFFFFFFFFA0
%00000000000EFFFFFFFF600000000000000000000000000257DFFFFFFFFFFFFFFFFFFFF910
%000000000009FFFFFFFFB0000000000000000000000000028DFFFFFFFFFFFFFFFFFFB61000
%000000000005FFFFFFFFF1000000000000000000000003AFFFFFFFFFFFFFFFFFC840000000
%000000000001FFFFFFFFF40000000000000000000005CFFFFFFFFFFFFFFFFB620000000000
%000000000000BFFFFFFFF800000000000000000005CFFFFFFFFFFFFFFFB610000000000000
%0000000000007FFFFFFFFB000000000000000005CFFFFFFFFFFFFFFD720000000000000000
%0000000000004FFFFFFFFE0000000000000003CFFFFFFFFFFFFFFA40000000000000000000
%0000000000001FFFFFFFFF10000000000002AFFFFFFFFFFFFFE81000000000000000000000
%0000000000000DFFFFFFFF3000000000007EFFFFFFFFFFFFD6100000000000000000000000
%0000000000000BFFFFFFFF50000000003DFFFFFFFFFFFFD600000000000000000000000000
%00000000000009FFFFFFFF7000000019FFFFFFFFFFFFE60000000000000000000000000000
%00000000000007FFFFFFFF80000003DFFFFFFFFFFFE7100000000000000000000000000000
%00000000000006FFFFFFFF8000008FFFFFFFFFFFFA20000000000000000000000000000000
%00000000000005FFFFFFFF90001BFFFFFFFFFFFC3000000000000000000000000000000000
%00000000000004FFFFFFFF9003DFFFFFFFFFFF700000000000000000000000000000000000
%00000000000003FFFFFFFF906FFFFFFFFFFFC2000000000000000000000000000000000000
%00000000000003FFFFFFFFA9FFFFFFFFFFF700000000000000000000000000000000000000
%00000000000003FFFFFFFFFFFFFFFFFFFD3000000000000000000000000000000000000000
%00000000000004FFFFFFFFFFFFFFFFFF910000000000000000000000000000000000000000
%00000000000004FFFFFFFFFFFFFFFFE6000000000000000000000000000000000000000000
%00000000000005FFFFFFFFFFFFFFFD30000000000000000000000000000000000000000000
%00000000000007FFFFFFFFFFFFFFB100000000000000000000000000000000000000000000
%00000000000008FFFFFFFFFFFFF90000000000000000000000000000000000000000000000
%0000000000000AFFFFFFFFFFFF700000000000000000000000000000000000000000000000
%0000000000000DFFFFFFFFFFF5000000000000000000000000000000000000000000000000
%0000000000001FFFFFFFFFFE40000000000000000000000000000000000000000000000000
%0000000000003FFFFFFFFFE300000000000000000000000000000000000000000000000000
%0000000000005FFFFFFFFE3000000000000000000000000000000000000000000000000000
%0000000000002EFFFFFFD20000000000000000000000000000000000000000000000000000
%00000000000003CFFFFC200000000000000000000000000000000000000000000000000000
%00000000000000014551000000000000000000000000000000000000000000000000000000
%%EndPreview
%%EndProlog
%%Page "noteheads.s0triangle" 1
gsave newpath
25 178 moveto
28 179 34 180 38 180 curveto
43 180 45 180 59 172 curveto
164 118 279 83 396 68 curveto
434 63 466 60 512 59 curveto
542 58 545 58 550 56 curveto
564 51 570 39 565 28 curveto
561 20 553 16 524 8 curveto
386 -27 266 -95 164 -195 curveto
153 -205 144 -214 142 -214 curveto
137 -216 131 -216 119 -214 curveto
108 -213 99 -208 95 -203 curveto
91 -198 91 -193 94 -178 curveto
103 -136 103 -82 94 -35 curveto
87 1 74 39 58 70 curveto
43 98 23 127 8 142 curveto
1 149 -1 153 -1 158 curveto
-1 162 1 167 4 170 curveto
8 173 17 177 25 178 curveto
closepath
155 74 moveto
140 79 128 83 127 84 curveto
126 84 127 80 132 69 curveto
158 19 170 -33 170 -88 curveto
170 -108 171 -111 172 -110 curveto
179 -104 197 -90 208 -81 curveto
259 -43 317 -11 377 13 curveto
385 16 391 19 391 19 curveto
389 19 354 24 344 26 curveto
280 37 218 53 155 74 curveto
closepath
1 0 0 setrgbcolor fill grestore
%%EOF

View File

@ -999,6 +999,67 @@ void VLSong::DelNote(size_t measure, VLFraction at)
} }
} }
void VLSong::ExtendNote(size_t measure, VLFraction at)
{
VLNoteList::iterator i = fMeasures[measure].fMelody.begin();
VLFraction t(0);
for (;;) {
if (t == at) {
if (i->fPitch == VLNote::kNoPitch)
return; // Don't extend rests
do {
VLNoteList::iterator j=i;
++j;
if (j != fMeasures[measure].fMelody.end()) {
//
// Extend across next note/rest
//
i->fDuration += j->fDuration;
fMeasures[measure].fMelody.erase(j);
} else if (++measure < fMeasures.size()) {
//
// Extend into next measure
//
VLNoteList::iterator k = fMeasures[measure].fMelody.begin();
if (k->fTied & VLNote::kTiedWithPrev) {
//
// Already extended, extend further
//
i = k;
continue; // Go for another spin
} else {
bool wasTied = k->fTied & VLNote::kTiedWithNext;
//
// Extend previous note
//
k->fPitch = i->fPitch;
k->fTied = VLNote::kTiedWithPrev;
i->fTied != VLNote::kTiedWithNext;
k->fLyrics.clear();
if (wasTied) {
//
// Extend further
//
i = k;
continue;
}
}
}
} while (0);
//
// Finished extending
//
return;
}
VLFraction tEnd = t+i->fDuration;
if (tEnd > at)
break; // Past the point, quit
t = tEnd;
++i;
}
}
static void TransposePinned(int8_t & pitch, int semi) static void TransposePinned(int8_t & pitch, int semi)
{ {
if (pitch == VLNote::kNoPitch) if (pitch == VLNote::kNoPitch)

View File

@ -315,6 +315,7 @@ struct VLSong {
void AddNote(VLLyricsNote note, size_t measure, VLFraction at); void AddNote(VLLyricsNote note, size_t measure, VLFraction at);
void DelChord(size_t measure, VLFraction at); void DelChord(size_t measure, VLFraction at);
void DelNote(size_t measure, VLFraction at); void DelNote(size_t measure, VLFraction at);
void ExtendNote(size_t measure, VLFraction at);
void AddRepeat(size_t beginMeasure, size_t endMeasure, int times); void AddRepeat(size_t beginMeasure, size_t endMeasure, int times);
void DelRepeat(size_t beginMeasure, size_t endMeasure); void DelRepeat(size_t beginMeasure, size_t endMeasure);
void AddEnding(size_t beginMeasure, size_t endMeasure, size_t volta); void AddEnding(size_t beginMeasure, size_t endMeasure, size_t volta);

View File

@ -36,6 +36,7 @@ enum VLMusicElement {
kMusicNaturalCursor, kMusicNaturalCursor,
kMusicRestCursor, kMusicRestCursor,
kMusicKillCursor, kMusicKillCursor,
kMusicExtendCursor,
kMusicCoda, kMusicCoda,
kMusicElements kMusicElements
}; };

View File

@ -44,6 +44,7 @@ static NSString * sElementNames[kMusicElements] = {
@"naturalcursor", @"naturalcursor",
@"restcursor", @"restcursor",
@"killcursor", @"killcursor",
@"extendcursor",
@"coda" @"coda"
}; };
@ -654,9 +655,17 @@ static int8_t sSharpAcc[] = {
- (void) accidentalFromEvent:(NSEvent *)event - (void) accidentalFromEvent:(NSEvent *)event
{ {
fCursorAccidental = (VLMusicElement)0;
//
// Extension
//
if ([event modifierFlags] & NSShiftKeyMask) {
fCursorAccidental = kMusicExtendCursor;
return;
}
const VLProperties & prop = [self song]->fProperties.front(); const VLProperties & prop = [self song]->fProperties.front();
fCursorAccidental = (VLMusicElement)0;
if (prop.fKey >= 0) { if (prop.fKey >= 0) {
if (prop.fKey >= sSharpAcc[fCursorPitch % 12]) { // Sharp in Key if (prop.fKey >= sSharpAcc[fCursorPitch % 12]) { // Sharp in Key
switch ([event modifierFlags] & (NSAlternateKeyMask|NSCommandKeyMask)) { switch ([event modifierFlags] & (NSAlternateKeyMask|NSCommandKeyMask)) {

View File

@ -22,7 +22,9 @@
VLNote newNote(1, fClickMode==' ' ? fCursorActualPitch : VLNote::kNoPitch); VLNote newNote(1, fClickMode==' ' ? fCursorActualPitch : VLNote::kNoPitch);
[[self document] willChangeSong]; [[self document] willChangeSong];
if (fClickMode == 'k') if (fCursorAccidental == kMusicExtendCursor)
[self song]->ExtendNote(fCursorMeasure, fCursorAt);
else if (fClickMode == 'k')
[self song]->DelNote(fCursorMeasure, fCursorAt); [self song]->DelNote(fCursorMeasure, fCursorAt);
else else
[self song]->AddNote(VLLyricsNote(newNote), fCursorMeasure, fCursorAt); [self song]->AddNote(VLLyricsNote(newNote), fCursorMeasure, fCursorAt);
@ -75,37 +77,40 @@
VLMusicElement cursorElt; VLMusicElement cursorElt;
cursorX = [self noteXInMeasure:fCursorMeasure at:fCursorAt]; cursorX = [self noteXInMeasure:fCursorMeasure at:fCursorAt];
switch (fClickMode) { if (fCursorAccidental == kMusicExtendCursor) {
default:
cursorY = cursorY =
[self noteYInMeasure:fCursorMeasure [self noteYInMeasure:fCursorMeasure
withPitch:fCursorPitch withPitch:fCursorPitch
accidental:&accidental] accidental:&accidental];
-kNoteY; cursorElt = fCursorAccidental;
[self drawLedgerLinesWithPitch:fCursorPitch } else
at:NSMakePoint(cursorX, switch (fClickMode) {
[self systemY:fCursorMeasure/fMeasPerSystem])]; default:
cursorElt = kMusicNoteCursor; cursorY =
break; [self noteYInMeasure:fCursorMeasure
case 'r': withPitch:fCursorPitch accidental:&accidental] - kNoteY;
cursorY = [self noteYInMeasure:fCursorMeasure [self drawLedgerLinesWithPitch:fCursorPitch
withPitch:65 at:NSMakePoint(cursorX,
accidental:&accidental]; [self systemY:fCursorMeasure/fMeasPerSystem])];
cursorElt = kMusicRestCursor; cursorElt = kMusicNoteCursor;
break; break;
case 'k': case 'r':
cursorY = [self noteYInMeasure:fCursorMeasure cursorY = [self noteYInMeasure:fCursorMeasure
withPitch:fCursorPitch withPitch:65 accidental:&accidental];
accidental:&accidental]; cursorElt = kMusicRestCursor;
cursorElt = kMusicKillCursor; break;
break; case 'k':
} cursorY = [self noteYInMeasure:fCursorMeasure
withPitch:fCursorPitch accidental:&accidental];
cursorElt = kMusicKillCursor;
break;
}
NSPoint at = NSMakePoint(cursorX-kNoteX, cursorY); NSPoint at = NSMakePoint(cursorX-kNoteX, cursorY);
[[self musicElement:cursorElt] [[self musicElement:cursorElt]
compositeToPoint:at compositeToPoint:at
operation: NSCompositeSourceOver]; operation: NSCompositeSourceOver];
if (fCursorAccidental) { if (fCursorAccidental && fCursorAccidental != kMusicExtendCursor) {
at.y += kNoteY; at.y += kNoteY;
switch (cursorElt= fCursorAccidental) { switch (cursorElt= fCursorAccidental) {
case kMusicFlatCursor: case kMusicFlatCursor: