Applied dsalt's libespeak patch. It doesn't work for me, but the build is fine if not built with make libespeak=yes so it doesn't hurt anything.

git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@2091 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Jens Ayton 2009-03-15 16:14:03 +00:00
parent 66f5f8c095
commit 886bfccbab
12 changed files with 188 additions and 35 deletions

View File

@ -21,6 +21,11 @@ else
ADDITIONAL_OBJCFLAGS = -std=c99 -DLOADSAVEGUI -DLINUX -DDOCKING_CLEARANCE_ENABLED -DALLOW_PROCEDURAL_PLANETS -DXP_UNIX -Wno-import `sdl-config --cflags`
oolite_LIB_DIRS += -L/usr/X11R6/lib/
endif
ifeq ($(libespeak),yes)
ADDITIONAL_OBJC_LIBS += -lespeak
ADDITIONAL_OBJCFLAGS+=-DHAVE_LIBESPEAK=1
GNUSTEP_OBJ_DIR_NAME := $(GNUSTEP_OBJ_DIR_NAME).spk
endif
ifeq ($(debug),yes)
ADDITIONAL_CFLAGS += -g -O0
ADDITIONAL_OBJCFLAGS += -g -O0

View File

@ -367,6 +367,8 @@
digrams-apostrophe = "";
// this string represents the 4 character phonemes associated with each digram.
phonograms = "AEb=UW==sEH=IHt=IHl=EHt=st==AAn=lOW=nUW=T===nOW=AEl=lEY=hEY=JEH=zEY=sEH=bIY=sOW=UHs=EHz=AEr=mAE=IHn=dIY=rEY=EH==UXr=AEt=EHn=bEH=rAX=lAX=vEH=tIY=EHd=AAr=kw==AXn=tEY=IHz=rIY=AAn=";
// this string similarly, but for espeak. (Note also Apple 'AA' is changed, else 'or' would sound like 'ar'.)
espkphonos = "ab=='u:=sE==It==Il==Et==st==0n==l'oUn'u:T===n'oUal==l'eIh'eIdZ'Ez'eIs'E=b'i:s'oU'Us='Ez='ar=m'a='In=d'i:r'eI'E=='Vr='at='En=b'E=ra2=la2=v'E=t'i:'Ed=0r==kw==a2n=t'eI'Iz=r'i:0n==";
"interstellar-space" = "Interstellar space";
"not-applicable" = "N/A";

View File

@ -1,4 +1,10 @@
(
// Format:
// (
// [required] Original text,
// [required] replacement text (Apple),
// [optional] replacement text (espeak) or "_" (original text is unchanged)
// )
(
"\\n",
" "
@ -10,7 +16,12 @@
(
// must come before ' Cr'
Cruiser,
"[[inpt PHON]]kr1UWz2AXr[[inpt TEXT]]"
"[[inpt PHON]]kr1UWz2AXr[[inpt TEXT]]",
"[[kr'u:z3]]"
),
(
" cr.",
" credits."
),
(
" Cr",
@ -24,41 +35,50 @@
Purse,
", Total "
),
(
"Mark III",
"Mach Three"
),
(
"Mark II",
"Mach Two"
),
(
"Mark I",
"Mach One"
),
( "Mark V", "Mark Five" ),
( "Mark IV", "Mark Four" ),
( "Mark III", "Mark Three" ),
( "Mark II", "Mark Two" ),
( "Mark I", "Mark One" ),
( "MkV", "Mark Five" ),
( "MkIV", "Mark Four" ),
( "MkIII", "Mark Three" ),
( "MkII", "Mark Two" ),
( "MkI", "Mark One" ),
( "Mk V", "Mark Five" ),
( "Mk IV", "Mark Four" ),
( "Mk III", "Mark Three" ),
( "Mk II", "Mark Two" ),
( "Mk I", "Mark One" ),
(
GalCop,
"[[inpt PHON]]g1AElkUXp[[inpt TEXT]]"
"[[inpt PHON]]g1AElkUXp[[inpt TEXT]]",
_
),
(
Witchspace,
"[[inpt PHON]]w1IHCsp2EYs[[inpt TEXT]]"
"[[inpt PHON]]w1IHCsp2EYs[[inpt TEXT]]",
_
),
(
"Fer-de-Lance",
"[[inpt PHON]]f1<EY<<AE=dEH=l2UXns[[inpt TEXT]]"
"[[inpt PHON]]f1<EY<<AE=dEH=l2UXns[[inpt TEXT]]",
"[[f'e3 d@ l'A:ns]]"
),
(
Sidewinder,
"[[inpt PHON]]s1AYdw2AYndAX[[inpt TEXT]]"
"[[inpt PHON]]s1AYdw2AYndAX[[inpt TEXT]]",
_
),
(
Rebel,
"[[inpt PHON]]rEHbUXl[[inpt TEXT]]"
"[[inpt PHON]]rEHbUXl[[inpt TEXT]]",
_
),
(
"Metal fragment",
"metal [[inpt PHON]]fr1AEgmUHnt[[inpt TEXT]]"
"metal [[inpt PHON]]fr1AEgmUHnt[[inpt TEXT]]",
_
),
(
Ident,
@ -84,4 +104,4 @@
"€",
"credits"
)
)
)

