Écrit par GuillaumeTechnoProjet Skyfall

Skyfall, partie 7 : un éditeur de pistes pour la musique

10 novembre 2026 : les neuf musiques de Skyfall sont devenues des données, et le jeu a eu un éditeur de pistes pour les jouer et les modifier. Un piano roll, des instruments et un mixage par partie, des fichiers .mid et des notes tirées de mots ou d'une prise au micro.

L'éditeur de pistes de Skyfall avec Elderhollow ouverte : la liste des parties à gauche, et la mélodie de flûte en mauve dans le piano roll, de la mesure 5 à la mesure 12, sous ses accords.

Partie 7 de l’histoire de Skyfall. Dans la partie 6, le jeu a eu sa musique : 9 pistes rendues par un synthé en Python. Du 10 au 12 novembre, j’ai bâti trois outils pour créer le contenu du jeu : un éditeur de pistes pour la musique, un éditeur de cartes et un éditeur de sprites. Cet article parle du premier, l’éditeur de pistes, arrivé le 10 novembre. La partie 8 parle de l’éditeur de cartes, et la partie 9 de l’éditeur de sprites.

Table des matières

La musique en données

Dans la partie 6, chaque piste était du code Python. music.py et themes.py écrivaient les notes avec des boucles et des règles, et le synthé les rendait en OGG. Pour changer une note, il fallait changer un programme.

Le 10 novembre, toutes les notes sont passées dans des données. Chaque piste est maintenant un fichier JSON dans tools/audio/songs/, avec chaque note, chaque partie, les couches d’instruments, la batterie et les réglages de mixage. song.py rend le fichier. Le code qui a d’abord écrit ces fichiers était jetable, et j’ai supprimé music.py et themes.py dans le même commit. Ce sont maintenant les fichiers JSON qui font foi.

J’ai rendu de nouveau les neuf pistes à partir des nouveaux fichiers. La musique est la même, mais les cordes pincées et le bruit ont de nouvelles graines aléatoires, alors le son change un peu. Depuis, chaque note tire son hasard de son propre moment de départ, et chaque percussion n’est rendue qu’une fois. Un nouveau rendu donne un fichier identique à l’octet près, que la piste soit rendue seule, en lot, ou après une modification ailleurs dans la chanson.

L’éditeur de pistes

L’éditeur est une application LÖVE autonome, comme l’éditeur de cartes de la partie 5. Je le lance avec love tools/audio/editor depuis la racine du projet. Il n’utilise aucune ligne du jeu, mais il a l’allure des nouveaux menus : la même trousse d’interface en pixel art, et le même ciel derrière l’en-tête.

LÖVE ne fait pas la synthèse du son. Au lancement, l’éditeur démarre un petit serveur de rendu en Python, tools/audio/editor.py, et l’arrête en quittant. Le serveur rend chaque partie dans son propre fichier WAV, un stem. Il enregistre aussi les chansons, exporte les fichiers OGG, et lit et écrit les fichiers .mid. Les parties se rendent en parallèle. L’éditeur joue les stems ensemble, alors couper le son d’une partie, l’écouter seule ou changer son volume ne demande aucun nouveau rendu.

L'éditeur de pistes avec Elderhollow ouverte. À gauche, les 10 parties avec leurs boutons M et S et leur curseur de volume : harpe, harpe doublée, basse pincée, cordes, mélodie de flûte, harmonie de flûte, batterie, grosse caisse, percussions et contrebasse. Au centre, le piano roll montre les mesures 5 à 12 avec leurs accords, les notes de la mélodie de flûte en mauve et celles des autres parties estompées derrière. À droite, l'onglet Part avec la couche de flûte, le gate, l'humanisation et le mixage.
La mélodie de flûte d'Elderhollow, à partir de la mesure 5.

Le piano roll

Le centre de l’écran est un piano roll. Un clic dessine une note, un glisser la déplace ou la redimensionne, et un clic droit la supprime. Les notes se copient, se collent et se suppriment en groupe, et une bande sous le piano roll règle la vélocité de chaque note. Chaque changement peut s’annuler. La grille descend jusqu’aux triolets, dont une gigue en 12/8 a besoin.

