-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTotalLipSync.ash
143 lines (137 loc) · 7.35 KB
/
TotalLipSync.ash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// TOTAL LIP SYNC MODULE - Header
// by Gunnar Harboe (Snarky), v0.6
//
// Description:
// This module enables speech-based lip sync animation for any speech mode (while the AGS built-in
// speech-based lip sync does not currently work for LucasArts-style speech), and supports a number of
// different file formats for the lip sync data files.
//
// Use:
// You need to generate and edit the synchronization data in an external application (see below),
// or with the AGS Lip Sync Manager plugin. This module then reads the data files created and plays
// back the animation in sync with the audio.
//
// To lip sync a character, give them a speech view where each frame has the mouth position
// for a particular sound (a "phoneme"). Frame 0 should be the "no sound"/"mouth closed" frame.
// Then set up the module to define the mapping from phonemes to frames. This is done similarly to
// the built-in speech-based lip sync described in the manual.
//
// When using this module, the built-in AGS lip sync should be set to "disabled".
//
// Configure the module on startup - for example:
//
// function game_start()
// {
// TotalLipSync.Init(eLipSyncPamelaIgnoreStress);
// TotalLipSync.AddPhonemeMappings("None",0);
// TotalLipSync.AddPhonemeMappings("AY/AA/AH/AE",1);
// TotalLipSync.AddPhonemeMappings("W/OW/OY/UW",2);
// // etc.
// }
//
// A default mapping for each format is also provided, and can be activated with:
//
// TotalLipSync.AutoMapPhonemes();
//
// To use lip sync, simply call the function Character.SaySync(String message) with a speech clip
// prefix - for example:
//
// function cOceanSpiritDennis_Interact()
// {
// cOceanSpiritDennis.SaySync("&13 No touching, or it's FIGHTS!");
// }
//
// This will play speech file number 13, and (given the configuration settings above) lip sync the
// speech animation according to the data in the file ocea13.pam in the game installation directory.
// There's also Character.SayAtSync(), which works like Character.SayAt().
//
//
//
// The file formats supported by this module are:
//
// Pamela (.pam):
// This format is produced by PAMELA and the AGS Lip Sync Manager plugin.
// http://www-personal.monash.edu.au/~myless/catnap/pamela/
// http://www.adventuregamestudio.co.uk/forums/index.php?topic=37792.0
//
// Moho Switch (.dat)
// This format is used by Papagayo; PAMELA and other applications can also export to it.
// http://www.lostmarble.com/papagayo/
//
// Annosoft (.anno)
// This is the format used by SAPI 5.1 Lipsync.
// http://www.annosoft.com/sapi_lipsync/docs/index.html
//
// Rhubarb Lip-Sync (.tsv)
// This is one format used by Rhubarb Lip-Sync, a tool developed for lip-syncing 'Thimbleweed Park'.
// https://github.com/DanielSWolf/rhubarb-lip-sync
//
//
//
// This work is licensed under a Creative Commons Attribution 4.0 International License.
// https://creativecommons.org/licenses/by/4.0/
//
// It is based on code by Steven Poulton (Calin Leafshade):
// http://www.adventuregamestudio.co.uk/forums/index.php?topic=36284.msg554642#msg554642
//
// And on AGS engine code:
// https://github.com/adventuregamestudio/ags/
// ags/Editor/AGS.Editor/Components/SpeechComponent.cs
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////
/// The format of lip sync data files to parse
enum TotalLipSyncFileFormat
{
/// Lip sync data in Pamela format, distinguishing vowel stress (.pam files)
eLipSyncPamelaStressed,
/// Lip sync data in Pamela format, ignoring vowel stress (.pam files)
eLipSyncPamelaIgnoreStress,
/// Lip sync data in Moho Switch format (used by e.g. Papagayo; .dat files)
eLipSyncMoho,
/// Lip sync data in Anno format (used by SAPI 5.1 Lipsync; .anno files)
eLipSyncAnno,
/// Lip sync data in Rhubarb format (.tsv files)
eLipSyncRhubarb
};
enum Casing
{
eCasingLowerCase = -1,
eCasingDefaultCase,
eCasingUpperCase
};
struct TotalLipSync
{
/// Initializes TotalLipSync. This method should be called on startup.
import static void Init(TotalLipSyncFileFormat lipSyncFormat, String fileExtension=0);
/// Sets the directory to read the lip sync data files from. Default "$DATA$/sync" (a /sync/ folder packaged as custom data) in AGS 3.6.0+, or "$INSTALLDATA$/sync" in older versions
import static void SetDataDirectory(String dataDirectory);
/// Sets the file extension of the data files. Default depends on the lipSyncFormat set with TotalLipSync.Init()
import static void SetFileExtension(String fileExtension);
/// Sets the casing (capitalization) to use for the sync filenames. Default eCasingDefaultCase
import static void SetFileCasing(Casing fileCasing);
/// Sets the frame rate of the lip sync data file. Used by Pamela and Moho formats. Default 24
import static void SetDataFileFrameRate(int frameRate);
/// Sets a dummy view that is used to enable Sierra lip sync. This view must have exactly 1 loop and 1 frame, and should not be used for anything else (since it will be overwritten by this module).
import static void SetSierraDummyView(int viewNumber);
/// Sets the frame number to display when undefined in the sync file. (Typically corresponds to silence.) Default 0
import static void SetDefaultFrame(int frameNumber);
/// Sets up a default mapping of phonemes to animation frames, according to the lipSyncFormat set with TotalLipSync.Init()
import static void AutoMapPhonemes();
/// Adds a mapping from a phoneme to an animation frame that will be displayed for this phoneme. Phonemes are case-insensitive.
import static void AddPhonemeMapping(String phoneme, int frame);
/// Adds mappings from a set of phonemes to an animation frame that will be displayed for those phonemes, separated by a slash '/'. Phonemes are case-insensitive.
import static void AddPhonemeMappings(String phonemes, int frame);
/// Clears all phoneme mappings.
import static void ClearPhonemeMappings();
/// Returns the character that is currently being lip synced, or null if none.
import static Character* GetCurrentLipSyncingCharacter();
/// Returns the phoneme code that is currently active (i.e. the phoneme being spoken at this time). If lip sync not currently running, null. If running but no phoneme set yet, "".
import static String GetCurrentPhoneme();
/// Returns the animation frame (i.e. the mouth shape) that is currently being displayed. -1 if no character is currently being lip synced.
import static int GetCurrentFrame();
};
/// Says the specified text using the character's speech settings, while playing a speech-based lip-sync animation. The line must have a speech clip prefix ("&N " where N is the number of the speech file), and there must be a matching lip-sync data file in the data directory.
import void SaySync(this Character*, String message);
/// Says the specified text at the specified position of the screen using the character's speech settings, while playing a speech-based lip-sync animation. The line must have a speech clip prefix ("&N " where N is the number of the speech file), and there must be a matching lip-sync data file in the data directory.
import void SayAtSync(this Character*, int x, int y, int width, String message);