mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 11:14: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();
|
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)
|
static uint8_t & FirstTie(VLMeasure & measure)
|
||||||
{
|
{
|
||||||
VLNoteList::iterator i = measure.fMelody.begin();
|
VLNoteList::iterator i = measure.fMelody.begin();
|
||||||
|
|
|
@ -420,6 +420,9 @@ public:
|
||||||
iterator begin() { return iterator(*this, false); }
|
iterator begin() { return iterator(*this, false); }
|
||||||
iterator end() { return iterator(*this, true); }
|
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 AddChord(VLChord chord, VLLocation at);
|
||||||
void AddNote(VLLyricsNote note, VLLocation at);
|
void AddNote(VLLyricsNote note, VLLocation at);
|
||||||
void DelChord(VLLocation at);
|
void DelChord(VLLocation at);
|
||||||
|
|
|
@ -896,6 +896,15 @@ const float kSemiFloor = -1.0f*kLineH;
|
||||||
fClickMode = 'k';
|
fClickMode = 'k';
|
||||||
[self setNeedsDisplay:YES];
|
[self setNeedsDisplay:YES];
|
||||||
break;
|
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) drawNotesForSystem:(int)system;
|
||||||
- (void) addNoteAtCursor;
|
- (void) addNoteAtCursor;
|
||||||
- (void) drawNoteCursor:(int)vertPos at:(VLLocation)at visual:(uint16_t)visual;
|
- (void) drawNoteCursor:(int)vertPos at:(VLLocation)at visual:(uint16_t)visual;
|
||||||
|
- (void) playNoteAtCursor;
|
||||||
|
- (void) moveCursorToNextNote;
|
||||||
|
- (void) moveCursorToPrevNote;
|
||||||
|
|
||||||
@end
|
@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
|
- (void) drawLedgerLines:(int)vertPos at:(NSPoint)p
|
||||||
{
|
{
|
||||||
p.x += kLedgerX;
|
p.x += kLedgerX;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user