@patterkit/model 0.25.0 → 0.27.0

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,33 +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
- /** One unit of a line as it would be spoken. `start` and `end` are code-point offsets into the text, end exclusive. */
8
- interface SpeechUnit {
9
- kind: SpeechUnitKind;
10
- weight: number;
11
- start: number;
12
- end: number;
13
- }
14
- /** A digit's weight: most read as one or two syllables. */
15
- declare const SPEECH_DIGIT_WEIGHT = 1.5;
16
- /** A Han character's weight in Japanese text. */
17
- declare const SPEECH_KANJI_WEIGHT = 2;
18
- /** A short pause's weight (`,` `;` `、`), and a long one's (`.` `?` `。`). */
19
- declare const SPEECH_PAUSE_SHORT_WEIGHT = 1;
20
- declare const SPEECH_PAUSE_LONG_WEIGHT = 2;
21
- /**
22
- * A line broken into the units it would be spoken in: its syllables, its beats with the mouth shut, and its pauses,
23
- * in order, each with a weight. `locale` is the language the line is spoken in (the project's main language, not the
24
- * one being shown); it decides English's and French's silent e, and Japanese kanji, which also apply when the line
25
- * has any kana in it.
26
- */
27
- declare function speechUnits(text: string, locale?: string): SpeechUnit[];
28
- /** How many syllables a line would be spoken in: its syllables' and shut beats' weights, pauses aside. `locale` is
29
- * the language it's spoken in, as for `speechUnits`. */
30
- declare function countSyllables(text: string, locale?: string): number;
31
-
32
5
  type ScalarValue = boolean | number | string | string[];
33
6
  /** Developer-defined host metadata (spec §17). Opaque to Patter. */
34
7
  type GameData = Record<string, unknown>;
@@ -458,11 +431,13 @@ declare const DEFAULT_PAD_AFTER = 0.6;
458
431
  /** The range validation keeps a `padAfter` or `padAfterDefault` within, in seconds. */
459
432
  declare const PAD_AFTER_MIN = -10;
460
433
  declare const PAD_AFTER_MAX = 60;
461
- /** How many syllables a second a line with no recording is timed at, unless the project sets its own
462
- * (`estimateSyllablesPerSecond`), and the range validation keeps a project's within. */
463
- declare const DEFAULT_ESTIMATE_SYLLABLES_PER_SECOND = 4;
464
- declare const ESTIMATE_SYLLABLES_PER_SECOND_MIN = 2;
465
- 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;
466
441
  /** The shortest and longest a line with no recording lasts, in seconds (`estimateLineDuration`). The shortest is a
467
442
  * speaking time, the least a spoken word plausibly takes, not a reading time: see SUBTITLE_READING_MIN. */
468
443
  declare const LINE_DURATION_MIN = 0.5;
@@ -471,14 +446,26 @@ declare const LINE_DURATION_MAX = 18;
471
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
472
447
  * line ends, overlapping the next if it must. The line itself still ends when it's said (`estimateLineDuration`). */
473
448
  declare const SUBTITLE_READING_MIN = 1.5;
474
- /** How long a line with no recording lasts, in seconds: the total weight of its speech units (its syllables and its
475
- * pauses, `speechUnits`) at `syllablesPerSecond` (default 4, the project's `estimateSyllablesPerSecond` when it
476
- * sets one), clamped to 0.5 to 18 seconds. `text` and `locale` are the line as it's spoken, in the project's main
477
- * language (a line result's `spokenText` and `spokenLocale`), never a translation being shown. This is the one
478
- * rule every Patter tool and runtime times a line by: Patterpad's Play window, the playable HTML page, and the
479
- * Unity, Unreal, and Godot runtimes, which the conformance corpus holds to the same numbers. A rate that isn't a
480
- * positive number is the default. A line with a recording lasts as long as the recording, whatever this says. */
481
- 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;
482
469
  /** A qualifier as it reaches a compiled bundle: its `gameId` and authored name (the unlocalised fallback). */
