|
From: Yoda-JM <yo...@us...> - 2010-10-08 14:00:40
|
Module: performous
Branch: master
Commit: d756b8e1514b656f11b657441551bebb49146da6
Author: Vincent Le Ligeour <yo...@us...>
Date: Fri Oct 8 16:01:21 2010 +0200
Enabled multiple midi vocal tracks management
---
game/song.cc | 14 +++++++-------
game/song.hh | 22 +++++++++++++++++-----
game/songparser-ini.cc | 9 ++-------
game/songparser-txt.cc | 6 +++---
4 files changed, 29 insertions(+), 22 deletions(-)
diff --git a/game/song.cc b/game/song.cc
index 901e3cb..2795a43 100644
--- a/game/song.cc
+++ b/game/song.cc
@@ -7,7 +7,7 @@
void Song::reload(bool errorIgnore) {
loadStatus = NONE;
- vocals.reload();
+ vocalTracks.clear();
instrumentTracks.clear();
beats.clear();
midifilename.clear();
@@ -37,9 +37,9 @@ void Song::reload(bool errorIgnore) {
void Song::dropNotes() {
// Singing
- if (!vocals.notes.empty()) {
- vocals.notes.clear();
- vocals.notes.push_back(Note()); // Dummy note to indicate there is a track
+ if (!vocalTracks.empty()) {
+ for (VocalTracks::iterator it = vocalTracks.begin(); it != vocalTracks.end(); ++it)
+ it->second.notes.clear();
}
// Instruments
if (!instrumentTracks.empty()) {
@@ -71,10 +71,10 @@ namespace {
bool noteEndLessThan(Note const& a, Note const& b) { return a.end < b.end; }
}
-Song::Status Song::status(double time) const {
+Song::Status Song::status(double time) {
Note target; target.end = time;
- Notes::const_iterator it = std::lower_bound(vocals.notes.begin(), vocals.notes.end(), target, noteEndLessThan);
- if (it == vocals.notes.end()) return FINISHED;
+ Notes::const_iterator it = std::lower_bound(getVocalTrack().notes.begin(), getVocalTrack().notes.end(), target, noteEndLessThan);
+ if (it == getVocalTrack().notes.end()) return FINISHED;
if (it->begin > time + 4.0) return INSTRUMENTAL_BREAK;
return NORMAL;
}
diff --git a/game/song.hh b/game/song.hh
index 75c96f7..58f2546 100644
--- a/game/song.hh
+++ b/game/song.hh
@@ -38,10 +38,11 @@ namespace TrackName {
/// class to load and parse songfiles
class Song: boost::noncopyable {
friend class SongParser;
- VocalTrack vocals; ///< notes for the sing part
+ VocalTracks vocalTracks; ///< notes for the sing part
+ VocalTrack dummyVocal; ///< notes for the sing part
public:
/// constructor
- Song(std::string const& path_, std::string const& filename_): vocals(TrackName::LEAD_VOCAL), path(path_), filename(filename_) { reload(false); }
+ Song(std::string const& path_, std::string const& filename_): dummyVocal(TrackName::LEAD_VOCAL), path(path_), filename(filename_) { reload(false); }
/// reload song
void reload(bool errorIgnore = true);
/// parse field
@@ -57,15 +58,26 @@ class Song: boost::noncopyable {
/// status of song
enum Status { NORMAL, INSTRUMENTAL_BREAK, FINISHED };
/** Get the song status at a given timestamp **/
- Status status(double time) const;
+ Status status(double time);
int randomIdx; ///< sorting index used for random order
- VocalTrack& getVocalTrack(std::string vocalTrack = TrackName::LEAD_VOCAL) { (void) vocalTrack; return vocals; };
+ void insertVocalTrack(std::string vocalTrack, VocalTrack track) {
+ vocalTracks.erase(vocalTrack);
+ vocalTracks.insert(std::make_pair<std::string, VocalTrack>(vocalTrack, track));
+ };
+ // Change default value to HARMONIC_{1,2,3} to sing harmonics
+ VocalTrack& getVocalTrack(std::string vocalTrack = TrackName::LEAD_VOCAL) {
+ if(vocalTracks.find(vocalTrack) != vocalTracks.end()) {
+ return vocalTracks.find(vocalTrack)->second;
+ } else {
+ return dummyVocal;
+ }
+ };
InstrumentTracks instrumentTracks; ///< guitar etc. notes for this song
DanceTracks danceTracks; ///< dance tracks
bool hasDance() const { return !danceTracks.empty(); }
bool hasDrums() const { return instrumentTracks.find(TrackName::DRUMS) != instrumentTracks.end(); }
bool hasGuitars() const { return instrumentTracks.size() - hasDrums(); }
- bool hasVocals() const { return !vocals.notes.empty(); }
+ bool hasVocals() const { return !vocalTracks.empty(); }
std::string path; ///< path of songfile
std::string filename; ///< name of songfile
std::string midifilename; ///< name of midi file in FoF format
diff --git a/game/songparser-ini.cc b/game/songparser-ini.cc
index 5839255..398b092 100644
--- a/game/songparser-ini.cc
+++ b/game/songparser-ini.cc
@@ -24,11 +24,9 @@ namespace {
}
bool isVocalTrack(std::string name) {
if(name == TrackName::LEAD_VOCAL) return true;
- /*
else if(name == TrackName::HARMONIC_1) return true;
else if(name == TrackName::HARMONIC_2) return true;
else if(name == TrackName::HARMONIC_3) return true;
- */
return false;
}
/// Change the MIDI track name to Performous track name
@@ -46,11 +44,9 @@ namespace {
else if (name == "BASS") name = TrackName::BASS;
else if (name == "GUITAR") name = TrackName::GUITAR;
else if (name == "VOCALS") name = TrackName::LEAD_VOCAL;
- /*
else if (name == "HARM1") name = TrackName::HARMONIC_1;
else if (name == "HARM2") name = TrackName::HARMONIC_2;
else if (name == "HARM3") name = TrackName::HARMONIC_3;
- */
else return false;
return true;
}
@@ -126,7 +122,7 @@ void SongParser::iniParseHeader() {
else if (midi.tracks.size() == 1) name = TrackName::GUITAR; // Original (old) FoF songs only have one track
else continue; // not a valid track
// Add dummy notes to tracks so that they can be seen in song browser
- if (isVocalTrack(name)) s.getVocalTrack().notes.push_back(Note());
+ if (isVocalTrack(name)) s.insertVocalTrack(name, VocalTrack(name));
else {
for (MidiFileParser::NoteMap::const_iterator it2 = it->notes.begin(); it2 != it->notes.end(); ++it2) {
// If a track has not enough notes on any level, ignore it
@@ -270,8 +266,7 @@ void SongParser::iniParse() {
}
}
}
- s.getVocalTrack().notes.clear();
- s.getVocalTrack() = vocal;
+ s.insertVocalTrack(name, vocal);
}
}
// Figure out if we have BRE in the song
diff --git a/game/songparser-txt.cc b/game/songparser-txt.cc
index f658e07..fd9d451 100644
--- a/game/songparser-txt.cc
+++ b/game/songparser-txt.cc
@@ -22,20 +22,20 @@ void SongParser::txtParseHeader() {
while (getline(line) && txtParseField(line)) {}
if (s.title.empty() || s.artist.empty()) throw std::runtime_error("Required header fields missing");
if (m_bpm != 0.0) addBPM(0, m_bpm);
- s.getVocalTrack().notes.push_back(Note()); // Dummy note to indicate there is a track
+ s.insertVocalTrack(TrackName::LEAD_VOCAL, VocalTrack(TrackName::LEAD_VOCAL)); // Dummy note to indicate there is a track
}
/// Parse notes
void SongParser::txtParse() {
std::string line;
- VocalTrack &vocal = m_song.getVocalTrack();
- vocal.notes.clear();
+ VocalTrack vocal(TrackName::LEAD_VOCAL);
while (getline(line) && txtParseField(line)) {} // Parse the header again
if (m_bpm != 0.0) addBPM(0, m_bpm);
while (txtParseNote(line, vocal) && getline(line)) {} // Parse notes
// Workaround for the terminating : 1 0 0 line, written by some converters
if (!vocal.notes.empty() && vocal.notes.back().type != Note::SLEEP
&& vocal.notes.back().begin == vocal.notes.back().end) vocal.notes.pop_back();
+ m_song.insertVocalTrack(TrackName::LEAD_VOCAL, vocal);
}
bool SongParser::txtParseField(std::string const& line) {
|