mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 19:23:59 +00:00
Automatically resize song
This commit is contained in:
parent
d33b9ed728
commit
39f81a1a24
|
@ -818,6 +818,19 @@ void VLMeasure::MMAChords(std::string & chords, const VLProperties & prop,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VLMeasure::IsEmpty() const
|
||||||
|
{
|
||||||
|
return fChords.size() == 1 && fMelody.size() == 1
|
||||||
|
&& fChords.front().fPitch == VLNote::kNoPitch
|
||||||
|
&& fMelody.front().fPitch == VLNote::kNoPitch;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VLMeasure::NoChords() const
|
||||||
|
{
|
||||||
|
return fChords.size() == 1
|
||||||
|
&& fChords.front().fPitch == VLNote::kNoPitch;
|
||||||
|
}
|
||||||
|
|
||||||
VLSong::VLSong(bool initialize)
|
VLSong::VLSong(bool initialize)
|
||||||
{
|
{
|
||||||
if (!initialize)
|
if (!initialize)
|
||||||
|
@ -827,21 +840,27 @@ VLSong::VLSong(bool initialize)
|
||||||
VLProperties defaultProperties = {fourFour, 0, 1, 3};
|
VLProperties defaultProperties = {fourFour, 0, 1, 3};
|
||||||
|
|
||||||
fProperties.push_back(defaultProperties);
|
fProperties.push_back(defaultProperties);
|
||||||
fMeasures.resize(32); // Leadin, AABA
|
|
||||||
|
|
||||||
VLLyricsNote rest = VLLyricsNote(VLRest(1));
|
AddMeasure();
|
||||||
VLChord rchord;
|
|
||||||
rchord.fDuration = 1;
|
|
||||||
|
|
||||||
for (int i=0; i<32; ++i) {
|
|
||||||
fMeasures[i].fChords.push_back(rchord);
|
|
||||||
fMeasures[i].fMelody.push_back(rest);
|
|
||||||
}
|
|
||||||
|
|
||||||
fGoToCoda = -1;
|
fGoToCoda = -1;
|
||||||
fCoda = -1;
|
fCoda = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VLSong::AddMeasure()
|
||||||
|
{
|
||||||
|
VLFraction dur = fProperties[0].fTime;
|
||||||
|
VLLyricsNote rest = VLLyricsNote(VLRest(dur));
|
||||||
|
VLChord rchord;
|
||||||
|
rchord.fDuration = dur;
|
||||||
|
VLMeasure meas;
|
||||||
|
|
||||||
|
meas.fChords.push_back(rchord);
|
||||||
|
meas.fMelody.push_back(rest);
|
||||||
|
|
||||||
|
fMeasures.push_back(meas);
|
||||||
|
}
|
||||||
|
|
||||||
void VLSong::swap(VLSong & other)
|
void VLSong::swap(VLSong & other)
|
||||||
{
|
{
|
||||||
fProperties.swap(other.fProperties);
|
fProperties.swap(other.fProperties);
|
||||||
|
@ -866,6 +885,12 @@ void VLSong::clear()
|
||||||
//
|
//
|
||||||
void VLSong::AddChord(VLChord chord, size_t measure, VLFraction at)
|
void VLSong::AddChord(VLChord chord, size_t measure, VLFraction at)
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// Always keep an empty measure in reserve
|
||||||
|
//
|
||||||
|
while (measure+1 >= fMeasures.size())
|
||||||
|
AddMeasure();
|
||||||
|
|
||||||
VLChordList::iterator i = fMeasures[measure].fChords.begin();
|
VLChordList::iterator i = fMeasures[measure].fChords.begin();
|
||||||
VLFraction t(0);
|
VLFraction t(0);
|
||||||
|
|
||||||
|
@ -925,6 +950,11 @@ void VLSong::DelChord(size_t measure, VLFraction at)
|
||||||
t = tEnd;
|
t = tEnd;
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// Trim excess empty measures
|
||||||
|
//
|
||||||
|
if (measure == fMeasures.size()-2 && fMeasures[measure].IsEmpty())
|
||||||
|
fMeasures.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t & FirstTie(VLMeasure & measure)
|
uint8_t & FirstTie(VLMeasure & measure)
|
||||||
|
@ -945,6 +975,12 @@ uint8_t & LastTie(VLMeasure & measure)
|
||||||
//
|
//
|
||||||
void VLSong::AddNote(VLLyricsNote note, size_t measure, VLFraction at)
|
void VLSong::AddNote(VLLyricsNote note, size_t measure, VLFraction at)
|
||||||
{
|
{
|
||||||
|
//
|
||||||
|
// Always keep an empty measure in reserve
|
||||||
|
//
|
||||||
|
while (measure+1 >= fMeasures.size())
|
||||||
|
AddMeasure();
|
||||||
|
|
||||||
VLNoteList::iterator i = fMeasures[measure].fMelody.begin();
|
VLNoteList::iterator i = fMeasures[measure].fMelody.begin();
|
||||||
VLFraction t(0);
|
VLFraction t(0);
|
||||||
|
|
||||||
|
@ -1031,6 +1067,11 @@ void VLSong::DelNote(size_t measure, VLFraction at)
|
||||||
t = tEnd;
|
t = tEnd;
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// Trim excess empty measures
|
||||||
|
//
|
||||||
|
if (measure == fMeasures.size()-2 && fMeasures[measure].IsEmpty())
|
||||||
|
fMeasures.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VLSong::ExtendNote(size_t measure, VLFraction at)
|
void VLSong::ExtendNote(size_t measure, VLFraction at)
|
||||||
|
@ -1159,7 +1200,17 @@ void VLSong::Transpose(int semi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t VLSong::CountStanzas() const
|
size_t VLSong::EmptyEnding() const
|
||||||
|
{
|
||||||
|
size_t full = fMeasures.size();
|
||||||
|
|
||||||
|
while (full-- && fMeasures[full].IsEmpty())
|
||||||
|
;
|
||||||
|
|
||||||
|
return fMeasures.size()-(full+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t VLSong::CountStanzas() const
|
||||||
{
|
{
|
||||||
size_t stanzas = 0;
|
size_t stanzas = 0;
|
||||||
|
|
||||||
|
@ -1233,6 +1284,7 @@ void VLSong::LilypondNotes(std::string & notes) const
|
||||||
std::string indent = "";
|
std::string indent = "";
|
||||||
size_t seenEnding = 0;
|
size_t seenEnding = 0;
|
||||||
int numEndings = 0;
|
int numEndings = 0;
|
||||||
|
size_t endMeasure = fMeasures.size()-EmptyEnding();
|
||||||
for (size_t measure=0; measure<fMeasures.size(); ++measure) {
|
for (size_t measure=0; measure<fMeasures.size(); ++measure) {
|
||||||
VLNoteList::const_iterator i = fMeasures[measure].fMelody.begin();
|
VLNoteList::const_iterator i = fMeasures[measure].fMelody.begin();
|
||||||
VLNoteList::const_iterator e = fMeasures[measure].fMelody.end();
|
VLNoteList::const_iterator e = fMeasures[measure].fMelody.end();
|
||||||
|
@ -1850,7 +1902,7 @@ bool VLSong::DoesEndEnding(size_t measure, bool * repeat, size_t * volta) const
|
||||||
VLSong::iterator::iterator(const VLSong & song, bool end)
|
VLSong::iterator::iterator(const VLSong & song, bool end)
|
||||||
: fSong(song)
|
: fSong(song)
|
||||||
{
|
{
|
||||||
fMeasure = end ? fSong.CountMeasures() : 0;
|
fMeasure = end ? fSong.CountMeasures()-fSong.EmptyEnding() : 0;
|
||||||
AdjustStatus();
|
AdjustStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -247,6 +247,9 @@ struct VLMeasure {
|
||||||
|
|
||||||
void MMANotes(std::string & notes, const VLProperties & prop, VLFraction extra) const;
|
void MMANotes(std::string & notes, const VLProperties & prop, VLFraction extra) const;
|
||||||
void MMAChords(std::string & chords, const VLProperties & prop, bool initial) const;
|
void MMAChords(std::string & chords, const VLProperties & prop, bool initial) const;
|
||||||
|
|
||||||
|
bool IsEmpty() const;
|
||||||
|
bool NoChords() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VLRepeat {
|
struct VLRepeat {
|
||||||
|
@ -350,6 +353,7 @@ struct VLSong {
|
||||||
void DeleteMeasures(size_t beginMeasure, size_t endMeasure);
|
void DeleteMeasures(size_t beginMeasure, size_t endMeasure);
|
||||||
|
|
||||||
size_t CountMeasures() const { return fMeasures.size(); }
|
size_t CountMeasures() const { return fMeasures.size(); }
|
||||||
|
size_t EmptyEnding() const;
|
||||||
size_t CountStanzas() const;
|
size_t CountStanzas() const;
|
||||||
size_t CountTopLedgers() const;
|
size_t CountTopLedgers() const;
|
||||||
size_t CountBotLedgers() const;
|
size_t CountBotLedgers() const;
|
||||||
|
@ -357,6 +361,8 @@ struct VLSong {
|
||||||
void LilypondChords(std::string & chords) const;
|
void LilypondChords(std::string & chords) const;
|
||||||
void LilypondStanza(std::string & lyrics, size_t stanza) const;
|
void LilypondStanza(std::string & lyrics, size_t stanza) const;
|
||||||
VLFract TiedDuration(size_t measure);
|
VLFract TiedDuration(size_t measure);
|
||||||
|
private:
|
||||||
|
void AddMeasure();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Local Variables:
|
// Local Variables:
|
||||||
|
|
|
@ -65,6 +65,7 @@ enum VLRecalc {
|
||||||
char fClickMode;
|
char fClickMode;
|
||||||
float fClefKeyW;
|
float fClefKeyW;
|
||||||
float fMeasureW;
|
float fMeasureW;
|
||||||
|
size_t fLastMeasures;
|
||||||
int fGroups;
|
int fGroups;
|
||||||
int fQuarterBeats;
|
int fQuarterBeats;
|
||||||
int fDivPerGroup;
|
int fDivPerGroup;
|
||||||
|
|
|
@ -96,6 +96,7 @@ static float sFlatPos[] = {
|
||||||
fNumTopLedgers = 0;
|
fNumTopLedgers = 0;
|
||||||
fNumBotLedgers = 2;
|
fNumBotLedgers = 2;
|
||||||
fNumStanzas = 2;
|
fNumStanzas = 2;
|
||||||
|
fLastMeasures = 0;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -272,7 +273,7 @@ VLMusicElement sSemi2Accidental[12][12] = {
|
||||||
fClefKeyW = kClefX+kClefW+(std::labs(prop.fKey)+1)*kKeyW;
|
fClefKeyW = kClefX+kClefW+(std::labs(prop.fKey)+1)*kKeyW;
|
||||||
fMeasureW = fGroups*(fDivPerGroup+1)*kNoteW;
|
fMeasureW = fGroups*(fDivPerGroup+1)*kNoteW;
|
||||||
fMeasPerSystem = std::max<int>(1, std::floor((sz.width-fClefKeyW) / fDisplayScale / fMeasureW));
|
fMeasPerSystem = std::max<int>(1, std::floor((sz.width-fClefKeyW) / fDisplayScale / fMeasureW));
|
||||||
fNumSystems = (song->CountMeasures()+fMeasPerSystem-1)/fMeasPerSystem;
|
fNumSystems = std::max(2lu, (song->CountMeasures()+fMeasPerSystem-1)/fMeasPerSystem);
|
||||||
sz.height = fNumSystems*kSystemH;
|
sz.height = fNumSystems*kSystemH;
|
||||||
|
|
||||||
NSSize boundsSz = {sz.width / fDisplayScale, sz.height / fDisplayScale};
|
NSSize boundsSz = {sz.width / fDisplayScale, sz.height / fDisplayScale};
|
||||||
|
@ -289,6 +290,7 @@ VLMusicElement sSemi2Accidental[12][12] = {
|
||||||
NSMakePoint(0.0, NSMaxY([dv frame])-NSHeight([cv bounds]))];
|
NSMakePoint(0.0, NSMaxY([dv frame])-NSHeight([cv bounds]))];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fLastMeasures = song->CountMeasures();
|
||||||
fNeedsRecalc = kNoRecalc;
|
fNeedsRecalc = kNoRecalc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,7 +520,7 @@ VLMusicElement sSemi2Accidental[12][12] = {
|
||||||
|
|
||||||
- (void)drawRect:(NSRect)rect
|
- (void)drawRect:(NSRect)rect
|
||||||
{
|
{
|
||||||
if (fNeedsRecalc || [self inLiveResize]) {
|
if (fNeedsRecalc || [self inLiveResize] || [self song]->CountMeasures() != fLastMeasures) {
|
||||||
[self recalculateDimensions];
|
[self recalculateDimensions];
|
||||||
rect = [self bounds];
|
rect = [self bounds];
|
||||||
}
|
}
|
||||||
|
|
|
@ -308,7 +308,8 @@ const char * sSteps = "C DbD EbE F GbG AbA BbB ";
|
||||||
[melody addAttribute: [NSXMLNode attributeWithName:@"id"
|
[melody addAttribute: [NSXMLNode attributeWithName:@"id"
|
||||||
stringValue:@"MELO"]];
|
stringValue:@"MELO"]];
|
||||||
|
|
||||||
for (int measure = 0; measure < song->CountMeasures(); ++measure) {
|
size_t endMeasure = song->CountMeasures()-song->EmptyEnding();
|
||||||
|
for (int measure = 0; measure < endMeasure; ++measure) {
|
||||||
NSXMLElement * melMeas = [NSXMLNode elementWithName:@"measure"];
|
NSXMLElement * melMeas = [NSXMLNode elementWithName:@"measure"];
|
||||||
[melMeas addAttribute:
|
[melMeas addAttribute:
|
||||||
[NSXMLNode attributeWithName:@"number"
|
[NSXMLNode attributeWithName:@"number"
|
||||||
|
@ -601,18 +602,6 @@ int8_t sStepToPitch[] = {
|
||||||
int m = [[[measure attributeForName:@"number"]
|
int m = [[[measure attributeForName:@"number"]
|
||||||
stringValue] intValue]-1;
|
stringValue] intValue]-1;
|
||||||
|
|
||||||
if (m >= song->CountMeasures()) {
|
|
||||||
size_t oldSz = song->fMeasures.size();
|
|
||||||
song->fMeasures.resize(m+1);
|
|
||||||
VLLyricsNote rest = VLLyricsNote(VLRest(prop.fTime));
|
|
||||||
VLChord rchord;
|
|
||||||
rchord.fDuration = prop.fTime;
|
|
||||||
for (size_t i=oldSz; i<=m; ++i) {
|
|
||||||
song->fMeasures[i].fChords.push_back(rchord);
|
|
||||||
song->fMeasures[i].fMelody.push_back(rest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[self readBarlines:[measure elementsForName:@"barline"] measure:m
|
[self readBarlines:[measure elementsForName:@"barline"] measure:m
|
||||||
repeat:&repeat inRepeat:&inRepeat error:outError];
|
repeat:&repeat inRepeat:&inRepeat error:outError];
|
||||||
if ([measure nodeForXPath:@".//sound[@coda=\"A\"]" error:outError])
|
if ([measure nodeForXPath:@".//sound[@coda=\"A\"]" error:outError])
|
||||||
|
|
Loading…
Reference in New Issue
Block a user