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
|
#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
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
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) { return a.begin < b.begin; }
/// Compares end of two notes
static bool ltEnd(Note const& a, Note const& b) { return a.end < b.end; }
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;
|