Le piano roll connaît la tonalité de la chanson. Les rangées dans la gamme sont plus claires, et la rangée de la tonique a une teinte dorée. Au-dessus des notes, une rangée de noms d’accords et de repères de sections indique où on est dans la chanson. Avec All parts, les notes des autres parties s’affichent estompées derrière la partie qu’on modifie. Avec Hear notes, chaque note joue quand on la dessine.

Une partie de batterie est un kit, et chaque rangée du piano roll joue un élément. La batterie d’Elderhollow, c’est un bodhrán aigu à 140 Hz, un bodhrán grave à 85 Hz, une cymbale crash et un clap.

L'éditeur de pistes avec la partie Drums d'Elderhollow. Le piano roll a quatre rangées, bodhrán aigu, bodhrán grave, crash et clap, avec des coups verts sur les deux bodhráns et une crash à la mesure 5. À droite, la section Drum kit liste chaque élément avec son son, son niveau, son panoramique et sa hauteur : 140 Hz pour le bodhrán aigu et 85 Hz pour le grave.
La batterie d'Elderhollow : deux bodhráns, une crash et un clap.

Instruments et mixage

L’onglet Part, à droite, règle le son d’une partie. Un instrument a une ou plusieurs couches, et chaque note les joue toutes. Chaque couche prend une voix du synthé, avec son niveau, son panoramique, sa transposition et son désaccord. Sous l’instrument, le gate règle la durée des notes, et l’humanisation décale chaque note de quelques millisecondes. Le mixage a le volume de la partie, sa réverbération, un coupe-bas et un coupe-haut, un écho avec son délai, et « Pump with the kick », qui baisse la partie sur les temps de la grosse caisse.

L’onglet Song contient le reste : le titre et une courte description, la piste du jeu qui joue la chanson, le tempo, la longueur en mesures, la queue, si elle boucle dans le jeu, la grille, la tonalité et son mode, la réverbération de la chanson, et les temps où le pompage baisse le son. Chaque chanson a aussi une cible de volume sonore. Export to game écrit l’OGG à ce volume, dans assets/audio/music/.

L'onglet Song d'Elderhollow : la description « Forest map, E Dorian jig in 12/8 », la piste de jeu battle_forest, un tempo de 132 BPM, 28 mesures, une queue de 3 secondes, Loops in game coché, une grille en triolets de croches, la tonalité de mi dorien, les réglages de réverbération et le pompage sur les temps 1 et 3.
Elderhollow : une gigue en mi dorien en 12/8, à 132 BPM, longue de 28 mesures.

Neuf pistes dans un sélecteur

Le sélecteur de chansons montre les neuf pistes du jeu sous forme de cartes. La piste de combat de chaque arène a l’aperçu de l’arène, et les autres pistes ont le coucher de soleil de l’écran titre : le combat sous l’orage que jouaient les deux cartes Towerfall, le menu principal et la fanfare de victoire. Chaque carte donne la tonalité, le tempo, la longueur et le nombre de parties. Les tempos vont de 84 BPM pour le menu principal à 165 BPM pour Embergrove, un riff en ré phrygien.

« + New song » commence une chanson qu’aucune piste du jeu ne joue encore. Elle va dans songs/unassigned/, et Export to game reste désactivé tant qu’elle n’a pas de piste. Le menu Game track, dans l’onglet Song, lui en donne une. L’ancienne chanson de la piste passe dans Unassigned. Ainsi, chaque piste garde une chanson et aucune chanson ne se perd.

Le sélecteur de chansons : 11 cartes en grille. Storm battle, Stormkeep, Elderhollow, Cragspire, Embergrove, Oubliette, Driftmoor, Main menu et Victory, chacune avec l'aperçu de son arène ou un coucher de soleil, une courte description, son tempo et sa longueur, puis deux cartes New song dans Unassigned.
Les neuf pistes du jeu et deux chansons dans Unassigned.

Les fichiers .mid

L’onglet Song exporte une chanson en fichier .mid et en importe un. Un fichier .mid déposé sur la fenêtre s’importe aussi. Un aller-retour redonne la chanson sans changement. À l’import, les pistes du fichier .mid vont aux parties du même nom, et une nouvelle piste devient une nouvelle partie. Une piste peut donc passer dans n’importe quel logiciel de musique et revenir.

Des notes à partir de mots