483
470
  interface BundleQualifier {
484
471
  gameId: string;
@@ -787,10 +774,11 @@ interface ProjectFile {
787
774
  /** The project's default `padAfter` for every line and text beat that sets none and has no default above it.
788
775
  * Absent = `DEFAULT_PAD_AFTER`. */
789
776
  padAfterDefault?: number;
790
- /** How many syllables a second a line with no recording is timed at (`estimateLineDuration`), from 2 to 10.
791
- * Only estimates use it: a line with a recording lasts as long as the recording. Absent =
792
- * `DEFAULT_ESTIMATE_SYLLABLES_PER_SECOND`. */
793
- 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;
794
782
  /** Localise text lines in dialogue scenes (design/proposals/action-text.md). Off (absent) by default: a
795
783
  * dialogue scene's text beats (`isDialogueScene`) are then ACTION, left out of the loc files and the
796
784
  * written word counts, and compiled with `action: true`. On: they're localised and shown as a text
@@ -1207,9 +1195,8 @@ interface Bundle {
1207
1195
  speakerPattern?: string;
1208
1196
  /** The project's own `padAfterDefault`, when it sets one; absent = `DEFAULT_PAD_AFTER`. */
1209
1197
  padAfterDefault?: number;
1210
- /** The project's own `estimateSyllablesPerSecond`, when it sets one; absent =
1211
- * `DEFAULT_ESTIMATE_SYLLABLES_PER_SECOND`. */
1212
- estimateSyllablesPerSecond?: number;
1198
+ /** The project's own `estimateSpeed`, when it sets one; absent = `DEFAULT_ESTIMATE_SPEED`. */
1199
+ estimateSpeed?: number;
1213
1200
  properties?: PropertyDecl[];
1214
1201
  /** Host / world scope declarations, baked from the project so the runtime can self-back a declared
1215
1202
  * scope (`@world`, ...) when no host resolver claims its token. Absent = no host scopes. */
@@ -1504,4 +1491,4 @@ interface ExtensionFieldDecl {
1504
1491
  /** A node's extension values in a bundle: extension id -> field -> value, raw. */
1505
1492
  type NodeExtensions = Record<string, Record<string, unknown>>;
1506
1493
 
1507
- 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 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,33 +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
- /** One unit of a line as it would be spoken. `start` and `end` are code-point offsets into the text, end exclusive. */
8
- interface SpeechUnit {
9
- kind: SpeechUnitKind;
10
- weight: number;
11
- start: number;
12
- end: number;
13
- }
14
- /** A digit's weight: most read as one or two syllables. */
15
- declare const SPEECH_DIGIT_WEIGHT = 1.5;
16
- /** A Han character's weight in Japanese text. */
17
- declare const SPEECH_KANJI_WEIGHT = 2;
18
- /** A short pause's weight (`,` `;` `、`), and a long one's (`.` `?` `。`). */
19
- declare const SPEECH_PAUSE_SHORT_WEIGHT = 1;
20
- declare const SPEECH_PAUSE_LONG_WEIGHT = 2;
21
- /**
22
- * A line broken into the units it would be spoken in: its syllables, its beats with the mouth shut, and its pauses,
23
- * in order, each with a weight. `locale` is the language the line is spoken in (the project's main language, not the
24
- * one being shown); it decides English's and French's silent e, and Japanese kanji, which also apply when the line
25
- * has any kana in it.
26
- */
27
- declare function speechUnits(text: string, locale?: string): SpeechUnit[];
28
- /** How many syllables a line would be spoken in: its syllables' and shut beats' weights, pauses aside. `locale` is
29
- * the language it's spoken in, as for `speechUnits`. */
30
- declare function countSyllables(text: string, locale?: string): number;
31
-
32
5
  type ScalarValue = boolean | number | string | string[];
33
6
  /** Developer-defined host metadata (spec §17). Opaque to Patter. */
34
7
  type GameData = Record<string, unknown>;
@@ -458,11 +431,13 @@ declare const DEFAULT_PAD_AFTER = 0.6;
458
431
  /** The range validation keeps a `padAfter` or `padAfterDefault` within, in seconds. */
459
432
  declare const PAD_AFTER_MIN = -10;
460
433
  declare const PAD_AFTER_MAX = 60;
461
- /** How many syllables a second a line with no recording is timed at, unless the project sets its own
462
- * (`estimateSyllablesPerSecond`), and the range validation keeps a project's within. */
463
- declare const DEFAULT_ESTIMATE_SYLLABLES_PER_SECOND = 4;
464
- declare const ESTIMATE_SYLLABLES_PER_SECOND_MIN = 2;
465
- 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;
466
441
  /** The shortest and longest a line with no recording lasts, in seconds (`estimateLineDuration`). The shortest is a
467
442
  * speaking time, the least a spoken word plausibly takes, not a reading time: see SUBTITLE_READING_MIN. */
468
443
  declare const LINE_DURATION_MIN = 0.5;
@@ -471,14 +446,26 @@ declare const LINE_DURATION_MAX = 18;
471
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
472
447
  * line ends, overlapping the next if it must. The line itself still ends when it's said (`estimateLineDuration`). */
473
448
  declare const SUBTITLE_READING_MIN = 1.5;
474
- /** How long a line with no recording lasts, in seconds: the total weight of its speech units (its syllables and its
475
- * pauses, `speechUnits`) at `syllablesPerSecond` (default 4, the project's `estimateSyllablesPerSecond` when it
476
- * sets one), clamped to 0.5 to 18 seconds. `text` and `locale` are the line as it's spoken, in the project's main
477
- * language (a line result's `spokenText` and `spokenLocale`), never a translation being shown. This is the one
478
- * rule every Patter tool and runtime times a line by: Patterpad's Play window, the playable HTML page, and the
479
- * Unity, Unreal, and Godot runtimes, which the conformance corpus holds to the same numbers. A rate that isn't a
480
- * positive number is the default. A line with a recording lasts as long as the recording, whatever this says. */
481
- 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;
482
469
  /** A qualifier as it reaches a compiled bundle: its `gameId` and authored name (the unlocalised fallback). */
483
470
  interface BundleQualifier {
484
471
  gameId: string;
@@ -787,10 +774,11 @@ interface ProjectFile {
787
774
  /** The project's default `padAfter` for every line and text beat that sets none and has no default above it.
788
775
  * Absent = `DEFAULT_PAD_AFTER`. */
789
776
  padAfterDefault?: number;
790
- /** How many syllables a second a line with no recording is timed at (`estimateLineDuration`), from 2 to 10.
791
- * Only estimates use it: a line with a recording lasts as long as the recording. Absent =
792
- * `DEFAULT_ESTIMATE_SYLLABLES_PER_SECOND`. */
793
- 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;
794
782
  /** Localise text lines in dialogue scenes (design/proposals/action-text.md). Off (absent) by default: a
795
783
  * dialogue scene's text beats (`isDialogueScene`) are then ACTION, left out of the loc files and the
796
784
  * written word counts, and compiled with `action: true`. On: they're localised and shown as a text
@@ -1207,9 +1195,8 @@ interface Bundle {
1207
1195
  speakerPattern?: string;
1208
1196
  /** The project's own `padAfterDefault`, when it sets one; absent = `DEFAULT_PAD_AFTER`. */
1209
1197
  padAfterDefault?: number;
1210
- /** The project's own `estimateSyllablesPerSecond`, when it sets one; absent =
1211
- * `DEFAULT_ESTIMATE_SYLLABLES_PER_SECOND`. */
1212
- estimateSyllablesPerSecond?: number;
1198
+ /** The project's own `estimateSpeed`, when it sets one; absent = `DEFAULT_ESTIMATE_SPEED`. */
1199
+ estimateSpeed?: number;
1213
1200
  properties?: PropertyDecl[];
1214
1201
  /** Host / world scope declarations, baked from the project so the runtime can self-back a declared
1215
1202
  * scope (`@world`, ...) when no host resolver claims its token. Absent = no host scopes. */
@@ -1504,4 +1491,4 @@ interface ExtensionFieldDecl {
1504
1491
  /** A node's extension values in a bundle: extension id -> field -> value, raw. */
1505
1492
  type NodeExtensions = Record<string, Record<string, unknown>>;
1506
1493
 
1507
- 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 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 };