Initial add of all files

This commit is contained in:
Gregory John Casamento 2020-01-30 16:28:18 -05:00
parent 36343b81b1
commit d526f6f50d
12 changed files with 610 additions and 0 deletions

View file

@ -18,6 +18,9 @@
/* Define to 1 if you have the <flite/flite.h> header file. */
#undef HAVE_FLITE_FLITE_H
/* Define to 1 if you have the <pocketsphinx/pocketsphinx.h> header file */
#undef HAVE_LIBPOCKETSPHINX
/* Define to 1 if you have the `floorf' function. */
#undef HAVE_FLOORF

View file

@ -0,0 +1,32 @@
include $(GNUSTEP_MAKEFILES)/common.make
# Set the default. Eventually this should be conditional.
GSSPEECHRECOGNITIONENGINE = Pocketsphinx
VERSION = 0.1
# This is an app not a tool because, eventually, it will present the user
# interface for the GUI part of the speech engine.
APP_NAME = GSSpeechRecognitionServer
GSSpeechRecognitionServer_LANGUAGES = English
GSSpeechRecognitionServer_OBJC_FILES = \
GSSpeechRecognitionEngine.m \
GSSpeechRecognitionServer.m \
GSSpeechRecognitionSynthesizer.m \
main.m
ifeq ($(GSSPEECHRECOGNITIONENGINE), Pocketsphinx)
POCKETSPHINX_BASE_LIBS = -lpocketsphinx
GSSpeechRecognitionServer_OBJC_FILES += PocketsphinxSpeechRecognitionEngine.m
GSSpeechRecognitionServer_INCLUDE_DIRS += -I/usr/local/include/pocketsphinx -I../../Headers \
-I../../Headers/Additions
GSSpeechRecognitionServer_LIB_DIRS += -L../../Source/$(GNUSTEP_OBJ_DIR) \
-L/usr/local/lib -lgnustep-gui \
$(POCKETSPHINX_BASE_LIBS)
endif
include $(GNUSTEP_MAKEFILES)/application.make

View file

@ -0,0 +1,52 @@
#import <Foundation/Foundation.h>
/**
* GSSpeechEngine is an abstract speech server. One concrete subclass should
* be implemented for each speech engine. Currently, only one may be compiled
* in to the speech server at any given time. This limitation may be removed
* in future if pluggable speech engines are considered beneficial.
*/
@interface GSSpeechEngine : NSObject
/**
* Begin speaking the specified string.
*/
- (void)startSpeaking: (NSString*)aString notifyWhenDone: (id)aDelegate;
/**
* Stop speaking.
*/
- (void)stopSpeaking;
/**
* Returns YES if the engine is currently outputting speech.
*/
- (BOOL)isSpeaking;
/**
* Returns an array of voices supported by this speech synthesizer.
*/
- (NSArray*)voices;
/**
* Sets the voice.
*/
- (void)setVoice: (NSString*)aVoice;
/**
* Returns the current voice.
*/
- (NSString*)voice;
/**
* Returns the name of the default voice for this speech engine.
*/
- (NSString*)defaultVoice;
@end
@interface NSObject (GSSpeechEngineDelegate)
/**
* Called when the speech engine has finished speaking a phrase. Should be
* used to notify the original caller.
*/
- (void)didFinishSpeaking: (BOOL)didFinish;
@end
@interface GSSpeechEngine (Default)
/**
* Returns a new instance of the default speech engine.
*/
+ (GSSpeechEngine*)defaultSpeechEngine;
@end

View file

@ -0,0 +1,15 @@
#import "GSSpeechEngine.h"
/**
* Dummy implementation of a speech engine. Doesn't do anything.
*/
@implementation GSSpeechEngine
+ (GSSpeechEngine*)defaultSpeechEngine { return [[self new] autorelease]; }
- (void)startSpeaking: (NSString*)aString notifyWhenDone: (id)anObject{}
- (void)stopSpeaking {}
- (BOOL)isSpeaking { return NO; }
- (NSArray*)voices { return [NSArray arrayWithObject: @"default"]; }
- (void)setVoice: (NSString*)aVoice {}
- (NSString*)voice { return @"default"; }
- (NSString*)defaultVoice { return @"default"; }
@end

View file