Plus tard ce jour-là, l’éditeur a appris à écrire des notes à partir d’une description. Un bouton sous l’instrument d’une partie écrit les notes de cette partie, ou retravaille celles qu’elle a. Un autre bouton, sous la liste des parties, le fait pour toutes les parties d’un coup. Les deux ouvrent une fenêtre où je décris ce que je veux.

La demande part vers un modèle de langage avec toute la chanson : la tonalité, les accords, les sections, et l’instrument et les notes de chaque partie. Le modèle retravaille donc les notes existantes au lieu de les remplacer à l’aveugle. Il répond en motifs avec des répétitions, et tools/audio/compose.py vérifie la réponse avant qu’une seule note arrive. La demande passe par l’outil en ligne de commande déjà connecté sur ma machine, sans clé d’API, ou par une clé d’API, facturée à la demande. Une courte chanson reçoit sa réponse en environ 12 secondes.

La réponse arrive en une seule étape d’annulation. Elle va aux parties selon leur nom, alors les modifications que je fais pendant qu’elle s’écrit restent.

Des notes tirées d’une prise au micro

La même fenêtre prend un exemple audio, avec ou sans description. tools/audio/transcribe.py lit l’audio avec numpy et ffmpeg et écrit les notes qu’il entend. L’exemple peut être un fichier, choisi ou déposé sur la fenêtre, ou une prise au micro, de 3 minutes au plus. Pour une seule partie, un exemple sans description ne quitte jamais ma machine : il entre dans la partie note pour note. Une partie de batterie en prend les percussions, une basse la ligne la plus grave et une mélodie la ligne du haut.

Trois bascules règlent ce qui joue pendant une prise. Le décompte joue une mesure de clics au tempo de la chanson, et l’éditeur coupe cette mesure de la prise, alors la prise commence sur le premier temps. Le clic peut aussi jouer pendant toute la prise. Et la chanson peut jouer derrière, sans ses parties coupées. Sans casque, le micro enregistre tout ça aussi. Une rangée Bars indique où l’exemple va dans la chanson, d’une mesure à une autre, et une prise s’arrête d’elle-même après la dernière mesure.

Avec le bouton pour toutes les parties, l’exemple mène l’arrangement. Il entre dans une partie tel quel, et le modèle écrit les autres parties autour : une ligne de basse, des accords, un groove et des contre-chants, sans copier sa mélodie ni son rythme. Une chanson vide prend d’abord le tempo et la longueur de l’exemple.

La transcription reste une esquisse. Une mélodie seule revient presque note pour note, et c’est souvent le cas des lignes de basse et de la batterie. Les arpèges qui résonnent gagnent des notes en trop, et les accords d’une nappe lente commencent en retard.

Le même soir, la piste d’Elderhollow a eu une dixième partie, une contrebasse.

Un test qui clique

love tools/audio/editor --selftest lance l’éditeur sans fenêtre et le pilote avec de vrais événements de souris et de clavier. Il dessine une note, la déplace, la supprime, monte une vélocité, joue la chanson, change le tempo, renomme une partie, choisit une voix, coupe une partie, puis exporte un fichier .mid et le réimporte. Après chaque geste, il vérifie la chanson. Du côté Python, song_test.py vérifie que les fichiers de chansons font l’aller-retour, que chaque voix se rend, et que les fichiers .mid reviennent sans changement. compose_test.py vérifie la transcription, la demande et les vérifications de la réponse avec des substituts, sans jamais appeler le vrai service.

En chiffres

  • 6 commits le 10 novembre pour l’éditeur et ses fonctions.
  • Environ 3 900 lignes de Lua pour l’éditeur, et environ 4 100 lignes de Python dans tools/audio/, le synthé et les effets sonores compris.
  • 9 pistes de jeu, de 5 à 10 parties chacune, et environ 10 900 notes en tout.

L’histoire de Skyfall

  1. D’un cube dans Defold à un nouveau départ dans LÖVE
  2. Sauts muraux, un vrai arc et un réseau silencieux
  3. Des manches, de la pluie, des torches et une reprise VHS
  4. La salle de guerre et l’armurerie
  5. Un éditeur de cartes, un fantôme et la forge des champions
  6. Des menus en pixel art, six arènes et enfin du son
  7. Un éditeur de pistes pour la musique (cet article)
  8. Un éditeur de cartes qui dessine avec le jeu
  9. Un éditeur de sprites pour les blocs et les décors