mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 03:04:00 +00:00
Walk through melody with cursor keys
This commit is contained in:
parent
ba5724f232
commit
b24fc07200
|
@ -601,6 +601,88 @@ void VLSong::DelChord(VLLocation at)
|
|||
fMeasures.pop_back();
|
||||
}
|
||||
|
||||
VLLyricsNote VLSong::FindNote(VLLocation at)
|
||||
{
|
||||
VLNoteList::iterator i = fMeasures[at.fMeasure].fMelody.begin();
|
||||
VLFraction t(0);
|
||||
|
||||
for (;;) {
|
||||
VLFraction tEnd = t+i->fDuration;
|
||||
if (tEnd > at.fAt)
|
||||
return *i;
|
||||
t = tEnd;
|
||||
++i;
|
||||
}
|
||||
return ++at.fMeasure < fMeasures.size()
|
||||
? fMeasures[at.fMeasure].fMelody.front() : VLLyricsNote();
|
||||
}
|
||||
|
||||
bool VLSong::PrevNote(VLLocation &at)
|
||||
{
|
||||
uint32_t meas = at.fMeasure;
|
||||
VLFraction where = at.fAt;
|
||||
for (;;) {
|
||||
bool found = false;
|
||||
VLNoteList::iterator i = fMeasures[meas].fMelody.begin();
|
||||
VLNoteList::iterator end = fMeasures[meas].fMelody.end();
|
||||
VLFraction t(0);
|
||||
VLFraction prevAt(0);
|
||||
while (i != end) {
|
||||
VLFraction tEnd = t+i->fDuration;
|
||||
if (tEnd > where)
|
||||
break;
|
||||
if (i->fPitch != VLNote::kNoPitch && !(i->fTied & VLNote::kTiedWithPrev)) {
|
||||
prevAt = t;
|
||||
found = true;
|
||||
}
|
||||
t = tEnd;
|
||||
++i;
|
||||
}
|
||||
if (found) {
|
||||
at.fMeasure = meas;
|
||||
at.fAt = prevAt;
|
||||
|
||||
return true;
|
||||
}
|
||||
if (!meas--)
|
||||
break;
|
||||
where = VLFraction(1000);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VLSong::NextNote(VLLocation &at)
|
||||
{
|
||||
uint32_t meas = at.fMeasure;
|
||||
VLFraction where = at.fAt;
|
||||
bool first = false;
|
||||
for (;;) {
|
||||
VLNoteList::iterator i = fMeasures[meas].fMelody.begin();
|
||||
VLNoteList::iterator end = fMeasures[meas].fMelody.end();
|
||||
VLFraction t(0);
|
||||
while (i != end) {
|
||||
VLFraction tEnd = t+i->fDuration;
|
||||
if ((t > where || first) && i->fPitch != VLNote::kNoPitch
|
||||
&& !(i->fTied & VLNote::kTiedWithPrev)
|
||||
) {
|
||||
at.fMeasure = meas;
|
||||
at.fAt = t;
|
||||
|
||||
return true;
|
||||
}
|
||||
first = false;
|
||||
t = tEnd;
|
||||
++i;
|
||||
}
|
||||
if (++meas < fMeasures.size()) {
|
||||
where = VLFraction(0);
|
||||
first = true;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint8_t & FirstTie(VLMeasure & measure)
|
||||
{
|
||||
VLNoteList::iterator i = measure.fMelody.begin();
|
||||
|
|
|
@ -420,6 +420,9 @@ public:
|
|||
iterator begin() { return iterator(*this, false); }
|
||||
iterator end() { return iterator(*this, true); }
|
||||
|
||||
VLLyricsNote FindNote(VLLocation at);
|
||||
bool PrevNote(VLLocation & at);
|
||||
bool NextNote(VLLocation & at);
|
||||
void AddChord(VLChord chord, VLLocation at);
|
||||
void AddNote(VLLyricsNote note, VLLocation at);
|
||||
void DelChord(VLLocation at);
|
||||
|
|
|
@ -896,6 +896,15 @@ const float kSemiFloor = -1.0f*kLineH;
|
|||
fClickMode = 'k';
|
||||
[self setNeedsDisplay:YES];
|
||||
break;
|
||||
case '?':
|
||||
[self playNoteAtCursor];
|
||||
break;
|
||||
case 0xF702: // Left arrow
|
||||
[self moveCursorToPrevNote];
|
||||
break;
|
||||
case 0xF703: // Right arrow
|
||||
[self moveCursorToNextNote];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
- (void) drawNotesForSystem:(int)system;
|
||||
- (void) addNoteAtCursor;
|
||||
- (void) drawNoteCursor:(int)vertPos at:(VLLocation)at visual:(uint16_t)visual;
|
||||
- (void) playNoteAtCursor;
|
||||
- (void) moveCursorToNextNote;
|
||||
- (void) moveCursorToPrevNote;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -43,6 +43,32 @@
|
|||
}
|
||||
}
|
||||
|
||||
- (void) playNoteAtCursor
|
||||
{
|
||||
VLNote note = [self song]->FindNote(fCursorLocation);
|
||||
if (note.fPitch != VLNote::kNoPitch) {
|
||||
fCursorRegion = kRegionNote;
|
||||
int section = [self song]->fMeasures[fCursorLocation.fMeasure].fPropIdx;
|
||||
fCursorVertPos = [self gridInSection:section withPitch:note.fPitch visual:note.fVisual];
|
||||
fCursorVisual = note.fVisual & VLNote::kAccidentalsMask;
|
||||
[self setNeedsDisplay:YES];
|
||||
|
||||
VLSoundOut::Instance()->PlayNote(note);
|
||||
}
|
||||
}
|
||||
|
||||
- (void) moveCursorToNextNote
|
||||
{
|
||||
if ([self song]->NextNote(fCursorLocation))
|
||||
[self playNoteAtCursor];
|
||||
}
|
||||
|
||||
- (void) moveCursorToPrevNote
|
||||
{
|
||||
if ([self song]->PrevNote(fCursorLocation))
|
||||
[self playNoteAtCursor];
|
||||
}
|
||||
|
||||
- (void) drawLedgerLines:(int)vertPos at:(NSPoint)p
|
||||
{
|
||||
p.x += kLedgerX;
|
||||
|
|
Loading…
Reference in New Issue
Block a user