1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
#pragma once
#include <map>
#include <string>
#include <vector>
#include "color.hh"
#include "musicalscale.hh"
/// stores duration of a note
struct Duration {
double begin; ///< beginning timestamp in seconds
double end; ///< ending timestamp in seconds
Duration();
/// create a new Duration object and initialize begin and end
Duration(double b, double e): begin(b), end(e) {}
/// compares begin timestamps of two Duration structs
static bool ltBegin(Duration const& a, Duration const& b) { return a.begin < b.begin; }
/// compares end timestamps of two Duration structs
static bool ltEnd(Duration const& a, Duration const& b) { return a.end < b.end; }
};
typedef std::vector<Duration> Durations;
typedef std::map<int, Durations> NoteMap;
/// Sort by instrument track name
struct CompInstrumentTrack {
bool operator()(std::string const& l, std::string const& r) const {
// TODO: Sort other guitar tracks (coop / rhythm) properly
return l > r;
}
};
struct InstrumentTrack {
// TODO: name should not be needed here (contained into the map)
InstrumentTrack(std::string n): name(n) {}
std::string name;
NoteMap nm;
};
// keep these ones
typedef std::map<std::string, InstrumentTrack, CompInstrumentTrack> InstrumentTracks;
typedef std::map<std::string, InstrumentTrack const*, CompInstrumentTrack> InstrumentTracksConstPtr; // this one really needed ? can't we save only the map key for comparison ?
static inline bool isTrackInside(InstrumentTracks const& track_map, std::string const& name) {
return track_map.find(name) != track_map.end();
}
// TODO: Make Note use Duration
/// note read from songfile
struct Note {
Note();
double begin; ///< begin time
double end; ///< end time
double phase; /// Position within a measure, [0, 1)
// FIXME: Remove gameplay variables from here (Note should be immutable).
/// power of note (how well it is being hit right now)
mutable double power;
/// which players sung well
mutable std::vector<Color> stars;
/// note type
enum Type { FREESTYLE = 'F', NORMAL = ':', GOLDEN = '*', SLIDE = '+', SLEEP = '-',
TAP = '1', HOLDBEGIN = '2', HOLDEND = '3', ROLL = '4', MINE = 'M', LIFT = 'L'} 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
double diff(double n) const { return diff(note, n); }
/// Difference of n from note, so that note + diff(note, n) is n (mod 12)
static double diff(double note, double n);
/// Maximum score
double maxScore() const;
/// The length of the time period [a,b] that falls within the note in seconds
double clampDuration(double b, double e) const;
/// Score when singing over time period (a, b), which needs not to be entirely within the note
double score(double freq, double b, double e) const;
/// How precisely the note is hit (always 1.0 for freestyle, 0..1 for others)
double powerFactor(double note) const;
/// Compares begin of two notes
static bool ltBegin(Note const& a, Note const& b) {
if (a.begin == b.begin) {
if (a.type == Note::SLEEP) return true;
if (b.type == Note::SLEEP) return false;
}
return a.begin < b.begin;
}
/// Compares end of two notes
static bool ltEnd(Note const& a, Note const& b) { return a.end < b.end; }
/// Compare equality of two notes, used for deleting duplicates when programatically creating the duet track.
static bool equal(Note const& a, Note const& b) {
if (a.type == Note::SLEEP) return (a.type == b.type);
return (a.begin == b.begin && a.end == b.end && a.note == b.note && a.type == b.type);
}
/// Check if two notes overlap
static bool overlapping(Note const& a, Note const& b) { return (a.end > b.begin && a.type != Note::SLEEP && b.type != Note::SLEEP); }
private:
double scoreMultiplier() const;
};
typedef std::vector<Note> Notes;
class VocalTrack {
public:
VocalTrack(std::string name);
void reload();
std::string name;
Notes notes;
int noteMin, noteMax; ///< lowest and highest note
double beginTime, endTime; ///< the period where there are notes
double m_scoreFactor; ///< normalization factor for the scoring system
MusicalScale scale; ///< scale in which song is sung
};
typedef std::map<std::string, VocalTrack> VocalTracks;
struct DanceTrack {
DanceTrack(std::string& description, Notes& notes);
//track description
std::string description;
//container for the actual note data
Notes notes;
};
enum DanceDifficulty {
BEGINNER,
EASY,
MEDIUM,
HARD,
CHALLENGE,
DIFFICULTYCOUNT
};
typedef std::map<DanceDifficulty, DanceTrack> DanceDifficultyMap;
typedef std::map<std::string, DanceDifficultyMap> DanceTracks;
|