From 24ec2a92b56ca4296fe65b70524e36a8e1c67c2e Mon Sep 17 00:00:00 2001 From: Alexander Kassouni Date: Sat, 5 Sep 2026 22:43:52 -0700 Subject: phonemes --- docs/index.html | 2 +- docs/phonology.html | 42 ++++++++++++++++++++++++++++++++++++------ docs/playback.html | 2 +- docs/quirks.html | 2 +- docs/scheduling.html | 9 ++++++--- 5 files changed, 45 insertions(+), 12 deletions(-) (limited to 'docs') diff --git a/docs/index.html b/docs/index.html index d6a0817..7017da5 100644 --- a/docs/index.html +++ b/docs/index.html @@ -60,7 +60,7 @@ entirely from the samples.

font renderer, and the every-other-frame cursor.
  • 4. The phonology engine - Na_VoiceSe in full: the 55-entry digraph table, short/long + Na_VoiceSe in full: the 53-entry digraph table, short/long vowel tables, silent e, magic e, and punctuation flush.
  • 5. Playback diff --git a/docs/phonology.html b/docs/phonology.html index ebbc872..075f3a2 100644 --- a/docs/phonology.html +++ b/docs/phonology.html @@ -47,8 +47,13 @@ rewritten.

    0. Lone mute

    if (a == 0x85 && b == 0xFF && c == 0xFF) return;
    -

    Returns before touching any state, so a lone punctuation mark does not disturb the -previous-character history.

    +

    sou_num_org, sou_num2_org and sou_num3_org are assigned +before this test, so they are overwritten; what survives is +sou_last_num / sou_last_num2, which are written further down. A lone +punctuation mark therefore leaves the digraph history intact, but still clobbers the +context bytes a pending mode 2 call will read — +sou_num3_org for its short-vowel lookup, sou_num_org for its dedup +comparison.

    1. Silent e (:2612)

    if (a == 'e' && b > 0x77 && class(last_num) == vowel && class(last_num2) == consonant) {
    @@ -71,6 +76,17 @@ are consumed by one sample.

    The digraph table — Sou_ConnectCheck (:2316)

    53 entries. All are two characters except you, the only rule that reads c; one pairs a letter with a space rather than another letter (i␣).

    +
    +i␣ is very nearly unreachable. Its b is 0x81, +which is also a punctuation-flush trigger — so rule 3 below sets r28 = 3 and +unconditionally reassigns a, discarding the 0x05. It survives only when +the previous call's b was also punctuation, which forces r28 = 1 +instead; 0x05 then falls through Sou_TanboinHenkan's +default: return a and reaches playback unchanged. Every other digraph has a letter +in b and so never meets rule 3 — for those, "r28 = 2 falls straight +through to playback" holds as written. +
    +
    ai→0x0F
    al→0x02
    an→0x39
    ar→0x16
    as→0x3A
    be→0x3B
    by→0x3C
    @@ -110,9 +126,23 @@ each one a recorded syllable.

    a = Sou_ConnectCheck(sou_last_num2, sou_num_org, sou_num2_org);
     if (a < 0x53 || a > 0x76) break;      // it merged, or wasn't a letter — leave it
     a = Sou_TanboinHenkan(a, b);
    -

    This gives the final letter of a word a chance to pair with the letter before it -instead of being dropped against the following space. Note the guard also drops the -whole branch if a > 0x77 before it starts.

    +

    The intent is to give the final letter of a word a chance to pair with the letter +before it instead of being dropped against the following space. What it does is narrower. +a is reloaded from sou_last_num2 — the previous call's +b — and if Sou_ConnectCheck finds no merge it returns that byte +unchanged, so Sou_TanboinHenkan speaks the previous letter a second time and the +word-final letter is never voiced at all.

    + +

    Worked example, cat␣. Window (c, a, t) doesn't merge, so +r28 = 1 plays hard c and queues a; the deferred call plays +a. Window (t, ␣, …) then hits rule 3, reloads +a = sou_last_num2 = 'a', fails to merge at, and plays a +again. The t makes no sound. The branch only pays off when the reloaded pair +does merge — then the merged code plays and the 0x53–0x76 +guard breaks out before Sou_TanboinHenkan can touch it.

    + +

    Note the guard also drops the whole branch if a > 0x77 before it starts, and +that nothing is queued on this path.

    4. Vowel length (:2658, for r28 == 1 or 4)

    if (class(a) == vowel && class(b) == consonant && c == 'e')
    @@ -168,7 +198,7 @@ with the first syllable of the spoken number: 0=ze(ro)
     get codes nothing else reaches. The digraph names here are just labels for shared
     samples — the recording itself presumably says the number.

    -

    The deferred second syllable — mode 2

    +

    The deferred second syllable — mode 2

    Sou_SpecialRoutine10 (:1708) runs once per game frame inside Na_GameFrame:

    diff --git a/docs/playback.html b/docs/playback.html index 1cf9464..73be9a2 100644 --- a/docs/playback.html +++ b/docs/playback.html @@ -33,7 +33,7 @@ into the phoneme path — the pitch and volume bumps below never apply to the pl CodeCharEffect 0x86clickNA_SE_BEBE, then mute 0x81 0x84 0x85space, newline, mutemute -0x82?mute, and pitch × 1.24 / 1.30 / 1.13 for sequence 243 / 244 / 245 +0x82?mute, and pitch × 1.24 / 1.30 / 1.13 for sou_now_voice_seq 1 / 2 / 3 — the small index Na_SpecChange sets alongside sequence 243 / 244 / 245, not the sequence number itself 0x83!mute, and volume × 1.15 anything elseplays; sets sou_now_boin (dead, see quirks) diff --git a/docs/quirks.html b/docs/quirks.html index bb860c9..c46fdb2 100644 --- a/docs/quirks.html +++ b/docs/quirks.html @@ -145,7 +145,7 @@ the config. See gating.

    Everything else in extraction.md §1 was re-verified against the current tree -and holds: the voice table, the 55 digraph entries, both vowel tables, the per-spec +and holds: the voice table, the 53 digraph entries, both vowel tables, the per-spec timbre values, and the spec→sequence→bank mapping.

    diff --git a/docs/scheduling.html b/docs/scheduling.html index 581dff6..07f1e52 100644 --- a/docs/scheduling.html +++ b/docs/scheduling.html @@ -111,9 +111,12 @@ volume adjustment is skipped entirely. (What happens for other values is not what it looks like.)

    It also contains one very specific special case: if the character is ♪ at exactly -normal scale in colour rgba(50, 60, 50, 255), the NPC id is forced to 0, -suppressing the melody. This is presumably a specific piece of dialogue where a -literal music note glyph should stay silent.

    +normal scale in colour rgba(50, 60, 50, 255) and the NPC id is non-zero, that id +is forced to 0. This does not silence it — Na_VoiceSe's ♪ escape +only bails on voice == 0xFA, and melody_seq_offset[0] / +melody_seq_size[0] are a real 0x120-byte entry. The effect is to play +the figure on instrument 0 rather than the speaker's own, presumably so one particular +line reads as a generic note instead of that character's timbre.

    End of message

    -- cgit v1.3.1