Thursday, September 03, 2009

Sound Effects

Bon, il est temps de faire du bruit. Voilà le bout de code de la libntxm qui traite les nouvelles notes lors de la lecture du pattern. Le reste du temps, le player se contente d'ajuster le volume et de traiter les effets définis par une "cell" (une case du pattern).

Pour pouvoir faire des effets sonores, il faudra en quelques sortes que j'appelle ce même code à la demande depuis le processeur ARM9, probablement en réutilisant la technique d'IPC qui a servi à indiquer que le module devait être lancé ou arrêté (cf. NTXM7::updateCommands et le fichier command7.cpp)

It's been roughly 1 year that my game engine is waiting for sound effects. Let's see how to proceed, and add them to the ARM7 NTXM player that is the core of sound playback on the DS. This post is a sort of "exploration mission" to see how i'll proceed with programming them.
Primo, if i want to issue sound effects, the first thing to do is to ensure that I can invoke the "playNote" function (and surrounding code) on request from the game engine running on ARM9 . The most likely approach will be to mimmic the IPC approach 0xtob used to instruct the ARM7 to start or stop playing the whole song.
Funny enough, all the "commands handling code" always look the same. PLAY_SAMPLE and PLAY_INST commands already exist (i guess 0xtob needed them for the nitrotracker), but the actual stubs are missing. On the other hand, the "proxy" functions at the ARM9 are already present in command9.cpp ; they just lack an API in ntxm9.cpp ...

It should be running in a couple of evenings. It's really a shame it took me so0o long to check it out. It sounds that most of the effort will be to make GobExpression invoke ntxm9::playNote(), after all.

Tss. Même après l'an 2000, tous ces codes de "gestion des commandes" se ressemblent. PLAY_SAMPLE et PLAY_INST existent déjà, j'ai même déjà struct PlayInstCommand. Ils ne sont juste pas encore implémentés, mais Oxtob a bien préparé le terrain, pas de doute. Eh bien on va y remédier.
Cerise sur le gateau: CommandPlayInst et CommandStopInst sont déjà là dans command9.cpp ... Il reste juste à ajouter ça à NTXM9 et à faire en sorte que ce soit appelable depuis le GameScript et confrères.

edit: okay. Ca marche. Les pommes font "bzing!" quand on les prend. Il a fallu un peu plus de code que prévu du côté du game engine: c'est la première fois qu'une GobExpression du script appelle du code C++ ;)

6 comments:

cyborgjeff said...

et que j'enregistre qq trucs sympas ;)

PypeBros said...

idée: je coinçais depuis un moment sur "comment gérer une séquence d'évènements" (ouverture de porte, fin de niveau, mort, etc.)
En fait, la "timeline" sur laquelle aligner toutes les actions pourrait tout simplement être le pattern lui-même:
play pattern X
- at row 2 : set gob0.state4
- at row 20 : fade out
- at row 63 : level(green2.cmd)

PypeBros said...

axion0 := sound(C-5 4 60) plutôt que "using sound (C-5 4 60) as 0" ?
Ca me permettrait de faire plus tard "axion0.score := 100" ou "axion0.decrease c4" pour définir l'effet qu'a la disparition d'un appleman sur la logique du jeu ...

PypeBros said...

ou alors je considère simplement qu'il peut y avoir un fichier de macros du genre %define APPLEMAN_KILLED d4 et j'écris un 'template' pour l'appleman (quelque soit le jeu/niveau) avec statX35->nil on fail [APPLEMAN_KILLED]

"nasm -e appleman.tcm -P macros.ash >appleman.cmd" pourrait faire l'affaire.

PypeBros said...

ou

sed -e "s/#.*//;" gedsdemo/efsroot/appleman.cmd | cpp - -DAPPLEMAN_KILLED=d4 | less

ça marcherait aussi ...

PypeBros said...

Dans le même genre, struct StartPlayCommand contient déjà u8 potpos et u16 row. Il faudra ajuster RecvCommandStartPlay dans command7.cpp, void NTXM7::play(bool repeat) et NTXM9::play(bool repeat).

CommandStartPlay dans ntxm9.cpp semble déjà prêt.