Initial code for voice synchronization.
git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@566 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -0,0 +1,480 @@
|
||||
//
|
||||
//
|
||||
// Ur-Quan Masters Voice-over / Subtitle Synchronization tool
|
||||
// Copyright 2003 by Geoffrey Hausheer
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Library General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Library General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
// USA.
|
||||
//
|
||||
// contact tcpaiqgvnmbf28f001@sneakemail.com for bugs/issues
|
||||
//
|
||||
#define SYNC_VER "0.12"
|
||||
#define SKIP_SINGLE_LINES
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#ifdef WIN32
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#define MKDIR mkdir
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#define MKDIR(dir) mkdir((dir), 0777)
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#define SYNC_EXTRA_VER "Linux"
|
||||
#elif defined WIN32
|
||||
#define SYNC_EXTRA_VER "Windows"
|
||||
#else
|
||||
#define SYNC_EXTRA_VER "Unknown"
|
||||
#endif
|
||||
#include <math.h>
|
||||
#include <vorbis/codec.h>
|
||||
#include <vorbis/vorbisfile.h>
|
||||
|
||||
#include <FL/Fl.H>
|
||||
#include <FL/fl_ask.H>
|
||||
#include "synchronizer.h"
|
||||
|
||||
#include "synch.h"
|
||||
|
||||
#define WRAP_LEN 50
|
||||
|
||||
const char races[][13] = {
|
||||
"arilou",
|
||||
"blackur",
|
||||
"chmmr",
|
||||
"comandr",
|
||||
"druuge",
|
||||
"ilwrath",
|
||||
"melnorm",
|
||||
"mycon",
|
||||
"orz",
|
||||
"pkunk",
|
||||
"rebel",
|
||||
"shofixt",
|
||||
"slyhome",
|
||||
"slyland",
|
||||
"spahome",
|
||||
"spathi",
|
||||
"starbas",
|
||||
"supox",
|
||||
"syreen",
|
||||
"talkpet",
|
||||
"thradd",
|
||||
"umgah",
|
||||
"urquan",
|
||||
"utwig",
|
||||
"vux",
|
||||
"yehat",
|
||||
"zoqfot",
|
||||
""
|
||||
};
|
||||
|
||||
FILEDATA *curtrack, *racedata[MAX_TRACKS];
|
||||
CLIPTXTDATA *playing_clip;
|
||||
XTRATRACKDATA *trackxtra;
|
||||
Synchronizer *synch;
|
||||
WAVESTRUCT *WaveData;
|
||||
|
||||
char path[80];
|
||||
char savepath[80] = ".";
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv) {
|
||||
int i = 0;
|
||||
synch = new Synchronizer;
|
||||
trackxtra = new XTRATRACKDATA;
|
||||
init_sound ();
|
||||
//Initial global objects.
|
||||
while (strlen(races[i]))
|
||||
{
|
||||
synch->RaceChooser->add (races[i], (void *)i);
|
||||
i++;
|
||||
}
|
||||
|
||||
synch->show(argc, argv);
|
||||
|
||||
return Fl::run();
|
||||
}
|
||||
|
||||
void CleanUp()
|
||||
{
|
||||
int i;
|
||||
int max = synch->TrackSelector->nitems();
|
||||
|
||||
for (i=0;i<max;i++)
|
||||
if (racedata[i])
|
||||
delete racedata[i];
|
||||
}
|
||||
void DoExit()
|
||||
{
|
||||
reset_sound (WaveData);
|
||||
CleanUp();
|
||||
exit(0);
|
||||
}
|
||||
void DeactivateOptions()
|
||||
{
|
||||
synch->TrackSelector->deactivate();
|
||||
synch->RaceChooser->deactivate();
|
||||
synch->ChooseAllButton->deactivate();
|
||||
synch->ClearAllButton->deactivate();
|
||||
}
|
||||
void ActivateOptions()
|
||||
{
|
||||
synch->TrackSelector->activate();
|
||||
synch->RaceChooser->activate();
|
||||
synch->ChooseAllButton->activate();
|
||||
synch->ClearAllButton->activate();
|
||||
}
|
||||
|
||||
void PrintFrameNum ()
|
||||
{
|
||||
char buf[20];
|
||||
sprintf(buf,"%d of %d",playing_clip->frame_num, curtrack->num_lines);
|
||||
synch->CurrentFrame->value(buf);
|
||||
}
|
||||
|
||||
void UpdatePlayTime (int start)
|
||||
{
|
||||
int i, max, mins, secs;
|
||||
unsigned long tracktime = 0;
|
||||
char buf[20];
|
||||
max = synch->TrackSelector->nitems();
|
||||
for (i= start; i <= max; i++)
|
||||
if (synch->TrackSelector->checked(i))
|
||||
tracktime += racedata[i-1]->tracktime;
|
||||
mins = tracktime / 60;
|
||||
secs = tracktime - 60 * mins;
|
||||
sprintf (buf,"%d:%02d",mins,secs);
|
||||
synch->PlayTime->value(buf);
|
||||
}
|
||||
|
||||
void StopPlayback ()
|
||||
{
|
||||
reset_sound (WaveData);
|
||||
WaveData=NULL;
|
||||
trackxtra->tracknum = 0;
|
||||
ActivateOptions();
|
||||
}
|
||||
|
||||
void StartPlayback ()
|
||||
{
|
||||
int i, start, max;
|
||||
max = synch->TrackSelector->nitems();
|
||||
if (! trackxtra->tracknum)
|
||||
{
|
||||
start = 1;
|
||||
} else {
|
||||
start = trackxtra->tracknum + 1;
|
||||
}
|
||||
trackxtra->tracknum = 0;
|
||||
for (i=start; i<= max; i++) {
|
||||
if (synch->TrackSelector->checked(i))
|
||||
{
|
||||
trackxtra->tracknum = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (trackxtra->tracknum)
|
||||
{
|
||||
char *block;/* pointer to the block */
|
||||
unsigned long blockSize;/* holds the size of the block */
|
||||
char buf[80];
|
||||
AUDIOHDR audiohdr;
|
||||
trackxtra->paused = 0;
|
||||
reset_sound (WaveData);
|
||||
WaveData = NULL;
|
||||
DeactivateOptions();
|
||||
curtrack = racedata[trackxtra->tracknum-1];
|
||||
playing_clip = curtrack->clip;
|
||||
if (! playing_clip) {
|
||||
fprintf (stderr, "Couldn't find track text for %s\n",curtrack->filename);
|
||||
return;
|
||||
}
|
||||
synch->CurrentTrack->value(curtrack->filename);
|
||||
UpdatePlayTime(trackxtra->tracknum);
|
||||
PrintFrameNum();
|
||||
synch->TextScreen->value(playing_clip->str);
|
||||
sprintf (buf, "%s/%s",path, curtrack->filename);
|
||||
if (read_ogg (buf, &audiohdr)) {
|
||||
fprintf (stderr, "Ogg Read failed!\n");
|
||||
playing_clip = 0;
|
||||
return;
|
||||
}
|
||||
curtrack->chksum = checksum(buf);
|
||||
WaveData = play_sound(&audiohdr);
|
||||
trackxtra->time=get_clock();
|
||||
} else {
|
||||
StopPlayback();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void RestartFrame ()
|
||||
{
|
||||
if (trackxtra->tracknum) {
|
||||
trackxtra->tracknum--;
|
||||
}
|
||||
StartPlayback();
|
||||
}
|
||||
|
||||
void SaveTimestamps()
|
||||
{
|
||||
char buf[80], buf1[80];
|
||||
CLIPTXTDATA *curclip;
|
||||
FILE *fh;
|
||||
strcpy (buf1, curtrack->filename);
|
||||
buf1[strlen(buf1)-4]=0;
|
||||
sprintf (buf, "%s/%s.ts",savepath, buf1);
|
||||
fh = fopen(buf,"w");
|
||||
fprintf(fh,"Version: %s-%s-%s\n",SYNC_VER, SYNC_EXTRA_VER, AUDIO_TYPE);
|
||||
fprintf(fh,"Checksum: %lu\n",curtrack->chksum);
|
||||
curclip = curtrack->clip;
|
||||
while (curclip != NULL) {
|
||||
fprintf(fh,"%8.3f\n",(double)(curclip->time)/clocks_per_sec);
|
||||
curclip = curclip->Next;
|
||||
}
|
||||
fclose (fh);
|
||||
}
|
||||
|
||||
|
||||
void NextFrame ()
|
||||
{
|
||||
unsigned long curtime;
|
||||
if (! trackxtra->tracknum || trackxtra->paused)
|
||||
return;
|
||||
if (playing_clip->Next == NULL)
|
||||
StartPlayback();
|
||||
else {
|
||||
curtime = get_clock();
|
||||
printf ("Frame time: %d\n",curtime-trackxtra->time);
|
||||
playing_clip = playing_clip->Next;
|
||||
playing_clip->time = curtime-trackxtra->time;
|
||||
synch->TextScreen->value(playing_clip->str);
|
||||
PrintFrameNum();
|
||||
if (playing_clip->Next == NULL)
|
||||
SaveTimestamps();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void wrapstr (char *dst, char *src)
|
||||
{
|
||||
int i,j,last=0;
|
||||
for (i = 0; i < strlen (src); i++) {
|
||||
*dst++ = src[i];
|
||||
if (i == last) {
|
||||
if (i != 0) {
|
||||
*dst++ = '\n';
|
||||
}
|
||||
last = strlen(src);
|
||||
for (j=i+1; j < strlen (src); j++) {
|
||||
if (j -i > WRAP_LEN)
|
||||
break;
|
||||
if (src[j] == ' ') {
|
||||
last = j;
|
||||
}
|
||||
}
|
||||
if (j == strlen (src))
|
||||
last = j;
|
||||
}
|
||||
}
|
||||
*dst = 0;
|
||||
}
|
||||
|
||||
void PauseFrame ()
|
||||
{
|
||||
unsigned long curtime;
|
||||
if(trackxtra->paused)
|
||||
unpause_sound(WaveData);
|
||||
else
|
||||
pause_sound(WaveData);
|
||||
curtime = get_clock();
|
||||
trackxtra->time = curtime - trackxtra->time;
|
||||
trackxtra->paused = ! trackxtra->paused;
|
||||
}
|
||||
|
||||
void GetTracks (int value)
|
||||
{
|
||||
const char *race;
|
||||
char buf[80];
|
||||
char str[MAX_LEN];
|
||||
int i = 0, read_data = 0;
|
||||
CLIPTXTDATA *curclip;
|
||||
FILE *fh;
|
||||
|
||||
race = races[value - 1];
|
||||
CleanUp();
|
||||
sprintf (path, "comm/%s",race);
|
||||
sprintf (buf, "%s/%s.txt",path, race);
|
||||
fh = fopen (buf, "r");
|
||||
if (!fh) {
|
||||
char buf1[100];
|
||||
sprintf (buf1, "Could not find %s!",buf);
|
||||
fl_alert (buf1);
|
||||
return;
|
||||
}
|
||||
char tmp[80];
|
||||
MKDIR ("timestamp");
|
||||
sprintf(savepath,"timestamp/%s",race);
|
||||
MKDIR (savepath);
|
||||
synch->TrackSelector->clear ();
|
||||
while (fgets(str,512,fh))
|
||||
{
|
||||
str[strlen (str) - 1] = 0;
|
||||
if(str[0] == '#')
|
||||
{
|
||||
char *tmp;
|
||||
read_data = 0;
|
||||
tmp = strtok (str, "\t ");
|
||||
if ((tmp = strtok (NULL, "\t ")) != NULL)
|
||||
{
|
||||
#ifdef SKIP_SINGLE_LINES
|
||||
if (i && racedata[i-1]->num_lines < 2) {
|
||||
delete racedata[i-1];
|
||||
i--;
|
||||
}
|
||||
#endif
|
||||
if (i && ! racedata[i-1]->tracktime) {
|
||||
char buf[80];
|
||||
sprintf(buf,"%s/%s",path, racedata[i-1]->filename);
|
||||
racedata[i-1]->tracktime = get_ogg_runtime(buf);
|
||||
synch->TrackSelector->add (racedata[i-1]->filename);
|
||||
if (! racedata[i-1]->tracktime) {
|
||||
fprintf(stderr, "couldn't read %s\n", racedata[i-1]->filename);
|
||||
racedata[i-1]->tracktime = 1;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
racedata[i-1] = new FILEDATA;
|
||||
strcpy (racedata[i-1]->filename, tmp);
|
||||
curclip = NULL;
|
||||
read_data = 1;
|
||||
}
|
||||
}
|
||||
else if (read_data && strlen (str))
|
||||
{
|
||||
if (racedata[i-1]->clip == NULL) {
|
||||
racedata[i-1]->clip = new CLIPTXTDATA;
|
||||
curclip = racedata[i-1]->clip;
|
||||
} else {
|
||||
curclip->Next = new CLIPTXTDATA;
|
||||
curclip = curclip->Next;
|
||||
}
|
||||
wrapstr (curclip->str, str);
|
||||
racedata[i-1]->num_lines++;
|
||||
curclip->frame_num = racedata[i-1]->num_lines;
|
||||
}
|
||||
if (feof (fh))
|
||||
break;
|
||||
|
||||
}
|
||||
#ifdef SKIP_SINGLE_LINES
|
||||
if (i && racedata[i-1]->num_lines < 2) {
|
||||
delete racedata[i-1];
|
||||
i--;
|
||||
}
|
||||
#endif
|
||||
if (i && ! racedata[i-1]->tracktime) {
|
||||
char buf[80];
|
||||
sprintf(buf,"%s/%s",path, racedata[i-1]->filename);
|
||||
racedata[i-1]->tracktime = get_ogg_runtime(buf);
|
||||
synch->TrackSelector->add (racedata[i-1]->filename);
|
||||
}
|
||||
synch->TrackSelector->position (1);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
get_ogg_runtime (char *filename) {
|
||||
OggVorbis_File vf;
|
||||
vorbis_info *vi;
|
||||
FILE *fh;
|
||||
unsigned long runtime;
|
||||
double rt;
|
||||
fh = fopen(filename, "rb");
|
||||
if (fh == NULL)
|
||||
return (0);
|
||||
if(ov_open(fh, &vf, NULL, 0) < 0)
|
||||
return (0);
|
||||
rt = ov_time_total(&vf, -1);
|
||||
runtime = (unsigned long)(rt + 0.5);
|
||||
ov_clear(&vf);
|
||||
fclose(fh);
|
||||
printf("%s : %lu (%f)\n",filename, runtime, rt);
|
||||
return(runtime);
|
||||
}
|
||||
int
|
||||
read_ogg (char *filename, AUDIOHDR *audiohdr) {
|
||||
OggVorbis_File vf;
|
||||
vorbis_info *vi;
|
||||
FILE *fh;
|
||||
char *wav;
|
||||
int current_section;
|
||||
|
||||
fh = fopen(filename, "rb");
|
||||
if (fh == NULL) {
|
||||
fprintf (stderr, "Couldn't find file: %s\n", filename);
|
||||
return (1);
|
||||
}
|
||||
if(ov_open(fh, &vf, NULL, 0) < 0) {
|
||||
fprintf(stderr,"Input does not appear to be an Ogg bitstream.\n");
|
||||
return (1);
|
||||
}
|
||||
vi=ov_info(&vf,-1);
|
||||
audiohdr->samp_freq = vi->rate;
|
||||
audiohdr->channels = vi->channels;
|
||||
audiohdr->bits_per_sample = 16;
|
||||
{
|
||||
const unsigned int extra=10000;
|
||||
unsigned int numsamples = extra+(unsigned int)ov_pcm_total(&vf,0);
|
||||
unsigned int numbytes = numsamples*vi->channels*2; // 16bit output wav
|
||||
char *wavptr;
|
||||
int eof = 0;
|
||||
unsigned long readbytes = 0;
|
||||
audiohdr->data = new char[numbytes];
|
||||
wavptr = audiohdr->data;
|
||||
while(!eof){
|
||||
long ret=ov_read(&vf,wavptr,numbytes-readbytes,0,2,1,¤t_section);
|
||||
if (ret == 0) {
|
||||
eof=1;
|
||||
} else if (ret > 0) {
|
||||
readbytes += ret;
|
||||
wavptr += ret;
|
||||
}
|
||||
}
|
||||
audiohdr->data_len = readbytes;
|
||||
}
|
||||
ov_clear(&vf);
|
||||
fclose(fh);
|
||||
return (0);
|
||||
}
|
||||
|
||||
unsigned long checksum(char *filename)
|
||||
{
|
||||
int fh;
|
||||
unsigned long chk= 0, buf = 0;
|
||||
fh = open(filename,O_RDONLY);
|
||||
if (fh == -1)
|
||||
return 0;
|
||||
while (read (fh,&buf,sizeof(buf)) > 0 )
|
||||
chk = ((chk << 1) | (chk >> 31)) ^ buf;
|
||||
close(fh);
|
||||
return (chk);
|
||||
}
|
||||
Reference in New Issue
Block a user