@patterkit/model 0.26.0 → 0.27.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -2,37 +2,6 @@ import { AstNode } from '@wildwinter/expr';
2
2
  export { RESERVED_PROPERTY_NAMES, isCaseOnlyPropertyName, isValidPropertyName, propertyNameify } from '@wildwinter/expr';
3
3
  export { gameIdify, isValidGameId } from '@wildwinter/toolkit';
4
4
 
5
- /** What a speech unit is: a syllable (the mouth opens), a beat with the mouth shut (っ), or a pause. */
6
- type SpeechUnitKind = "syllable" | "closed" | "pause";
7
- /** A syllable's vowel, for a mouth shape: ə is a vowel the script shows that isn't one of the five. */
8
- type SpeechVowel = "a" | "e" | "i" | "o" | "u" | "ə";
9
- /** One unit of a line as it would be spoken. `start` and `end` are code-point offsets into the text, end exclusive.
10
- * `vowel` is a syllable's vowel where the script says it, absent otherwise (and on a pause or a shut beat). */
11
- interface SpeechUnit {
12
- kind: SpeechUnitKind;
13
- weight: number;
14
- start: number;
15
- end: number;
16
- vowel?: SpeechVowel;
17
- }
18
- /** A digit's weight: most read as one or two syllables. */
19
- declare const SPEECH_DIGIT_WEIGHT = 1.5;
20
- /** A Han character's weight in Japanese text. */
21
- declare const SPEECH_KANJI_WEIGHT = 2;
22
- /** A short pause's weight (`,` `;` `、`), and a long one's (`.` `?` `。`). */
23
- declare const SPEECH_PAUSE_SHORT_WEIGHT = 1;
24
- declare const SPEECH_PAUSE_LONG_WEIGHT = 2;
25
- /**
26
- * A line broken into the units it would be spoken in: its syllables, its beats with the mouth shut, and its pauses,
27
- * in order, each with a weight. `locale` is the language the line is spoken in (the project's main language, not the
28
- * one being shown); it decides English's and French's silent e, and Japanese kanji, which also apply when the line
29
- * has any kana in it.
30
- */
31
- declare function speechUnits(text: string, locale?: string): SpeechUnit[];
32
- /** How many syllables a line would be spoken in: its syllables' and shut beats' weights, pauses aside. `locale` is
33
- * the language it's spoken in, as for `speechUnits`. */
34
- declare function countSyllables(text: string, locale?: string): number;
35
-
36
5
  type ScalarValue = boolean | number | string | string[];
37
6
  /** Developer-defined host metadata (spec §17). Opaque to Patter. */
38
7
  type GameData = Record<string, unknown>;
@@ -462,11 +431,13 @@ declare const DEFAULT_PAD_AFTER = 0.6;
462
431
  /** The range validation keeps a `padAfter` or `padAfterDefault` within, in seconds. */
463
432
  declare const PAD_AFTER_MIN = -10;
464
433
  declare const PAD_AFTER_MAX = 60;
465
- /** How many syllables a second a line with no recording is timed at, unless the project sets its own
466
- * (`estimateSyllablesPerSecond`), and the range validation keeps a project's within. */
467
- declare const DEFAULT_ESTIMATE_SYLLABLES_PER_SECOND = 4;
468
- declare const ESTIMATE_SYLLABLES_PER_SECOND_MIN = 2;
469
- declare const ESTIMATE_SYLLABLES_PER_SECOND_MAX = 10;
434
+ /** How fast a line with no recording is timed against the default, unless the project sets its own
435
+ * (`estimateSpeed`), and the range validation keeps a project's within: higher is faster. */
436
+ declare const DEFAULT_ESTIMATE_SPEED = 1;
437
+ declare const ESTIMATE_SPEED_MIN = 0.5;
438
+ declare const ESTIMATE_SPEED_MAX = 2.5;
439
+ /** How many weighted characters a second a line with no recording is timed at, at speed 1 (`estimateLineDuration`). */
440
+ declare const LINE_CHARS_PER_SECOND = 14;
470
441
  /** The shortest and longest a line with no recording lasts, in seconds (`estimateLineDuration`). The shortest is a
471
442
  * speaking time, the least a spoken word plausibly takes, not a reading time: see SUBTITLE_READING_MIN. */
472
443
  declare const LINE_DURATION_MIN = 0.5;
@@ -475,14 +446,26 @@ declare const LINE_DURATION_MAX = 18;
475
446
  * for a tool that shows a line as a subtitle or overhead text, which keeps it up at least this long after a shorter
476
447
  * line ends, overlapping the next if it must. The line itself still ends when it's said (`estimateLineDuration`). */
477
448
  declare const SUBTITLE_READING_MIN = 1.5;
