rajouté des commentaires
This commit is contained in:
parent
b542aea9b3
commit
b5e08cedd5
3 changed files with 36 additions and 8 deletions
|
@ -9,6 +9,7 @@
|
|||
class AudioEmitter {
|
||||
private:
|
||||
std::unique_ptr<FMOD::System> system;
|
||||
FMOD::Sound* metronome_Sound;
|
||||
FMOD::Channel *timer{nullptr};
|
||||
std::vector<std::unique_ptr<FMOD::Sound>> chords;
|
||||
std::vector<std::unique_ptr<FMOD::Sound>> drums;
|
||||
|
|
|
@ -133,6 +133,7 @@ AudioEmitter::AudioEmitter() {
|
|||
{0,1,1.5,2,2.5,3,3.5,4,5,6,7}
|
||||
};
|
||||
|
||||
//matrice récupérées sur https://musiquealgorithmique.fr/chaines-de-markov-2/
|
||||
markov_matrix_chords = {{0, 0.10, 0.00, 0.40, 0.35, 0.15, 0.00},
|
||||
// Depuis ii (1)
|
||||
{0.10, 0, 0.00, 0.25, 0.65, 0.00, 0.00},
|
||||
|
@ -147,6 +148,7 @@ AudioEmitter::AudioEmitter() {
|
|||
// Depuis vii° (6)
|
||||
{0.80, 0.00, 0.00, 0.00, 0.20, 0.00, 0.00}};
|
||||
|
||||
//matrice générée par Deepseek, a globalement fait une gaussienne en donnant une probabilité plus élevée au notes proches de la note joué
|
||||
markov_matrix_melody = {// A1 (0)
|
||||
{0.05, 0.30, 0.25, 0.15, 0.10, 0.05, 0.03, 0.02, 0.02,
|
||||
0.01, 0.01, 0.00, 0.00, 0.00, 0.00},
|
||||
|
@ -202,7 +204,7 @@ AudioEmitter::AudioEmitter() {
|
|||
chordProgression[i] = chord;
|
||||
}
|
||||
|
||||
FMOD::Sound *metronome_Sound;
|
||||
//Son joué en boucle avec un volume nul, permet à tout les channels de s'accorder sur le tempo et d'obtenir le temps global
|
||||
ERRCHECK(system->createSound("media/percussions/drums1.wav", FMOD_DEFAULT, nullptr,
|
||||
&metronome_Sound));
|
||||
ERRCHECK(system->playSound(metronome_Sound, nullptr, true, &timer));
|
||||
|
@ -221,6 +223,7 @@ int AudioEmitter::firstNote() {
|
|||
}
|
||||
|
||||
int sampleIndex(const std::vector<float> &probabilities) {
|
||||
//Renvoie un indice aléatoire selon un tableau de probabilités, fonction générée par ChatGPT
|
||||
// Créer un générateur aléatoire
|
||||
static std::random_device rd;
|
||||
static std::mt19937 gen(rd());
|
||||
|
@ -234,6 +237,7 @@ int sampleIndex(const std::vector<float> &probabilities) {
|
|||
|
||||
int randomWeightedChoice(const std::vector<int> &values,
|
||||
const std::vector<double> &weights) {
|
||||
//Renvoie une valeur aléatoire selon un tableau de poids, fonction générée par ChatGPT
|
||||
if (values.size() != weights.size() || values.empty()) {
|
||||
throw std::invalid_argument(
|
||||
"Les tableaux doivent être de même taille et non vides.");
|
||||
|
@ -279,14 +283,17 @@ int AudioEmitter::nextNote(int currentNote) {
|
|||
* in seconds, second is the note
|
||||
*/
|
||||
std::vector<std::pair<float, int>> AudioEmitter::generateMusic() {
|
||||
//Génère la musique aléatoirement, et renvoie l'ensemble des notes sous forme pairs {s,n}, où s est le temps en seconde où la note est joué, et n la hauteur de la note
|
||||
//Pour générer la musique aléatoirement, on utilise une chaîne de Markov. Sachant qu'on joue un note donnée, on a un ensemble de probabilités pour jouer la note suivante
|
||||
//Pour savoir à quel rythme nous jouons les notes, on tire aléatoirement dans un ensemble de rythmes possibles, on tire des rythmes plus ou moins complexe en fonction de si on est au début ou à la fin de la musique
|
||||
std::vector<std::pair<float, int>> result;
|
||||
if (current_beat >= nbr_melo_total) {
|
||||
if (current_beat >= nbr_melo_total) { //On génère un nombre fini de mélodies, pour avoir une musique de 4min
|
||||
return result;
|
||||
}
|
||||
result.reserve(16 * nbr_melo_max);
|
||||
float beatDuration = tempo / 60.f;
|
||||
float beatDuration = tempo / 60.f; //temps en seconde d'un beat musicale
|
||||
unsigned int sampleRate = 48000;
|
||||
int maxsize = 400;
|
||||
|
||||
int variation = 0;
|
||||
if (((current_beat / nbr_melo_max) % 4) < 2) { //On change la manière dont sont joués les accords toutes les 2*nbr_melo_max mélodies générées
|
||||
variation = 0;
|
||||
|
@ -295,6 +302,10 @@ std::vector<std::pair<float, int>> AudioEmitter::generateMusic() {
|
|||
variation = 1;
|
||||
}
|
||||
int nbrChords = 7;
|
||||
|
||||
//Pour jouer des sons, on alloue des channel, pour éviter de se retrouver à cours de channel, on en libère régulièrement
|
||||
//Ce système permet de générer une musique potentiellement indéfiniment
|
||||
int maxsize = 400;
|
||||
if (activeChannels.size() > maxsize) {
|
||||
for (int i = 0; i < maxsize / 2; i += 1) {
|
||||
if (activeChannels[i]) {
|
||||
|
@ -302,6 +313,9 @@ std::vector<std::pair<float, int>> AudioEmitter::generateMusic() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//On créé une boucle de 4 accords, qu'on va répéter quelques fois avant de la faire varier
|
||||
//Les accords joués sont aussi décidés via une chaîne de Markov
|
||||
chordProgression[0] = nextChord(chordProgression[3]);
|
||||
for (int i = 1; i < 4; i += 1) {
|
||||
chordProgression[i] = nextChord(chordProgression[i - 1]);
|
||||
|
@ -322,8 +336,9 @@ std::vector<std::pair<float, int>> AudioEmitter::generateMusic() {
|
|||
activeChannels.push_back(channelChords);
|
||||
// Mélodie
|
||||
if (i >= 1) { //Pour laisser une mesure avant que les notes soient générées
|
||||
//On choisi un rythme au hasard, plus ou moins complexe en fonction de l'avancement dans la musique
|
||||
int index_rythme = floor(((i - 1) * 1.f / nbr_melo_total) * (rythmes.size() - 1)) + ( rand() % nbr_melo_max ); //Les rythmes deviennent de plus en plus complexe, plus on avance dans le temps, plus le rythme est tiré de la fin du vecteur
|
||||
index_rythme = (int)fmin(index_rythme, rythmes.size() - 1);
|
||||
index_rythme = (int)fmin(index_rythme, rythmes.size() - 1); //pour éviter un index hors du tableau
|
||||
std::vector<float> rythme_melodie = rythmes[index_rythme];
|
||||
for (float time : rythme_melodie) {
|
||||
FMOD::Channel* channelNote = nullptr;
|
||||
|
@ -347,17 +362,28 @@ std::vector<std::pair<float, int>> AudioEmitter::generateMusic() {
|
|||
void AudioEmitter::audioUpdate() { system->update(); }
|
||||
|
||||
void AudioEmitter::audioEnd() {
|
||||
//release les différents éléments avant la fin du programme
|
||||
//FMOD a sa propre gestion mémoire, on doit donc simplement lui signaler que nous n'avons plus besoin de ces éléments
|
||||
for (int i = 0; i < activeChannels.size(); i += 1) {
|
||||
if (activeChannels[i]) {
|
||||
activeChannels[i]->stop();
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < notes.size(); i += 1) {
|
||||
notes[i].get()->release();
|
||||
}
|
||||
for (int i = 0; i < chords.size(); i += 1) {
|
||||
chords[i].get()->release();
|
||||
}
|
||||
timer->stop();
|
||||
metronome_Sound->release();
|
||||
system->close();
|
||||
system->release();
|
||||
}
|
||||
|
||||
float AudioEmitter::getTimeTempo() const {
|
||||
float AudioEmitter::getTimeTempo() const {
|
||||
//Renvoie le temps écoulé depuis le début de la musique, en beat musicaux
|
||||
//Par exemple, renvoie 4 au bout d'une mesure
|
||||
float beatDuration = tempo / 60.f / 8.f;
|
||||
unsigned long long dspClock = 0;
|
||||
ERRCHECK(timer->getDSPClock(&dspClock, nullptr));
|
||||
|
@ -365,6 +391,7 @@ float AudioEmitter::getTimeTempo() const {
|
|||
}
|
||||
|
||||
float AudioEmitter::getTime() const {
|
||||
//Renvoie le temps écoulé depuis le début de la musique, en secondes
|
||||
unsigned long long dspClock = 0;
|
||||
ERRCHECK(timer->getDSPClock(&dspClock, nullptr));
|
||||
return dspClock / 48000.f;
|
||||
|
|
|
@ -165,9 +165,9 @@ void Game::update_scores(bool good_action) {
|
|||
ScoreMultiplierText.setString(
|
||||
std::format("ScoreMultiplier = {}", score_multiplier));
|
||||
|
||||
if (score_multiplier < 15) {
|
||||
if (score_multiplier < 5) {
|
||||
carrot.changeState(Angry);
|
||||
} else if (score_multiplier < 60) {
|
||||
} else if (score_multiplier < 15) {
|
||||
carrot.changeState(Neutral);
|
||||
} else {
|
||||
carrot.changeState(Happy);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue