|
From: Felix B. <fbe...@us...> - 2010-05-19 05:11:35
|
Module: performous
Branch: master
Commit: 5557d7d2d57c900ea81306f7603e6d527d24b176
Author: Felix Bertram <fl...@be...>
Date: Tue May 18 22:09:37 2010 -0700
RockBand song sections
* parse song sections from MIDI file
* populate vector of song sections
* jump forward/backward to next song section
---
game/midifile.cc | 17 +++++++++++++----
game/midifile.hh | 7 +++++++
game/screen_sing.cc | 45 +++++++++++++++++++++++++++++++++++++++++----
game/song.hh | 7 +++++++
game/songparser-ini.cc | 6 ++++++
5 files changed, 74 insertions(+), 8 deletions(-)
diff --git a/game/midifile.cc b/game/midifile.cc
index be3300e..ca3a236 100644
--- a/game/midifile.cc
+++ b/game/midifile.cc
@@ -177,17 +177,26 @@ MidiFileParser::Track MidiFileParser::read_track(MidiStream& stream) {
// Lyrics are hidden here, only [text] are orders
if (data[0] != '[') m_lyric = data;
else if (!data.compare(0, sect_pfx.length(), sect_pfx)) {// [section verse_1]
- // TODO: clean up the section name some more
- const std::string sect_name = data.substr(sect_pfx.length(), data.length()-sect_pfx.length()-1);
+ std::string sect_name = data.substr(sect_pfx.length(), data.length()-sect_pfx.length()-1);
+ if (sect_name != "big_rock_ending") {
+ bool space = true;
+ for (std::string::iterator it = sect_name.begin(); it != sect_name.end(); it++) {
+ if (space) *it = toupper(*it); // start in uppercase
+ if (*it == '_') {*it = ' '; space = true;} // underscores to spaces
+ else space = false;
+ }
+ // replace gtr => guitar
#if MIDI_DEBUG_LEVEL > 2
- std::cout << "Section: " << sect_name << std::endl;
+ std::cout << "Section: " << sect_name << " at " << get_seconds(miditime) << std::endl;
#endif
+ songsections.push_back(SongSection(sect_name, get_seconds(miditime)));
+ } else cmdevents.push_back(std::string(data)); // see songparser-ini.cc: we need to keep the BRE in cmdevents
}
else cmdevents.push_back(std::string(data));
#if MIDI_DEBUG_LEVEL > 2
std::cout << "Text: " << data << std::endl;
#endif
- } break;
+ } break;
// 0x02: Copyright Notice
case 0x03: // Sequence or Track Name
track.name = data;
diff --git a/game/midifile.hh b/game/midifile.hh
index 33dcfe2..6db8258 100644
--- a/game/midifile.hh
+++ b/game/midifile.hh
@@ -76,6 +76,13 @@ class MidiFileParser{
};
typedef std::vector<Track> Tracks;
Tracks tracks;
+ struct SongSection {
+ std::string name;
+ double begin;
+ SongSection(std::string const& name, const double begin): name(name), begin(begin) {}
+ };
+ typedef std::vector<SongSection> SongSections;
+ SongSections songsections; ///< vector of song sections
uint16_t parse_header(MidiStream&);
Track read_track(MidiStream&);
void cout_midi_event(uint8_t type, uint8_t arg1, uint8_t arg2, uint32_t miditime);
diff --git a/game/screen_sing.cc b/game/screen_sing.cc
index c206d55..51e4bfa 100644
--- a/game/screen_sing.cc
+++ b/game/screen_sing.cc
@@ -263,11 +263,48 @@ void ScreenSing::manageEvent(SDL_Event event) {
if (key == SDLK_F5) dispInFlash(--config["audio/controller_delay"]);
if (key == SDLK_F6) dispInFlash(++config["audio/controller_delay"]);
bool seekback = false;
- if (m_song->danceTracks.empty()) { // Seeking backwards is currently not permitted for dance songs
- if (key == SDLK_HOME) { m_audio.seekPos(0.0); seekback = true; }
- if (key == SDLK_LEFT) { m_audio.seek(-5.0); seekback = true; }
+
+ if (m_song->songsections.empty()) {
+ // standard seeking in 5s increments
+ if (m_song->danceTracks.empty()) { // Seeking backwards is currently not permitted for dance songs
+ if (key == SDLK_HOME) { m_audio.seekPos(0.0); seekback = true; }
+ if (key == SDLK_LEFT) { m_audio.seek(-5.0); seekback = true;}
+ }
+ if (key == SDLK_RIGHT) m_audio.seek(5.0);
+ } else {
+ // seeking to the next song section
+ if (m_song->danceTracks.empty()) { // Seeking backwards is currently not permitted for dance songs
+ if (key == SDLK_HOME) { m_audio.seekPos(0.0); seekback = true; }
+ if (key == SDLK_LEFT) {
+ double pos = m_audio.getPosition();
+ for (std::vector<Song::SongSection>::reverse_iterator it= m_song->songsections.rbegin(); it != m_song->songsections.rend(); it++) {
+ double begin = it->begin;
+ if (begin < pos - 1.0) { // make sure we can jump across a marker!
+ m_audio.seekPos(begin);
+ // TODO: display popup with section name
+ const std::string name = it->name;
+ std::cout << "seek left from " << pos << " to " << name << " at " << begin << std::endl;
+ break;
+ }
+ }
+ seekback = true;
+ }
+ }
+ if (key == SDLK_RIGHT) {
+ double pos = m_audio.getPosition();
+ for (std::vector<Song::SongSection>::iterator it= m_song->songsections.begin(); it != m_song->songsections.end(); it++) {
+ double begin = it->begin;
+ if (begin > pos) {
+ m_audio.seekPos(begin);
+ // TODO: display popup with section name
+ const std::string name = it->name;
+ std::cout << "seek right from " << pos << " to " << name << " at " << begin << std::endl;
+ break;
+ }
+ }
+ }
}
- if (key == SDLK_RIGHT) m_audio.seek(5.0);
+
// Some things must be reset after seeking backwards
if (seekback) m_layout_singer->reset();
// Reload current song
diff --git a/game/song.hh b/game/song.hh
index f1062aa..fba45f0 100644
--- a/game/song.hh
+++ b/game/song.hh
@@ -92,6 +92,13 @@ class Song: boost::noncopyable {
Beats beats; ///< related to instrument and dance
bool hasBRE; ///< is there a Big Rock Ending? (used for drums only)
bool b0rkedTracks; ///< are some tracks broken? (so that user can be notified)
+ struct SongSection {
+ std::string name;
+ double begin;
+ SongSection(std::string const& name, const double begin): name(name), begin(begin) {}
+ };
+ typedef std::vector<SongSection> SongSections;
+ SongSections songsections; ///< vector of song sections
};
static inline bool operator<(Song const& l, Song const& r) { return l.collateByArtist < r.collateByArtist; }
diff --git a/game/songparser-ini.cc b/game/songparser-ini.cc
index 04dcb63..c110d50 100644
--- a/game/songparser-ini.cc
+++ b/game/songparser-ini.cc
@@ -130,6 +130,12 @@ void SongParser::iniParseHeader() {
}
}
}
+ // populate song sections
+ for (std::vector<MidiFileParser::SongSection>::iterator it= midi.songsections.begin(); it != midi.songsections.end(); it++) {
+ Song::SongSection tmp(it->name, it->begin);
+ s.songsections.push_back(tmp);
+ //std::cout << "Section " << tmp.name << " at " << tmp.begin << std::endl;
+ }
}
/// Parse notes
|