Refactor cursor handling from a pitch based approach to a grid based one

This commit is contained in:
Matthias Neeracher 2011-08-28 12:42:39 +02:00
parent c50fc4e885
commit ed2a79a74e
5 changed files with 88 additions and 212 deletions

View File

@ -63,6 +63,12 @@ enum VLRecalc {
kFirstRecalc kFirstRecalc
}; };
enum VLCursorVisual {
kCursorExtend = 1<<15,
kCursorFlagsMask= 0x8000,
kCursorNoPitch = -128
};
@class VLEditable; @class VLEditable;
@interface VLSheetView : NSView { @interface VLSheetView : NSView {
@ -76,9 +82,8 @@ enum VLRecalc {
VLRegion fCursorRegion; VLRegion fCursorRegion;
int fCursorMeasure; int fCursorMeasure;
VLFract fCursorAt; VLFract fCursorAt;
int fCursorPitch; int fCursorVertPos;
int fCursorActualPitch; uint16_t fCursorVisual;
VLMusicElement fCursorAccidental;
size_t fCursorStanza; size_t fCursorStanza;
int fSelStart; int fSelStart;
int fSelEnd; int fSelEnd;
@ -121,11 +126,11 @@ enum VLRecalc {
- (float) systemY:(int)system; - (float) systemY:(int)system;
- (int) gridInSection:(int)section withPitch:(int)pitch visual:(uint16_t)visual; - (int) gridInSection:(int)section withPitch:(int)pitch visual:(uint16_t)visual;
- (float) noteYInGrid:(int)vertPos;
- (float) noteYInSection:(int)section withPitch:(int)pitch visual:(uint16_t *)visual; - (float) noteYInSection:(int)section withPitch:(int)pitch visual:(uint16_t *)visual;
- (float) noteYInSection:(int)section withPitch:(int)pitch; - (float) noteYInSection:(int)section withPitch:(int)pitch;
- (VLMusicElement)accidentalForVisual:(uint16_t)visual; - (VLMusicElement)accidentalForVisual:(uint16_t)visual;
- (float) noteYInMeasure:(int)measure withPitch:(int)pitch visual:(uint16_t *)visual; - (float) noteYInMeasure:(int)measure withGrid:(int)vertPos;
- (float) noteYInMeasure:(int)measure withPitch:(int)pitch;
- (float) noteXInMeasure:(int)measure at:(VLFraction)at; - (float) noteXInMeasure:(int)measure at:(VLFraction)at;
- (void) scrollMeasureToVisible:(int)measure; - (void) scrollMeasureToVisible:(int)measure;

View File

@ -96,7 +96,8 @@ static float sFlatPos[] = {
fNeedsRecalc = kFirstRecalc; fNeedsRecalc = kFirstRecalc;
fClickMode = ' '; fClickMode = ' ';
fDisplayScale = 1.0f; fDisplayScale = 1.0f;
fCursorPitch = VLNote::kNoPitch; fCursorVertPos = 0;
fCursorVisual = 0;
fSelStart = 0; fSelStart = 0;
fSelEnd = -1; fSelEnd = -1;
fNumTopLedgers = 0; fNumTopLedgers = 0;
@ -152,12 +153,17 @@ static float sFlatPos[] = {
return VLPitchToGrid(pitch, visual, key); return VLPitchToGrid(pitch, visual, key);
} }
- (float) noteYInGrid:(int)vertPos
{
return (vertPos*0.5f - 1.0) * kLineH;
}
- (float) noteYInSection:(int)section withPitch:(int)pitch visual:(uint16_t *)visual - (float) noteYInSection:(int)section withPitch:(int)pitch visual:(uint16_t *)visual
{ {
int key = [self song]->fProperties[section].fKey; int key = [self song]->fProperties[section].fKey;
int grid = VLPitchToGrid(pitch, *visual, key); int grid = VLPitchToGrid(pitch, *visual, key);
return (grid*0.5f - 1.0) * kLineH; return [self noteYInGrid:grid];
} }
- (float) noteYInSection:(int)section withPitch:(int)pitch - (float) noteYInSection:(int)section withPitch:(int)pitch
@ -166,7 +172,7 @@ static float sFlatPos[] = {
uint16_t visual = 0; uint16_t visual = 0;
int grid = VLPitchToGrid(pitch, visual, key); int grid = VLPitchToGrid(pitch, visual, key);
return (grid*0.5f - 1.0) * kLineH; return [self noteYInGrid:grid];
} }
- (VLMusicElement)accidentalForVisual:(uint16_t)visual - (VLMusicElement)accidentalForVisual:(uint16_t)visual
@ -187,20 +193,10 @@ static float sFlatPos[] = {
} }
} }
- (float) noteYInMeasure:(int)measure withPitch:(int)pitch visual:(uint16_t *)visual - (float) noteYInMeasure:(int)measure withGrid:(int)vertPos
{ {
return [self systemY:fLayout->SystemForMeasure(measure)] return [self systemY:fLayout->SystemForMeasure(measure)]
+ [self noteYInSection:[self song]->fMeasures[measure].fPropIdx + [self noteYInGrid:vertPos];
withPitch:pitch visual:visual];
}
- (float) noteYInMeasure:(int)measure withPitch:(int)pitch
{
uint16_t dummyVis = 0;
return [self systemY:fLayout->SystemForMeasure(measure)]
+ [self noteYInSection:[self song]->fMeasures[measure].fPropIdx
withPitch:pitch visual:&dummyVis];
} }
- (float) noteXInMeasure:(int)measure at:(VLFraction)at - (float) noteXInMeasure:(int)measure at:(VLFraction)at
@ -674,109 +670,38 @@ const char * sBreak[3] = {"", "\xE2\xA4\xBE", "\xE2\x8E\x98"};
[fFieldEditor setAction:nil]; [fFieldEditor setAction:nil];
} }
const float kSemiFloor = -5.0f*kLineH; const float kSemiFloor = -1.0f*kLineH;
static int8_t sSemiToPitch[] = {
47, // B
48, 50, // D
52, 53, // F
55, 57, // A
59, 60, // Middle C
62, 64, // E
65, 67, // G
69, 71, // B
72, 74, // D
76, 77, // F
79, 81, // A
83, 84, // C
86, 88, // E
89, 91, // G
93, 95, // B
96, 98 // D
};
static int8_t sFlatAcc[] = {
6, // Cb
11,
4, // Db
9,
2, // Eb
7, // Fb
12,
5, // Gb
10,
3, // Ab
8,
1, // Bb
};
static int8_t sSharpAcc[] = {
2, // C# is the 2nd sharp
9,
4, // D#
11,
6, // E#
1, // F#
8,
3, // G#
10,
5, // A#
12,
7, // B#
};
- (void) accidentalFromEvent:(NSEvent *)event - (void) accidentalFromEvent:(NSEvent *)event
{ {
fCursorAccidental = (VLMusicElement)0;
//
// Extension
//
if (([event modifierFlags] & (NSShiftKeyMask|NSAlternateKeyMask|NSCommandKeyMask))==NSShiftKeyMask) {
fCursorAccidental = kMusicExtendCursor;
return;
}
int cursorSection =
[self song]->fMeasures[fCursorMeasure].fPropIdx;
const VLProperties & prop =
[self song]->fProperties[cursorSection];
switch ([event modifierFlags] & (NSShiftKeyMask|NSAlternateKeyMask|NSCommandKeyMask)) { switch ([event modifierFlags] & (NSShiftKeyMask|NSAlternateKeyMask|NSCommandKeyMask)) {
case NSShiftKeyMask:
fCursorVisual = kCursorExtend;
break;
case NSShiftKeyMask|NSAlternateKeyMask: case NSShiftKeyMask|NSAlternateKeyMask:
fCursorAccidental = kMusic2FlatCursor; // Gbb fCursorVisual = VLNote::kWant2Flat; // Gbb
fCursorActualPitch = fCursorPitch-2;
break; break;
case NSAlternateKeyMask: case NSAlternateKeyMask:
fCursorAccidental = kMusicFlatCursor; // Gb fCursorVisual = VLNote::kWantFlat; // Gb
fCursorActualPitch = fCursorPitch-1;
break; break;
case NSShiftKeyMask|NSCommandKeyMask: case NSShiftKeyMask|NSCommandKeyMask:
fCursorAccidental = kMusic2SharpCursor; // G## fCursorVisual = VLNote::kWant2Sharp; // G##
fCursorActualPitch = fCursorPitch+2;
break; break;
case NSCommandKeyMask: case NSCommandKeyMask:
fCursorAccidental = kMusicSharpCursor; // G# fCursorVisual = VLNote::kWantSharp; // G#
fCursorActualPitch = fCursorPitch+1;
break; break;
case NSAlternateKeyMask|NSCommandKeyMask: case NSAlternateKeyMask|NSCommandKeyMask:
fCursorAccidental = kMusicNaturalCursor; // G fCursorVisual = VLNote::kWantNatural; // G
fCursorActualPitch = fCursorPitch;
break; break;
default: default:
switch (VLVisualInKey(fCursorPitch, prop.fKey)) { fCursorVisual = 0;
case VLNote::kWantFlat:
fCursorActualPitch = fCursorPitch-1;
case VLNote::kWantSharp:
fCursorActualPitch = fCursorPitch+1;
default:
fCursorActualPitch = fCursorPitch;
}
break; break;
} }
} }
- (VLRegion) findRegionForEvent:(NSEvent *) event - (VLRegion) findRegionForEvent:(NSEvent *) event
{ {
fCursorPitch = VLNote::kNoPitch; fCursorVertPos = kCursorNoPitch;
NSPoint loc = [event locationInWindow]; NSPoint loc = [event locationInWindow];
loc = [self convertPoint:loc fromView:nil]; loc = [self convertPoint:loc fromView:nil];
@ -841,8 +766,7 @@ static int8_t sSharpAcc[] = {
} }
loc.y -= kSystemBaseline+kSemiFloor; loc.y -= kSystemBaseline+kSemiFloor;
int semi = static_cast<int>(roundf(loc.y / (0.5f*kLineH))); fCursorVertPos = static_cast<int>(roundf(loc.y / (0.5f*kLineH)));
fCursorPitch = sSemiToPitch[semi];
[self accidentalFromEvent:event]; [self accidentalFromEvent:event];
@ -854,16 +778,16 @@ static int8_t sSharpAcc[] = {
if ([event modifierFlags] & NSAlphaShiftKeyMask) if ([event modifierFlags] & NSAlphaShiftKeyMask)
return; // Keyboard mode, ignore mouse return; // Keyboard mode, ignore mouse
bool hadCursor = fCursorPitch != VLNote::kNoPitch; bool hadCursor = fCursorRegion == kRegionNote;
[self findRegionForEvent:event]; [self findRegionForEvent:event];
bool hasCursor = fCursorPitch != VLNote::kNoPitch; bool hasCursor = fCursorRegion == kRegionNote;
[self setNeedsDisplay:(hadCursor || hasCursor)]; [self setNeedsDisplay:(hadCursor || hasCursor)];
} }
- (void)flagsChanged:(NSEvent *)event - (void)flagsChanged:(NSEvent *)event
{ {
if (fCursorPitch != VLNote::kNoPitch) { if (fCursorRegion == kRegionNote) {
[self accidentalFromEvent:event]; [self accidentalFromEvent:event];
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
} }
@ -877,7 +801,7 @@ static int8_t sSharpAcc[] = {
- (void) mouseExited:(NSEvent *)event - (void) mouseExited:(NSEvent *)event
{ {
fCursorPitch = VLNote::kNoPitch; fCursorRegion = kRegionNowhere;
[[self window] setAcceptsMouseMovedEvents:NO]; [[self window] setAcceptsMouseMovedEvents:NO];
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
} }
@ -919,14 +843,6 @@ static int8_t sSharpAcc[] = {
NSString * k = [event charactersIgnoringModifiers]; NSString * k = [event charactersIgnoringModifiers];
switch ([k characterAtIndex:0]) { switch ([k characterAtIndex:0]) {
case '\r':
[self startKeyboardCursor];
[self addNoteAtCursor];
break;
case ' ':
[self startKeyboardCursor];
VLSoundOut::Instance()->PlayNote(VLNote(1, fCursorPitch));
break;
case 'r': case 'r':
if (fClickMode == 'r') if (fClickMode == 'r')
fClickMode = ' '; fClickMode = ' ';

View File

@ -14,8 +14,7 @@
- (void) drawNotesForSystem:(int)system; - (void) drawNotesForSystem:(int)system;
- (void) addNoteAtCursor; - (void) addNoteAtCursor;
- (void) startKeyboardCursor; - (void) drawNoteCursor:(int)vertPos inMeasure:(size_t)measure at:(VLFract)at visual:(uint16_t)visual;
- (void) drawNoteCursor:(int)pitch inMeasure:(size_t)measure at:(VLFract)at accidental:(VLMusicElement)accidental;
@end @end

View File

@ -21,58 +21,31 @@
- (void) addNoteAtCursor - (void) addNoteAtCursor
{ {
if (fCursorMeasure > -1 && fCursorActualPitch) { if (fCursorMeasure > -1 && fCursorVertPos != kCursorNoPitch) {
VLNote newNote(1, fClickMode==' ' ? fCursorActualPitch : VLNote::kNoPitch);
switch (fCursorAccidental) {
case kMusicFlatCursor:
newNote.fVisual |= VLNote::kWantFlat;
break;
case kMusicSharpCursor:
newNote.fVisual |= VLNote::kWantSharp;
break;
case kMusic2FlatCursor:
newNote.fVisual |= VLNote::kWant2Flat;
break;
case kMusic2SharpCursor:
newNote.fVisual |= VLNote::kWant2Sharp;
break;
case kMusicNaturalCursor:
newNote.fVisual |= VLNote::kWantNatural;
break;
default:
break;
}
[[self document] willChangeSong]; [[self document] willChangeSong];
if (fCursorAccidental == kMusicExtendCursor) if (fCursorVisual == kCursorExtend) {
newNote = [self song]->ExtendNote(fCursorMeasure, fCursorAt); VLNote oldNote = [self song]->ExtendNote(fCursorMeasure, fCursorAt);
else if (fClickMode == 'k') VLSoundOut::Instance()->PlayNote(oldNote);
} else if (fClickMode == 'k') {
[self song]->DelNote(fCursorMeasure, fCursorAt); [self song]->DelNote(fCursorMeasure, fCursorAt);
else } else {
int pitch = VLNote::kNoPitch;
if (fClickMode == ' ')
pitch = VLGridToPitch(fCursorVertPos, fCursorVisual,
[self song]->Properties(fCursorMeasure).fKey);
VLNote newNote(1, pitch, fCursorVisual & ~kCursorFlagsMask);
[self song]->AddNote(VLLyricsNote(newNote), fCursorMeasure, fCursorAt); [self song]->AddNote(VLLyricsNote(newNote), fCursorMeasure, fCursorAt);
[[self document] didChangeSong];
if (fClickMode == ' ')
VLSoundOut::Instance()->PlayNote(newNote); VLSoundOut::Instance()->PlayNote(newNote);
else }
fClickMode = ' '; [[self document] didChangeSong];
} }
} }
- (void) startKeyboardCursor - (void) drawLedgerLines:(int)vertPos at:(NSPoint)p
{
if (fCursorMeasure < 0) {
fCursorMeasure = 0;
fCursorPitch = VLNote::kMiddleC;
fCursorActualPitch = fCursorPitch;
fCursorAt = VLFraction(0);
}
}
- (void) drawLedgerLinesInSection:(int)section withPitch:(int)pitch visual:(uint16_t)visual at:(NSPoint)p
{ {
p.x += kLedgerX; p.x += kLedgerX;
int step = ([self gridInSection:section withPitch:pitch visual:visual]-2)/2;
int step = (vertPos-2) / 2;
for (int i=0; i-- > step; ) { for (int i=0; i-- > step; ) {
NSPoint p0 = p; NSPoint p0 = p;
p0.y += i*kLineH; p0.y += i*kLineH;
@ -89,36 +62,37 @@
} }
} }
- (void) drawNoteCursor:(int)pitch inMeasure:(size_t)measure at:(VLFract)at - (void) drawLedgerLinesInSection:(int)section withPitch:(int)pitch visual:(uint16_t)visual at:(NSPoint)p
accidental:(VLMusicElement)accidental {
mode:(char)mode [self drawLedgerLines:[self gridInSection:section withPitch:pitch visual:visual] at:p];
}
- (void) drawNoteCursor:(int)vertPos inMeasure:(size_t)measure at:(VLFract)at
visual:(uint16_t)visual mode:(char)mode
{ {
int cursorX; int cursorX;
int cursorY; int cursorY;
int cursorSect;
VLMusicElement cursorElt; VLMusicElement cursorElt;
VLMusicElement accidental = mode ? [self accidentalForVisual:visual] : kMusicNothing;
cursorX = [self noteXInMeasure:measure at:at]; cursorX = [self noteXInMeasure:measure at:at];
if (accidental == kMusicExtendCursor) { if (visual == kCursorExtend) {
cursorY = [self noteYInMeasure:measure withPitch:pitch]; cursorY = [self noteYInGrid:vertPos];
cursorElt = accidental; cursorElt = kMusicExtendCursor;
} else { } else {
uint16_t visual = 0;
switch (mode) { switch (mode) {
default: default:
cursorY = [self noteYInMeasure:measure withPitch:pitch visual:&visual] - kNoteY; cursorY = [self noteYInMeasure:measure withGrid:vertPos] - kNoteY;
cursorSect = [self song]->fMeasures[measure].fPropIdx; [self drawLedgerLines:vertPos at:NSMakePoint(cursorX,
[self drawLedgerLinesInSection:cursorSect withPitch:pitch [self systemY:fLayout->SystemForMeasure(measure)])];
visual:visual at:NSMakePoint(cursorX,
[self systemY:fLayout->SystemForMeasure(measure)])];
cursorElt = kMusicNoteCursor; cursorElt = kMusicNoteCursor;
break; break;
case 'r': case 'r':
cursorY = [self noteYInMeasure:measure withPitch:65]; cursorY = [self noteYInMeasure:measure withGrid:3];
cursorElt = kMusicRestCursor; cursorElt = kMusicRestCursor;
break; break;
case 'k': case 'k':
cursorY = [self noteYInMeasure:measure withPitch:pitch]; cursorY = [self noteYInGrid:vertPos];
cursorElt = kMusicKillCursor; cursorElt = kMusicKillCursor;
break; break;
} }
@ -128,9 +102,11 @@
[[self musicElement:cursorElt] [[self musicElement:cursorElt]
compositeToPoint:xy compositeToPoint:xy
operation: NSCompositeSourceOver]; operation: NSCompositeSourceOver];
if (mode && accidental && accidental != kMusicExtendCursor) {
xy.y += kNoteY; if (accidental) {
switch (cursorElt= accidental) { xy.y += kNoteY;
(int &)accidental += kMusicFlatCursor-kMusicFlat;
switch (accidental) {
case kMusicFlatCursor: case kMusicFlatCursor:
xy.x += kFlatW; xy.x += kFlatW;
xy.y += kFlatY; xy.y += kFlatY;
@ -152,22 +128,21 @@
xy.y += kNaturalY; xy.y += kNaturalY;
break; break;
} }
[[self musicElement:cursorElt] [[self musicElement:accidental]
compositeToPoint:xy compositeToPoint:xy
operation: NSCompositeSourceOver]; operation: NSCompositeSourceOver];
} }
} }
- (void) drawNoteCursor:(int)pitch inMeasure:(size_t)measure at:(VLFract)at - (void) drawNoteCursor:(int)vertPos inMeasure:(size_t)measure at:(VLFract)at visual:(uint16_t)visual
accidental:(VLMusicElement)accidental
{ {
[self drawNoteCursor:pitch inMeasure:measure at:at accidental:accidental mode:0]; [self drawNoteCursor:vertPos inMeasure:measure at:at visual:visual mode:0];
} }
- (void) drawNoteCursor - (void) drawNoteCursor
{ {
[self drawNoteCursor:fCursorPitch inMeasure:fCursorMeasure at:fCursorAt [self drawNoteCursor:fCursorVertPos inMeasure:fCursorMeasure at:fCursorAt
accidental:fCursorAccidental mode:fClickMode]; visual:fCursorVisual mode:fClickMode];
} }
- (void) drawNote:(int)visual at:(NSPoint)p - (void) drawNote:(int)visual at:(NSPoint)p
@ -390,7 +365,6 @@
accidental:[self accidentalForVisual:filterVisuals(step, visual)] accidental:[self accidentalForVisual:filterVisuals(step, visual)]
tied:tied]; tied:tied];
} else { } else {
VLMusicElement accidental;
pos = NSMakePoint([self noteXInMeasure:measIdx at:at], pos = NSMakePoint([self noteXInMeasure:measIdx at:at],
kSystemY+[self noteYInSection:measure.fPropIdx withPitch:65]); kSystemY+[self noteYInSection:measure.fPropIdx withPitch:65]);
[self drawRest:note->fVisual & VLNote::kNoteHeadMask at: pos]; [self drawRest:note->fVisual & VLNote::kNoteHeadMask at: pos];
@ -415,7 +389,7 @@
if (hasTriplets) { if (hasTriplets) {
[self drawTripletBracketFrom:tripletStartX to:tripletEndX atY:tripletY]; [self drawTripletBracketFrom:tripletStartX to:tripletEndX atY:tripletY];
} }
if (fCursorPitch != VLNote::kNoPitch && fLayout->SystemForMeasure(fCursorMeasure) == system) if (fCursorRegion == kRegionNote && fLayout->SystemForMeasure(fCursorMeasure) == system)
[self drawNoteCursor]; [self drawNoteCursor];
} }

View File

@ -16,14 +16,15 @@
#import "VLSheetViewLyrics.h" #import "VLSheetViewLyrics.h"
#import "VLSheetWindow.h" #import "VLSheetWindow.h"
#import "VLDocument.h" #import "VLDocument.h"
#import "VLPitchGrid.h"
@interface VLPlaybackEditable : VLEditable { @interface VLPlaybackEditable : VLEditable {
VLSheetView * fView; VLSheetView * fView;
size_t fStanza; size_t fStanza;
size_t fNoteMeasure; size_t fNoteMeasure;
VLFract fNoteAt; VLFract fNoteAt;
int fNotePitch; int fNoteVert;
VLMusicElement fNoteAccidental; uint16_t fNoteVisual;
size_t fChordMeasure; size_t fChordMeasure;
VLFract fChordAt; VLFract fChordAt;
} }
@ -50,29 +51,10 @@
{ {
VLMIDIUserEvent * event = (VLMIDIUserEvent *)[ev pointerValue]; VLMIDIUserEvent * event = (VLMIDIUserEvent *)[ev pointerValue];
if (event->fPitch) { if (event->fPitch) {
fNotePitch = event->fPitch;
fNoteAccidental = kMusicNothing;
switch (event->fVisual & VLNote::kAccidentalsMask) {
case VLNote::kWantFlat:
fNoteAccidental = kMusicFlatCursor;
break;
case VLNote::kWantSharp:
fNoteAccidental = kMusicSharpCursor;
break;
case VLNote::kWant2Flat:
fNoteAccidental = kMusic2FlatCursor;
break;
case VLNote::kWant2Sharp:
fNoteAccidental = kMusic2SharpCursor;
break;
case VLNote::kWantNatural:
fNoteAccidental = kMusicNaturalCursor;
break;
default:
break;
}
fNoteMeasure = event->fMeasure; fNoteMeasure = event->fMeasure;
fNoteAt = event->fAt; fNoteAt = event->fAt;
fNoteVisual = event->fVisual & VLNote::kAccidentalsMask;
fNoteVert = VLPitchToGrid(event->fPitch, fNoteVisual, [fView song]->Properties(fNoteMeasure).fKey);
fStanza = event->fStanza; fStanza = event->fStanza;
[fView highlightTextInStanza:fStanza measure:fNoteMeasure at:fNoteAt one:YES]; [fView highlightTextInStanza:fStanza measure:fNoteMeasure at:fNoteAt one:YES];
} else { } else {
@ -85,8 +67,8 @@
- (void) highlightCursor - (void) highlightCursor
{ {
if (fNoteMeasure != 0x80000000 && fNotePitch != VLNote::kNoPitch) if (fNoteMeasure != 0x80000000 && fNoteVert != kCursorNoPitch)
[fView drawNoteCursor:fNotePitch inMeasure:fNoteMeasure at:fNoteAt accidental:fNoteAccidental]; [fView drawNoteCursor:fNoteVert inMeasure:fNoteMeasure at:fNoteAt visual:fNoteVisual];
if (fChordMeasure != 0x80000000) if (fChordMeasure != 0x80000000)
[fView highlightChordInMeasure:fChordMeasure at:fChordAt]; [fView highlightChordInMeasure:fChordMeasure at:fChordAt];
} }