@ -0,0 +1,44 @@
#import <Foundation/Foundation.h>
@class GSSpeechEngine;
/**
* GSSpeechServer handles all of the engine-agnostic operations. Currently,
* there aren't any, but when the on-screen text interface is added it should
* go in here.
*/
@interface GSSpeechServer : NSObject {
GSSpeechEngine *engine;
}
/**
* Returns a shared instance of the speech server.
*/
+ (id)sharedServer;
/**
* Begins speaking the string specified by the first argument. Calls the
* delegate method on the client when done.
*/
- (BOOL)startSpeakingString: (NSString*)aString notifyWhenDone: (id)client;
/**
* Stop speaking.
*/
- (void)stopSpeaking;
/**
* Returns YES if the engine is currently outputting speech.
*/
- (BOOL)isSpeaking;
/**
* Returns an array of voices supported by this speech synthesizer.
*/
- (NSArray*)voices;
/**
* Sets the voice.
*/
- (void)setVoice: (NSString*)aVoice;
/**
* Returns the current voice.
*/
- (NSString*)voice;
/**
* Returns the name of the default voice.
*/
- (NSString*)defaultVoice;
@end

View file

@ -0,0 +1,72 @@
#import "GSSpeechServer.h"
#import "GSSpeechEngine.h"
#import "GSSpeechSynthesizer.h"
#import <Foundation/Foundation.h>
static GSSpeechServer *sharedInstance;
@implementation GSSpeechServer
+ (void)initialize
{
sharedInstance = [self new];
}
+ (void)start
{
NSConnection *connection = [NSConnection defaultConnection];
[connection setRootObject: sharedInstance];
if (NO == [connection registerName: @"GSSpeechServer"])
{
return;
}
[[NSRunLoop currentRunLoop] run];
}
+ (id)sharedServer
{
return sharedInstance;
}
- (id)init
{
if (nil == (self = [super init])) { return nil; }
engine = [GSSpeechEngine defaultSpeechEngine];
if (nil == engine)
{
[self release];
return nil;
}
return self;
}
- (id)newSynthesizer
{
return [[GSSpeechSynthesizer new] autorelease];
}
- (BOOL)startSpeakingString: (NSString*)aString notifyWhenDone: (id)client
{
[engine stopSpeaking];
[engine startSpeaking: aString notifyWhenDone: client];
return YES;
}
- (void)stopSpeaking
{
[engine stopSpeaking];
}
- (BOOL)isSpeaking
{
return [engine isSpeaking];
}
- (NSArray*)voices
{
return [engine voices];
}
- (oneway void)setVoice: (NSString*)aVoice
{
[engine setVoice: aVoice];
}
- (NSString*)voice
{
return [engine voice];
}
- (NSString*)defaultVoice
{
return [engine defaultVoice];
}
@end

View file

@ -0,0 +1,17 @@
#import "GSSpeechServer.h"
#import <AppKit/NSSpeechSynthesizer.h>
@interface GSSpeechSynthesizer : NSSpeechSynthesizer {
NSString *currentVoice;
id delegate;
}
- (id)initWithVoice: (NSString*)aVoice;
- (id)init;
- (NSString*)voice;
- (id)delegate;
- (void)setDelegate: (id)aDelegate;
- (void)setVoice: (NSString*)aVoice;
- (BOOL)startSpeakingString: (NSString*)aString;
- (void)stopSpeaking;
@end

View file

