rajouté des commentaires

This commit is contained in:
antpoms 2025-06-16 17:38:21 +02:00
parent b542aea9b3
commit b5e08cedd5
3 changed files with 36 additions and 8 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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);