giovedì 22 luglio 2010

iOS-ESpeak API proposal (UPDATE)

I would like to know your opinion of the following API proposal.
Instead of using an API like the one defined in NSSpeechSynthesizer where the strings are parsed every time you want to speech it, I decided to divide the 'parsing' and 'speaking' responsibility in two different classes:
  • ESSpeechSynthesizer
  • ESSpeechSynthesis
Here you have the API.

* ESSpeechSynthesis
* =================
* This class represent an unmutable synthesized message ready to be played.
@interface ESSpeechSynthesis : NSObject
{ .. }

@property(nonatomic, assign) id delegate;
@property(nonatomic, readonly) NSString *string;
@property(nonatomic, retain) NSString *identifier;
@property(nonatomic, readonly) NSDictionary *properties;

- (BOOL)isSpeaking;
- (BOOL)startSpeaking;
- (void)stopSpeaking;
- (void)pauseSpeaking;
- (void)continueSpeaking;


* ESSpeechSynthesisDelegate
* =========================
* This protocol represent the Synthesis delegate.
@protocol ESSpeechSynthesisDelegate

- (void)speechSynthesisBeginInterruption:(ESSpeechSynthesis *)sender;
- (void)speechSynthesisEndInterruption:(ESSpeechSynthesis *)sender;

- (void)speechSynthesisDecodeErrorDidOccur:(ESSpeechSynthesis *)sender error:(NSError *)error;
- (void)speechSynthesisDidFinishPlaying:(ESSpeechSynthesis *)sender successfully:(BOOL)flag;


* ESSpeechSynthesizer
* ===================
* This class represent a singleton that can convert a string into a sound message.
@interface ESSpeechSynthesizer: NSObject
{ ... }

@property(nonatomic, readonly) NSString* defaultVoice;
@property(nonatomic, retain) NSString* voice;

// ...

+ (ESSpeechSynthesizer *)sharedESSpeechSynthesizer;

- (NSArray *)availableVoices;
- (NSDictionary *)attributesForVoice:(NSString *)voice;

- (ESSpeechSynthesis *)synthesize:(NSString *)text;


Here you have an example of how to use this API:

// First obtain the synthesize singleton instance.
ESSpeechSynthesizer *synth = [ESSpeechSynthesizer sharedESSpeechSynthesizer];

// Then configure it, in this case just setup the voice language.
[synth setVoice:@"english"];

// Convert string into sound
ESpeechSynthesis speech = [synth synthesize:msg];

// Some log
NSLog(@"Available voices: %@", [synth availableVoices]);
NSLog(@"Start speacking: %@", speech);

// Set the delegate for notification
[speech setDelegate:self];

// Start speaking
[speech startSpeaking];

// This method will be invoked when the speaking is terminated
- (void)speechSynthesizerDidFinishPlaying:(ESSpeechSynthesis *)sender successfully:(BOOL)flag
// Release here if sound is not needed anymore
[speech release];
speech = nil;

All comments are welcome.

UPDATE: Please notice that the ESSpeechSynthesizer API is not thread safe, What do you think about a new thread safe method like the following:

@interface ESSpeechSynthesizer: NSObject

- (ESSpeechSynthesis *)synthesize:(NSString *)text properties:(NSDictionary *)props;


Where the dictionary instance is used to specify the synthesis attributes like: voice, gender, pitch, ....

As usual all comments are welcome !


5 commenti:

  1. Great Work John.

    I know that eSpeak is GPLV3 but i have heard that GPLV3 is incompatible with AppStore apps if so how do you propose to get around this?

    I am extremely interested in eSpeak for the iPhone and the Mac in general but am worried that the licensing may become an issue.

    The current Project I am working on is not free but is open source under BSD.

    Thanks for your good work.

    Oh BTW the thread safe idea looks good and would work well.



  2. Hello, I need eSpeak on iPhone very urgent, can you give it in a XCode project? And my email is
    Need for help.
    Best regards!

  3. can you give it in a xcode project? Thanks !

  4. Hi

    Could you please point out some steps about compiling it for iOS. You have any idea about apple restriction in submitting it to store.
    If you dont have any issue in sharing your ported code, please send me to my id.

  5. Hi,

    can you send me the xcode project?