Implemented voice-over subtitle synchronization

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@565 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
ghaushe
2003-01-18 23:08:39 +00:00
parent f585650073
commit 2975dd0e52
40 changed files with 3663 additions and 96 deletions
+46 -10
View File
@@ -1945,9 +1945,10 @@ RaceCommunication (void)
}
int
do_subtitles (UNICODE *pStr)
do_subtitles (UNICODE *pStr, UNICODE *pTimeStamp)
{
static DWORD TimeOut;
static unsigned long *cur_sub_ts;
// TODO: proper disabling of subtitles, this one prolly isn't 'safe'
if (optSubtitles == FALSE)
@@ -1981,6 +1982,8 @@ do_subtitles (UNICODE *pStr)
UNICODE ch;
COUNT numchars;
static UNICODE alien_phrase_buf[4096];
UNICODE *s;
static unsigned long subtitle_frames_ts[50];
CommData.AlienTextTemplate.pStr = alien_phrase_buf;
numchars = 0;
@@ -2001,6 +2004,27 @@ do_subtitles (UNICODE *pStr)
numchars += 6;
}
} while ((*CommData.AlienTextTemplate.pStr++ = ch));
if (s = pTimeStamp)
{
int pos;
cur_sub_ts = subtitle_frames_ts;
while (*s && (pos = wstrcspn (s, ",")))
{
UNICODE valStr[10];
wstrncpy (valStr, s, pos);
valStr[pos] = '\0';
*cur_sub_ts++ = wstrtoul(valStr,NULL,10);
s += pos;
if (*s)
s++;
}
*cur_sub_ts = 0;
TimeOut = GetTimeCounter ();
}
else
subtitle_frames_ts[0] = 0;
cur_sub_ts = subtitle_frames_ts;
CommData.AlienTextTemplate.pStr = alien_phrase_buf;
CommData.AlienTextTemplate.CharCount = 0;
#if 0
@@ -2029,17 +2053,29 @@ do_subtitles (UNICODE *pStr)
CommData.AlienTextTemplate.CharCount = t.pStr - CommData.AlienTextTemplate.pStr;
read_speed = speed_array[GLOBAL (glob_flags) & READ_SPEED_MASK];
talk_length = ONE_SECOND * CommData.AlienTextTemplate.CharCount / MODERATE_SPEED;
if (read_speed)
if (*cur_sub_ts)
{
silence_length = ONE_SECOND
* (CommData.AlienTextTemplate.CharCount + MODERATE_SPEED) / read_speed;
if (silence_length < talk_length)
talk_length = silence_length;
silence_length -= talk_length;
// We found subtitle timestamps, let's use them
// timestamps are stored as time per frame in milliseconds
talk_length = *cur_sub_ts++ * ONE_SECOND /1000;
silence_length = 0;
TimeOut += talk_length;
//sprintf (stderr, "Sound length is %d\n", talk_length);
}
else
{
read_speed = speed_array[GLOBAL (glob_flags) & READ_SPEED_MASK];
talk_length = ONE_SECOND * CommData.AlienTextTemplate.CharCount / MODERATE_SPEED;
if (read_speed)
{
silence_length = ONE_SECOND
* (CommData.AlienTextTemplate.CharCount + MODERATE_SPEED) / read_speed;
if (silence_length < talk_length)
talk_length = silence_length;
silence_length -= talk_length;
}
TimeOut = GetTimeCounter () + talk_length;
}
TimeOut = GetTimeCounter () + talk_length;
subtitle_state = SPACE_SUBTITLE;
break;
}
+6 -2
View File
@@ -25,7 +25,7 @@ void
NPCPhrase (int index)
{
UNICODE *pStr, numbuf[100];
void *pClip;
void *pClip, *pTimeStamp;
switch (index)
{
@@ -74,6 +74,7 @@ NPCPhrase (int index)
}
pStr = numbuf;
pClip = 0;
pTimeStamp = 0;
}
else
{
@@ -83,11 +84,14 @@ NPCPhrase (int index)
pClip = GetStringSoundClip (
SetAbsStringTableIndex (CommData.ConversationPhrases, index - 1)
);
pTimeStamp = GetStringTimeStamp (
SetAbsStringTableIndex (CommData.ConversationPhrases, index - 1)
);
}
break;
}
SpliceTrack (pClip, pStr);
SpliceTrack (pClip, pStr, pTimeStamp);
}
void
+2
View File
@@ -802,6 +802,8 @@ extern void RetrieveStarMap (void);
#define wstrupr strupr
#define wstrncpy strncpy
#define wstricmp stricmp
#define wstrtoul strtoul
#define wstrcspn strcspn
#endif /* _GLOBDATA_H */
@@ -23,7 +23,7 @@
#include "sound.h"
#include "libs/sound/trackplayer.h"
extern int do_subtitles (UNICODE *pStr);
extern int do_subtitles (UNICODE *pStr, UNICODE *TimeStamp);
static int tct, tcur, no_voice;
@@ -32,6 +32,7 @@ static struct
{
int text_spliced;
UNICODE *text;
UNICODE *timestamp;
TFB_SoundSample *sample;
} track_clip[MAX_CLIPS];
@@ -49,7 +50,7 @@ JumpTrack (int abort)
}
no_voice = 1;
do_subtitles ((void *)~0);
do_subtitles ((void *)~0, 0);
if (abort)
tcur = tct;
@@ -68,7 +69,7 @@ advance_track (int channel_finished)
PlayStream (track_clip[tcur].sample, SPEECH_SOURCE, AL_FALSE,
speechVolumeScale == 0.0f ? AL_FALSE : AL_TRUE);
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
do_subtitles (0);
do_subtitles (0, 0);
}
else if (channel_finished == 0)
{
@@ -115,8 +116,8 @@ PlayingTrack ()
{
if (tcur < tct)
{
if (do_subtitles (track_clip[tcur].text) ||
(no_voice && ++tcur < tct && do_subtitles (0)))
if (do_subtitles (track_clip[tcur].text, track_clip[tcur].timestamp) ||
(no_voice && ++tcur < tct && do_subtitles (0, 0)))
{
return (tcur + 1);
}
@@ -170,11 +171,11 @@ StopTrack ()
}
tct = tcur = 0;
no_voice = 0;
do_subtitles (0);
do_subtitles (0, 0);
}
void
SpliceTrack (UNICODE *TrackName, UNICODE *TrackText)
SpliceTrack (UNICODE *TrackName, UNICODE *TrackText, UNICODE *TimeStamp)
{
if (TrackText)
{
@@ -204,6 +205,7 @@ SpliceTrack (UNICODE *TrackName, UNICODE *TrackText)
track_clip[tct].text = TrackText;
track_clip[tct].text_spliced = 0;
track_clip[tct].timestamp = TimeStamp;
fprintf (stderr, "SpliceTrack(): loading %s\n", TrackName);
track_clip[tct].sample = (TFB_SoundSample *) HMalloc (sizeof (TFB_SoundSample));
+10 -7
View File
@@ -27,7 +27,7 @@
#define VOICE_CHANNEL 0
extern int do_subtitles (UNICODE *pStr);
extern int do_subtitles (UNICODE *pStr, UNICODE *pTimeStamp);
static int tct, tcur, no_voice;
#define MAX_CLIPS 50
@@ -35,6 +35,7 @@ static struct
{
int text_spliced;
UNICODE *text;
UNICODE *timestamp;
Mix_Chunk *chunk;
} track_clip[MAX_CLIPS];
@@ -47,7 +48,7 @@ JumpTrack (int abort)
Mix_HaltChannel (VOICE_CHANNEL);
no_voice = 1;
do_subtitles ((void *)~0);
do_subtitles ((void *)~0, 0);
if (abort)
tcur = tct;
@@ -63,7 +64,7 @@ advance_track (int channel_finished)
if (tcur < tct)
{
Mix_PlayChannel (VOICE_CHANNEL, track_clip[tcur].chunk, 0);
do_subtitles (0);
do_subtitles (0, 0);
}
else if (channel_finished == VOICE_CHANNEL)
{
@@ -94,8 +95,8 @@ PlayingTrack ()
{
if (tcur < tct)
{
if (do_subtitles (track_clip[tcur].text)
|| (no_voice && ++tcur < tct && do_subtitles (0)))
if (do_subtitles (track_clip[tcur].text, track_clip[tcur].timestamp)
|| (no_voice && ++tcur < tct && do_subtitles (0, 0)))
return (tcur + 1);
else if (track_clip[tcur].chunk)
return (Mix_Playing (VOICE_CHANNEL) ? (COUNT)(tcur + 1) : 0);
@@ -126,11 +127,11 @@ StopTrack ()
}
tct = tcur = 0;
no_voice = 0;
do_subtitles (0);
do_subtitles (0, 0);
}
void
SpliceTrack (UNICODE *TrackName, UNICODE *TrackText)
SpliceTrack (UNICODE *TrackName, UNICODE *TrackText, UNICODE *TimeStamp)
{
if (TrackText)
{
@@ -153,6 +154,7 @@ SpliceTrack (UNICODE *TrackName, UNICODE *TrackText)
track_clip[tct - 1].text_spliced = 1;
}
wstrcpy (&track_clip[tct - 1].text[slen1], TrackText);
track_clip[tct - 1].timestamp = 0;
}
}
else if (tct < MAX_CLIPS)
@@ -168,6 +170,7 @@ SpliceTrack (UNICODE *TrackName, UNICODE *TrackText)
track_clip[tct].text = TrackText;
track_clip[tct].text_spliced = 0;
track_clip[tct].timestamp = TimeStamp;
++tct;
}
}
+1 -1
View File
@@ -26,7 +26,7 @@ void JumpTrack(int abort);
void FastForward();
void FastReverse();
void StopTrack();
void SpliceTrack(UNICODE *filespec, UNICODE *textspec);
void SpliceTrack(UNICODE *filespec, UNICODE *textspec, UNICODE *TimeStamp);
int GetSoundData (void *data);
int GetSoundInfo (int *len, int *offs);
+150 -64
View File
@@ -54,11 +54,13 @@ _GetStringData (FILE *fp, DWORD length)
#ifdef WIN32
int omode;
#endif
int n, path_len;
int n, path_len, num_data_sets;
DWORD opos,
slen[MAX_STRINGS], StringOffs, tot_string_size,
clen[MAX_STRINGS], ClipOffs, tot_clip_size;
char CurrentLine[1024], clip_path[1024], *strdata, *clipdata;
clen[MAX_STRINGS], ClipOffs, tot_clip_size,
tslen[MAX_STRINGS], TSOffs, tot_ts_size;
char CurrentLine[1024], clip_path[1024], *strdata, *clipdata, *ts_data;
FILE *timestamp_fp = NULL;
if ((strdata = HMalloc (tot_string_size = POOL_SIZE)) == 0)
return (0);
@@ -86,12 +88,28 @@ _GetStringData (FILE *fp, DWORD length)
path_len = strlen (clip_path);
}
{
// try to open the timestamp file
char ts_file_name[1024];
strcpy (ts_file_name, _cur_resfile_name);
s = strrchr (ts_file_name, '.');
s += 2;
*s++ = 's';
*s = '\0';
if ((timestamp_fp = fopen (ts_file_name, "rb")))
{
fprintf (stderr, "Found timestamp file: %s\n", ts_file_name);
if ((ts_data = HMalloc (tot_ts_size = POOL_SIZE)) == 0)
return (0);
}
}
opos = ftell (fp);
#ifdef WIN32
omode = _setmode (fileno (fp), O_TEXT);
#endif
n = -1;
StringOffs = ClipOffs = 0;
StringOffs = ClipOffs = TSOffs = 0;
while (fgets (CurrentLine, sizeof (CurrentLine), fp) && n < MAX_STRINGS - 1)
{
int l;
@@ -115,6 +133,48 @@ _GetStringData (FILE *fp, DWORD length)
}
slen[++n] = 0;
// now lets check for timestamp data
if (timestamp_fp)
{
char TimeStampLine[1024], *tsptr;
BOOLEAN ts_ok = FALSE;
fgets (TimeStampLine, sizeof (TimeStampLine), timestamp_fp);
if (TimeStampLine[0] == '#')
{
tslen[n] = 0;
if ((tsptr = strstr (TimeStampLine,s))
&& (tsptr += strlen(s))
&& (++tsptr))
{
ts_ok = TRUE;
while (! strcspn(tsptr," \t\n") && *tsptr)
tsptr++;
if (*tsptr)
{
l = strlen (tsptr) + 1;
if (TSOffs + l > tot_ts_size
&& (ts_data = HRealloc (ts_data,
tot_ts_size += POOL_SIZE)) == 0)
{
HFree (strdata);
return (0);
}
strcpy (&ts_data[TSOffs], tsptr);
TSOffs += l;
tslen[n] = l;
}
}
}
if (! ts_ok)
{
// timestamp data is invalid, remove all of it
fprintf (stderr, "Invalid timestamp data for '%s'. Disabling timestamps\n", s);
HFree (ts_data);
fclose (timestamp_fp);
timestamp_fp = NULL;
TSOffs = 0;
}
}
clen[n] = 0;
s = strtok (NULL, " \t\n)");
if (s)
@@ -142,82 +202,108 @@ _GetStringData (FILE *fp, DWORD length)
&& (strdata = HRealloc (strdata,
tot_string_size += POOL_SIZE)) == 0)
{
HFree (clipdata);
return (0);
HFree (clipdata);
return (0);
}
if (slen[n])
{
--slen[n];
--StringOffs;
}
s = &strdata[StringOffs];
slen[n] += l;
StringOffs += l;
strcpy (s, CurrentLine);
}
if (slen[n])
if ((int)ftell (fp) - (int)opos >= (int)length)
break;
}
#ifdef WIN32
_setmode (fileno (fp), omode);
#endif
if (n >= 0)
{
while (slen[n] > 1 && strdata[StringOffs - 2] == '\n')
{
--slen[n];
--StringOffs;
strdata[StringOffs - 1] = '\0';
}
s = &strdata[StringOffs];
slen[n] += l;
StringOffs += l;
strcpy (s, CurrentLine);
}
if ((int)ftell (fp) - (int)opos >= (int)length)
break;
}
#ifdef WIN32
_setmode (fileno (fp), omode);
#endif
if (n >= 0)
{
while (slen[n] > 1 && strdata[StringOffs - 2] == '\n')
if (timestamp_fp)
fclose (timestamp_fp);
hData = 0;
num_data_sets = (ClipOffs ? 1 : 0) + (TSOffs ? 1 : 0) + 1;
if (++n && (hData = AllocStringTable (
(sizeof (STRING_TABLE_DESC) - sizeof (DWORD))
+ (sizeof (DWORD) * ((n + 1) * num_data_sets))
+ StringOffs
+ ClipOffs
+ TSOffs
)))
{
--slen[n];
--StringOffs;
strdata[StringOffs - 1] = '\0';
}
}
PDWORD lpStringOffs, lpClipOffs, lpTSOffs;
STRING_TABLEPTR lpST;
hData = 0;
if (++n && (hData = AllocStringTable (
(sizeof (STRING_TABLE_DESC) - sizeof (DWORD))
+ (sizeof (DWORD) * ((n + 1) << (ClipOffs ? 1 : 0)))
+ StringOffs
+ ClipOffs
)))
{
PDWORD lpStringOffs, lpClipOffs;
STRING_TABLEPTR lpST;
LockStringTable (hData, &lpST);
lpST->StringCount = n;
lpST->flags = 0;
if (ClipOffs)
lpST->flags |= HAS_SOUND_CLIPS;
if (TSOffs)
lpST->flags |= HAS_TIMESTAMP;
LockStringTable (hData, &lpST);
lpST->StringCount = n;
lpST->flags = 0;
if (ClipOffs)
lpST->flags |= HAS_SOUND_CLIPS;
memcpy (&lpST->StringOffsets[(n + 1) * num_data_sets], strdata, StringOffs);
memcpy ((BYTE *)&lpST->StringOffsets[(n + 1) * num_data_sets] + StringOffs,
clipdata, ClipOffs);
memcpy ((BYTE *)&lpST->StringOffsets[(n + 1) * num_data_sets]
+ StringOffs + ClipOffs, ts_data, TSOffs);
TSOffs = ((BYTE *)&lpST->StringOffsets[(n + 1) * num_data_sets]
- (BYTE *)lpST) + StringOffs + ClipOffs;
ClipOffs = TSOffs - ClipOffs;
StringOffs = ClipOffs - StringOffs;
memcpy (&lpST->StringOffsets[(n + 1) << (ClipOffs ? 1 : 0)], strdata, StringOffs);
memcpy ((BYTE *)&lpST->StringOffsets[(n + 1) << (ClipOffs ? 1 : 0)] + StringOffs,
clipdata, ClipOffs);
ClipOffs = ((BYTE *)&lpST->StringOffsets[(n + 1) << (ClipOffs ? 1 : 0)]
- (BYTE *)lpST) + StringOffs;
StringOffs = ClipOffs - StringOffs;
for (n = 0, lpStringOffs = lpST->StringOffsets,
lpClipOffs = &lpST->StringOffsets[lpST->StringCount + 1];
n < (int)lpST->StringCount; ++n, ++lpStringOffs, ++lpClipOffs)
{
*lpStringOffs = StringOffs;
StringOffs += slen[n];
if (lpST->flags & HAS_SOUND_CLIPS)
lpStringOffs = lpST->StringOffsets;
lpClipOffs = &lpST->StringOffsets[lpST->StringCount + 1];
{
*lpClipOffs = ClipOffs;
ClipOffs += clen[n];
long foo = (lpST->StringCount + 1) << ((lpST->flags & HAS_SOUND_CLIPS) ? 1 : 0);
}
lpTSOffs = &lpST->StringOffsets[(lpST->StringCount + 1)
<< ((lpST->flags & HAS_SOUND_CLIPS) ? 1 : 0)];
for (n = 0; n < (int)lpST->StringCount;
++n, ++lpStringOffs, ++lpClipOffs, ++lpTSOffs)
{
*lpStringOffs = StringOffs;
StringOffs += slen[n];
if (lpST->flags & HAS_SOUND_CLIPS)
{
*lpClipOffs = ClipOffs;
ClipOffs += clen[n];
}
if (lpST->flags & HAS_TIMESTAMP)
{
*lpTSOffs = TSOffs;
TSOffs += tslen[n];
}
}
*lpStringOffs = StringOffs;
if (lpST->flags & HAS_SOUND_CLIPS)
*lpClipOffs = ClipOffs;
if (lpST->flags & HAS_TIMESTAMP)
*lpTSOffs = TSOffs;
UnlockStringTable (hData);
}
*lpStringOffs = StringOffs;
if (lpST->flags & HAS_SOUND_CLIPS)
*lpClipOffs = ClipOffs;
UnlockStringTable (hData);
}
HFree (strdata);
HFree (strdata);
HFree (clipdata);
HFree (ts_data);
return (hData);
}
+33
View File
@@ -185,6 +185,39 @@ GetStringSoundClip (STRING String)
return (StringAddr);
}
STRINGPTR
GetStringTimeStamp (STRING String)
{
STRINGPTR StringAddr;
STRING_TABLE StringTable;
if ((StringTable = GetStringTable (String)) == 0)
StringAddr = 0;
else
{
COUNT StringIndex;
STRING_TABLEPTR StringTablePtr;
int offset;
StringIndex = STRING_INDEX (String);
LockStringTable (StringTable, &StringTablePtr);
offset = (StringTablePtr->flags & HAS_SOUND_CLIPS) ? 1 : 0;
if (!(StringTablePtr->flags & HAS_TIMESTAMP)
|| ((StringIndex += (StringTablePtr->StringCount + 1) << offset),
StringTablePtr->StringOffsets[StringIndex + 1]
== StringTablePtr->StringOffsets[StringIndex]))
StringAddr = 0;
else
{
StringAddr = (STRINGPTR)StringTablePtr;
((BYTE *) StringAddr) += StringTablePtr->StringOffsets[StringIndex];
}
UnlockStringTable (StringTable);
}
return (StringAddr);
}
STRINGPTR
GetStringAddress (STRING String)
{
+1
View File
@@ -34,6 +34,7 @@ typedef struct string_table
typedef STRING_TABLE_DESC *PSTRING_TABLE_DESC;
#define HAS_SOUND_CLIPS (1 << 0)
#define HAS_TIMESTAMP (1 << 1)
#define STRING_TABLEPTR PSTRING_TABLE_DESC
#define AllocStringTable(s) AllocResourceData((s),MEM_SOUND)
+1
View File
@@ -41,6 +41,7 @@ extern STRING SetRelStringTableIndex (STRING String, SIZE
extern COUNT GetStringLength (STRING String);
extern STRINGPTR GetStringAddress (STRING String);
extern STRINGPTR GetStringSoundClip (STRING String);
extern STRINGPTR GetStringTimeStamp (STRING String);
extern BOOLEAN GetStringContents (STRING String, STRINGPTR StringBuf,
BOOLEAN AppendSpace);
+6
View File
@@ -61,6 +61,12 @@ CDToContentDir (char *contentdir)
static int
Check_PC_3DO_opt (char *value, DWORD mask, char *opt)
{
if (value == NULL)
{
fprintf (stderr, "option '%s' requires a value!\n",opt);
return -1;
}
if ((mask & OPT_3DO) && strcmp (value, "3do") == 0)
return OPT_3DO;
if ((mask & OPT_PC) && strcmp (value, "pc") == 0)