mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 11:14:00 +00:00
Implement slurs, modernize C++
This commit is contained in:
parent
a0e47688a4
commit
136d66fecc
File diff suppressed because it is too large
Load Diff
|
@ -575,22 +575,15 @@ def _score
|
||||||
return score
|
return score
|
||||||
end
|
end
|
||||||
|
|
||||||
NEW_REXML = REXML::VERSION > "3.1.7"
|
|
||||||
|
|
||||||
xml = REXML::Document.new
|
xml = REXML::Document.new
|
||||||
xml.add REXML::XMLDecl.new('1.0', 'UTF-8')
|
xml.add REXML::XMLDecl.new('1.0', 'UTF-8')
|
||||||
xml.add REXML::DocType.new(['score-partwise', 'PUBLIC',
|
xml.add REXML::DocType.new(['score-partwise', 'PUBLIC',
|
||||||
'"-//Recordare//DTD MusicXML 1.1 Partwise//EN"',
|
'-//Recordare//DTD MusicXML 1.1 Partwise//EN',
|
||||||
NEW_REXML ? 'http://www.musicxml.org/dtds/partwise.dtd' :
|
'http://www.musicxml.org/dtds/partwise.dtd'])
|
||||||
'"http://www.musicxml.org/dtds/partwise.dtd"'])
|
|
||||||
xml.add_element(_score)
|
xml.add_element(_score)
|
||||||
if NEW_REXML
|
formatter = REXML::Formatters::Pretty.new(2)
|
||||||
formatter = REXML::Formatters::Pretty.new(2)
|
formatter.compact = true
|
||||||
formatter.compact = true
|
formatter.write(xml, $stdout)
|
||||||
formatter.write(xml, $stdout)
|
|
||||||
else
|
|
||||||
xml.write($stdout, 0)
|
|
||||||
end
|
|
||||||
|
|
||||||
# Local Variables:
|
# Local Variables:
|
||||||
# mode:ruby
|
# mode:ruby
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//
|
//
|
||||||
// (MN) Matthias Neeracher
|
// (MN) Matthias Neeracher
|
||||||
//
|
//
|
||||||
// Copyright © 2005-2011 Matthias Neeracher
|
// Copyright © 2005-2018 Matthias Neeracher
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "VLDocument.h"
|
#import "VLDocument.h"
|
||||||
|
@ -470,7 +470,7 @@
|
||||||
NewMusicSequence(&musicSequence);
|
NewMusicSequence(&musicSequence);
|
||||||
|
|
||||||
MusicSequenceFileLoad(musicSequence, (CFURLRef)[self fileURLWithExtension:@"mid"],
|
MusicSequenceFileLoad(musicSequence, (CFURLRef)[self fileURLWithExtension:@"mid"],
|
||||||
0, 0);
|
kMusicSequenceFile_MIDIType, 0);
|
||||||
|
|
||||||
size_t countIn = 0;
|
size_t countIn = 0;
|
||||||
if (playElements & kVLPlayCountIn)
|
if (playElements & kVLPlayCountIn)
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//
|
//
|
||||||
// (MN) Matthias Neeracher
|
// (MN) Matthias Neeracher
|
||||||
//
|
//
|
||||||
// Copyright © 2007-2011 Matthias Neeracher
|
// Copyright © 2007-2018 Matthias Neeracher
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "VLLilypondWriter.h"
|
#include "VLLilypondWriter.h"
|
||||||
|
@ -41,7 +41,7 @@ void VLLilypondWriter::Visit(VLSong & song)
|
||||||
fMelody += fSeenEnding ? "}}\n" : "}\n";
|
fMelody += fSeenEnding ? "}}\n" : "}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void VLLilypondWriter::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas)
|
void VLLilypondWriter::VisitMeasure(uint32_t m, VLProperties & p, VLMeasure & meas)
|
||||||
{
|
{
|
||||||
char measNo[8];
|
char measNo[8];
|
||||||
if (!(m % 4))
|
if (!(m % 4))
|
||||||
|
@ -166,8 +166,10 @@ void VLLilypondWriter::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas
|
||||||
fAccum.erase(trip, 15);
|
fAccum.erase(trip, 15);
|
||||||
while ((trip = fAccum.find(" ~ } \\times 2/3 { ")) != std::string::npos)
|
while ((trip = fAccum.find(" ~ } \\times 2/3 { ")) != std::string::npos)
|
||||||
fAccum.erase(trip+2, 17);
|
fAccum.erase(trip+2, 17);
|
||||||
while ((trip = fAccum.find(" ~.")) != std::string::npos)
|
while ((trip = fAccum.find("~.")) != std::string::npos)
|
||||||
fAccum.erase(trip, 2);
|
fAccum.erase(trip, 1);
|
||||||
|
while ((trip = fAccum.find("~(.")) != std::string::npos)
|
||||||
|
fAccum.replace(trip, 3, ".(");
|
||||||
|
|
||||||
if (fSong->fGoToCoda == m+1)
|
if (fSong->fGoToCoda == m+1)
|
||||||
fAccum += "\n"
|
fAccum += "\n"
|
||||||
|
@ -257,25 +259,43 @@ void VLLilypondWriter::VisitNote(VLLyricsNote & n)
|
||||||
nm = "s";
|
nm = "s";
|
||||||
}
|
}
|
||||||
const char * space = fAccum.size() ? " " : "";
|
const char * space = fAccum.size() ? " " : "";
|
||||||
const char * tie = n.fTied & VLNote::kTiedWithNext ? " ~" : "";
|
const char * tie;
|
||||||
|
switch (n.fTied & (VLNote::kTiedWithNext|VLNote::kSlurWithNext|VLNote::kStartSlur|VLNote::kEndSlur)) {
|
||||||
|
case VLNote::kTiedWithNext|VLNote::kSlurWithNext|VLNote::kStartSlur:
|
||||||
|
tie = "(";
|
||||||
|
break;
|
||||||
|
case VLNote::kTiedWithNext|VLNote::kStartSlur:
|
||||||
|
tie = "~(";
|
||||||
|
break;
|
||||||
|
case VLNote::kTiedWithNext:
|
||||||
|
tie = "~";
|
||||||
|
break;
|
||||||
|
case VLNote::kEndSlur:
|
||||||
|
tie = ")";
|
||||||
|
break;
|
||||||
|
case VLNote::kTiedWithNext|VLNote::kSlurWithNext:
|
||||||
|
default:
|
||||||
|
tie = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
char duration[32];
|
char duration[32];
|
||||||
if (n.fTied == VLNote::kTiedWithPrev && n.fVisual == fPrevNote.fVisual+1
|
if ((n.fTied & VLNote::kTiedWithPrev) && n.fVisual == fPrevNote.fVisual+1
|
||||||
&& n.fPitch == fPrevNote.fPitch
|
&& n.fPitch == fPrevNote.fPitch
|
||||||
)
|
) {
|
||||||
strcpy(duration, ".");
|
strcpy(duration, ".");
|
||||||
else if (n.fVisual & VLNote::kTupletMask)
|
} else if (n.fVisual & VLNote::kTupletMask) {
|
||||||
sprintf(duration, "%s\\times %d/%d { %s%d%s }",
|
sprintf(duration, "%s\\times %d/%d { %s%d%s }",
|
||||||
space, VLNote::TupletDenom(n.fVisual), VLNote::TupletNum(n.fVisual),
|
space, VLNote::TupletDenom(n.fVisual), VLNote::TupletNum(n.fVisual),
|
||||||
nm.c_str(), kValue[n.fVisual & VLNote::kNoteHeadMask], tie);
|
nm.c_str(), kValue[n.fVisual & VLNote::kNoteHeadMask], tie);
|
||||||
else
|
} else {
|
||||||
sprintf(duration, "%s%s%d%s",
|
sprintf(duration, "%s%s%d%s",
|
||||||
space, nm.c_str(), kValue[n.fVisual & VLNote::kNoteHeadMask], tie);
|
space, nm.c_str(), kValue[n.fVisual & VLNote::kNoteHeadMask], tie);
|
||||||
|
}
|
||||||
fAccum += duration;
|
fAccum += duration;
|
||||||
fPrevNote= n;
|
fPrevNote = n;
|
||||||
|
|
||||||
if (n.fPitch != VLNote::kNoPitch && !(n.fTied & VLNote::kTiedWithPrev))
|
if (n.fPitch != VLNote::kNoPitch && !(n.fTied & VLNote::kTiedWithPrev)) {
|
||||||
for (size_t i=0; i<fL.size(); ++i)
|
for (size_t i=0; i<fL.size(); ++i) {
|
||||||
if (n.fLyrics.size() <= i || !n.fLyrics[i]) {
|
if (n.fLyrics.size() <= i || !n.fLyrics[i]) {
|
||||||
fL[i] += " \\skip1";
|
fL[i] += " \\skip1";
|
||||||
} else {
|
} else {
|
||||||
|
@ -283,6 +303,8 @@ void VLLilypondWriter::VisitNote(VLLyricsNote & n)
|
||||||
if (n.fLyrics[i].fKind & VLSyllable::kHasNext)
|
if (n.fLyrics[i].fKind & VLSyllable::kHasNext)
|
||||||
fL[i] += " --";
|
fL[i] += " --";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * kLilypondStepNames[] = {
|
static const char * kLilypondStepNames[] = {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//
|
//
|
||||||
// (MN) Matthias Neeracher
|
// (MN) Matthias Neeracher
|
||||||
//
|
//
|
||||||
// Copyright © 2007 Matthias Neeracher
|
// Copyright © 2007-2018 Matthias Neeracher
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "VLModel.h"
|
#include "VLModel.h"
|
||||||
|
@ -14,10 +14,10 @@ class VLLilypondWriter: public VLSongVisitor {
|
||||||
public:
|
public:
|
||||||
VLLilypondWriter() {}
|
VLLilypondWriter() {}
|
||||||
|
|
||||||
virtual void Visit(VLSong & song);
|
void Visit(VLSong & song) override;
|
||||||
virtual void VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas);
|
void VisitMeasure(uint32_t m, VLProperties & p, VLMeasure & meas) override;
|
||||||
virtual void VisitNote(VLLyricsNote & n);
|
void VisitNote(VLLyricsNote & n) override;
|
||||||
virtual void VisitChord(VLChord & c);
|
void VisitChord(VLChord & c) override;
|
||||||
|
|
||||||
const std::string & Chords() const { return fChords; }
|
const std::string & Chords() const { return fChords; }
|
||||||
const std::string & Melody() const { return fMelody; }
|
const std::string & Melody() const { return fMelody; }
|
||||||
|
@ -30,9 +30,12 @@ private:
|
||||||
VLSong * fSong;
|
VLSong * fSong;
|
||||||
bool fUseSharps;
|
bool fUseSharps;
|
||||||
bool fInPickup;
|
bool fInPickup;
|
||||||
|
bool fInSlur;
|
||||||
bool fAutomaticLayout;
|
bool fAutomaticLayout;
|
||||||
int fPrevBreak;
|
int fPrevBreak;
|
||||||
size_t fSeenEnding;
|
size_t fSeenEnding;
|
||||||
|
size_t fPrevTie;
|
||||||
|
size_t fStartTie;
|
||||||
int fNumEndings;
|
int fNumEndings;
|
||||||
VLNote fPrevNote;
|
VLNote fPrevNote;
|
||||||
std::string fAccum;
|
std::string fAccum;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//
|
//
|
||||||
// (MN) Matthias Neeracher
|
// (MN) Matthias Neeracher
|
||||||
//
|
//
|
||||||
// Copyright © 2008-2011 Matthias Neeracher
|
// Copyright © 2008-2018 Matthias Neeracher
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "VLMIDIWriter.h"
|
#include "VLMIDIWriter.h"
|
||||||
|
@ -77,7 +77,7 @@ void VLMIDIWriter::Visit(VLSong & song)
|
||||||
VisitMeasures(song, true);
|
VisitMeasures(song, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VLMIDIWriter::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas)
|
void VLMIDIWriter::VisitMeasure(uint32_t m, VLProperties & p, VLMeasure & meas)
|
||||||
{
|
{
|
||||||
const VLLocation kStartOfMeasure = {m, VLFraction(0)};
|
const VLLocation kStartOfMeasure = {m, VLFraction(0)};
|
||||||
if (fVolta.size() <= m)
|
if (fVolta.size() <= m)
|
||||||
|
@ -98,7 +98,7 @@ void VLMIDIWriter::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas)
|
||||||
void VLMIDIWriter::VisitNote(VLLyricsNote & n)
|
void VLMIDIWriter::VisitNote(VLLyricsNote & n)
|
||||||
{
|
{
|
||||||
if (!(n.fTied & VLNote::kTiedWithPrev)) {
|
if (!(n.fTied & VLNote::kTiedWithPrev)) {
|
||||||
VLMIDIUserEvent event = {12, n.fPitch, fStanza, n.fVisual, fAt};
|
VLMIDIUserEvent event = {12, n.fPitch, static_cast<uint8_t>(fStanza), n.fVisual, fAt};
|
||||||
MusicTrackNewUserEvent(fTrack, fNoteTime,
|
MusicTrackNewUserEvent(fTrack, fNoteTime,
|
||||||
reinterpret_cast<const MusicEventUserData *>(&event));
|
reinterpret_cast<const MusicEventUserData *>(&event));
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ void VLMIDIWriter::VisitNote(VLLyricsNote & n)
|
||||||
void VLMIDIWriter::VisitChord(VLChord & c)
|
void VLMIDIWriter::VisitChord(VLChord & c)
|
||||||
{
|
{
|
||||||
if (c.fPitch != VLNote::kNoPitch) {
|
if (c.fPitch != VLNote::kNoPitch) {
|
||||||
VLMIDIUserEvent event = {12, 0, fStanza, 0, fAt};
|
VLMIDIUserEvent event = {12, 0, static_cast<uint8_t>(fStanza), 0, fAt};
|
||||||
MusicTrackNewUserEvent(fTrack, fChordTime,
|
MusicTrackNewUserEvent(fTrack, fChordTime,
|
||||||
reinterpret_cast<const MusicEventUserData *>(&event));
|
reinterpret_cast<const MusicEventUserData *>(&event));
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//
|
//
|
||||||
// (MN) Matthias Neeracher
|
// (MN) Matthias Neeracher
|
||||||
//
|
//
|
||||||
// Copyright © 2008-2011 Matthias Neeracher
|
// Copyright © 2008-2018 Matthias Neeracher
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "VLModel.h"
|
#include "VLModel.h"
|
||||||
|
@ -35,10 +35,10 @@ public:
|
||||||
VLMIDIWriter(MusicSequence music, size_t countIn)
|
VLMIDIWriter(MusicSequence music, size_t countIn)
|
||||||
: fMusic(music), fCountIn(countIn) {}
|
: fMusic(music), fCountIn(countIn) {}
|
||||||
|
|
||||||
virtual void Visit(VLSong & song);
|
void Visit(VLSong & song) override;
|
||||||
virtual void VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas);
|
void VisitMeasure(uint32_t m, VLProperties & p, VLMeasure & meas) override;
|
||||||
virtual void VisitNote(VLLyricsNote & n);
|
void VisitNote(VLLyricsNote & n) override;
|
||||||
virtual void VisitChord(VLChord & c);
|
void VisitChord(VLChord & c) override;
|
||||||
private:
|
private:
|
||||||
MusicSequence fMusic;
|
MusicSequence fMusic;
|
||||||
size_t fCountIn;
|
size_t fCountIn;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//
|
//
|
||||||
// (MN) Matthias Neeracher
|
// (MN) Matthias Neeracher
|
||||||
//
|
//
|
||||||
// Copyright © 2007 Matthias Neeracher
|
// Copyright © 2007-2018 Matthias Neeracher
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "VLMMAWriter.h"
|
#include "VLMMAWriter.h"
|
||||||
|
@ -22,7 +22,7 @@ void VLMMAWriter::Visit(VLSong & song)
|
||||||
VisitMeasures(song, true);
|
VisitMeasures(song, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VLMMAWriter::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas)
|
void VLMMAWriter::VisitMeasure(uint32_t m, VLProperties & p, VLMeasure & meas)
|
||||||
{
|
{
|
||||||
if (fPreview)
|
if (fPreview)
|
||||||
if (meas.fPropIdx < fBeginSection || meas.fPropIdx >= fEndSection)
|
if (meas.fPropIdx < fBeginSection || meas.fPropIdx >= fEndSection)
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//
|
//
|
||||||
// (MN) Matthias Neeracher
|
// (MN) Matthias Neeracher
|
||||||
//
|
//
|
||||||
// Copyright © 2007 Matthias Neeracher
|
// Copyright © 2007-2018 Matthias Neeracher
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "VLModel.h"
|
#include "VLModel.h"
|
||||||
|
@ -16,10 +16,10 @@ public:
|
||||||
: fPreview(preview), fBeginSection(beginSection), fEndSection(endSection)
|
: fPreview(preview), fBeginSection(beginSection), fEndSection(endSection)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual void Visit(VLSong & song);
|
void Visit(VLSong & song) override;
|
||||||
virtual void VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas);
|
void VisitMeasure(uint32_t m, VLProperties & p, VLMeasure & meas) override;
|
||||||
virtual void VisitNote(VLLyricsNote & n);
|
void VisitNote(VLLyricsNote & n) override;
|
||||||
virtual void VisitChord(VLChord & c);
|
void VisitChord(VLChord & c) override;
|
||||||
|
|
||||||
const std::string & Measures() const { return fMeasures; }
|
const std::string & Measures() const { return fMeasures; }
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//
|
//
|
||||||
// (MN) Matthias Neeracher
|
// (MN) Matthias Neeracher
|
||||||
//
|
//
|
||||||
// Copyright © 2005-2017 Matthias Neeracher
|
// Copyright © 2005-2018 Matthias Neeracher
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "VLModel.h"
|
#include "VLModel.h"
|
||||||
|
@ -107,11 +107,13 @@ VLNote::VLNote(VLFraction dur, int pitch, uint16_t visual)
|
||||||
|
|
||||||
std::string VLNote::Name(uint16_t accidental) const
|
std::string VLNote::Name(uint16_t accidental) const
|
||||||
{
|
{
|
||||||
if (uint16_t acc = (fVisual & kAccidentalsMask))
|
if (uint16_t acc = (fVisual & kAccidentalsMask)) {
|
||||||
if (acc == kWantNatural)
|
if (acc == kWantNatural) {
|
||||||
accidental |= acc;
|
accidental |= acc;
|
||||||
else
|
} else {
|
||||||
accidental = acc;
|
accidental = acc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return VLPitchName(fPitch, accidental);
|
return VLPitchName(fPitch, accidental);
|
||||||
}
|
}
|
||||||
|
@ -603,6 +605,57 @@ void VLSong::DelChord(VLLocation at)
|
||||||
fMeasures.pop_back();
|
fMeasures.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VLSong::note_iterator::note_iterator(const VLMeasureList::iterator &meas, const VLNoteList::iterator ¬e)
|
||||||
|
: fMeasIter(meas), fNoteIter(note)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VLSong::note_iterator &
|
||||||
|
VLSong::note_iterator::operator--()
|
||||||
|
{
|
||||||
|
if (fNoteIter == fMeasIter->fMelody.begin()) {
|
||||||
|
--fMeasIter;
|
||||||
|
fNoteIter = fMeasIter->fMelody.end();
|
||||||
|
}
|
||||||
|
--fNoteIter;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
VLSong::note_iterator &
|
||||||
|
VLSong::note_iterator::operator++()
|
||||||
|
{
|
||||||
|
++fNoteIter;
|
||||||
|
if (fNoteIter == fMeasIter->fMelody.end()) {
|
||||||
|
++fMeasIter;
|
||||||
|
fNoteIter = fMeasIter->fMelody.begin();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
VLSong::note_iterator::operator==(const note_iterator &other)
|
||||||
|
{
|
||||||
|
return fMeasIter == other.fMeasIter && fNoteIter == other.fNoteIter;
|
||||||
|
}
|
||||||
|
|
||||||
|
VLSong::note_iterator
|
||||||
|
VLSong::begin_note(size_t measure)
|
||||||
|
{
|
||||||
|
return note_iterator(fMeasures.begin()+measure, fMeasures[measure].fMelody.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
VLSong::note_iterator
|
||||||
|
VLSong::end_note(size_t measure)
|
||||||
|
{
|
||||||
|
return note_iterator(fMeasures.begin()+measure, fMeasures[measure].fMelody.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
VLSong::note_iterator
|
||||||
|
VLSong::end_note()
|
||||||
|
{
|
||||||
|
return end_note(fMeasures.size()-1);
|
||||||
|
}
|
||||||
|
|
||||||
VLLyricsNote VLSong::FindNote(VLLocation at)
|
VLLyricsNote VLSong::FindNote(VLLocation at)
|
||||||
{
|
{
|
||||||
VLNoteList::iterator i = fMeasures[at.fMeasure].fMelody.begin();
|
VLNoteList::iterator i = fMeasures[at.fMeasure].fMelody.begin();
|
||||||
|
@ -781,15 +834,19 @@ void VLSong::AddNote(VLLyricsNote note, VLLocation at)
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
i->fTied = 0;
|
i->fTied = 0;
|
||||||
if (note.fTied & VLNote::kTiedWithPrev) // kTiedWithNext is NEVER user set
|
if (note.fTied & VLNote::kTiedWithPrev) {// kTiedWithNext is NEVER user set
|
||||||
if (at.fMeasure && i == fMeasures[at.fMeasure].fMelody.begin()) {
|
auto j = i;
|
||||||
VLNoteList::iterator j = fMeasures[at.fMeasure-1].fMelody.end();
|
if (at.fAt != VLFraction(0) || at.fMeasure) {
|
||||||
|
if (at.fAt == VLFraction(0)) {
|
||||||
|
j = fMeasures[at.fMeasure-1].fMelody.end();
|
||||||
|
}
|
||||||
--j;
|
--j;
|
||||||
if (j->fPitch == i->fPitch) {
|
if (note.fPitch != VLNote::kNoPitch && j->fPitch != VLNote::kNoPitch) {
|
||||||
j->fTied |= VLNote::kTiedWithNext;
|
j->fTied |= VLNote::kTiedWithNext;
|
||||||
i->fTied |= VLNote::kTiedWithPrev;
|
i->fTied |= VLNote::kTiedWithPrev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VLSong::DelNote(VLLocation at)
|
void VLSong::DelNote(VLLocation at)
|
||||||
|
@ -906,6 +963,97 @@ VLNote VLSong::ExtendNote(VLLocation at)
|
||||||
return *i;
|
return *i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VLLocation VLSong::TieNote(VLLocation at, bool tieWithPrev)
|
||||||
|
{
|
||||||
|
VLNoteList::iterator i = fMeasures[at.fMeasure].fMelody.begin();
|
||||||
|
VLNoteList::iterator end= fMeasures[at.fMeasure].fMelody.end();
|
||||||
|
|
||||||
|
if (i==end)
|
||||||
|
return VLLocation(); // Empty song, do nothing
|
||||||
|
|
||||||
|
for (VLFraction t(0); i != end && t+i->fDuration <= at.fAt; ++i)
|
||||||
|
t += i->fDuration;
|
||||||
|
|
||||||
|
if (i == end)
|
||||||
|
--i;
|
||||||
|
if (i->fPitch == VLNote::kNoPitch)
|
||||||
|
return VLLocation(); // Don't tie rests
|
||||||
|
|
||||||
|
VLNoteList::iterator j=i;
|
||||||
|
auto startMeasure = at.fMeasure;
|
||||||
|
if (tieWithPrev) {
|
||||||
|
if (j != fMeasures[at.fMeasure].fMelody.begin()) {
|
||||||
|
--j;
|
||||||
|
//
|
||||||
|
// Extend across next note/rest
|
||||||
|
//
|
||||||
|
if (i->fPitch == j->fPitch) {
|
||||||
|
// Consolidate identical pitches
|
||||||
|
j->fDuration += i->fDuration;
|
||||||
|
fMeasures[at.fMeasure].fMelody.erase(i);
|
||||||
|
i = j;
|
||||||
|
} else {
|
||||||
|
i->fTied |= VLNote::kTiedWithPrev;
|
||||||
|
j->fTied |= VLNote::kTiedWithNext;
|
||||||
|
i->fLyrics.clear();
|
||||||
|
}
|
||||||
|
} else if (at.fMeasure-- > 0) {
|
||||||
|
//
|
||||||
|
// Extend into previous measure
|
||||||
|
//
|
||||||
|
j = fMeasures[at.fMeasure].fMelody.end();
|
||||||
|
--j;
|
||||||
|
if (j->fPitch != VLNote::kNoPitch) { // Don't tie with rests
|
||||||
|
i->fTied |= VLNote::kTiedWithPrev;
|
||||||
|
j->fTied |= VLNote::kTiedWithNext;
|
||||||
|
i->fLyrics.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
++j;
|
||||||
|
if (j != fMeasures[at.fMeasure].fMelody.end()) {
|
||||||
|
//
|
||||||
|
// Extend across next note/rest
|
||||||
|
//
|
||||||
|
if (i->fPitch == j->fPitch) {
|
||||||
|
// Consolidate identical pitches
|
||||||
|
i->fDuration += j->fDuration;
|
||||||
|
fMeasures[at.fMeasure].fMelody.erase(j);
|
||||||
|
} else {
|
||||||
|
i->fTied |= VLNote::kTiedWithNext;
|
||||||
|
j->fTied |= VLNote::kTiedWithPrev;
|
||||||
|
j->fLyrics.clear();
|
||||||
|
}
|
||||||
|
} else if (++at.fMeasure < fMeasures.size()) {
|
||||||
|
//
|
||||||
|
// Extend into next measure
|
||||||
|
//
|
||||||
|
j = fMeasures[at.fMeasure].fMelody.begin();
|
||||||
|
if (j->fPitch != VLNote::kNoPitch) { // Don't tie with rests
|
||||||
|
i->fTied |= VLNote::kTiedWithNext;
|
||||||
|
j->fTied |= VLNote::kTiedWithPrev;
|
||||||
|
j->fLyrics.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (i->fTied & VLNote::kTiedWithPrev) {
|
||||||
|
if (i == fMeasures[startMeasure].fMelody.begin()) {
|
||||||
|
if (startMeasure) {
|
||||||
|
i = fMeasures[--startMeasure].fMelody.end();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
at.fMeasure = startMeasure;
|
||||||
|
at.fAt = VLFraction();
|
||||||
|
for (j = fMeasures[startMeasure].fMelody.begin(); j != i; ++j) {
|
||||||
|
at.fAt = at.fAt+j->fDuration;
|
||||||
|
}
|
||||||
|
return at;
|
||||||
|
}
|
||||||
|
|
||||||
bool VLSong::IsNonEmpty() const
|
bool VLSong::IsNonEmpty() const
|
||||||
{
|
{
|
||||||
for (size_t measure=0; measure<fMeasures.size(); ++measure) {
|
for (size_t measure=0; measure<fMeasures.size(); ++measure) {
|
||||||
|
@ -1346,7 +1494,6 @@ bool VLSong::PrevWord(size_t stanza, VLLocation & at)
|
||||||
do {
|
do {
|
||||||
VLMeasure & meas = fMeasures[at.fMeasure];
|
VLMeasure & meas = fMeasures[at.fMeasure];
|
||||||
VLNoteList::iterator note = fMeasures[at.fMeasure].fMelody.begin();
|
VLNoteList::iterator note = fMeasures[at.fMeasure].fMelody.begin();
|
||||||
VLNoteList::iterator end = fMeasures[at.fMeasure].fMelody.end();
|
|
||||||
bool hasWord = false;
|
bool hasWord = false;
|
||||||
VLFraction word(0);
|
VLFraction word(0);
|
||||||
VLFraction now(0);
|
VLFraction now(0);
|
||||||
|
@ -1384,7 +1531,6 @@ bool VLSong::NextWord(size_t stanza, VLLocation & at)
|
||||||
do {
|
do {
|
||||||
VLMeasure & meas = fMeasures[at.fMeasure];
|
VLMeasure & meas = fMeasures[at.fMeasure];
|
||||||
VLNoteList::iterator note = fMeasures[at.fMeasure].fMelody.begin();
|
VLNoteList::iterator note = fMeasures[at.fMeasure].fMelody.begin();
|
||||||
VLNoteList::iterator end = fMeasures[at.fMeasure].fMelody.end();
|
|
||||||
VLFraction now(0);
|
VLFraction now(0);
|
||||||
|
|
||||||
while (note != meas.fMelody.end()) {
|
while (note != meas.fMelody.end()) {
|
||||||
|
@ -1459,7 +1605,6 @@ void VLSong::SetWord(size_t stanza, VLLocation at, std::string word, VLLocation
|
||||||
do {
|
do {
|
||||||
VLMeasure & meas = fMeasures[at.fMeasure];
|
VLMeasure & meas = fMeasures[at.fMeasure];
|
||||||
VLNoteList::iterator note = fMeasures[at.fMeasure].fMelody.begin();
|
VLNoteList::iterator note = fMeasures[at.fMeasure].fMelody.begin();
|
||||||
VLNoteList::iterator end = fMeasures[at.fMeasure].fMelody.end();
|
|
||||||
VLFraction now(0);
|
VLFraction now(0);
|
||||||
|
|
||||||
while (note != meas.fMelody.end()) {
|
while (note != meas.fMelody.end()) {
|
||||||
|
@ -1550,7 +1695,7 @@ void VLSong::AddRepeat(size_t beginMeasure, size_t endMeasure, int times)
|
||||||
VLRepeat & rp = fRepeats[r];
|
VLRepeat & rp = fRepeats[r];
|
||||||
if (rp.fEndings[0].fBegin == beginMeasure
|
if (rp.fEndings[0].fBegin == beginMeasure
|
||||||
&& rp.fEndings[0].fEnd >= endMeasure
|
&& rp.fEndings[0].fEnd >= endMeasure
|
||||||
)
|
) {
|
||||||
if (rp.fEndings[0].fEnd == endMeasure) {
|
if (rp.fEndings[0].fEnd == endMeasure) {
|
||||||
//
|
//
|
||||||
// Exact match, just change times
|
// Exact match, just change times
|
||||||
|
@ -1570,6 +1715,7 @@ void VLSong::AddRepeat(size_t beginMeasure, size_t endMeasure, int times)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VLRepeat rep;
|
VLRepeat rep;
|
||||||
|
|
||||||
|
@ -1795,13 +1941,15 @@ bool VLSong::DoesBeginEnding(size_t measure, bool * repeat, size_t * volta) cons
|
||||||
size_t v = (1<<rp.fTimes)-1;
|
size_t v = (1<<rp.fTimes)-1;
|
||||||
for (size_t e=1; e<rp.fEndings.size(); ++e)
|
for (size_t e=1; e<rp.fEndings.size(); ++e)
|
||||||
if (rp.fEndings[e].fBegin == measure) {
|
if (rp.fEndings[e].fBegin == measure) {
|
||||||
if (repeat)
|
if (repeat) {
|
||||||
if (e == rp.fEndings.size()-1
|
if (e == rp.fEndings.size()-1
|
||||||
&& rp.fEndings[e].fVolta == v
|
&& rp.fEndings[e].fVolta == v
|
||||||
)
|
) {
|
||||||
*repeat = false; // Not after last alternative
|
*repeat = false; // Not after last alternative
|
||||||
else
|
} else {
|
||||||
*repeat = true;
|
*repeat = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (volta)
|
if (volta)
|
||||||
*volta = rp.fEndings[e].fVolta;
|
*volta = rp.fEndings[e].fVolta;
|
||||||
|
|
||||||
|
@ -2279,6 +2427,7 @@ VLSongVisitor::~VLSongVisitor()
|
||||||
|
|
||||||
void VLSongVisitor::VisitMeasures(VLSong & song, bool performanceOrder)
|
void VLSongVisitor::VisitMeasures(VLSong & song, bool performanceOrder)
|
||||||
{
|
{
|
||||||
|
fSong = &song;
|
||||||
if (performanceOrder) {
|
if (performanceOrder) {
|
||||||
VLSong::iterator e = song.end();
|
VLSong::iterator e = song.end();
|
||||||
|
|
||||||
|
@ -2309,6 +2458,75 @@ void VLSongVisitor::VisitNotes(VLMeasure & measure, const VLProperties & prop,
|
||||||
|
|
||||||
if (decomposed) {
|
if (decomposed) {
|
||||||
measure.DecomposeNotes(prop, decomp);
|
measure.DecomposeNotes(prop, decomp);
|
||||||
|
// Set slur flags
|
||||||
|
bool inSlur = false;
|
||||||
|
bool inTie = false;
|
||||||
|
uint8_t prevPitch = 0;
|
||||||
|
if ((decomp.front().fTied & VLNote::kTiedWithPrev)) {
|
||||||
|
inTie = true;
|
||||||
|
prevPitch = decomp.front().fPitch;
|
||||||
|
auto predecessor = fSong->begin_note(&measure-&fSong->fMeasures[0]);
|
||||||
|
bool seenNote = false;
|
||||||
|
do {
|
||||||
|
--predecessor;
|
||||||
|
if (predecessor->fPitch != decomp.front().fPitch) {
|
||||||
|
inSlur = true;
|
||||||
|
if (!seenNote) {
|
||||||
|
decomp.front().fTied |= VLNote::kSlurWithPrev;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
seenNote = true;
|
||||||
|
} while (predecessor->fTied & VLNote::kTiedWithPrev);
|
||||||
|
}
|
||||||
|
VLLyricsNote *firstInTie = nullptr;
|
||||||
|
VLLyricsNote *prevInTie = nullptr;
|
||||||
|
for (auto ¬e: decomp) {
|
||||||
|
if ((note.fTied & VLNote::kTiedWithPrev) && note.fPitch != prevPitch) {
|
||||||
|
if (prevInTie) {
|
||||||
|
prevInTie->fTied |= VLNote::kSlurWithNext;
|
||||||
|
}
|
||||||
|
note.fTied |= VLNote::kSlurWithPrev;
|
||||||
|
inSlur = true;
|
||||||
|
}
|
||||||
|
if (note.fTied & VLNote::kTiedWithNext) {
|
||||||
|
if (!inTie) {
|
||||||
|
firstInTie = ¬e;
|
||||||
|
inTie = true;
|
||||||
|
}
|
||||||
|
prevInTie = ¬e;
|
||||||
|
prevPitch = note.fPitch;
|
||||||
|
} else {
|
||||||
|
if (inSlur) {
|
||||||
|
if (firstInTie) {
|
||||||
|
firstInTie->fTied |= VLNote::kStartSlur;
|
||||||
|
}
|
||||||
|
note.fTied |= VLNote::kEndSlur;
|
||||||
|
}
|
||||||
|
inSlur = false;
|
||||||
|
inTie = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (inTie) {
|
||||||
|
// Find out if measure-final tie contains slur
|
||||||
|
auto successor = fSong->begin_note(&measure-&fSong->fMeasures[0]+1);
|
||||||
|
if (successor->fPitch != prevPitch) {
|
||||||
|
prevInTie->fTied |= VLNote::kSlurWithNext;
|
||||||
|
}
|
||||||
|
while (!inSlur) {
|
||||||
|
if (successor->fPitch != prevPitch) {
|
||||||
|
inSlur = true;
|
||||||
|
} else if (!(successor->fTied & VLNote::kTiedWithNext)) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
++successor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (inSlur && firstInTie) {
|
||||||
|
firstInTie->fTied |= VLNote::kStartSlur;
|
||||||
|
}
|
||||||
|
|
||||||
n = decomp.begin();
|
n = decomp.begin();
|
||||||
e = decomp.end();
|
e = decomp.end();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//
|
//
|
||||||
// (MN) Matthias Neeracher
|
// (MN) Matthias Neeracher
|
||||||
//
|
//
|
||||||
// Copyright © 2005-2011 Matthias Neeracher
|
// Copyright © 2005-2018 Matthias Neeracher
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
|
@ -159,14 +159,18 @@ struct VLNote {
|
||||||
kOctave = 12
|
kOctave = 12
|
||||||
};
|
};
|
||||||
//
|
//
|
||||||
// We only allow ties BETWEEN measures. Within measures, we just store
|
// We only allow ties BETWEEN measures or different pitches. Within measures, we
|
||||||
// a combined note length.
|
// just store a combined note length.
|
||||||
//
|
//
|
||||||
uint8_t fTied; // Tied with note in adjacent measure
|
uint8_t fTied; // Tied with adjacent note
|
||||||
enum {
|
enum {
|
||||||
kNotTied = 0,
|
kNotTied = 0,
|
||||||
kTiedWithNext = 1,
|
kTiedWithNext = 1,
|
||||||
kTiedWithPrev = 2,
|
kTiedWithPrev = 2,
|
||||||
|
kSlurWithNext = 4,
|
||||||
|
kSlurWithPrev = 8,
|
||||||
|
kStartSlur = 16,
|
||||||
|
kEndSlur = 32,
|
||||||
};
|
};
|
||||||
//
|
//
|
||||||
// Hint at visual representation (Computed in DecomposeNotes)
|
// Hint at visual representation (Computed in DecomposeNotes)
|
||||||
|
@ -198,8 +202,8 @@ struct VLNote {
|
||||||
|
|
||||||
kTupletMask = 0xFF00
|
kTupletMask = 0xFF00
|
||||||
};
|
};
|
||||||
static int TupletNum(uint16_t visual) { return visual >> 12; }
|
static uint16_t TupletNum(uint16_t visual) { return visual >> 12; }
|
||||||
static int TupletDenom(uint16_t visual) { return (visual >> 8) & 0x0F; }
|
static uint16_t TupletDenom(uint16_t visual) { return (visual >> 8) & 0x0F; }
|
||||||
static uint16_t Tuplet(int num, int denom) { return (num << 12) | (denom << 8); }
|
static uint16_t Tuplet(int num, int denom) { return (num << 12) | (denom << 8); }
|
||||||
VLNote(VLFraction dur=0, int pitch=kNoPitch, uint16_t visual=0);
|
VLNote(VLFraction dur=0, int pitch=kNoPitch, uint16_t visual=0);
|
||||||
VLNote(std::string name);
|
VLNote(std::string name);
|
||||||
|
@ -342,6 +346,8 @@ struct VLMeasure {
|
||||||
bool IsEmpty() const;
|
bool IsEmpty() const;
|
||||||
bool NoChords() const;
|
bool NoChords() const;
|
||||||
bool CanSkipRests() const;
|
bool CanSkipRests() const;
|
||||||
|
bool SlurAtStart() const;
|
||||||
|
bool SlurAtEnd() const;
|
||||||
|
|
||||||
void DecomposeNotes(const VLProperties & prop, VLNoteList & decomposed) const;
|
void DecomposeNotes(const VLProperties & prop, VLNoteList & decomposed) const;
|
||||||
};
|
};
|
||||||
|
@ -420,6 +426,26 @@ 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); }
|
||||||
|
|
||||||
|
// Iterate over all notes in song
|
||||||
|
class note_iterator {
|
||||||
|
public:
|
||||||
|
note_iterator(const VLMeasureList::iterator &meas, const VLNoteList::iterator ¬e);
|
||||||
|
|
||||||
|
VLLyricsNote &operator*() { return *fNoteIter; }
|
||||||
|
VLLyricsNote *operator->() { return &*fNoteIter; }
|
||||||
|
note_iterator &operator--();
|
||||||
|
note_iterator &operator++();
|
||||||
|
bool operator==(const note_iterator &other);
|
||||||
|
bool operator!=(const note_iterator &other) { return !(*this == other); }
|
||||||
|
private:
|
||||||
|
VLNoteList::iterator fNoteIter;
|
||||||
|
VLMeasureList::iterator fMeasIter;
|
||||||
|
};
|
||||||
|
|
||||||
|
note_iterator begin_note(size_t measure=0);
|
||||||
|
note_iterator end_note(size_t measure);
|
||||||
|
note_iterator end_note();
|
||||||
|
|
||||||
VLLyricsNote FindNote(VLLocation at);
|
VLLyricsNote FindNote(VLLocation at);
|
||||||
bool PrevNote(VLLocation & at);
|
bool PrevNote(VLLocation & at);
|
||||||
bool NextNote(VLLocation & at);
|
bool NextNote(VLLocation & at);
|
||||||
|
@ -428,6 +454,7 @@ public:
|
||||||
void DelChord(VLLocation at);
|
void DelChord(VLLocation at);
|
||||||
void DelNote(VLLocation at);
|
void DelNote(VLLocation at);
|
||||||
VLNote ExtendNote(VLLocation at);
|
VLNote ExtendNote(VLLocation at);
|
||||||
|
VLLocation TieNote(VLLocation at, bool tieWithPrev);
|
||||||
void AddRepeat(size_t beginMeasure, size_t endMeasure, int times);
|
void AddRepeat(size_t beginMeasure, size_t endMeasure, int times);
|
||||||
void DelRepeat(size_t beginMeasure, size_t endMeasure);
|
void DelRepeat(size_t beginMeasure, size_t endMeasure);
|
||||||
void AddEnding(size_t beginMeasure, size_t endMeasure, size_t volta);
|
void AddEnding(size_t beginMeasure, size_t endMeasure, size_t volta);
|
||||||
|
@ -494,7 +521,7 @@ public:
|
||||||
virtual ~VLSongVisitor();
|
virtual ~VLSongVisitor();
|
||||||
|
|
||||||
virtual void Visit(VLSong & song) {}
|
virtual void Visit(VLSong & song) {}
|
||||||
virtual void VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas) {}
|
virtual void VisitMeasure(uint32_t m, VLProperties & p, VLMeasure & meas) {}
|
||||||
virtual void VisitNote(VLLyricsNote & n) {}
|
virtual void VisitNote(VLLyricsNote & n) {}
|
||||||
virtual void VisitChord(VLChord & c) {}
|
virtual void VisitChord(VLChord & c) {}
|
||||||
protected:
|
protected:
|
||||||
|
@ -504,6 +531,8 @@ protected:
|
||||||
void VisitNotes(VLMeasure & measure, const VLProperties & prop,
|
void VisitNotes(VLMeasure & measure, const VLProperties & prop,
|
||||||
bool decomposed);
|
bool decomposed);
|
||||||
void VisitChords(VLMeasure & measure);
|
void VisitChords(VLMeasure & measure);
|
||||||
|
private:
|
||||||
|
VLSong *fSong;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//
|
//
|
||||||
// (MN) Matthias Neeracher
|
// (MN) Matthias Neeracher
|
||||||
//
|
//
|
||||||
// Copyright © 2005-2007 Matthias Neeracher
|
// Copyright © 2005-2018 Matthias Neeracher
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "VLPDFView.h"
|
#import "VLPDFView.h"
|
||||||
|
@ -45,14 +45,14 @@
|
||||||
{
|
{
|
||||||
// Display single page mode.
|
// Display single page mode.
|
||||||
if ([self displayMode] > kPDFDisplaySinglePageContinuous)
|
if ([self displayMode] > kPDFDisplaySinglePageContinuous)
|
||||||
[self setDisplayMode: [self displayMode] - 2];
|
[self setDisplayMode: static_cast<PDFDisplayMode>([self displayMode] - 2)];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction) displayTwoUp: (id) sender
|
- (IBAction) displayTwoUp: (id) sender
|
||||||
{
|
{
|
||||||
// Display two-up.
|
// Display two-up.
|
||||||
if ([self displayMode] < kPDFDisplayTwoUp)
|
if ([self displayMode] < kPDFDisplayTwoUp)
|
||||||
[self setDisplayMode: [self displayMode] + 2];
|
[self setDisplayMode: static_cast<PDFDisplayMode>([self displayMode] + 2)];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction) zoomToFit: (id) sender
|
- (IBAction) zoomToFit: (id) sender
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//
|
//
|
||||||
// (MN) Matthias Neeracher
|
// (MN) Matthias Neeracher
|
||||||
//
|
//
|
||||||
// Copyright © 2007-2011 Matthias Neeracher
|
// Copyright © 2007-2018 Matthias Neeracher
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "VLPListDocument.h"
|
#import "VLPListDocument.h"
|
||||||
|
@ -26,11 +26,11 @@ public:
|
||||||
VLPlistVisitor(NSMutableDictionary * plist, bool performanceOrder)
|
VLPlistVisitor(NSMutableDictionary * plist, bool performanceOrder)
|
||||||
: fPlist(plist), fPerfOrder(performanceOrder) {}
|
: fPlist(plist), fPerfOrder(performanceOrder) {}
|
||||||
|
|
||||||
virtual void Visit(VLSong & song);
|
void Visit(VLSong & song) override;
|
||||||
protected:
|
protected:
|
||||||
virtual void VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas);
|
void VisitMeasure(uint32_t m, VLProperties & p, VLMeasure & meas) override;
|
||||||
virtual void VisitNote(VLLyricsNote & n);
|
void VisitNote(VLLyricsNote & n) override;
|
||||||
virtual void VisitChord(VLChord & c);
|
void VisitChord(VLChord & c) override;
|
||||||
|
|
||||||
NSArray * EncodeProperties(const std::vector<VLProperties> & properties);
|
NSArray * EncodeProperties(const std::vector<VLProperties> & properties);
|
||||||
NSDictionary * EncodeProperties(const VLProperties & properties);
|
NSDictionary * EncodeProperties(const VLProperties & properties);
|
||||||
|
@ -82,7 +82,7 @@ void VLPlistVisitor::Visit(VLSong & song)
|
||||||
[fPlist setObject:fMeasures forKey:@"measures"];
|
[fPlist setObject:fMeasures forKey:@"measures"];
|
||||||
}
|
}
|
||||||
|
|
||||||
void VLPlistVisitor::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas)
|
void VLPlistVisitor::VisitMeasure(uint32_t m, VLProperties & p, VLMeasure & meas)
|
||||||
{
|
{
|
||||||
fNotes = [NSMutableArray arrayWithCapacity:1];
|
fNotes = [NSMutableArray arrayWithCapacity:1];
|
||||||
fChords= [NSMutableArray arrayWithCapacity:1];
|
fChords= [NSMutableArray arrayWithCapacity:1];
|
||||||
|
@ -303,7 +303,7 @@ enum {
|
||||||
kPotentialSwing16th
|
kPotentialSwing16th
|
||||||
};
|
};
|
||||||
|
|
||||||
- (void)readMelody:(NSArray *)melody inMeasure:(size_t)measNo onsets:(int *)onsets lyrics:(uint8_t *)prevKind
|
- (void)readMelody:(NSArray *)melody inMeasure:(uint32_t)measNo onsets:(int *)onsets lyrics:(uint8_t *)prevKind
|
||||||
{
|
{
|
||||||
VLLocation at = {measNo, VLFraction(0)};
|
VLLocation at = {measNo, VLFraction(0)};
|
||||||
int lastOnset = 0;
|
int lastOnset = 0;
|
||||||
|
@ -328,7 +328,7 @@ enum {
|
||||||
[[ndict objectForKey:@"normalNotes"] intValue]);
|
[[ndict objectForKey:@"normalNotes"] intValue]);
|
||||||
|
|
||||||
if ([[ndict objectForKey:@"tied"] intValue] & VLNote::kTiedWithPrev) {
|
if ([[ndict objectForKey:@"tied"] intValue] & VLNote::kTiedWithPrev) {
|
||||||
if (at.fAt != VLFraction(0)) {
|
if (at.fAt != VLFraction(0) && note.fPitch == tiedNote.fPitch) {
|
||||||
//
|
//
|
||||||
// Extend preceding note
|
// Extend preceding note
|
||||||
//
|
//
|
||||||
|
@ -339,7 +339,7 @@ enum {
|
||||||
goto advanceAt;
|
goto advanceAt;
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
// Extend previous measure
|
// Slur or extend previous measure
|
||||||
//
|
//
|
||||||
note.fTied |= VLNote::kTiedWithPrev;
|
note.fTied |= VLNote::kTiedWithPrev;
|
||||||
}
|
}
|
||||||
|
@ -402,7 +402,7 @@ advanceAt:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)readChords:(NSArray *)chords inMeasure:(size_t)measNo
|
- (void)readChords:(NSArray *)chords inMeasure:(uint32_t)measNo
|
||||||
{
|
{
|
||||||
VLLocation at = {measNo, VLFraction(0)};
|
VLLocation at = {measNo, VLFraction(0)};
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//
|
//
|
||||||
// (MN) Matthias Neeracher
|
// (MN) Matthias Neeracher
|
||||||
//
|
//
|
||||||
// Copyright © 2005-2012 Matthias Neeracher
|
// Copyright © 2005-2018 Matthias Neeracher
|
||||||
//
|
//
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
@ -109,6 +109,7 @@ const uint32_t kNoMeasure = (uint32_t)-1;
|
||||||
IBOutlet id fKeyMenu;
|
IBOutlet id fKeyMenu;
|
||||||
IBOutlet id fTimeMenu;
|
IBOutlet id fTimeMenu;
|
||||||
IBOutlet id fDivisionMenu;
|
IBOutlet id fDivisionMenu;
|
||||||
|
IBOutlet NSMenu *fNoteActionMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
@property (nonatomic) int numTopLedgers;
|
@property (nonatomic) int numTopLedgers;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//
|
//
|
||||||
// (MN) Matthias Neeracher
|
// (MN) Matthias Neeracher
|
||||||
//
|
//
|
||||||
// Copyright © 2005-2008 Matthias Neeracher
|
// Copyright © 2005-2018 Matthias Neeracher
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "VLSheetView.h"
|
#import "VLSheetView.h"
|
||||||
|
@ -804,6 +804,11 @@ const float kSemiFloor = -1.0f*kLineH;
|
||||||
if ([event modifierFlags] & NSAlphaShiftKeyMask)
|
if ([event modifierFlags] & NSAlphaShiftKeyMask)
|
||||||
return; // Keyboard mode, ignore mouse
|
return; // Keyboard mode, ignore mouse
|
||||||
|
|
||||||
|
if ([event modifierFlags] & NSControlKeyMask) {
|
||||||
|
[[NSCursor contextualMenuCursor] set];
|
||||||
|
} else {
|
||||||
|
[[NSCursor arrowCursor] set];
|
||||||
|
}
|
||||||
bool hadCursor = fCursorRegion == kRegionNote;
|
bool hadCursor = fCursorRegion == kRegionNote;
|
||||||
[self findRegionForEvent:event];
|
[self findRegionForEvent:event];
|
||||||
bool hasCursor = fCursorRegion == kRegionNote;
|
bool hasCursor = fCursorRegion == kRegionNote;
|
||||||
|
@ -830,10 +835,29 @@ const float kSemiFloor = -1.0f*kLineH;
|
||||||
fCursorRegion = kRegionNowhere;
|
fCursorRegion = kRegionNowhere;
|
||||||
[[self window] setAcceptsMouseMovedEvents:NO];
|
[[self window] setAcceptsMouseMovedEvents:NO];
|
||||||
[self setNeedsDisplay:YES];
|
[self setNeedsDisplay:YES];
|
||||||
|
[[NSCursor arrowCursor] set];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) rightMouseDown:(NSEvent *)event
|
||||||
|
{
|
||||||
|
[[self document] endSong];
|
||||||
|
VLRegion region = [self findRegionForEvent:event];
|
||||||
|
switch (region) {
|
||||||
|
case kRegionNote:
|
||||||
|
[NSMenu popUpContextMenu:fNoteActionMenu withEvent:event forView:self];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) mouseDown:(NSEvent *)event
|
- (void) mouseDown:(NSEvent *)event
|
||||||
{
|
{
|
||||||
|
if ([event modifierFlags] & NSControlKeyMask) {
|
||||||
|
[self rightMouseDown:event];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
[[self document] endSong];
|
[[self document] endSong];
|
||||||
|
|
||||||
BOOL extend = ([event modifierFlags] & NSShiftKeyMask) != 0;
|
BOOL extend = ([event modifierFlags] & NSShiftKeyMask) != 0;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//
|
//
|
||||||
// (MN) Matthias Neeracher
|
// (MN) Matthias Neeracher
|
||||||
//
|
//
|
||||||
// Copyright © 2006-2017 Matthias Neeracher
|
// Copyright © 2006-2018 Matthias Neeracher
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "VLSheetView.h"
|
#import "VLSheetView.h"
|
||||||
|
@ -224,7 +224,7 @@ std::string NormalizeName(NSString* rawName)
|
||||||
// Build new list
|
// Build new list
|
||||||
//
|
//
|
||||||
for (int m = 0; m<kLayout.NumMeasures(); ++m) {
|
for (int m = 0; m<kLayout.NumMeasures(); ++m) {
|
||||||
int measIdx = m+kFirstMeas;
|
uint32_t measIdx = m+kFirstMeas;
|
||||||
if (measIdx >= song->CountMeasures())
|
if (measIdx >= song->CountMeasures())
|
||||||
break;
|
break;
|
||||||
const VLMeasure measure = song->fMeasures[measIdx];
|
const VLMeasure measure = song->fMeasures[measIdx];
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//
|
//
|
||||||
// (MN) Matthias Neeracher
|
// (MN) Matthias Neeracher
|
||||||
//
|
//
|
||||||
// Copyright © 2006-2007 Matthias Neeracher
|
// Copyright © 2006-2018 Matthias Neeracher
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "VLSheetView.h"
|
#import "VLSheetView.h"
|
||||||
|
@ -211,7 +211,7 @@ float VLCocoaFontHandler::Width(const char * utf8Text)
|
||||||
// Build new list
|
// Build new list
|
||||||
//
|
//
|
||||||
for (int m = 0; m<kLayout.NumMeasures(); ++m) {
|
for (int m = 0; m<kLayout.NumMeasures(); ++m) {
|
||||||
int measIdx = m+kFirstMeas;
|
uint32_t measIdx = m+kFirstMeas;
|
||||||
if (measIdx >= song->CountMeasures())
|
if (measIdx >= song->CountMeasures())
|
||||||
break;
|
break;
|
||||||
const VLMeasure measure = song->fMeasures[measIdx];
|
const VLMeasure measure = song->fMeasures[measIdx];
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//
|
//
|
||||||
// (MN) Matthias Neeracher
|
// (MN) Matthias Neeracher
|
||||||
//
|
//
|
||||||
// Copyright © 2005-2011 Matthias Neeracher
|
// Copyright © 2005-2018 Matthias Neeracher
|
||||||
//
|
//
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
@ -19,6 +19,11 @@
|
||||||
- (void) moveCursorToNextNote;
|
- (void) moveCursorToNextNote;
|
||||||
- (void) moveCursorToPrevNote;
|
- (void) moveCursorToPrevNote;
|
||||||
|
|
||||||
|
- (IBAction) tieNoteWithPrev:(id)sender;
|
||||||
|
- (IBAction) tieNoteWithNext:(id)sender;
|
||||||
|
- (IBAction) addRest:(id)sender;
|
||||||
|
- (IBAction) deleteNote:(id)sender;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
// Local Variables:
|
// Local Variables:
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
//
|
//
|
||||||
// (MN) Matthias Neeracher
|
// (MN) Matthias Neeracher
|
||||||
//
|
//
|
||||||
// Copyright © 2005-2011 Matthias Neeracher
|
// Copyright © 2005-2018 Matthias Neeracher
|
||||||
//
|
//
|
||||||
|
|
||||||
#import "VLSheetView.h"
|
#import "VLSheetView.h"
|
||||||
|
@ -19,6 +19,43 @@
|
||||||
|
|
||||||
@implementation VLSheetView (Notes)
|
@implementation VLSheetView (Notes)
|
||||||
|
|
||||||
|
- (IBAction)tieNoteWithPrev:(id)sender
|
||||||
|
{
|
||||||
|
if (fCursorLocation.fMeasure != kNoMeasure) {
|
||||||
|
[[self document] willChangeSong];
|
||||||
|
[self song]->TieNote(fCursorLocation, true);
|
||||||
|
[[self document] didChangeSong];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction)tieNoteWithNext:(id)sender
|
||||||
|
{
|
||||||
|
if (fCursorLocation.fMeasure != kNoMeasure) {
|
||||||
|
[[self document] willChangeSong];
|
||||||
|
[self song]->TieNote(fCursorLocation, false);
|
||||||
|
[[self document] didChangeSong];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction)addRest:(id)sender
|
||||||
|
{
|
||||||
|
if (fCursorLocation.fMeasure != kNoMeasure) {
|
||||||
|
VLLyricsNote note;
|
||||||
|
[[self document] willChangeSong];
|
||||||
|
[self song]->AddNote(note, fCursorLocation);
|
||||||
|
[[self document] didChangeSong];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (IBAction)deleteNote:(id)sender
|
||||||
|
{
|
||||||
|
if (fCursorLocation.fMeasure != kNoMeasure) {
|
||||||
|
[[self document] willChangeSong];
|
||||||
|
[self song]->DelNote(fCursorLocation);
|
||||||
|
[[self document] didChangeSong];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void) addNoteAtCursor
|
- (void) addNoteAtCursor
|
||||||
{
|
{
|
||||||
if (fCursorLocation.fMeasure != kNoMeasure && fCursorVertPos != kCursorNoPitch) {
|
if (fCursorLocation.fMeasure != kNoMeasure && fCursorVertPos != kCursorNoPitch) {
|
||||||
|
@ -349,7 +386,7 @@
|
||||||
|
|
||||||
for (int m = 0; m<kLayout.NumMeasures(); ++m) {
|
for (int m = 0; m<kLayout.NumMeasures(); ++m) {
|
||||||
VLVisualFilter filterVisuals(kProp.fKey);
|
VLVisualFilter filterVisuals(kProp.fKey);
|
||||||
int measIdx = m+kFirstMeas;
|
uint32_t measIdx = m+kFirstMeas;
|
||||||
if (measIdx >= song->CountMeasures())
|
if (measIdx >= song->CountMeasures())
|
||||||
break;
|
break;
|
||||||
const VLMeasure & measure = song->fMeasures[measIdx];
|
const VLMeasure & measure = song->fMeasures[measIdx];
|
||||||
|
|
|
@ -132,8 +132,8 @@ void VLSoundScheduler::Schedule(VLSoundEvent * what, float when)
|
||||||
what->Perform();
|
what->Perform();
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::auto_ptr<VLSoundOut> sSoundOut;
|
static std::unique_ptr<VLSoundOut> sSoundOut;
|
||||||
static std::auto_ptr<VLSoundScheduler> sSoundScheduler;
|
static std::unique_ptr<VLSoundScheduler> sSoundScheduler;
|
||||||
|
|
||||||
VLSoundOut * VLSoundOut::Instance()
|
VLSoundOut * VLSoundOut::Instance()
|
||||||
{
|
{
|
||||||
|
@ -160,7 +160,7 @@ void VLSoundOut::PlayFile(CFDataRef file)
|
||||||
MusicSequence music;
|
MusicSequence music;
|
||||||
|
|
||||||
NewMusicSequence(&music);
|
NewMusicSequence(&music);
|
||||||
MusicSequenceFileLoadData(music, file, 0, 0);
|
MusicSequenceFileLoadData(music, file, kMusicSequenceFile_MIDIType, 0);
|
||||||
PlaySequence(music);
|
PlaySequence(music);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,7 +517,7 @@ void VLAUSoundOut::Play(const int8_t * note, size_t numNotes)
|
||||||
|
|
||||||
const int8_t kNoteVelocity = 127;
|
const int8_t kNoteVelocity = 127;
|
||||||
for (int i=0; i<numNotes; ++i) {
|
for (int i=0; i<numNotes; ++i) {
|
||||||
MIDINoteMessage n = {0, note[i], kNoteVelocity, 0, 1.0};
|
MIDINoteMessage n = {0, static_cast<UInt8>(note[i]), kNoteVelocity, 0, 1.0};
|
||||||
MusicTrackNewMIDINoteEvent(track, 0.0, &n);
|
MusicTrackNewMIDINoteEvent(track, 0.0, &n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
BIN
TestData/.DS_Store
vendored
BIN
TestData/.DS_Store
vendored
Binary file not shown.
|
@ -1642,6 +1642,8 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
GCC_DYNAMIC_NO_PIC = NO;
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
|
||||||
|
@ -1665,6 +1667,8 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
COPY_PHASE_STRIP = YES;
|
COPY_PHASE_STRIP = YES;
|
||||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
||||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||||
|
@ -1686,6 +1690,8 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "c++17";
|
||||||
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
|
||||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||||
GCC_PREFIX_HEADER = Sources/VocalEasel_Prefix.pch;
|
GCC_PREFIX_HEADER = Sources/VocalEasel_Prefix.pch;
|
||||||
|
|
|
@ -22,8 +22,8 @@
|
||||||
</BuildActionEntries>
|
</BuildActionEntries>
|
||||||
</BuildAction>
|
</BuildAction>
|
||||||
<TestAction
|
<TestAction
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.GDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.GDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
buildConfiguration = "Development">
|
buildConfiguration = "Development">
|
||||||
<Testables>
|
<Testables>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user