Automatically resize song

This commit is contained in:
Matthias Neeracher 2007-05-04 05:21:16 +00:00
parent d33b9ed728
commit 39f81a1a24
5 changed files with 77 additions and 27 deletions

View File

@ -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,6 +1200,16 @@ void VLSong::Transpose(int semi)
} }
} }
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 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();
} }

View File

@ -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:

View File

@ -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;

View File

@ -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];
} }

View File

@ -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])