View File

@ -17,7 +17,7 @@ Dave MacLachlan (Jester)
Nic
No Sleep Nigel
Erich Ritz (drumz)
Darren Salt
Darren Salt (dsalt/_ds_)
Adam Sampson
Rob C Skilton (KZ9999)
Dylan Smith (winston)

2
debian/control vendored
View File

@ -4,7 +4,7 @@ Priority: optional
Maintainer: Chris Crowther <hikari@hikari.org.uk>
Standards-Version: 3.7.2
Build-Depends: debhelper (>= 5),
libsdl1.2-dev, libsdl-mixer1.2-dev,
libsdl1.2-dev, libsdl-mixer1.2-dev, libespeak-dev,
libgnustep-base-dev, gnustep-core-devel,
libpng-dev, mesa-common-dev

2
debian/rules vendored
View File

@ -36,7 +36,7 @@ build-stamp:
dh_testdir
$(MAKE) -C $(JS_SRC)/fdlibm -f Makefile.ref BUILD_OPT=1
$(MAKE) -C $(JS_SRC) -f Makefile.ref BUILD_OPT=1
$(GSMAKE)
$(GSMAKE) libespeak=yes
touch $@
clean: clean-stamp unpatch

View File

@ -67,6 +67,8 @@ enum
GUI_ROW_GAMEOPTIONS_VOLUME,
#if OOLITE_MAC_OS_X
GUI_ROW_GAMEOPTIONS_GROWL,
#endif
#if OOLITE_SPEECH_SYNTH
GUI_ROW_GAMEOPTIONS_SPEECH,
#endif
GUI_ROW_GAMEOPTIONS_MUSIC,

View File

