|
From: Lasse Kärkkäi. <tr...@us...> - 2009-07-15 04:01:30
|
Module: performous
Branch: master
Commit: 254a4650453e1a5f8ff8ef25c739f1d6e5d551ca
Author: Lasse Karkkainen <tro...@tr...>
Date: Wed Jul 15 06:43:47 2009 +0300
Rewritten lyric hack part of INI/MID song parser.
Support slide notes added for parser, notegraph and note.
Scoring and Note::diff need to be rewritten to make slides work properly.
---
game/notegraph.cc | 39 ++++++++++++++++++++++-----------------
game/notes.cc | 4 ++--
game/notes.hh | 8 ++++----
game/songparser-ini.cc | 45 +++++++++++++++++++++++++++++----------------
4 files changed, 57 insertions(+), 39 deletions(-)
diff --git a/game/notegraph.cc b/game/notegraph.cc
index 5cc0999..d82dc91 100644
--- a/game/notegraph.cc
+++ b/game/notegraph.cc
@@ -19,25 +19,29 @@ void NoteGraph::reset() {
}
namespace {
- void drawNotebar(Texture const& texture, double x, double y, double w, double h) {
+ void drawNotebar(Texture const& texture, double x, double ybeg, double yend, double w, double h) {
UseTexture tblock(texture);
glutil::Begin block(GL_TRIANGLE_STRIP);
- glTexCoord2f(0.0f, 0.0f); glVertex2f(x, y);
- glTexCoord2f(0.0f, 1.0f); glVertex2f(x, y + h);
+ glTexCoord2f(0.0f, 0.0f); glVertex2f(x, ybeg);
+ glTexCoord2f(0.0f, 1.0f); glVertex2f(x, ybeg + h);
if (w >= 2.0 * h) {
- glTexCoord2f(0.5f, 0.0f); glVertex2f(x + h, y);
- glTexCoord2f(0.5f, 1.0f); glVertex2f(x + h, y + h);
- glTexCoord2f(0.5f, 0.0f); glVertex2f(x + w - h, y);
- glTexCoord2f(0.5f, 1.0f); glVertex2f(x + w - h, y + h);
+ double tmp = h / w;
+ double y1 = (1.0 - tmp) * ybeg + tmp * yend;
+ double y2 = tmp * ybeg + (1.0 - tmp) * yend;
+ glTexCoord2f(0.5f, 0.0f); glVertex2f(x + h, y1);
+ glTexCoord2f(0.5f, 1.0f); glVertex2f(x + h, y1 + h);
+ glTexCoord2f(0.5f, 0.0f); glVertex2f(x + w - h, y2);
+ glTexCoord2f(0.5f, 1.0f); glVertex2f(x + w - h, y2 + h);
} else {
+ double ymid = 0.5 * (ybeg + yend);
float crop = 0.25f * w / h;
- glTexCoord2f(crop, 0.0f); glVertex2f(x + 0.5 * w, y);
- glTexCoord2f(crop, 1.0f); glVertex2f(x + 0.5 * w, y + h);
- glTexCoord2f(1.0f - crop, 0.0f); glVertex2f(x + 0.5 * w, y);
- glTexCoord2f(1.0f - crop, 1.0f); glVertex2f(x + 0.5 * w, y + h);
+ glTexCoord2f(crop, 0.0f); glVertex2f(x + 0.5 * w, ymid);
+ glTexCoord2f(crop, 1.0f); glVertex2f(x + 0.5 * w, ymid + h);
+ glTexCoord2f(1.0f - crop, 0.0f); glVertex2f(x + 0.5 * w, ymid);
+ glTexCoord2f(1.0f - crop, 1.0f); glVertex2f(x + 0.5 * w, ymid + h);
}
- glTexCoord2f(1.0f, 0.0f); glVertex2f(x + w, y);
- glTexCoord2f(1.0f, 1.0f); glVertex2f(x + w, y + h);
+ glTexCoord2f(1.0f, 0.0f); glVertex2f(x + w, yend);
+ glTexCoord2f(1.0f, 1.0f); glVertex2f(x + w, yend + h);
}
}
@@ -96,7 +100,7 @@ void NoteGraph::drawNotes() {
Texture* t1;
Texture* t2;
switch (it->type) {
- case Note::NORMAL: t1 = &m_notebar; t2 = &m_notebar_hl; break;
+ case Note::NORMAL: case Note::SLIDE: t1 = &m_notebar; t2 = &m_notebar_hl; break;
case Note::GOLDEN: t1 = &m_notebargold; t2 = &m_notebargold_hl; break;
case Note::FREESTYLE: // Freestyle notes use custom handling
{
@@ -113,13 +117,14 @@ void NoteGraph::drawNotes() {
default: throw std::logic_error("Unknown note type: don't know how to render");
}
double x = m_baseX + it->begin * pixUnit + m_noteUnit; // left x coordinate: begin minus border (side borders -noteUnit wide)
- double y = m_baseY + (it->note + 1) * m_noteUnit; // top y coordinate (on the one higher note line)
+ double ybeg = m_baseY + (it->notePrev + 1) * m_noteUnit; // top y coordinate (on the one higher note line)
+ double yend = m_baseY + (it->note + 1) * m_noteUnit; // top y coordinate (on the one higher note line)
double w = (it->end - it->begin) * pixUnit - m_noteUnit * 2.0; // width: including borders on both sides
double h = -m_noteUnit * 2.0; // height: 0.5 border + 1.0 bar + 0.5 border = 2.0
- drawNotebar(*t1, x, y, w, h);
+ drawNotebar(*t1, x, ybeg, yend, w, h);
if (alpha > 0.0) {
glColor4f(1.0f, 1.0f, 1.0f, alpha * m_notealpha);
- drawNotebar(*t2, x, y, w, h);
+ drawNotebar(*t2, x, ybeg, yend, w, h);
glColor4f(1.0f, 1.0f, 1.0f, m_notealpha);
}
}
diff --git a/game/notes.cc b/game/notes.cc
index 9833315..90b1594 100644
--- a/game/notes.cc
+++ b/game/notes.cc
@@ -54,7 +54,7 @@ double MusicalScale::getNoteOffset(double freq) const {
return 12.0 * std::log(frac) / std::log(2.0);
}
-Note::Note(): begin(getNaN()), end(getNaN()), power(getNaN()), type(NORMAL), note() {}
+Note::Note(): begin(getNaN()), end(getNaN()), power(getNaN()), type(NORMAL), note(), notePrev() {}
double Note::diff(double note, double n) { return remainder(n - note, 12.0); }
double Note::maxScore() const { return scoreMultiplier(0.0) * (end - begin); }
@@ -69,7 +69,7 @@ double Note::scoreMultiplier(double error) const {
double max = 0.0;
switch (type) {
case FREESTYLE: power += 1.0; return 1.0;
- case NORMAL: max = 1.0; break;
+ case NORMAL: case SLIDE: max = 1.0; break;
case GOLDEN: max = 2.0; break;
case SLEEP: break;
}
diff --git a/game/notes.hh b/game/notes.hh
index bb402f8..7a486d4 100644
--- a/game/notes.hh
+++ b/game/notes.hh
@@ -30,14 +30,15 @@ class MusicalScale {
/// note read from songfile
struct Note {
+ Note();
double begin, ///< begin time
end; ///< end time
/// power of note
mutable double power;
/// note type
- enum Type { FREESTYLE = 'F', NORMAL = ':', GOLDEN = '*', SLEEP = '-'} type;
- /// note
- int note;
+ enum Type { FREESTYLE = 'F', NORMAL = ':', GOLDEN = '*', SLIDE = '+', SLEEP = '-'} type;
+ int note; ///< MIDI pitch of the note (at the end for slide notes)
+ int notePrev; ///< MIDI pitch of the previous note (should be same as note for everything but SLIDE)
/// lyrics syllable for that note
std::string syllable;
/// Difference of n from note
@@ -48,7 +49,6 @@ struct Note {
double maxScore() const;
/// score when singing
double score(double freq, double b, double e) const;
- Note();
static bool ltBegin(Note const& a, Note const& b) { return a.begin < b.begin; }
static bool ltEnd(Note const& a, Note const& b) { return a.end < b.end; }
private:
diff --git a/game/songparser-ini.cc b/game/songparser-ini.cc
index 40112ec..05a495b 100644
--- a/game/songparser-ini.cc
+++ b/game/songparser-ini.cc
@@ -48,24 +48,37 @@ void SongParser::iniParse() {
Note n;
n.begin = midi.get_seconds(it2->begin);
n.end = midi.get_seconds(it2->end);
- n.note = it2->note;
+ n.notePrev = n.note = it2->note;
n.type = n.note > 100 ? Note::SLEEP : Note::NORMAL;
n.syllable = it2->lyric;
- if (!n.syllable.empty()) {
- switch (*n.syllable.rbegin()) {
- case '#': {
- n.type = Note::FREESTYLE;
- n.syllable.erase(n.syllable.size()-1);
- if( *n.syllable.rbegin() != '-' ) n.syllable += " ";
- break;
- }
- case '-': eraseLast(n.syllable, '-'); break;
- case '+': if (!s.notes.empty()) eraseLast(s.notes.back().syllable); *n.syllable.rbegin() = '~'; break;
- default: n.syllable += " "; break;
+ std::string& syl = n.syllable;
+ if (n.type != Note::SLEEP) {
+ if (!syl.empty()) {
+ bool erase = false;
+ // Examine note styles (specified by the last character of the syllable)
+ {
+ char& ch = *syl.rbegin();
+ if (ch == '#') { n.type = Note::FREESTYLE; erase = true; }
+ if (ch == '^') { n.type = Note::GOLDEN; erase = true; }
+ if (ch == '+') { n.type = Note::SLIDE; ch = '~'; }
+ }
+ if (erase) syl.erase(syl.size() - 1);
+ // Add spaces between words, remove hyphens
+ {
+ char ch = *syl.rbegin();
+ if (ch == '-') syl.erase(syl.size() - 1);
+ else if (ch != '~') syl += ' ';
+ }
+ }
+ // Special processing for slides (which depend on the previous note)
+ if (n.type == Note::SLIDE) {
+ Notes::reverse_iterator prev = s.notes.rbegin();
+ while (prev != s.notes.rend() && prev->type == Note::SLEEP) ++prev;
+ if (prev == s.notes.rend()) throw std::runtime_error("The song begins with a slide note");
+ eraseLast(prev->syllable); // Erase the space if there is any
+ n.notePrev = prev->note;
}
m_maxScore += n.maxScore();
- }
- if (n.type == Note::NORMAL || n.type == Note::FREESTYLE) {
s.noteMin = std::min(s.noteMin, n.note);
s.noteMax = std::max(s.noteMax, n.note);
s.notes.push_back(n);
@@ -76,14 +89,14 @@ void SongParser::iniParse() {
}
if (!s.notes.empty()) break;
}
- if (s.notes.empty()) {
+ /*if (s.notes.empty()) {
Note n;
n.begin = 30.0;
n.end = 31.0;
n.syllable = "TODO";
s.noteMin = s.noteMax = n.note = 60;
s.notes.push_back(n);
- }
+ }*/
}
|