mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 11:14:00 +00:00
Transpose songs
This commit is contained in:
parent
9a6768e8f3
commit
1b61bcd41e
|
@ -541,3 +541,53 @@ void VLSong::DelNote(size_t measure, VLFraction at)
|
|||
}
|
||||
}
|
||||
|
||||
static void TransposePinned(int8_t & pitch, int semi)
|
||||
{
|
||||
if (pitch == VLNote::kNoPitch)
|
||||
return;
|
||||
|
||||
int pitchInOctave = pitch % 12;
|
||||
int octave = pitch-pitchInOctave;
|
||||
pitchInOctave += semi;
|
||||
if (pitchInOctave < 0)
|
||||
pitch = octave+pitchInOctave+12;
|
||||
else if (pitchInOctave > 11)
|
||||
pitch = octave+pitchInOctave-12;
|
||||
else
|
||||
pitch = octave+pitchInOctave;
|
||||
}
|
||||
|
||||
void VLSong::Transpose(int semi)
|
||||
{
|
||||
for (int pass=0; pass<2 && semi;) {
|
||||
int8_t low = 127;
|
||||
int8_t high = 0;
|
||||
for (int measure=0; measure<fMeasures.size(); ++measure) {
|
||||
VLNoteList::iterator i = fMeasures[measure].fMelody.begin();
|
||||
VLNoteList::iterator e = fMeasures[measure].fMelody.end();
|
||||
|
||||
for (; i!=e; ++i) {
|
||||
if (i->fPitch == VLNote::kNoPitch)
|
||||
continue;
|
||||
i->fPitch += semi;
|
||||
low = std::min(low, i->fPitch);
|
||||
high = std::max(high, i->fPitch);
|
||||
}
|
||||
}
|
||||
if (low < VLNote::kMiddleC-6 && high < VLNote::kMiddleC+7)
|
||||
semi += 12; // Transpose an Octave up
|
||||
else if (low > VLNote::kMiddleC+7 && high > VLNote::kMiddleC+16)
|
||||
semi -= 12; // Transpose an Octave down
|
||||
else
|
||||
break; // Looks like we're done
|
||||
}
|
||||
for (int measure=0; measure<fMeasures.size(); ++measure) {
|
||||
VLChordList::iterator i = fMeasures[measure].fChords.begin();
|
||||
VLChordList::iterator e = fMeasures[measure].fChords.end();
|
||||
|
||||
for (; i!=e; ++i) {
|
||||
TransposePinned(i->fPitch, semi);
|
||||
TransposePinned(i->fRootPitch, semi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -217,6 +217,7 @@ struct VLSong {
|
|||
void AddNote(VLNote note, size_t measure, VLFraction at);
|
||||
void DelChord(size_t measure, VLFraction at);
|
||||
void DelNote(size_t measure, VLFraction at);
|
||||
void Transpose(int semitones);
|
||||
|
||||
size_t CountMeasures() const { return fMeasures.size(); }
|
||||
};
|
||||
|
|
|
@ -345,8 +345,24 @@ static float sFlatPos[] = {
|
|||
|
||||
- (IBAction) setKey:(id)sender
|
||||
{
|
||||
[[NSAlert alertWithMessageText:@"Transpose Song?"
|
||||
defaultButton:@"Transpose"
|
||||
alternateButton:@"Cancel"
|
||||
otherButton:@"Change Key"
|
||||
informativeTextWithFormat:
|
||||
@"Do you want to transpose the song into the new key?"]
|
||||
beginSheetModalForWindow:[self window]
|
||||
modalDelegate:self didEndSelector:@selector(setKey:returnCode:contextInfo:)
|
||||
contextInfo:sender];
|
||||
}
|
||||
|
||||
- (void)setKey:(NSAlert *)alert returnCode:(int)returnCode contextInfo:(id)sender
|
||||
{
|
||||
if (returnCode == NSAlertAlternateReturn)
|
||||
return;
|
||||
|
||||
int key = [[sender selectedItem] tag];
|
||||
[[self document] setKey: key transpose: YES];
|
||||
[[self document] setKey:key transpose:returnCode==NSAlertDefaultReturn];
|
||||
fNeedsRecalc = kRecalc;
|
||||
[self setNeedsDisplay: YES];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user