@ -4549,14 +4549,16 @@ static PlayerEntity *sSharedPlayer = nil;
forRow:GUI_ROW_GAMEOPTIONS_GROWL align:GUI_ALIGN_CENTER];
[gui setKey:GUI_KEY_OK forRow:GUI_ROW_GAMEOPTIONS_GROWL];
}
#endif
#if OOLITE_SPEECH_SYNTH
// Speech control
if (isSpeechOn)
[gui setText:DESC(@"gameoptions-spoken-messages-yes") forRow:GUI_ROW_GAMEOPTIONS_SPEECH align:GUI_ALIGN_CENTER];
else
[gui setText:DESC(@"gameoptions-spoken-messages-no") forRow:GUI_ROW_GAMEOPTIONS_SPEECH align:GUI_ALIGN_CENTER];
[gui setKey:GUI_KEY_OK forRow:GUI_ROW_GAMEOPTIONS_SPEECH];
#else
#endif
#if !OOLITE_MAC_OS_X
// window/fullscreen
if([gameView inFullScreenMode])
{

View File

@ -1946,7 +1946,7 @@ static NSTimeInterval time_last_frame;
switching_resolution = NO;
}
#if OOLITE_MAC_OS_X
#if OOLITE_SPEECH_SYNTH
if ((guiSelectedRow == GUI_ROW_GAMEOPTIONS_SPEECH)&&(([gameView isDown:gvArrowKeyRight])||([gameView isDown:gvArrowKeyLeft])))
{
if ([gameView isDown:gvArrowKeyRight] != isSpeechOn)

View File

@ -330,3 +330,13 @@ enum {
#else
#define OOLITE_FAST_ENUMERATION 0
#endif
/* Speech synthesis
*/
#if MAC_OS_X || defined(HAVE_LIBESPEAK)
#define OOLITE_SPEECH_SYNTH 1
#else
#define OOLITE_SPEECH_SYNTH 0
#endif

View File

@ -246,6 +246,8 @@ enum
#if OOLITE_MAC_OS_X
NSSpeechSynthesizer *speechSynthesizer; // use this from OS X 10.3 onwards
#endif
#if OOLITE_SPEECH_SYNTH
NSArray *speechArray;
#endif
}

View File

@ -69,6 +69,9 @@ MA 02110-1301, USA.
#import "OOConvertSystemDescriptions.h"
#endif
#ifdef HAVE_LIBESPEAK
#include <espeak/speak_lib.h>
#endif
#define kOOLogUnconvertedNSLog @"unclassified.Universe"
@ -159,13 +162,15 @@ static OOComparisonResult comparePrice(id dict1, id dict2, void * context);
// Set up the internal game strings
descriptions = [[ResourceManager dictionaryFromFilesNamed:@"descriptions.plist" inFolder:@"Config" andMerge:YES] retain];
#if OOLITE_SPEECH_SYNTH
#if OOLITE_MAC_OS_X
//// speech stuff
speechSynthesizer = [[NSSpeechSynthesizer alloc] init];
//Jester Speech Begin
#elif defined(HAVE_LIBESPEAK)
espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 100, NULL, 0);
espeak_SetParameter(espeakPUNCTUATION, espeakPUNCT_NONE, 0);
#endif
speechArray = [[ResourceManager arrayFromFilesNamed:@"speech_pronunciation_guide.plist" inFolder:@"Config" andMerge:YES] retain];
//Jester Speech End
#endif
[[GameController sharedController] logProgress:DESC(@"loading-ships")];
@ -327,9 +332,13 @@ static OOComparisonResult comparePrice(id dict1, id dict2, void * context);
[[OOCacheManager sharedCache] flush];
#ifndef OOLITE_MAC_OS_X
#if OOLITE_SPEECH_SYNTH
[speechArray release];
#if OOLITE_MAC_OS_X
[speechSynthesizer release];
#elif defined(HAVE_LIBESPEAK)
espeak_Cancel();
#endif
#endif
[super dealloc];
@ -5005,7 +5014,7 @@ OOINLINE BOOL EntityInRange(Vector p1, Entity *e2, float range)
{
if (![currentMessage isEqual:text])
{
#if OOLITE_MAC_OS_X
#if OOLITE_SPEECH_SYNTH
PlayerEntity* player = [PlayerEntity sharedPlayer];
//speech synthesis
if ([player isSpeechOn])
@ -5023,14 +5032,17 @@ OOINLINE BOOL EntityInRange(Vector p1, Entity *e2, float range)
for (speechEnumerator = [speechArray objectEnumerator]; (thePair = [speechEnumerator nextObject]); )
{
NSString *original_phrase = [thePair stringAtIndex:0];
#if OOLITE_MAC_OS_X
NSString *replacement_phrase = [thePair stringAtIndex:1];
spoken_text = [[spoken_text componentsSeparatedByString: original_phrase] componentsJoinedByString: replacement_phrase];
#else
NSString *replacement_phrase = [thePair stringAtIndex:([thePair count] > 2 ? 2 : 1)];
if (![replacement_phrase isEqualToString:@"_"])
#endif
spoken_text = [[spoken_text componentsSeparatedByString: original_phrase] componentsJoinedByString: replacement_phrase];
}
spoken_text = [[spoken_text componentsSeparatedByString: systemName] componentsJoinedByString: systemSaid];
spoken_text = [[spoken_text componentsSeparatedByString: h_systemName] componentsJoinedByString: h_systemSaid];
}
if ([self isSpeaking]) [self stopSpeaking];
[self startSpeakingString:spoken_text];
@ -5912,8 +5924,11 @@ OOINLINE BOOL EntityInRange(Vector p1, Entity *e2, float range)
- (NSString *) generatePhoneticSystemName:(Random_Seed) s_seed
{
int i;
#if OOLITE_MAC_OS_X
NSString *phonograms = [self descriptionForKey:@"phonograms"];
#else
NSString *phonograms = [self descriptionForKey:@"espkphonos"];
#endif
NSMutableString *name = [NSMutableString string];
int size = 4;
@ -5933,7 +5948,11 @@ OOINLINE BOOL EntityInRange(Vector p1, Entity *e2, float range)
rotate_seed(&s_seed);
}
#if OOLITE_MAC_OS_X
return [NSString stringWithFormat:@"[[inpt PHON]]%@[[inpt TEXT]]", name];
#else
return [NSString stringWithFormat:@"[[%@]]", name];
#endif
}
@ -7810,6 +7829,97 @@ static OOComparisonResult comparePrice(id dict1, id dict2, void * context)
return [speechSynthesizer isSpeaking];
}
#elif defined(HAVE_LIBESPEAK)
- (void) startSpeakingString:(NSString *) text
{
#if 0
// First, do some translation of phoneme representation from Apple to espeak.
// We recognise phonemes listed at
// http://developer.apple.com/documentation/userexperience/conceptual/speechsynthesisprogrammingguide/Phonemes/chapter_952_section_1.html
// and controls "[[inpt PHON]]" and "[[inpt TEXT]]".
NSMutableArray *frags = [NSMutableArray arrayWithCapacity:20];
[frags setArray:[text componentsSeparatedByString:@"[[inpt PHON]]"]];
int frag;
for (frag = 1; frag < [frags count]; ++frag)
{
NSArray *parts = [[frags objectAtIndex:frag] componentsSeparatedByString:@"[[inpt TEXT]]"];
const char *oldp = [[parts stringAtIndex:0] cString] - 1;
char *newp = malloc (strlen (oldp) * 2);
char *ptr = newp;
while (*++oldp)
{
switch (*oldp)
{
case '%': case '@': *ptr++ = ' '; break;
case 'A':
switch (*++oldp)
{
case 'A': *ptr++ = '\''; *ptr++ = 'A'; *ptr++ = ':'; break; // AA 'A:
case 'E': *ptr++ = '\''; *ptr++ = 'a'; break; // AE 'a
case 'O': *ptr++ = '\''; *ptr++ = 'O'; *ptr++ = ':'; break; // AO 'O:
case 'W': *ptr++ = '\''; *ptr++ = 'a'; *ptr++ = 'U'; break; // AW 'aU
case 'X': *ptr++ = 'a'; *ptr++ = '2'; break; // AX a2
case 'Y': *ptr++ = '\''; *ptr++ = 'a'; *ptr++ = 'I'; break; // AY 'aI
default: --oldp; *ptr++ = 'A'; break;
}
case 'C': *ptr++ = 't'; *ptr++ = 'S'; break; // C tS
case 'E':
switch (*++oldp)
{
case 'H': *ptr++ = '\''; *ptr++ = 'E'; break; // EH 'E
case 'Y': *ptr++ = '\''; *ptr++ = 'e'; *ptr++ = 'I'; break; // EY 'eI
default: --oldp; *ptr++ = 'E'; break;
}
case 'I':
switch (*++oldp)
{
case 'H': *ptr++ = '\''; *ptr++ = 'I'; break; // IH 'I
case 'X': *ptr++ = 'I'; *ptr++ = '2'; break; // IX I2
case 'Y': *ptr++ = '\''; *ptr++ = 'i'; *ptr++ = ':'; break; // IY 'i:
default: --oldp; *ptr++ = 'I'; break;
}
case 'J': *ptr++ = 'd'; *ptr++ = 'Z'; break; // J dZ
case 'O':
switch (*++oldp)
{
case 'W': *ptr++ = '\''; *ptr++ = 'o'; *ptr++ = 'U'; break; // OW 'oU
case 'Y': *ptr++ = '\''; *ptr++ = 'O'; *ptr++ = 'I'; break; // OY 'OI
default: --oldp; *ptr++ = 'O'; break;
}
case 'U':
switch (*++oldp)
{
case 'H': *ptr++ = '\''; *ptr++ = 'U'; break; // UH 'U
case 'W': *ptr++ = '\''; *ptr++ = 'u'; *ptr++ = ':'; break; // UW 'u:
case 'X': *ptr++ = '\''; *ptr++ = 'V'; break; // UX 'V
default: --oldp; *ptr++ = 'U'; break;
}
case 'y': *ptr++ = 'j'; break; // y j
default: *ptr++ = *oldp; break;
}
}
*ptr = 0;
[frags replaceObjectAtIndex:frag withObject:[NSString stringWithFormat:@"[[%s]]%@", newp, ([frags count] == 2 ? [parts objectAtIndex:1] : (id)@"")]];
free (newp);
}
text = [frags componentsJoinedByString:@""];
#endif
size_t length = [text length];
const char *ctext = [text cString];
espeak_Synth(ctext, length + 1 /* inc. NUL */, 0, POS_CHARACTER, length, espeakCHARS_UTF8 | espeakPHONEMES | espeakENDPAUSE, NULL, NULL);
}
- (void) stopSpeaking
{
espeak_Cancel();
}
- (BOOL) isSpeaking
{
return espeak_IsPlaying();
}
#else
- (void) startSpeakingString:(NSString *) text {}