478
- /** How long a line with no recording lasts, in seconds: the total weight of its speech units (its syllables and its
479
- * pauses, `speechUnits`) at `syllablesPerSecond` (default 4, the project's `estimateSyllablesPerSecond` when it
480
- * sets one), clamped to 0.5 to 18 seconds. `text` and `locale` are the line as it's spoken, in the project's main
481
- * language (a line result's `spokenText` and `spokenLocale`), never a translation being shown. This is the one
482
- * rule every Patter tool and runtime times a line by: Patterpad's Play window, the playable HTML page, and the
483
- * Unity, Unreal, and Godot runtimes, which the conformance corpus holds to the same numbers. A rate that isn't a
484
- * positive number is the default. A line with a recording lasts as long as the recording, whatever this says. */
485
- declare function estimateLineDuration(text: string, locale?: string, syllablesPerSecond?: number): number;
449
+ /** Reads a project file's timing for lines without audio from before `estimateSpeed`: a project carrying the old
450
+ * `estimateSyllablesPerSecond` (syllables a second, 4 the default) and no `estimateSpeed` gets `estimateSpeed` =
451
+ * the old value / 4, and the old key goes either way, so the next save writes only the new one. A value that isn't
452
+ * a number is carried across as it is, for validation to report. Changes `project` in place and returns it. Every
453
+ * reader of a project file calls this once, where it parses the file. */
454
+ declare function normaliseEstimateSpeed<T extends object>(project: T): T;
455
+ /** The characters `estimateLineDuration` weighs other than 1, as inclusive code point ranges with their weight: Han
456
+ * 3 (CJK Unified Ideographs, Extension A, the Compatibility Ideographs, and Extensions B onwards), kana 2
457
+ * (hiragana, katakana, the katakana phonetic extensions, and halfwidth katakana), a Hangul syllable block 2.5, and
458
+ * the soft hyphen 0. Plain ranges rather than Unicode properties, so every runtime holds the same list. */
459
+ declare const LINE_CHAR_WEIGHTS: readonly (readonly [number, number, number])[];
460
+ /** How long a line with no recording lasts, in seconds: its weighted characters (`LINE_CHAR_WEIGHTS`, a character
461
+ * being a code point, 1 unless listed there) at `LINE_CHARS_PER_SECOND` times `speed` (default 1, the project's
462
+ * `estimateSpeed` when it sets one), clamped to 0.5 to 18 seconds. `text` is the line as it's spoken, in the
463
+ * project's main language (a line result's `spokenText`), never a translation being shown. `locale` is reserved:
464
+ * nothing reads it yet. This is the one rule every Patter tool and runtime times a line by: Patterpad's Play
465
+ * window, the playable HTML page, and the Unity, Unreal, and Godot runtimes, which the conformance corpus holds to
466
+ * the same numbers. A speed that isn't a finite positive number is 1. A line with a recording lasts as long as the
467
+ * recording, whatever this says. */
468
+ declare function estimateLineDuration(text: string, locale?: string, speed?: number): number;
486
469
  /** A qualifier as it reaches a compiled bundle: its `gameId` and authored name (the unlocalised fallback). */
