Aller au contenu

snd : musique et effets

Le son, c'est un synthétiseur pour la musique et de courts échantillons PCM pour les effets. Les deux se font entièrement dans l'App : la musique est un fichier texte qu'on écrit dans l'éditeur, les effets sont des .wav qu'on dépose (l'App les convertit).

La règle qui gouverne tout : le son est un effet de _update(), jamais de _draw(). _draw() peut être abandonné sous charge sans casser le rejeu, donc un snd.* appelé depuis lui est une erreur. Les appels au son vont dans _update().

Les fonctions

snd.music(nom [, boucle]) / snd.music()

Lance le morceau nom — le nom d'un fichier .son du jeu, sans l'extension (game.son → snd.music("game")). boucle vrai le répète. Sans argument, coupe la musique. Un nom inconnu est une erreur qui liste les morceaux existants (comme gfx.background).

snd.play(nom [, vol])

Joue un effet une fois — le nom d'un fichier .sfx, sans l'extension. vol de 0 à 15 (plein par défaut). Deux effets à la fois ; un troisième vole la voix la plus ancienne. Un effet inconnu est silencieux, pas une erreur (comme un sprite manquant) : une faute de frappe ne plante jamais un jeu.

snd.stop()

Coupe tout d'un coup, musique et effets.

snd.volume(musique [, sfx])

Volumes maîtres, 0 à 15. snd.volume(8) règle le niveau de la musique ; un second argument règle celui des effets.

function _update()
  local p = pad.get()
  if depart and p & pad.START ~= 0 then snd.music("theme", true) end
  if p & pad.A ~= 0 and not (prec & pad.A) then snd.play("tir") end
  prec = p
end

La musique : le fichier .son

Un morceau est un petit fichier texte à la manière d'un tracker — lisible, diffable, écrit à la main dans l'éditeur. Créez une musique dans l'atelier (bibliothèque, Sounds, +) : elle s'ouvre sur un squelette qui joue déjà.

; theme.son — la musique du titre
tempo 8                          ; trames par ligne (60/8 ≈ 7,5 lignes/s)

inst lead  onde=pulse25 env=1,3,10,6   ; A,D en trames ; S niveau 0..15 ; R trames
inst bass  onde=tri     env=0,0,12,2

pattern intro
C-4 lead v12 | C-2 bass | --- | ---
E-4          | ---      | --- | ---
G-4 . a047   | G-2      | --- | ---
--- | --- | --- | ---
fin

morceau
intro intro
boucle 0                         ; reprise à l'entrée 0 (omis = pas de boucle)
fin
  • tempo N — trames par ligne. Plus petit = plus rapide.
  • inst nom onde=… env=A,D,S,R — un instrument. onde vaut pulse12, pulse25, pulse50 (carré), tri, scie, ou bruit. L'enveloppe est comptée en trames : attaque, decay, niveau de sustain (0–15), release.
  • pattern nom … fin — un bloc de lignes. Chaque ligne, ce sont les 4 canaux séparés par |. Dans une case : une note comme C-4 (C-0 à B-7), --- rien, off note-off, . garde l'instrument courant du canal. Optionnel par case : vNN volume, aXYZ arpège (fondamentale, +Y, +Z demi-tons). Un pattern dure autant de lignes qu'on en écrit — il boucle là, pas à 64.
  • morceau … fin — la suite des patterns à jouer, puis éventuellement boucle i pour reprendre à l'entrée i.

Quatre canaux synthé jouent ensemble. Un canal de bruit a quand même besoin d'une note (elle fixe la cadence du LFSR). Un jeu peut tenir plusieurs morceaux ; snd.music("nom") en choisit un.

Les effets : .sfx depuis un .wav

Déposez un .wav sur les Sounds de la bibliothèque, l'App le convertit en .sfx (PCM 8 bits mono à 24 kHz). WAV PCM, 8 ou 16 bits, mono ou stéréo, n'importe quelle fréquence — il est ramené en mono et rééchantillonné. Un jeu tient jusqu'à 64 effets et environ 80 secondes en tout (1 920 Kio à 24 kHz) ; l'App refuse un bundle qui dépasse, avec les chiffres. Vous pouvez aussi déposer un .sfx déjà prêt.

Les sons dans l'atelier

Dans la bibliothèque de l'atelier, Sounds tient les sons bruts et Audio bundles les regroupe. Déposez un .wav (converti en effet), un .sfx ou un .son, ou créez une musique ; un double-clic ouvre un son dans un onglet, où un effet montre sa forme d'onde et une musique s'édite en texte, et ▶ Listen le joue par le synthétiseur de la console. Regroupez des sons dans un bundle audio, nommez chacun à plat, et attachez le bundle au projet — ses pièces arrivent dans le jeu sous <nom>.sfx / <nom>.son, exactement ce que snd.play("nom") / snd.music("nom") lisent. Contrairement à un niveau, il n'y a rien à compiler : un son se suffit à lui-même. ▶ Play lance le jeu avec son son.

Vous pouvez toujours envoyer un .son/.sfx/.wav directement dans les fichiers d'un projet pour un cas ponctuel ; la bibliothèque est la part réutilisable par-dessus. Voir travailler dans l'App.

Ce que les noms ne disent pas

  • Le temps se compte en trames, pas en secondes. Le tempo d'un morceau, une enveloppe : tout compte des trames logiques — la même horloge que le jeu, donc le rejeu est exact.
  • Pas de math.sin dans le bac à sable. Le synthé emploie des tables entières figées, comme sys.sin ; vous n'y touchez jamais, mais c'est ce qui rend le son identique au bit près sur le simulateur et sur la carte.
  • Sur la carte, les effets vivent en flash et sont lus en place ; la musique est minuscule et vit en RAM. Vous n'avez rien de tout ça à gérer. Au premier lancement d'un jeu, ses effets sont écrits en flash — quelques secondes pour une réserve pleine — puis laissés tels quels tant que ses sons ne changent pas ; ceux d'un autre jeu prennent la place quand il se lance.