Topics

[espeak-ng:master] reported: Multiple instance of eSpeak inside a single process #github

espeak-ng@groups.io Integration <espeak-ng@...>
 

[espeak-ng:master] New Comment on Issue #659 Multiple instance of eSpeak inside a single process
By valdisvi:

Depending on espeak_AUDIO_OUTPUT settings, espeak_Synth() may be called asynchronously and you may try calling it immediately again. But why you need it, and if you really need it, why limit yourself to single process?

espeak-ng@groups.io Integration <espeak-ng@...>
 

[espeak-ng:master] New Comment on Issue #659 Multiple instance of eSpeak inside a single process
By b00f:

I am not sure if #68 related to this.

But why you need it, and if you really need it, why limit yourself to single process?

Creating two different instances of eSpeask one for male voice and another for female voice and users can switch between them instantly. However users might call it from different threads. So in this case I thought having two separated instances might be better (thread safe and no need to lock for changing voice parameters).

espeak-ng@groups.io Integration <espeak-ng@...>
 

[espeak-ng:master] New Comment on Issue #659 Multiple instance of eSpeak inside a single process
By rhdunn:

Issue #68 will affect this as espeak currently tracks state in global variables. As such, calling espeak_Initialize multiple times will affect any running instances.

The other issue is that the APIs for setting the voice and other speech parameters do not support having multiple contexts. I would propose supporting something like:

unsigned int context;
status = espeak_ng_CreateContext(&context);

status = espeak_ng_SetVoiceByNameForContext(context, "af");
status = espeak_ng_SynthesizeForContext(context, ...);
// ...

status = espeak_ng_ReleaseContext(&context);

This API on its own (i.e. without fixing issue #68) would allow you to implement the instant voice switching.

There would also be an ESPEAKNG_DEFAULT_CONTEXT definition set to 0. Then, the non-context based version of an API will call the context based version passing ESPEAKNG_DEFAULT_CONTEXT as the default context. These forwarding APIs could be implemented in a compatibility.c file which would also contain the current espeak_api.c compatibility APIs.

If the context is not registered or the default context, an ENS_INVALID_CONTEXT status code will be returned.

NOTE: The current espeak_Synth, espeak_ng_Synthesize, espeak_Synth_Mark, and espeak_ng_SynthesizeMark functions support a unique_identifier parameter. This will work the same as the new context parameter. The only difference is that these APIs will not fail if the context is not registered, so existing applications do not fail.

The synthesize APIs will forward differently in that espeak_Synth will not change, and espeak_ng_SynthesizeForContext will forward to espeak_ng_Synthesize, passing the context parameter as the unique_identifier parameter. Before forwarding, espeak_ng_SynthesizeForContext will check the validity of the context. This will be how backward compatibility is maintained.

espeak-ng@groups.io Integration <espeak-ng@...>
 

[espeak-ng:master] New Comment on Issue #659 Multiple instance of eSpeak inside a single process
By b00f:

Issue #68 will affect this as espeak currently tracks state in global variables. As such, calling espeak_Initialize multiple times will affect any running instances.

I faced the same issue which I couldn't terminate eSpeak-ng instances if two instances is loaded. Another topic. But it's good to mention it here.

Thanks for your explanation. If I am not mistake you are suggestion using context for loading two instance at the same time?

espeak-ng@groups.io Integration <espeak-ng@...>
 

[espeak-ng:master] New Comment on Issue #659 Multiple instance of eSpeak inside a single process
By rhdunn:

Think of a context being like a thread (voice settings, etc.) instead of a process (instance of espeak). There will only be one instance of espeak initialized, but each context will maintain its own voice stack, etc.

This means that if you are not using a synchronized mode, you need to be careful to ensure to not call the synthesize methods from different threads at the same time as they will interfere with each other.