mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 11:14:00 +00:00
Remove vestigial MMA / Partial/Visual note infrastructure
This commit is contained in:
parent
3a5c3df5ec
commit
a60d6612ff
|
@ -140,7 +140,7 @@
|
|||
<key>CFBundleSignature</key>
|
||||
<string>VçEz</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0a3</string>
|
||||
<string>1.0a4</string>
|
||||
<key>NSMainNibFile</key>
|
||||
<string>MainMenu</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
|
|
@ -92,27 +92,6 @@ static std::string PitchName(int8_t pitch, bool useSharps)
|
|||
+ std::string(kVLFlatStr);
|
||||
}
|
||||
|
||||
static std::string MMAPitchName(int8_t pitch, bool useSharps)
|
||||
{
|
||||
if (pitch == VLNote::kNoPitch)
|
||||
return "r";
|
||||
char name[3];
|
||||
name[2] = 0;
|
||||
name[1] = 'n';
|
||||
pitch %= 12;
|
||||
if (kScale[pitch] != ' ') {
|
||||
name[0] = kScale[pitch];
|
||||
} else if (useSharps) {
|
||||
name[0] = kScale[pitch-1];
|
||||
name[1] = '#';
|
||||
} else {
|
||||
name[0] = kScale[pitch+1];
|
||||
name[1] = '&';
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
VLNote::VLNote(std::string name)
|
||||
{
|
||||
//
|
||||
|
@ -151,77 +130,6 @@ void VLNote::Name(std::string & name, bool useSharps) const
|
|||
name = PitchName(fPitch, useSharps);
|
||||
}
|
||||
|
||||
static struct {
|
||||
VLFract fVal;
|
||||
const char * fName;
|
||||
} sMMADur [] = {
|
||||
{{1,1}, "1"},
|
||||
{{1,2}, "2"},
|
||||
{{1,3}, "23"},
|
||||
{{1,4}, "4"},
|
||||
{{1,6}, "81"},
|
||||
{{1,8}, "8"},
|
||||
{{1,12}, "82"},
|
||||
{{1,16}, "16"},
|
||||
{{1,24}, "6"},
|
||||
{{1,32}, "32"},
|
||||
{{1,64}, "64"},
|
||||
{{0,0}, 0}
|
||||
};
|
||||
|
||||
void VLNote::MMAName(std::string & name, VLFraction at, VLFraction dur, VLFraction prevDur, VLFraction nextDur, const VLProperties & prop) const
|
||||
{
|
||||
if (fTied & kTiedWithPrev) {
|
||||
if (fTied & kTiedWithNext) {
|
||||
name = "~<>~";
|
||||
} else {
|
||||
name = '~';
|
||||
}
|
||||
return;
|
||||
}
|
||||
bool useSharps = prop.fKey >= 0;
|
||||
|
||||
name.clear();
|
||||
VLFraction prevPart(0);
|
||||
while (dur.fNum) {
|
||||
VLFraction part;
|
||||
bool grouped = dur==nextDur ||
|
||||
(prevPart!=0 ? dur==prevPart : dur==prevDur);
|
||||
prop.PartialNote(at, dur, grouped, &part);
|
||||
const char * durName;
|
||||
for (int d=0; sMMADur[d].fName; ++d)
|
||||
if (part == sMMADur[d].fVal) {
|
||||
durName = sMMADur[d].fName;
|
||||
break;
|
||||
}
|
||||
if (!strcmp(durName, "82")) {
|
||||
//
|
||||
// Distinguish 2nd pair of swing 8ths from regular triplet
|
||||
//
|
||||
const VLFraction kBeat(1, prop.fTime.fDenom);
|
||||
VLFraction withinBeat = at % kBeat;
|
||||
if (withinBeat != 2*kBeat/3)
|
||||
durName = "3";
|
||||
}
|
||||
if (name.size())
|
||||
name += '+';
|
||||
name += durName;
|
||||
prevPart = part;
|
||||
dur -= part;
|
||||
at += part;
|
||||
}
|
||||
int pitch = fTied & kTiedWithPrev ? kNoPitch : fPitch;
|
||||
name += MMAPitchName(pitch, useSharps);
|
||||
if (pitch != kNoPitch) {
|
||||
for (int raise = (pitch-kMiddleC)/kOctave; raise>0; --raise)
|
||||
name += '+';
|
||||
for (int lower = (kMiddleC+kOctave-1-pitch)/kOctave; lower>0; --lower)
|
||||
name += '-';
|
||||
}
|
||||
if (fTied & kTiedWithNext)
|
||||
name += '~';
|
||||
}
|
||||
|
||||
void VLNote::MakeRepresentable()
|
||||
{
|
||||
if (fDuration > 1)
|
||||
|
@ -467,263 +375,11 @@ void VLChord::Name(std::string & base, std::string & ext, std::string & root, bo
|
|||
root = PitchName(fRootPitch, useSharps);
|
||||
}
|
||||
|
||||
//
|
||||
// MMA supports a large but finite list of chords
|
||||
//
|
||||
static const VLChordModifier kMMAModifiers[] = {
|
||||
{"", 0, 0},
|
||||
{"+", _ kmAug5th, _ km5th},
|
||||
{"11", _ kmMin7th | _ kmMaj9th | _ km11th, 0},
|
||||
{"11b9", _ kmMin7th | _ kmMin9th | _ km11th, 0},
|
||||
{"13", _ kmMin7th | _ kmMaj9th | _ km11th | _ kmMaj13th, 0},
|
||||
{"5", 0, _ kmMaj3rd},
|
||||
{"6", _ kmDim7th, 0},
|
||||
{"69", _ kmDim7th | _ kmMaj9th, 0},
|
||||
{"7", _ kmMin7th, 0},
|
||||
{"7#11", _ kmMin7th | _ kmAug11th, 0},
|
||||
{"7#5", _ kmMin7th | _ kmAug5th, _ km5th},
|
||||
{"7#5#9", _ kmMin7th | _ kmAug5th | _ kmAug9th, _ km5th},
|
||||
{"7#5b9", _ kmMin7th | _ kmAug5th | _ kmMin9th, _ km5th},
|
||||
{"7#9", _ kmMin7th | _ kmAug9th, 0},
|
||||
{"7#9#11", _ kmMin7th | _ kmAug9th | _ kmAug11th, 0},
|
||||
{"7b5", _ kmMin7th | _ kmDim5th, _ km5th},
|
||||
{"7b5#9", _ kmMin7th | _ kmDim5th | _ kmAug9th, _ km5th},
|
||||
{"7b5b9", _ kmMin7th | _ kmDim5th | _ kmMin9th, _ km5th},
|
||||
{"7b9", _ kmMin7th | _ kmMin9th, 0},
|
||||
{"7sus", _ kmMin7th | _ km4th, _ kmMaj3rd},
|
||||
{"7sus2", _ kmMin7th | _ kmMaj2nd, _ kmMaj3rd},
|
||||
{"9", _ kmMin7th | _ kmMaj9th, 0},
|
||||
{"9#11", _ kmMin7th | _ kmMaj9th | _ kmAug11th, 0},
|
||||
{"9#5", _ kmMin7th | _ kmMaj9th | _ kmAug5th, _ km5th},
|
||||
{"9b5", _ kmMin7th | _ kmMaj9th | _ kmDim5th, _ km5th},
|
||||
{"9sus", _ kmMaj9th, 0},
|
||||
{"M13", _ kmMaj7th | _ kmMaj13th, 0},
|
||||
{"M7", _ kmMaj7th, 0},
|
||||
{"M7#11", _ kmMaj7th | _ kmMaj9th | _ kmAug11th, 0},
|
||||
{"M7#5", _ kmMaj7th | _ kmAug5th, _ km5th},
|
||||
{"M7b5", _ kmMaj7th | _ kmDim5th, _ km5th},
|
||||
{"M9", _ kmMaj7th | _ kmMaj9th, 0},
|
||||
{"aug9", _ kmMin7th | _ kmMaj9th | _ kmAug5th, _ km5th},
|
||||
{"dim3", _ kmMin3rd | _ kmDim5th, _ kmMaj3rd | _ km5th},
|
||||
{"dim7", _ kmMin3rd | _ kmDim5th | _ kmDim7th, _ kmMaj3rd | _ km5th},
|
||||
{"m", _ kmMin3rd, _ kmMaj3rd},
|
||||
{"m#5", _ kmMin3rd | _ kmAug5th, _ kmMaj3rd | _ km5th},
|
||||
{"m(maj7)", _ kmMin3rd | _ kmMaj7th, _ kmMaj3rd},
|
||||
{"m(sus9)", _ kmMin3rd | _ kmMaj9th, _ kmMaj3rd},
|
||||
{"m11", _ kmMin3rd | _ kmMin7th | _ kmMaj9th | _ km11th, _ kmMaj3rd},
|
||||
{"m6", _ kmMin3rd | _ kmDim7th, _ kmMaj3rd},
|
||||
{"m69", _ kmMin3rd | _ kmDim7th | _ kmMaj9th, _ kmMaj3rd},
|
||||
{"m7", _ kmMin3rd | _ kmMin7th, _ kmMaj3rd},
|
||||
{"m7b5", _ kmMin3rd | _ kmMin7th | _ kmDim5th, _ kmMaj3rd | _ km5th},
|
||||
{"m7b9", _ kmMin3rd | _ kmMin7th | _ kmMin9th, _ kmMaj3rd},
|
||||
{"m9", _ kmMin3rd | _ kmMin7th | _ kmMaj9th, _ kmMaj3rd},
|
||||
{"m9b5", _ kmMin3rd | _ kmMin7th | _ kmMaj9th | _ kmDim5th, _ kmMaj3rd | _ km5th},
|
||||
{"mM7", _ kmMin3rd | _ kmMaj7th, _ kmMaj3rd},
|
||||
{"mb5", _ kmMin3rd | _ kmDim5th, _ kmMaj3rd | _ km5th},
|
||||
{"sus", _ km4th, _ kmMaj3rd},
|
||||
{"sus2", _ kmMaj2nd, _ kmMaj3rd},
|
||||
{"sus9", _ kmMaj9th, 0},
|
||||
{NULL, 0, 0}
|
||||
};
|
||||
|
||||
bool VLChord::MMAName(std::string & name, bool useSharps, bool initial) const
|
||||
{
|
||||
VLFraction dur = fDuration;
|
||||
int quarters = static_cast<int>(dur*4.0f+0.5f);
|
||||
name = "";
|
||||
if (!quarters--)
|
||||
return initial;
|
||||
if (fPitch == kNoPitch) {
|
||||
name = initial ? 'z' : '/';
|
||||
} else {
|
||||
std::string base, ext;
|
||||
VLNote::Name(base, useSharps);
|
||||
|
||||
size_t best = 0;
|
||||
size_t bestBits = 32;
|
||||
size_t bestScore= 0;
|
||||
for (size_t i=0; kMMAModifiers[i].fName; ++i) {
|
||||
uint32_t steps = (kmUnison | kmMaj3rd | km5th)
|
||||
| kMMAModifiers[i].fAddSteps
|
||||
&~kMMAModifiers[i].fDelSteps;
|
||||
if (fSteps == steps) {
|
||||
//
|
||||
// Exact match
|
||||
//
|
||||
best = i;
|
||||
break;
|
||||
}
|
||||
steps ^= fSteps;
|
||||
size_t bits=0;
|
||||
size_t score=0;
|
||||
for (uint32_t b=steps; b; b &= (b-1))
|
||||
++bits;
|
||||
for (size_t b=0; b<32; ++b)
|
||||
if (steps & (1<<b))
|
||||
score += 32-b;
|
||||
if (bits < bestBits || (bits==bestBits && score < bestScore)) {
|
||||
best = i;
|
||||
bestBits = bits;
|
||||
bestScore = score;
|
||||
}
|
||||
}
|
||||
ext = kMMAModifiers[best].fName;
|
||||
name = base+ext;
|
||||
if (fRootPitch != kNoPitch)
|
||||
name += '/' + PitchName(fRootPitch, useSharps);
|
||||
std::toupper(base[0]);
|
||||
size_t mod;
|
||||
while ((mod = name.find("Maj")) != std::string::npos)
|
||||
name.erase(mod+1, 2);
|
||||
while ((mod = name.find(kVLSharpStr)) != std::string::npos)
|
||||
name.replace(mod, 3, "#", 1);
|
||||
while ((mod = name.find(kVLFlatStr)) != std::string::npos)
|
||||
name.replace(mod, 3, "&", 1);
|
||||
}
|
||||
while (quarters--)
|
||||
name += " /";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static VLFraction MaxNote(VLFraction d)
|
||||
{
|
||||
if (d >= 1)
|
||||
return 1;
|
||||
if (d.fNum == 1 && !(d.fDenom & (d.fDenom-1))) // Power of 2
|
||||
return d;
|
||||
|
||||
|
||||
VLFraction note(1,2);
|
||||
VLFraction triplet(1,3);
|
||||
|
||||
for (;;) {
|
||||
if (d >= note)
|
||||
return note;
|
||||
else if (d >= triplet)
|
||||
return triplet;
|
||||
note /= 2;
|
||||
triplet /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void TrimNote(VLFraction at, VLFraction & d, VLFraction grid)
|
||||
{
|
||||
if (at < grid && d > grid-at)
|
||||
d = MaxNote(grid-at);
|
||||
}
|
||||
|
||||
void VLProperties::PartialNote(VLFraction at, VLFraction totalDuration,
|
||||
bool grouped, VLFraction * noteDuration) const
|
||||
{
|
||||
const VLFraction kBeat(1, fTime.fDenom);
|
||||
|
||||
at %= fTime;
|
||||
*noteDuration = MaxNote(std::min(MaxNote(totalDuration), fTime-at)); // Don't extend past measure
|
||||
|
||||
if (at.fDenom > kBeat.fDenom) { // Break up notes not starting on beat
|
||||
// Don't extend past "middle" of measure
|
||||
if (fTime.fNum & 1) // Odd timecode, round up (most 5/4 seems to be 3+2, not 2+3)
|
||||
TrimNote(at, *noteDuration, VLFraction((fTime.fNum+1)/2, fTime.fDenom));
|
||||
else
|
||||
TrimNote(at, *noteDuration, fTime / 2);
|
||||
at %= kBeat;
|
||||
if (at == 2*kBeat/3)
|
||||
TrimNote(0, *noteDuration, kBeat); // Allow syncopated beats in swing
|
||||
else
|
||||
TrimNote(at, *noteDuration, kBeat);// Don't let other notes span beats
|
||||
}
|
||||
if (!(noteDuration->fDenom % 3))
|
||||
if (*noteDuration != totalDuration) {
|
||||
if (((at+*noteDuration)%kBeat) > 0)
|
||||
*noteDuration *= VLFraction(3,4); // avoid frivolous triplets
|
||||
} else if (*noteDuration > VLFraction(1,4*fDivisions) && !grouped) {
|
||||
if (*noteDuration == VLFraction(1,2*fDivisions))
|
||||
if (at % VLFraction(1, 4*fDivisions/3) == 0)
|
||||
return; // Permit larger swing notes
|
||||
*noteDuration *= VLFraction(3,4); // avoid other isolated triplets
|
||||
}
|
||||
}
|
||||
|
||||
void VLProperties::VisualNote(VLFraction at, VLFraction actualDur,
|
||||
bool prevTriplet,
|
||||
VLFraction *visualDur, bool * triplet) const
|
||||
{
|
||||
bool swing= !(fDivisions % 3); // In swing mode?
|
||||
VLFraction swung(3, fDivisions*8, true); // Which notes to swing
|
||||
VLFraction swingGrid(2*swung); // Alignment of swing notes
|
||||
|
||||
if (*triplet = !(actualDur.fDenom % 3)) {
|
||||
if (swing) { // Swing 8ths / 16ths are written as straight 8ths
|
||||
if (actualDur == 4*swung/3 && (at % swingGrid) == 0) {
|
||||
*visualDur = swung;
|
||||
*triplet = false;
|
||||
} else if (actualDur == 2*swung/3 && ((at+actualDur) % swingGrid) == 0 && !prevTriplet) {
|
||||
*visualDur = swung;
|
||||
*triplet = false;
|
||||
} else {
|
||||
*visualDur = 3*actualDur/2;
|
||||
}
|
||||
} else {
|
||||
*visualDur = 3*actualDur/2;
|
||||
}
|
||||
} else {
|
||||
*visualDur = actualDur;
|
||||
}
|
||||
}
|
||||
|
||||
VLMeasure::VLMeasure()
|
||||
: fPropIdx(0)
|
||||
{
|
||||
}
|
||||
|
||||
void VLMeasure::MMANotes(std::string & notes, const VLProperties & prop,
|
||||
VLFraction extra) const
|
||||
{
|
||||
VLFraction at(0);
|
||||
VLNoteList::const_iterator i = fMelody.begin();
|
||||
VLNoteList::const_iterator e = fMelody.end();
|
||||
|
||||
notes.clear();
|
||||
VLFraction prevDur(0);
|
||||
for (; i!=e; ++i) {
|
||||
std::string note;
|
||||
VLFraction nextDur(0);
|
||||
VLFraction dur(i->fDuration);
|
||||
VLNoteList::const_iterator n=i;
|
||||
if (++n != e)
|
||||
nextDur = n->fDuration;
|
||||
else
|
||||
dur += extra;
|
||||
i->MMAName(note, at, dur, prevDur, nextDur, prop);
|
||||
if (notes.size()>1)
|
||||
notes += ' ';
|
||||
if (note == "~")
|
||||
notes += note;
|
||||
else
|
||||
notes += note+';';
|
||||
at += i->fDuration;
|
||||
}
|
||||
if (notes == "~")
|
||||
notes += "<>;";
|
||||
}
|
||||
|
||||
void VLMeasure::MMAChords(std::string & chords, const VLProperties & prop,
|
||||
bool initial) const
|
||||
{
|
||||
VLChordList::const_iterator i = fChords.begin();
|
||||
VLChordList::const_iterator e = fChords.end();
|
||||
|
||||
chords.clear();
|
||||
for (; i!=e; ++i) {
|
||||
std::string chord;
|
||||
initial = i->MMAName(chord, prop.fKey >= 0, initial);
|
||||
if (chords.size())
|
||||
chords += ' ';
|
||||
chords += chord;
|
||||
}
|
||||
}
|
||||
|
||||
bool VLMeasure::IsEmpty() const
|
||||
{
|
||||
return fChords.size() == 1 && fMelody.size() == 1
|
||||
|
|
|
@ -150,7 +150,6 @@ struct VLNote {
|
|||
VLNote(VLFraction dur=0, int pitch=kNoPitch);
|
||||
VLNote(std::string name);
|
||||
void Name(std::string & name, bool useSharps = false) const;
|
||||
void MMAName(std::string & name, VLFraction at, VLFraction dur, VLFraction prevDur, VLFraction nextDur, const VLProperties & prop) const;
|
||||
void MakeRepresentable();
|
||||
void AlignToGrid(VLFraction at, VLFraction grid);
|
||||
};
|
||||
|
@ -209,7 +208,6 @@ struct VLChord : VLNote {
|
|||
VLChord(VLFraction dur=0, int pitch=kNoPitch, int rootPitch=kNoPitch);
|
||||
VLChord(std::string name);
|
||||
void Name(std::string & base, std::string & ext, std::string & root, bool useSharps = false) const;
|
||||
bool MMAName(std::string & name, bool useSharps, bool initial) const;
|
||||
};
|
||||
|
||||
struct VLChordModifier {
|
||||
|
@ -224,15 +222,6 @@ struct VLProperties {
|
|||
int8_t fMode; // 1 = major -1 = minor
|
||||
int8_t fDivisions; // Number of divisions per quarter note
|
||||
|
||||
//
|
||||
// Subdivide a note and adjust for swing
|
||||
//
|
||||
void PartialNote(VLFraction at, VLFraction totalDuration, bool grouped, VLFraction * noteDuration) const;
|
||||
//
|
||||
// Determine visual representation of note head
|
||||
//
|
||||
void VisualNote(VLFraction at, VLFraction actualDur, bool prevTriplet, VLFraction *visualDur, bool * triplet) const;
|
||||
|
||||
bool operator==(const VLProperties & other)
|
||||
{ return fTime == other.fTime && fKey == other.fKey && fMode == other.fMode
|
||||
&& fDivisions == other.fDivisions;
|
||||
|
@ -256,9 +245,6 @@ struct VLMeasure {
|
|||
|
||||
VLMeasure();
|
||||
|
||||
void MMANotes(std::string & notes, const VLProperties & prop, VLFraction extra) const;
|
||||
void MMAChords(std::string & chords, const VLProperties & prop, bool initial) const;
|
||||
|
||||
bool IsEmpty() const;
|
||||
bool NoChords() const;
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user