487
470
  interface BundleQualifier {
488
471
  gameId: string;
@@ -791,10 +774,11 @@ interface ProjectFile {
791
774
  /** The project's default `padAfter` for every line and text beat that sets none and has no default above it.
792
775
  * Absent = `DEFAULT_PAD_AFTER`. */
793
776
  padAfterDefault?: number;
794
- /** How many syllables a second a line with no recording is timed at (`estimateLineDuration`), from 2 to 10.
795
- * Only estimates use it: a line with a recording lasts as long as the recording. Absent =
796
- * `DEFAULT_ESTIMATE_SYLLABLES_PER_SECOND`. */
797
- estimateSyllablesPerSecond?: number;
777
+ /** How fast a line with no recording is timed against the default (`estimateLineDuration`), from 0.5 to 2.5:
778
+ * higher is faster. Only estimates use it: a line with a recording lasts as long as the recording. Absent =
779
+ * `DEFAULT_ESTIMATE_SPEED`. A project file from before 0.45 may carry `estimateSyllablesPerSecond` instead:
780
+ * `normaliseEstimateSpeed` reads it as this. */
781
+ estimateSpeed?: number;
798
782
  /** Localise text lines in dialogue scenes (design/proposals/action-text.md). Off (absent) by default: a
799
783
  * dialogue scene's text beats (`isDialogueScene`) are then ACTION, left out of the loc files and the
800
784
  * written word counts, and compiled with `action: true`. On: they're localised and shown as a text
@@ -818,7 +802,7 @@ interface ProjectFile {
818
802
  * meaningful when `audioFolders` is on. Authoring metadata; never reaches the bundle. */
819
803
  audioRoot?: string;
820
804
  /** Audio Folders mode (#206): when true, a dialogue line's recording status is DERIVED from which
821
- * rung's derived folder (under `audioRoot`) holds its `<beatId>.wav|mp3` (top-down the ladder, implicit
805
+ * rung's derived folder (under `audioRoot`) holds its `<beatId>.wav|ogg|mp3` (top-down the ladder, implicit
822
806
  * "missing"), instead of being set manually. Authoring metadata; never reaches the bundle. Default off. */
823
807
  audioFolders?: boolean;
824
808
  /** Scratch recording (Patterpad #224): the recording-status rung whose folder is the source/dest for
@@ -1211,9 +1195,8 @@ interface Bundle {
1211
1195
  speakerPattern?: string;
1212
1196
  /** The project's own `padAfterDefault`, when it sets one; absent = `DEFAULT_PAD_AFTER`. */
1213
1197
  padAfterDefault?: number;
1214
- /** The project's own `estimateSyllablesPerSecond`, when it sets one; absent =
1215
- * `DEFAULT_ESTIMATE_SYLLABLES_PER_SECOND`. */
1216
- estimateSyllablesPerSecond?: number;
1198
+ /** The project's own `estimateSpeed`, when it sets one; absent = `DEFAULT_ESTIMATE_SPEED`. */
1199
+ estimateSpeed?: number;
1217
1200
  properties?: PropertyDecl[];
1218
1201
  /** Host / world scope declarations, baked from the project so the runtime can self-back a declared
1219
1202
  * scope (`@world`, ...) when no host resolver claims its token. Absent = no host scopes. */
@@ -1508,4 +1491,4 @@ interface ExtensionFieldDecl {
1508
1491
  /** A node's extension values in a bundle: extension id -> field -> value, raw. */
1509
1492
  type NodeExtensions = Record<string, Record<string, unknown>>;
1510
1493
 
1511
- export { AUTHORING_SCHEMA, type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, type BundleExtension, type BundleQualifier, COMMON_GENDERS, type CaptionDelimiters, type CastMember, type Comment, type CommentMessage, type CommentRange, type CompiledBlock, type CompiledEffect, type CompiledGroup, type CompiledScene, type CompiledSnippet, type CoverageDriver, DEFAULT_CAPTION_CHARACTER, DEFAULT_CAPTION_DELIMITERS, DEFAULT_DOCUMENTATION_CLASSES, DEFAULT_ESTIMATE_SYLLABLES_PER_SECOND, DEFAULT_LAYOUT, DEFAULT_PAD_AFTER, DEFAULT_QUALIFIERS, DEFAULT_RECORDING_STATUSES, DEFAULT_SPEAKER_PATTERN, DEFAULT_WRITING_STATUSES, type DocLine, type DocumentationClass, ESTIMATE_SYLLABLES_PER_SECOND_MAX, ESTIMATE_SYLLABLES_PER_SECOND_MIN, EXTENSIONS_DIR, EXTENSION_SCHEMA, EXTENSION_SHARD, type EditRecord, type Effect, type EngineSave, type EstimatingConfig, type Expression, type ExtensionFieldDecl, type ExtensionShard, FLOW_SCHEMA, type FlowCursor, type FlowFile, type FlowNode, type FlowSnapshot, type FlowState, type FlowValues, type GameData, type GameDataField, type GameDataFieldType, type GameDataFields, type GameDataNodeKind, type GameEventBeat, type GrammaticalGender, type Group, HANDOFF_SCHEMA, type HandoffFile, type HandoffImport, type HandoffLine, type HandoffRow, type HostScopeDecl, type HostScopeRegistry, type HostScopeSpec, type Jump, type JumpTarget, LINE_DURATION_MAX, LINE_DURATION_MIN, type LineBeat, type LocaleFile, MANIFEST_EXTENSION, type NodeExtensions, PAD_AFTER_MAX, PAD_AFTER_MIN, PROJECT_EXTENSION_STEM, PROJECT_LOCALE_SCENE, PROJECT_SCHEMA, type ProjectDictionary, type ProjectExtension, type ProjectFile, type ProjectLayout, type PromptBeat, type PropertyDecl, type PropertyType, RERECORD_STATUS, RERECORD_STATUS_DECL, type RecordingFolder, type RecordingStatusDecl, SAVE_SCHEMA, SAVE_VERSION, SPEAKER_PATTERN_KEY, SPEECH_DIGIT_WEIGHT, SPEECH_KANJI_WEIGHT, SPEECH_PAUSE_LONG_WEIGHT, SPEECH_PAUSE_SHORT_WEIGHT, STRINGS_SCHEMA, SUBTITLE_READING_MIN, type SaveEnvelope, type SaveGame, type SaveGameV3, type SavedChoice, type SavedChoiceOption, type SavedChoicePrompt, type ScalarValue, type Scene, type SceneFolder, type SceneFolderLayout, type SceneNavRow, type Selector, type SelectorExhaust, type SelectorOrder, type SelectorSnapshot, type SequenceOptions, type Snippet, type SpeakerQualifier, type SpeechUnit, type SpeechUnitKind, type SpeechVowel, type StackFrame, type Suggestion, type SuggestionSource, type TextBeat, UNRESOLVED_KEY, type VcsKind, type WritingStatusDecl, castStringKey, countSyllables, deriveRecordingFolders, effectiveGameId, estimateLineDuration, formatSpeakerLabel, isContentlessBeat, isDialogueScene, projectLayout, projectQualifiers, qualifierStringKey, resolveSceneRef, sceneAddressIndex, sceneFolderLayout, sceneFolderPath, speakerLabelKey, speechUnits, textIsAction, usedQualifiers, usedSpeakerPairs, walkNodes };
1494
+ export { AUTHORING_SCHEMA, type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, type BundleExtension, type BundleQualifier, COMMON_GENDERS, type CaptionDelimiters, type CastMember, type Comment, type CommentMessage, type CommentRange, type CompiledBlock, type CompiledEffect, type CompiledGroup, type CompiledScene, type CompiledSnippet, type CoverageDriver, DEFAULT_CAPTION_CHARACTER, DEFAULT_CAPTION_DELIMITERS, DEFAULT_DOCUMENTATION_CLASSES, DEFAULT_ESTIMATE_SPEED, DEFAULT_LAYOUT, DEFAULT_PAD_AFTER, DEFAULT_QUALIFIERS, DEFAULT_RECORDING_STATUSES, DEFAULT_SPEAKER_PATTERN, DEFAULT_WRITING_STATUSES, type DocLine, type DocumentationClass, ESTIMATE_SPEED_MAX, ESTIMATE_SPEED_MIN, EXTENSIONS_DIR, EXTENSION_SCHEMA, EXTENSION_SHARD, type EditRecord, type Effect, type EngineSave, type EstimatingConfig, type Expression, type ExtensionFieldDecl, type ExtensionShard, FLOW_SCHEMA, type FlowCursor, type FlowFile, type FlowNode, type FlowSnapshot, type FlowState, type FlowValues, type GameData, type GameDataField, type GameDataFieldType, type GameDataFields, type GameDataNodeKind, type GameEventBeat, type GrammaticalGender, type Group, HANDOFF_SCHEMA, type HandoffFile, type HandoffImport, type HandoffLine, type HandoffRow, type HostScopeDecl, type HostScopeRegistry, type HostScopeSpec, type Jump, type JumpTarget, LINE_CHARS_PER_SECOND, LINE_CHAR_WEIGHTS, LINE_DURATION_MAX, LINE_DURATION_MIN, type LineBeat, type LocaleFile, MANIFEST_EXTENSION, type NodeExtensions, PAD_AFTER_MAX, PAD_AFTER_MIN, PROJECT_EXTENSION_STEM, PROJECT_LOCALE_SCENE, PROJECT_SCHEMA, type ProjectDictionary, type ProjectExtension, type ProjectFile, type ProjectLayout, type PromptBeat, type PropertyDecl, type PropertyType, RERECORD_STATUS, RERECORD_STATUS_DECL, type RecordingFolder, type RecordingStatusDecl, SAVE_SCHEMA, SAVE_VERSION, SPEAKER_PATTERN_KEY, STRINGS_SCHEMA, SUBTITLE_READING_MIN, type SaveEnvelope, type SaveGame, type SaveGameV3, type SavedChoice, type SavedChoiceOption, type SavedChoicePrompt, type ScalarValue, type Scene, type SceneFolder, type SceneFolderLayout, type SceneNavRow, type Selector, type SelectorExhaust, type SelectorOrder, type SelectorSnapshot, type SequenceOptions, type Snippet, type SpeakerQualifier, type StackFrame, type Suggestion, type SuggestionSource, type TextBeat, UNRESOLVED_KEY, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, estimateLineDuration, formatSpeakerLabel, isContentlessBeat, isDialogueScene, normaliseEstimateSpeed, projectLayout, projectQualifiers, qualifierStringKey, resolveSceneRef, sceneAddressIndex, sceneFolderLayout, sceneFolderPath, speakerLabelKey, textIsAction, usedQualifiers, usedSpeakerPairs, walkNodes };
package/dist/index.d.ts CHANGED
@@ -2,37 +2,6 @@ import { AstNode } from '@wildwinter/expr';
2
2
  export { RESERVED_PROPERTY_NAMES, isCaseOnlyPropertyName, isValidPropertyName, propertyNameify } from '@wildwinter/expr';
3
3
  export { gameIdify, isValidGameId } from '@wildwinter/toolkit';
4
4
 
5
- /** What a speech unit is: a syllable (the mouth opens), a beat with the mouth shut (っ), or a pause. */
6
- type SpeechUnitKind = "syllable" | "closed" | "pause";
7
- /** A syllable's vowel, for a mouth shape: ə is a vowel the script shows that isn't one of the five. */
8
- type SpeechVowel = "a" | "e" | "i" | "o" | "u" | "ə";
9
- /** One unit of a line as it would be spoken. `start` and `end` are code-point offsets into the text, end exclusive.
10
- * `vowel` is a syllable's vowel where the script says it, absent otherwise (and on a pause or a shut beat). */
11
- interface SpeechUnit {
12
- kind: SpeechUnitKind;
13
- weight: number;
14
- start: number;
15
- end: number;
16
- vowel?: SpeechVowel;
17
- }
18
- /** A digit's weight: most read as one or two syllables. */
19
- declare const SPEECH_DIGIT_WEIGHT = 1.5;
20
- /** A Han character's weight in Japanese text. */
21
- declare const SPEECH_KANJI_WEIGHT = 2;
22
- /** A short pause's weight (`,` `;` `、`), and a long one's (`.` `?` `。`). */
23
- declare const SPEECH_PAUSE_SHORT_WEIGHT = 1;
24
- declare const SPEECH_PAUSE_LONG_WEIGHT = 2;
25
- /**
26
- * A line broken into the units it would be spoken in: its syllables, its beats with the mouth shut, and its pauses,
27
- * in order, each with a weight. `locale` is the language the line is spoken in (the project's main language, not the
28
- * one being shown); it decides English's and French's silent e, and Japanese kanji, which also apply when the line
29
- * has any kana in it.
30
- */
31
- declare function speechUnits(text: string, locale?: string): SpeechUnit[];
32
- /** How many syllables a line would be spoken in: its syllables' and shut beats' weights, pauses aside. `locale` is
33
- * the language it's spoken in, as for `speechUnits`. */
34
- declare function countSyllables(text: string, locale?: string): number;
35
-
36
5
  type ScalarValue = boolean | number | string | string[];
37
6
  /** Developer-defined host metadata (spec §17). Opaque to Patter. */
38
7
  type GameData = Record<string, unknown>;
@@ -462,11 +431,13 @@ declare const DEFAULT_PAD_AFTER = 0.6;
462
431
  /** The range validation keeps a `padAfter` or `padAfterDefault` within, in seconds. */
463
432
  declare const PAD_AFTER_MIN = -10;
464
433
  declare const PAD_AFTER_MAX = 60;
465
- /** How many syllables a second a line with no recording is timed at, unless the project sets its own
466
- * (`estimateSyllablesPerSecond`), and the range validation keeps a project's within. */
467
- declare const DEFAULT_ESTIMATE_SYLLABLES_PER_SECOND = 4;
468
- declare const ESTIMATE_SYLLABLES_PER_SECOND_MIN = 2;
469
- declare const ESTIMATE_SYLLABLES_PER_SECOND_MAX = 10;
434
+ /** How fast a line with no recording is timed against the default, unless the project sets its own
435
+ * (`estimateSpeed`), and the range validation keeps a project's within: higher is faster. */
436
+ declare const DEFAULT_ESTIMATE_SPEED = 1;
437
+ declare const ESTIMATE_SPEED_MIN = 0.5;
438
+ declare const ESTIMATE_SPEED_MAX = 2.5;
439
+ /** How many weighted characters a second a line with no recording is timed at, at speed 1 (`estimateLineDuration`). */
440
+ declare const LINE_CHARS_PER_SECOND = 14;
470
441
  /** The shortest and longest a line with no recording lasts, in seconds (`estimateLineDuration`). The shortest is a
471
442
  * speaking time, the least a spoken word plausibly takes, not a reading time: see SUBTITLE_READING_MIN. */
472
443
  declare const LINE_DURATION_MIN = 0.5;
@@ -475,14 +446,26 @@ declare const LINE_DURATION_MAX = 18;
475
446
  * for a tool that shows a line as a subtitle or overhead text, which keeps it up at least this long after a shorter
476
447
  * line ends, overlapping the next if it must. The line itself still ends when it's said (`estimateLineDuration`). */
477
448
  declare const SUBTITLE_READING_MIN = 1.5;
478
- /** How long a line with no recording lasts, in seconds: the total weight of its speech units (its syllables and its
479
- * pauses, `speechUnits`) at `syllablesPerSecond` (default 4, the project's `estimateSyllablesPerSecond` when it
480
- * sets one), clamped to 0.5 to 18 seconds. `text` and `locale` are the line as it's spoken, in the project's main
481
- * language (a line result's `spokenText` and `spokenLocale`), never a translation being shown. This is the one
482
- * rule every Patter tool and runtime times a line by: Patterpad's Play window, the playable HTML page, and the
483
- * Unity, Unreal, and Godot runtimes, which the conformance corpus holds to the same numbers. A rate that isn't a
484
- * positive number is the default. A line with a recording lasts as long as the recording, whatever this says. */
485
- declare function estimateLineDuration(text: string, locale?: string, syllablesPerSecond?: number): number;
449
+ /** Reads a project file's timing for lines without audio from before `estimateSpeed`: a project carrying the old
450
+ * `estimateSyllablesPerSecond` (syllables a second, 4 the default) and no `estimateSpeed` gets `estimateSpeed` =
451
+ * the old value / 4, and the old key goes either way, so the next save writes only the new one. A value that isn't
452
+ * a number is carried across as it is, for validation to report. Changes `project` in place and returns it. Every
453
+ * reader of a project file calls this once, where it parses the file. */
454
+ declare function normaliseEstimateSpeed<T extends object>(project: T): T;
455
+ /** The characters `estimateLineDuration` weighs other than 1, as inclusive code point ranges with their weight: Han
456
+ * 3 (CJK Unified Ideographs, Extension A, the Compatibility Ideographs, and Extensions B onwards), kana 2
457
+ * (hiragana, katakana, the katakana phonetic extensions, and halfwidth katakana), a Hangul syllable block 2.5, and
458
+ * the soft hyphen 0. Plain ranges rather than Unicode properties, so every runtime holds the same list. */
459
+ declare const LINE_CHAR_WEIGHTS: readonly (readonly [number, number, number])[];
460
+ /** How long a line with no recording lasts, in seconds: its weighted characters (`LINE_CHAR_WEIGHTS`, a character
461
+ * being a code point, 1 unless listed there) at `LINE_CHARS_PER_SECOND` times `speed` (default 1, the project's
462
+ * `estimateSpeed` when it sets one), clamped to 0.5 to 18 seconds. `text` is the line as it's spoken, in the
463
+ * project's main language (a line result's `spokenText`), never a translation being shown. `locale` is reserved:
464
+ * nothing reads it yet. This is the one rule every Patter tool and runtime times a line by: Patterpad's Play
465
+ * window, the playable HTML page, and the Unity, Unreal, and Godot runtimes, which the conformance corpus holds to
466
+ * the same numbers. A speed that isn't a finite positive number is 1. A line with a recording lasts as long as the
467
+ * recording, whatever this says. */
468
+ declare function estimateLineDuration(text: string, locale?: string, speed?: number): number;
486
469
  /** A qualifier as it reaches a compiled bundle: its `gameId` and authored name (the unlocalised fallback). */
487
470
  interface BundleQualifier {
488
471
  gameId: string;
@@ -791,10 +774,11 @@ interface ProjectFile {
791
774
  /** The project's default `padAfter` for every line and text beat that sets none and has no default above it.
792
775
  * Absent = `DEFAULT_PAD_AFTER`. */
793
776
  padAfterDefault?: number;
794
- /** How many syllables a second a line with no recording is timed at (`estimateLineDuration`), from 2 to 10.
795
- * Only estimates use it: a line with a recording lasts as long as the recording. Absent =
796
- * `DEFAULT_ESTIMATE_SYLLABLES_PER_SECOND`. */
797
- estimateSyllablesPerSecond?: number;
777
+ /** How fast a line with no recording is timed against the default (`estimateLineDuration`), from 0.5 to 2.5:
778
+ * higher is faster. Only estimates use it: a line with a recording lasts as long as the recording. Absent =
779
+ * `DEFAULT_ESTIMATE_SPEED`. A project file from before 0.45 may carry `estimateSyllablesPerSecond` instead:
780
+ * `normaliseEstimateSpeed` reads it as this. */
781
+ estimateSpeed?: number;
798
782
  /** Localise text lines in dialogue scenes (design/proposals/action-text.md). Off (absent) by default: a
799
783
  * dialogue scene's text beats (`isDialogueScene`) are then ACTION, left out of the loc files and the
800
784
  * written word counts, and compiled with `action: true`. On: they're localised and shown as a text
@@ -818,7 +802,7 @@ interface ProjectFile {
818
802
  * meaningful when `audioFolders` is on. Authoring metadata; never reaches the bundle. */
819
803
  audioRoot?: string;
820
804
  /** Audio Folders mode (#206): when true, a dialogue line's recording status is DERIVED from which
821
- * rung's derived folder (under `audioRoot`) holds its `<beatId>.wav|mp3` (top-down the ladder, implicit
805
+ * rung's derived folder (under `audioRoot`) holds its `<beatId>.wav|ogg|mp3` (top-down the ladder, implicit
822
806
  * "missing"), instead of being set manually. Authoring metadata; never reaches the bundle. Default off. */
823
807
  audioFolders?: boolean;
824
808
  /** Scratch recording (Patterpad #224): the recording-status rung whose folder is the source/dest for
@@ -1211,9 +1195,8 @@ interface Bundle {
1211
1195
  speakerPattern?: string;
1212
1196
  /** The project's own `padAfterDefault`, when it sets one; absent = `DEFAULT_PAD_AFTER`. */
1213
1197
  padAfterDefault?: number;
1214
- /** The project's own `estimateSyllablesPerSecond`, when it sets one; absent =
1215
- * `DEFAULT_ESTIMATE_SYLLABLES_PER_SECOND`. */
1216
- estimateSyllablesPerSecond?: number;
1198
+ /** The project's own `estimateSpeed`, when it sets one; absent = `DEFAULT_ESTIMATE_SPEED`. */
1199
+ estimateSpeed?: number;
1217
1200
  properties?: PropertyDecl[];
1218
1201
  /** Host / world scope declarations, baked from the project so the runtime can self-back a declared
1219
1202
  * scope (`@world`, ...) when no host resolver claims its token. Absent = no host scopes. */
@@ -1508,4 +1491,4 @@ interface ExtensionFieldDecl {
1508
1491
  /** A node's extension values in a bundle: extension id -> field -> value, raw. */
1509
1492
  type NodeExtensions = Record<string, Record<string, unknown>>;
1510
1493
 
1511
- export { AUTHORING_SCHEMA, type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, type BundleExtension, type BundleQualifier, COMMON_GENDERS, type CaptionDelimiters, type CastMember, type Comment, type CommentMessage, type CommentRange, type CompiledBlock, type CompiledEffect, type CompiledGroup, type CompiledScene, type CompiledSnippet, type CoverageDriver, DEFAULT_CAPTION_CHARACTER, DEFAULT_CAPTION_DELIMITERS, DEFAULT_DOCUMENTATION_CLASSES, DEFAULT_ESTIMATE_SYLLABLES_PER_SECOND, DEFAULT_LAYOUT, DEFAULT_PAD_AFTER, DEFAULT_QUALIFIERS, DEFAULT_RECORDING_STATUSES, DEFAULT_SPEAKER_PATTERN, DEFAULT_WRITING_STATUSES, type DocLine, type DocumentationClass, ESTIMATE_SYLLABLES_PER_SECOND_MAX, ESTIMATE_SYLLABLES_PER_SECOND_MIN, EXTENSIONS_DIR, EXTENSION_SCHEMA, EXTENSION_SHARD, type EditRecord, type Effect, type EngineSave, type EstimatingConfig, type Expression, type ExtensionFieldDecl, type ExtensionShard, FLOW_SCHEMA, type FlowCursor, type FlowFile, type FlowNode, type FlowSnapshot, type FlowState, type FlowValues, type GameData, type GameDataField, type GameDataFieldType, type GameDataFields, type GameDataNodeKind, type GameEventBeat, type GrammaticalGender, type Group, HANDOFF_SCHEMA, type HandoffFile, type HandoffImport, type HandoffLine, type HandoffRow, type HostScopeDecl, type HostScopeRegistry, type HostScopeSpec, type Jump, type JumpTarget, LINE_DURATION_MAX, LINE_DURATION_MIN, type LineBeat, type LocaleFile, MANIFEST_EXTENSION, type NodeExtensions, PAD_AFTER_MAX, PAD_AFTER_MIN, PROJECT_EXTENSION_STEM, PROJECT_LOCALE_SCENE, PROJECT_SCHEMA, type ProjectDictionary, type ProjectExtension, type ProjectFile, type ProjectLayout, type PromptBeat, type PropertyDecl, type PropertyType, RERECORD_STATUS, RERECORD_STATUS_DECL, type RecordingFolder, type RecordingStatusDecl, SAVE_SCHEMA, SAVE_VERSION, SPEAKER_PATTERN_KEY, SPEECH_DIGIT_WEIGHT, SPEECH_KANJI_WEIGHT, SPEECH_PAUSE_LONG_WEIGHT, SPEECH_PAUSE_SHORT_WEIGHT, STRINGS_SCHEMA, SUBTITLE_READING_MIN, type SaveEnvelope, type SaveGame, type SaveGameV3, type SavedChoice, type SavedChoiceOption, type SavedChoicePrompt, type ScalarValue, type Scene, type SceneFolder, type SceneFolderLayout, type SceneNavRow, type Selector, type SelectorExhaust, type SelectorOrder, type SelectorSnapshot, type SequenceOptions, type Snippet, type SpeakerQualifier, type SpeechUnit, type SpeechUnitKind, type SpeechVowel, type StackFrame, type Suggestion, type SuggestionSource, type TextBeat, UNRESOLVED_KEY, type VcsKind, type WritingStatusDecl, castStringKey, countSyllables, deriveRecordingFolders, effectiveGameId, estimateLineDuration, formatSpeakerLabel, isContentlessBeat, isDialogueScene, projectLayout, projectQualifiers, qualifierStringKey, resolveSceneRef, sceneAddressIndex, sceneFolderLayout, sceneFolderPath, speakerLabelKey, speechUnits, textIsAction, usedQualifiers, usedSpeakerPairs, walkNodes };
1494
+ export { AUTHORING_SCHEMA, type AuthoringFile, type Beat, type Block, type Bundle, type BundleCastMember, type BundleExtension, type BundleQualifier, COMMON_GENDERS, type CaptionDelimiters, type CastMember, type Comment, type CommentMessage, type CommentRange, type CompiledBlock, type CompiledEffect, type CompiledGroup, type CompiledScene, type CompiledSnippet, type CoverageDriver, DEFAULT_CAPTION_CHARACTER, DEFAULT_CAPTION_DELIMITERS, DEFAULT_DOCUMENTATION_CLASSES, DEFAULT_ESTIMATE_SPEED, DEFAULT_LAYOUT, DEFAULT_PAD_AFTER, DEFAULT_QUALIFIERS, DEFAULT_RECORDING_STATUSES, DEFAULT_SPEAKER_PATTERN, DEFAULT_WRITING_STATUSES, type DocLine, type DocumentationClass, ESTIMATE_SPEED_MAX, ESTIMATE_SPEED_MIN, EXTENSIONS_DIR, EXTENSION_SCHEMA, EXTENSION_SHARD, type EditRecord, type Effect, type EngineSave, type EstimatingConfig, type Expression, type ExtensionFieldDecl, type ExtensionShard, FLOW_SCHEMA, type FlowCursor, type FlowFile, type FlowNode, type FlowSnapshot, type FlowState, type FlowValues, type GameData, type GameDataField, type GameDataFieldType, type GameDataFields, type GameDataNodeKind, type GameEventBeat, type GrammaticalGender, type Group, HANDOFF_SCHEMA, type HandoffFile, type HandoffImport, type HandoffLine, type HandoffRow, type HostScopeDecl, type HostScopeRegistry, type HostScopeSpec, type Jump, type JumpTarget, LINE_CHARS_PER_SECOND, LINE_CHAR_WEIGHTS, LINE_DURATION_MAX, LINE_DURATION_MIN, type LineBeat, type LocaleFile, MANIFEST_EXTENSION, type NodeExtensions, PAD_AFTER_MAX, PAD_AFTER_MIN, PROJECT_EXTENSION_STEM, PROJECT_LOCALE_SCENE, PROJECT_SCHEMA, type ProjectDictionary, type ProjectExtension, type ProjectFile, type ProjectLayout, type PromptBeat, type PropertyDecl, type PropertyType, RERECORD_STATUS, RERECORD_STATUS_DECL, type RecordingFolder, type RecordingStatusDecl, SAVE_SCHEMA, SAVE_VERSION, SPEAKER_PATTERN_KEY, STRINGS_SCHEMA, SUBTITLE_READING_MIN, type SaveEnvelope, type SaveGame, type SaveGameV3, type SavedChoice, type SavedChoiceOption, type SavedChoicePrompt, type ScalarValue, type Scene, type SceneFolder, type SceneFolderLayout, type SceneNavRow, type Selector, type SelectorExhaust, type SelectorOrder, type SelectorSnapshot, type SequenceOptions, type Snippet, type SpeakerQualifier, type StackFrame, type Suggestion, type SuggestionSource, type TextBeat, UNRESOLVED_KEY, type VcsKind, type WritingStatusDecl, castStringKey, deriveRecordingFolders, effectiveGameId, estimateLineDuration, formatSpeakerLabel, isContentlessBeat, isDialogueScene, normaliseEstimateSpeed, projectLayout, projectQualifiers, qualifierStringKey, resolveSceneRef, sceneAddressIndex, sceneFolderLayout, sceneFolderPath, speakerLabelKey, textIsAction, usedQualifiers, usedSpeakerPairs, walkNodes };