How Animal Crossing (GameCube, GAFE01, USA rev 0) turns a
message string into villager babble. Every claim here is traced to a function in the
ac-decomp tree.
message text (game charset, 1 byte/char) │ │ 1. mMsg_sound_voice_get() 256-entry table ▼ char code ──► voice code (0x53–0x86) gating + voice selection │ 2. mMsg_sound_voice_mode_get() animalese / click / silent │ mNpc_GetNpcSoundSpec() speaker ──► spec 2–9 ▼ Na_SpecChange() spec ──► sequence 243/244/245 windowing │ 3. mMsg_sound_voice_entry() collect (a, b, c) over two cursor steps ▼ ~1 character per 2 game frames draw-time trigger │ 4. mFontSentence_animal_voice_se() glyph scale ──► volume ▼ sAdo_VoiceSe(a, b, c, npc, scale, mode) phonology │ 5. Na_VoiceSe() digraphs, long vowels, silent e ▼ ──► phoneme code 0x01–0x77 playback │ 6. Sou_VoiceStart() write port 0 of a JAudio2 subtrack │ sequence dyntbl ──► instrument (code − 1) ▼ 7. ProgToVp(bank, inst) ──► NoteToVoice() ──► smzwavetable DSP ──► one 30–400 ms VADPCM sample, 22050 Hz, pitched down 4–9 semitones
A phoneme code is literally a soundfont instrument number plus one. The whole "engine" is a lookup table with about fifty special cases; the character comes almost entirely from the samples.
Na_VoiceSe in full: the 53-entry digraph table, short/long
vowel tables, silent e, magic e, and punctuation flush.Pages 1–7 document the runtime pipeline as decompiled. Page 8 documents the data: how to walk a dumped disc image down to individual VADPCM frames, with the audio table-of-contents, bank/sample formats, sequence disassembly and decoding notes. Together they are intended to be a complete reference for a reimplementation.
Verified against ac-decomp at commit 09ca8e8b (DOL and REL
100 % linked) and against a dumped GAFE01 USA rev 0 disc image.