@ -0,0 +1,140 @@
#import "GSSpeechSynthesizer.h"
static GSSpeechServer *server;
static int clients;
@interface GSSpeechSynthesizer (Private)
+ (void)connectionDied: (NSNotification*)aNotification;
@end
@implementation GSSpeechSynthesizer
+ (void)initialize
{
server = [[GSSpeechServer sharedServer] retain];
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(connectionDied:)
name: NSConnectionDidDieNotification
object: nil];
}
/**
* If the remote end exits before freeing the GSSpeechSynthesizer then we need
* to send it a -release message to make sure it dies.
*/
+ (void)connectionDied: (NSNotification*)aNotification
{
NSEnumerator *e = [[[aNotification object] localObjects] objectEnumerator];
NSObject *o = nil;
for (o = [e nextObject] ; nil != o ; o = [e nextObject])
{
if ([o isKindOfClass: self])
{
[o release];
}
}
}
/**
* If no clients have been active for some time, kill the speech server to
* conserve resources.
*/
+ (void)exitIfUnneeded: (NSTimer*)sender
{
if (clients == 0)
{
exit(0);
}
}
- (id)initWithVoice: (NSString*)aVoice
{
clients++;
if (nil == (self = [super init]))
{
return nil;
}
[self setVoice: currentVoice];
return self;
}
- (id)init
{
return [self initWithVoice: nil];
}
- (NSString*)voice
{
return currentVoice;
}
- (id)delegate
{
return delegate;
}
- (void)setDelegate: (id)aDelegate
{
// Either -retain or -release can throw an exception due to DO.
NS_DURING
aDelegate = [aDelegate retain];
NS_HANDLER
NS_ENDHANDLER
NS_DURING
[delegate release];
NS_HANDLER
NS_ENDHANDLER
delegate = aDelegate;
}
- (void)setVoice: (NSString*)aVoice
{
if (nil == aVoice)
{
aVoice = [server defaultVoice];
}
ASSIGN(currentVoice, aVoice);
}
- (BOOL)startSpeakingString: (NSString*)aString
{
[server setVoice: currentVoice];
return [server startSpeakingString: aString notifyWhenDone: self];
}
- (void)didFinishSpeaking: (BOOL)didFinish
{
// Throw the delegate away if it is throwing exceptions during
// notification.
NS_DURING
[delegate speechSynthesizer: self didFinishSpeaking: didFinish];
NS_HANDLER
NS_DURING
id d = delegate;
delegate = nil;
[d release];
NS_HANDLER
NS_ENDHANDLER
NS_ENDHANDLER
}
- (void)stopSpeaking
{
[server stopSpeaking];
}
- (void)dealloc
{
clients--;
[currentVoice release];
if (clients == 0)
{
[NSTimer scheduledTimerWithTimeInterval: 600
target: object_getClass(self)
selector: @selector(exitIfUnneeded:)
userInfo: nil
repeats: NO];
}
[super dealloc];
}
@end

View file

@ -0,0 +1,126 @@
#import "GSSpeechEngine.h"
#include <flite/flite.h>
cst_voice *register_cmu_us_kal16();
/**
* Implementation of a speech engine using flite. This should be the default
* for resource-constrained platforms.
*/
@interface FliteSpeechEngine : GSSpeechEngine {
/** The audio device used for sound output. */
cst_audiodev *ad;
/** The current voice. Only one supported at the moment. */
cst_voice *v;
/** Flag set to tell the playback thread to exit. */
volatile BOOL shouldEndSpeaking;
/** Flag indicating whether the engine is currently speaking. */
volatile BOOL isSpeaking;
}
@end
@implementation FliteSpeechEngine
+ (void)initialize
{
flite_init();
}
- (id)init
{
if (nil == (self = [super init])) { return nil; }
// Only one voice supported by flite unless others are compiled in.
v = register_cmu_us_kal16();
if (NULL == v)
{
[self release];
return nil;
}
// Each wave should be the same format.
cst_wave *w = flite_text_to_wave("test", v);
ad = audio_open(w->sample_rate, w->num_channels, CST_AUDIO_LINEAR16);
delete_wave(w);
if (NULL == ad)
{
[self release];
return nil;
}
return self;
}
- (void)sayString: (NSArray*)args
{
id pool = [NSAutoreleasePool new];
NSString *aString = [args objectAtIndex: 0];
int i,n,r;
int num_shorts;
BOOL didFinish = YES;
cst_wave *w = flite_text_to_wave([aString UTF8String], v);
num_shorts = w->num_samples * w->num_channels;
for (i=0; i < num_shorts; i += r/2)
{
if (num_shorts > i+CST_AUDIOBUFFSIZE)
{
n = CST_AUDIOBUFFSIZE;
}
else
{
n = num_shorts-i;
}
r = audio_write(ad, &w->samples[i], n*2);
if (shouldEndSpeaking)
{
didFinish = NO;
break;
}
}
isSpeaking = NO;
NS_DURING
[[args objectAtIndex: 1] didFinishSpeaking: didFinish];
NS_HANDLER
NS_ENDHANDLER;
[args release];
[pool release];
delete_wave(w);
}
- (void)startSpeaking: (NSString*)aString notifyWhenDone: (id)aDelegate
{
[[[aDelegate delegate] connectionForProxy] enableMultipleThreads];
NSArray *arg = [[NSArray alloc] initWithObjects: aString, aDelegate, nil];
shouldEndSpeaking = NO;
isSpeaking = YES;
[NSThread detachNewThreadSelector: @selector(sayString:)
toTarget: self
withObject: arg];
}
- (BOOL)isSpeaking
{
return isSpeaking;
}
- (void)stopSpeaking
{
shouldEndSpeaking = YES;
// Spin until the other thread has died.
while (isSpeaking) {}
}
- (void)dealloc
{
[self stopSpeaking];
audio_close(ad);
[super dealloc];
}
@end
@implementation GSSpeechEngine (Flite)
+ (GSSpeechEngine*)defaultSpeechEngine
{
return [[[FliteSpeechEngine alloc] init] autorelease];
}
@end

