Musique: recopiez et jouez facilement une partition avec des notes en clair

Bonjour :slight_smile:

Ma première modeste contribution pour de la musique de buzzer :

Tapez au kilomètre les notes d’une partition musicale avec ENFIN des notes en clair (do ré mi… et non plus les notes américaines A B C… ou pire, les fréquences) et jouez-les sur votre buzzer avec une simple fonction “joue”.
Autant de morceaux que vous voulez dans une appli.

Plus d’info en lisez-moi dans le fichier joint. Ce programme comprend un “LA” accordable, et les altérations.

Pour l’instant elle utilise la fonction “Tone” donc 1 seule voie possible, mais j’ai bon espoir de faire une version “maison” de la vibration avec 2 voies (et donc pour double buzzer).

Happy music!
Michel

Musique.zip (4.22 KB)

bonjour, quelques remarques :

Je ne suis pas convaincu que ton système d'écriture des partitions soit vraiment ... agréable. En cas d'erreur de saisie, il faut compter les caractères dans une longue chaine, par ex. De plus, pour un musicien, c'est une erreur de croire que Do dièze et Ré bémol, c'est la même chose, donc qu'on peut n'en garder qu'un. Ca c'est le point de vue du mathématicien, pas du musicien !

Dans ta classe Musique, tu mets tout dans le constructeur. C'est maladroit.
Déjà tu pourrais mettre une valeur par défaut au paramètre la, et mieux choisir les types :

Musique( const char *partition, float tempo, byte brocheBIP, float la = 440);

Ensuite il me paraitraît plus judicieux de rendre l'objet Musique réutilisable en faisant des fonctions d'initialisation:

Musique ( byte brocheBIP );  // la broche ne changera pas
int ChargerPartition ( const char* partoche ); // renvoie 0 si OK, -1 si erreur
void FixerTempo ( float tempo ); // 100 par défaut
void Accorder ( float frequence_La4 ); // 440. par defaut

Enfin, n'attend pas l'exécution (jouer()) pour fait plein de calculs et de tests. Fais ça dans la fonction ChargerPartition() en stockant un tableau de fréquences et un tableau de temps - ou mieux, un seul tableau de structures :

struct Evenement {
  float frequence; // 0. pour du silence, par convetion
  unsigned int millsecondes;
};

Ta fonction jouer() deviendra beaucoup plus simple et fiable.

Merci d'avoir pris le temps de me répondre de façon aussi détaillée!

Ma philosophie a été de prendre le moins de place possible pour taper des partitions déjà composées au kilomètre
(je m'en suis servi pour développer des jouets pour bébé) pas pour jouer du Mozart ou pour composer le dernier tube en électro !

Désolé mais selon mes lointains souvenirs, mon prof de solfège disait que "ré bémol" était incorrect, il m'a toujours appris à dire "do dièse". Question de convention, c'est la même fréquence.

Ton approche par programmation modulaire est très intéressante. Je vais étudier ce que tu as dit et m'exercer a corriger comme tu dis. Je débute et je n'ai pas l'habitude d"utiliser des structures.
Mais cela prend plus de place non?
Ma philosophie a été de tout compacter au maximum et gagner le maximum d'octets (réflexe des 32Ko+2Ko qui me rappellent furieusement les 38Ko du C64 de mes débuts)

PS: pourquoi mettre des floats pour la tempo et la? cela prend plus de place et je n'ai pas besoin d'une telle précision.

Quirole:
Désolé mais selon mes lointains souvenirs, mon prof de solfège disait que "ré bémol" était incorrect, il m'a toujours appris à dire "do dièse". Question de convention, c'est la même fréquence.

Archi-faux. D'accord c'est la même fréquence, mais comme je l'ait dit, c'est le point de vue du physicien, pas celui du musicien.
Si le morceau est en tonalité de La bémol, les notes de la gamme sont: Ab Bb C Db Eb F G. Sur la portée il y a 4 bémol à la clef, et quand la note est un Ré bémol, ça s'écrit bien Ré bémol et surtout pas Do dièze. C'est comme ça !

je n'ai pas l'habitude d"utiliser des structures.
Mais cela prend plus de place non?

Généralement les éléments d'une structure sont alignées sur un pas fixe, 2 ou 4 octets, ça dépend du compilateur. Donc dans le cas cité, il n'y a pas de perte de place.
Si une structure contient des éléments de type byte, là oui on perd un peu de place. Il existe une déclaration "pragma packed" (c'est pas exactement ça, renseigne toi) qui place les éléments "bord à bord" sans perte de place.

Ma philosophie a été de tout compacter au maximum et gagner le maximum d'octets (réflexe des 32Ko+2Ko qui me rappellent furieusement les 38Ko du C64 de mes débuts)

Optimiser c'est bien, mais avoir un code simple, court et maintenable c'est bien aussi !

PS: pourquoi mettre des floats pour la tempo et la? cela prend plus de place et je n'ai pas besoin d'une telle précision.

Parce qu'intrinsèquement, une fréquence est un nombre réel, et un tempo aussi.
Tu injectes ton souci d'optimisation au niveau de l'interface de ton programme, ça le rend moins clair.
Si tu es le seul à utiliser ton code, OK, tu supportes tes propres limitations. Mais si tu veux le faire utiliser par d'autres, sois sûr que quelqu'un voudra régler le La à 440.5 Hz, et ça va merder.
Mieux vaut sacrifier quelques octets pour être cohérent avec le problème à traiter. Et n'optimiser que ce qui a besoin de l'être.