From 24ec2a92b56ca4296fe65b70524e36a8e1c67c2e Mon Sep 17 00:00:00 2001 From: Alexander Kassouni Date: Sat, 5 Sep 2026 22:43:52 -0700 Subject: phonemes --- docs/phonology.html | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) (limited to 'docs/phonology.html') 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:

-- cgit v1.3.1