View file

@ -0,0 +1,12 @@
#import <Foundation/Foundation.h>
@interface GSSpeechRecognitionServer
+ (void)start;
@end
int main(void)
{
[NSAutoreleasePool new];
[GSSpeechRecognitonServer start];
return 0;
}

79
configure vendored
View file

@ -5663,6 +5663,85 @@ fi
#--------------------------------------------------------------------
<<<<<<< Updated upstream
=======
# NSSpeechRecognizer
#--------------------------------------------------------------------
# Check whether --enable-speech-recognizer was given.
if test "${enable_speech_recognizer+set}" = set; then :
enableval=$enable_speech_recognizer;
else
enable_speech_recognizer=yes
fi
BUILD_SPEECH_RECOGNIZER=
# has pocketsphinx, for speech recognition.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ps_start_utt in -lpocketsphinx" >&5
$as_echo_n "checking for ps_start_utt in -lpocketsphinx... " >&6; }
if ${ac_cv_lib_pocketsphinx_ps_start_utt+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lpocketsphinx $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char ps_start_utt ();
int
main ()
{
return ps_start_utt ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_pocketsphinx_ps_start_utt=yes
else
ac_cv_lib_pocketsphinx_ps_start_utt=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pocketsphinx_ps_start_utt" >&5
$as_echo "$ac_cv_lib_pocketsphinx_ps_start_utt" >&6; }
if test "x$ac_cv_lib_pocketsphinx_ps_start_utt" = xyes; then :
have_speech_recognizer=yes
else
have_speech_recognizer=no
fi
for ac_header in pocketsphinx/pocketsphinx.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "pocketsphinx/pocketsphinx.h" "ac_cv_header_pocketsphinx_pocketsphinx_h" "$ac_includes_default"
if test "x$ac_cv_header_pocketsphinx_pocketsphinx_h" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_POCKETSPHINX_POCKETSPHINX_H 1
_ACEOF
have_pocketsphinx=yes
else
have_pocketsphinx=no
fi
done
if test $have_pocketsphinx = yes -a $have_speech_recognizer = yes -a $enable_speech_recognizer = yes; then
#if test $have_speech_recognizer = yes -a $enable_speech_recognizer = yes; then
BUILD_SPEECH_RECOGNIZER="speech_recognizer"
POCKETSPHINX_BASE_LIBS="-lpocketsphinx"
fi
#--------------------------------------------------------------------
>>>>>>> Stashed changes
# Find CUPS
#--------------------------------------------------------------------
GSCUPS_CFLAGS=

View file

@ -538,6 +538,24 @@ if test $have_flite = yes -a $have_speech = yes -a $enable_speech = yes; then
fi
AC_SUBST(BUILD_SPEECH)
#--------------------------------------------------------------------
# NSSpeechRecognizer
#--------------------------------------------------------------------
AC_ARG_ENABLE(speech-recognizer,
[ --disable-speech-recognizer Disable speech recognition server],,
enable_speech_recognizer=yes)
BUILD_SPEECH_RECOGNIZER=
# has pocketsphinx, for speech recognition.
AC_CHECK_LIB(pocketsphinx, ps_start_utt, have_speech_recognizer=yes, have_speech_recognizer=no)
AC_CHECK_HEADERS(pocketsphinx/pocketsphinx.h, have_pocketsphinx=yes, have_pocketsphinx=no)
if test $have_pocketsphinx = yes -a $have_speech_recognizer = yes -a $enable_speech_recognizer = yes; then
#if test $have_speech_recognizer = yes -a $enable_speech_recognizer = yes; then
BUILD_SPEECH_RECOGNIZER="speech_recognizer"
POCKETSPHINX_BASE_LIBS="-lpocketsphinx"
fi
AC_SUBST(BUILD_SPEECH_RECOGNIZER)
#--------------------------------------------------------------------
# Find CUPS
#--------------------------------------------------------------------