commit e8f60761378fe392d80e89d0e3481316119e9809

Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Tue Jun 30 14:44:09 2009 +0000

    Further build and install integration
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1030 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 5b410e0dfc1852ee5c0d56d64b326d5130aed18a
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Tue Jun 30 13:24:27 2009 +0000

    Added utility project (preparesphinx) to copy the stuff pocketsphinx requires to run
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1029 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 2457575de160b378affdfa7a37cac1282d0024ca
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Tue Jun 30 13:18:59 2009 +0000

    Added a few more comments in config file
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1028 f001bc3a-424a-0410-80a0-a715b8f413a8

commit ffc40b15b409a79bdea286898ad1e8694fc1623c
Author: garmt.noname@gmail.com <garmt.noname@gmail.com@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Tue Jun 30 10:38:54 2009 +0000

    Added resampling to 8kHz so that it works with freeswitch (specify only L16/96/8000 codec in profile of media_engine/rtpfactory).
    Changed logging to DEBUG level rather than INFO.
    Added channel_guard for stop response.
    
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1027 f001bc3a-424a-0410-80a0-a715b8f413a8

commit d11439611186b46f1bfabc036b7e5d76f33f8b0e
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Mon Jun 29 19:46:54 2009 +0000

    Added entries for PocketSphinx (mrcppocketsphinx) and Flite (mrcpflite) plugins into unimrcpserver.xml (disabled by default)
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1026 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 63bc73426ba4efdf648a28cd3c1ff1daaef5bb49
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Mon Jun 29 15:04:01 2009 +0000

    Added enumeration of pocketsphinx models (narrowband, wideband), supported wideband either
    
    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1025 f001bc3a-424a-0410-80a0-a715b8f413a8

commit d11439611186b46f1bfabc036b7e5d76f33f8b0e
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Mon Jun 29 19:46:54 2009 +0000

    Added entries for PocketSphinx (mrcppocketsphinx) and Flite (mrcpflite) plugins into unimrcpserver.xml (disabled by default)

    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1026 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 63bc73426ba4efdf648a28cd3c1ff1daaef5bb49
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Mon Jun 29 15:04:01 2009 +0000

    Added enumeration of pocketsphinx models (narrowband, wideband), supported wideband either

    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1025 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 04970484e4357e2a1c3c4385840640caada33468
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Mon Jun 29 13:21:35 2009 +0000

    Removed engine->guard, as all relevant calls are made within the context of the same thread

    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1024 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 9bac2f3abdcfea5397aca4b86e209af090631e7a
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Mon Jun 29 13:15:30 2009 +0000

    Initialized 16kHz codec descriptor for flite channel, since available flite voice are in 16kHz.

    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1023 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 4e902eb985b433416723f15646d3e99d385d18cb
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Sun Jun 28 20:05:22 2009 +0000

    Do not create bridge if resampling is required.
    Several sampling rates are supported, but there is no resampling yet.

    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1022 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 6d35b1246a7061e4c8f3f608bb17e146870d63bd
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Sun Jun 28 18:14:25 2009 +0000

    Added makefile target to install pocketsphinx.xml with make install

    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1021 f001bc3a-424a-0410-80a0-a715b8f413a8

commit c2b75c89d57c02bd8d4360aebcb7406ecbf90eb0
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Sun Jun 28 18:10:01 2009 +0000

    Set svn props (eol:native)

    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1020 f001bc3a-424a-0410-80a0-a715b8f413a8

commit dd91ebea823dd2169e8c30f0cfe87fa199e1a0c2
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Sun Jun 28 17:46:46 2009 +0000

    Loaded pocketsphinx's properties from config file

    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1019 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 2ba91890593d7a64136e675bb937efd9a2542cc7
Author: garmt.noname@gmail.com <garmt.noname@gmail.com@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Sun Jun 28 12:29:54 2009 +0000

    Removed session tasks, most channel tasks, flite voices are no longer global

    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1018 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 0d739127f9267b3ad871d1a53a863802f101a6b5
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Sat Jun 27 09:15:20 2009 +0000

    Implemented save_waveform, utterance will be saved in the filesystem

    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1017 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 4ffd282ddf54ad861d73f36567ad201d135feff5
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Sat Jun 27 08:24:19 2009 +0000

    Set 2 digits precision (digits after the decimal point) while generating float type values (Issue-35).

    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1016 f001bc3a-424a-0410-80a0-a715b8f413a8

commit 90446f5e6ece40e91fd5b340a45e6773e4e80a0f
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8>
Date:   Sat Jun 27 07:42:52 2009 +0000

    Set noinut and recognition timeouts if specified in RECOGNIZE request, reset input timer on partial match

    git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1015 f001bc3a-424a-0410-80a0-a715b8f413a8



git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@14104 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
Brian West
2009-07-02 00:54:48 +00:00
parent 03b73eb46e
commit 6d8d1a09d0
15 changed files with 776 additions and 453 deletions

View File

@@ -37,7 +37,6 @@
typedef struct flite_synth_engine_t flite_synth_engine_t;
typedef struct flite_synth_channel_t flite_synth_channel_t;
typedef struct flite_synth_msg_t flite_synth_msg_t;
/** Declaration of synthesizer engine methods */
static apt_bool_t flite_synth_engine_destroy(mrcp_resource_engine_t *engine);
@@ -58,6 +57,16 @@ static apt_bool_t flite_synth_channel_open(mrcp_engine_channel_t *channel);
static apt_bool_t flite_synth_channel_close(mrcp_engine_channel_t *channel);
static apt_bool_t flite_synth_channel_request_process(mrcp_engine_channel_t *channel, mrcp_message_t *request);
static apt_bool_t flite_synth_channel_close_t(mrcp_engine_channel_t *channel); // wait for speak thread
/** flite channel methods for processing MRCP channel request **/
static apt_bool_t flite_synth_channel_speak(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response);
static apt_bool_t flite_synth_channel_stop(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response);
static apt_bool_t flite_synth_channel_pause(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response);
static apt_bool_t flite_synth_channel_resume(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response);
// static apt_bool_t flite_synth_channel_setparams(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response);
// static apt_bool_t flite_synth_channel_getparams(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response);
static const struct mrcp_engine_channel_method_vtable_t channel_vtable = {
flite_synth_channel_destroy,
flite_synth_channel_open,
@@ -83,34 +92,25 @@ static const mpf_audio_stream_vtable_t audio_stream_vtable = {
/** Declaration of flite synthesizer engine */
struct flite_synth_engine_t {
apt_consumer_task_t *task;
int iChannels;
apr_thread_mutex_t *guard;
struct {
cst_voice *awb;
cst_voice *kal;
cst_voice *rms;
cst_voice *slt;
} voices;
};
// flite stuff
APT_BEGIN_EXTERN_C
/** declarations for flite voices **/
cst_voice *register_cmu_us_awb(void);
void unregister_cmu_us_awb(cst_voice * v);
cst_voice *register_cmu_us_kal(void);
void unregister_cmu_us_kal(cst_voice * v);
cst_voice *register_cmu_us_rms(void);
void unregister_cmu_us_rms(cst_voice * v);
cst_voice *register_cmu_us_slt(void);
void unregister_cmu_us_awb(cst_voice * v);
void unregister_cmu_us_kal(cst_voice * v);
void unregister_cmu_us_rms(cst_voice * v);
void unregister_cmu_us_slt(cst_voice * v);
APT_END_EXTERN_C
static struct {
cst_voice *awb;
cst_voice *kal;
cst_voice *rms;
cst_voice *slt;
} voices;
/** Declaration of flite synthesizer channel */
struct flite_synth_channel_t {
@@ -122,27 +122,12 @@ struct flite_synth_channel_t {
mpf_buffer_t *audio_buffer; // Audio buffer
int iId; // Synth channel simultaneous reference count
cst_voice *voice;
cst_wave *wave;
apr_pool_t *pool;
apt_consumer_task_t *task;
apr_thread_mutex_t *channel_guard;
};
typedef enum flite_synth_msg_type_e {
flite_synth_MSG_OPEN_CHANNEL,
flite_synth_MSG_CLOSE_CHANNEL,
flite_synth_MSG_REQUEST_PROCESS
} flite_synth_msg_type_e;
/** Declaration of flite synthesizer task message */
struct flite_synth_msg_t {
flite_synth_msg_type_e type;
mrcp_engine_channel_t *channel;
mrcp_message_t *request;
};
/* mutex: may be flite library is not thread safe*/
static apr_thread_mutex_t *flite_mutex;
struct flite_speak_msg_t {
flite_synth_channel_t *channel;
mrcp_message_t *request;
@@ -150,16 +135,9 @@ struct flite_speak_msg_t {
typedef struct flite_speak_msg_t flite_speak_msg_t;
// all calls to the Flite API functions (after initialization)
// will be carried out using a separate task
static apt_bool_t flite_synth_msg_signal(flite_synth_msg_type_e type, mrcp_engine_channel_t *channel, mrcp_message_t *request);
static apt_bool_t flite_synth_msg_process(apt_task_t *task, apt_task_msg_t *msg);
static apt_bool_t flite_synth_channel_open_t(mrcp_engine_channel_t * channel);
static apt_bool_t flite_synth_channel_close_t(mrcp_engine_channel_t * channel);
// and we have a special task for the actual synthesis -
// we have a special task for the actual synthesis -
// the task is created when a mrcp speak message is received
static apt_bool_t flite_speak_msg_process(apt_task_t *task, apt_task_msg_t *msg);
static apt_bool_t flite_speak(apt_task_t *task, apt_task_msg_t *msg);
/** Declare this macro to use log routine of the server where the plugin is loaded from */
MRCP_PLUGIN_LOGGER_IMPLEMENT
@@ -169,44 +147,9 @@ MRCP_PLUGIN_DECLARE(mrcp_resource_engine_t*) mrcp_plugin_create(apr_pool_t *pool
{
/* create flite engine */
flite_synth_engine_t *flite_engine = (flite_synth_engine_t *) apr_palloc(pool,sizeof(flite_synth_engine_t));
apt_task_msg_pool_t *msg_pool;
apt_task_vtable_t *task_vtable = 0;
flite_engine->iChannels = 0;
/* create task/thread to run flite engine in the context of this task */
msg_pool = apt_task_msg_pool_create_dynamic(sizeof(flite_synth_msg_t),pool);
flite_engine->task = apt_consumer_task_create(flite_engine,msg_pool,pool);
if (!flite_engine->task)
{
apt_log(APT_LOG_MARK, APT_PRIO_ERROR, "MRCP_PLUGIN_DECLARE cannot create task");
return NULL;
}
task_vtable = apt_consumer_task_vtable_get(flite_engine->task);
if (task_vtable)
{
task_vtable->process_msg = flite_synth_msg_process;
}
else
{
apt_log(APT_LOG_MARK, APT_PRIO_ERROR, "MRCP_PLUGIN_DECLARE cannot use task vtable");
return NULL;
}
/* create flite mutex */
if (apr_thread_mutex_create(&flite_mutex,APR_THREAD_MUTEX_DEFAULT,pool) != APR_SUCCESS)
{
apt_log(APT_LOG_MARK, APT_PRIO_ERROR,"Failed to create flite mutex");
return NULL;
}
/* create channel mutex */
if (apr_thread_mutex_create(&flite_engine->guard,APR_THREAD_MUTEX_DEFAULT,pool) != APR_SUCCESS)
{
apt_log(APT_LOG_MARK, APT_PRIO_ERROR, "Failed to create channel guard");
return NULL;
}
/* create resource engine base */
return mrcp_resource_engine_create(
MRCP_SYNTHESIZER_RESOURCE, /* MRCP resource identifier */
@@ -218,17 +161,7 @@ MRCP_PLUGIN_DECLARE(mrcp_resource_engine_t*) mrcp_plugin_create(apr_pool_t *pool
/** Destroy synthesizer engine */
static apt_bool_t flite_synth_engine_destroy(mrcp_resource_engine_t *engine)
{
flite_synth_engine_t *flite_engine = (flite_synth_engine_t *) engine->obj;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_engine_destroy");
if(flite_engine->task) {
apt_task_t *task = apt_consumer_task_base_get(flite_engine->task);
apt_task_destroy(task);
flite_engine->task = NULL;
}
apr_thread_mutex_destroy(flite_engine->guard);
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_engine_destroy");
return TRUE;
}
@@ -236,19 +169,16 @@ static apt_bool_t flite_synth_engine_destroy(mrcp_resource_engine_t *engine)
static apt_bool_t flite_synth_engine_open(mrcp_resource_engine_t *engine)
{
flite_synth_engine_t *flite_engine = (flite_synth_engine_t *) engine->obj;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_engine_open");
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_engine_open");
flite_init();
voices.awb = register_cmu_us_awb();
voices.kal = register_cmu_us_kal();
voices.rms = register_cmu_us_rms();
voices.slt = register_cmu_us_slt();
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "fliteInitialize success");
flite_engine->voices.awb = register_cmu_us_awb();
flite_engine->voices.kal = register_cmu_us_kal();
flite_engine->voices.rms = register_cmu_us_rms();
flite_engine->voices.slt = register_cmu_us_slt();
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite init success");
if (flite_engine->task) {
apt_task_t *task = apt_consumer_task_base_get(flite_engine->task);
apt_task_start(task);
}
return TRUE;
}
@@ -256,18 +186,12 @@ static apt_bool_t flite_synth_engine_open(mrcp_resource_engine_t *engine)
static apt_bool_t flite_synth_engine_close(mrcp_resource_engine_t *engine)
{
flite_synth_engine_t *flite_engine = (flite_synth_engine_t *) engine->obj;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_engine_close");
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_engine_close");
if (flite_engine->task)
{
apt_task_t *task = apt_consumer_task_base_get(flite_engine->task);
apt_task_terminate(task,TRUE);
}
unregister_cmu_us_awb(voices.awb);
unregister_cmu_us_kal(voices.kal);
unregister_cmu_us_rms(voices.rms);
unregister_cmu_us_slt(voices.slt);
unregister_cmu_us_awb(flite_engine->voices.awb);
unregister_cmu_us_kal(flite_engine->voices.kal);
unregister_cmu_us_rms(flite_engine->voices.rms);
unregister_cmu_us_slt(flite_engine->voices.slt);
return TRUE;
}
@@ -279,24 +203,31 @@ static mrcp_engine_channel_t* flite_synth_engine_channel_create(mrcp_resource_en
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) apr_palloc(pool,sizeof(flite_synth_channel_t));
mpf_codec_descriptor_t *codec_descriptor = NULL;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_engine_channel_create");
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_engine_channel_create");
// codec_descriptor = (mpf_codec_descriptor_t *) apr_palloc(pool,sizeof(mpf_codec_descriptor_t));
// codec_descriptor = (mpf_codec_descriptor_t *) apr_palloc(pool,sizeof(mpf_codec_descriptor_t));
// mpf_codec_descriptor_init(codec_descriptor);
// codec_descriptor->channel_count = 1;
// codec_descriptor->payload_type = 96;
// apt_string_set(&codec_descriptor->name,"L16");
// apt_string_set(&codec_descriptor->name,"LPCM");
// codec_descriptor->sampling_rate = 16000;
//
synth_channel->flite_engine = (flite_synth_engine_t *) engine->obj;
synth_channel->speak_request = NULL; // no active speak request in progress
synth_channel->stop_response = NULL;
synth_channel->paused = FALSE;
synth_channel->pool = pool;
synth_channel->wave = NULL;
synth_channel->audio_buffer = NULL;
synth_channel->voice = NULL;
synth_channel->iId = 0;
if (apr_thread_mutex_create(&synth_channel->channel_guard,APR_THREAD_MUTEX_DEFAULT,pool) != APR_SUCCESS)
{
apt_log(APT_LOG_MARK, APT_PRIO_ERROR, "Failed to create channel guard");
return NULL;
}
/* create engine channel base */
synth_channel->channel = mrcp_engine_source_channel_create(
engine, /* resource engine */
@@ -313,9 +244,7 @@ static mrcp_engine_channel_t* flite_synth_engine_channel_create(mrcp_resource_en
}
synth_channel->audio_buffer = mpf_buffer_create(pool);
apr_thread_mutex_lock(synth_channel->flite_engine->guard);
synth_channel->iId = ++synth_channel->flite_engine->iChannels;
apr_thread_mutex_unlock(synth_channel->flite_engine->guard);
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_engine_channel_create created channel %d", synth_channel->iId);
@@ -326,24 +255,24 @@ static mrcp_engine_channel_t* flite_synth_engine_channel_create(mrcp_resource_en
static apt_bool_t flite_synth_channel_destroy(mrcp_engine_channel_t *channel)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_channel_destroy - channel %d", synth_channel->iId);
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_channel_destroy - channel %d", synth_channel->iId);
if(synth_channel->task)
{
apt_task_t *task = apt_consumer_task_base_get(synth_channel->task);
if (!apt_task_destroy(task))
if (!task || !apt_task_destroy(task))
{
apt_log(APT_LOG_MARK, APT_PRIO_WARNING, "Speak task destroy failed - channel %d", synth_channel->iId);
}
else
{
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "Speak task destroyed - channel %d", synth_channel->iId);
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "Speak task destroyed - channel %d", synth_channel->iId);
}
}
synth_channel->task = NULL;
apr_thread_mutex_lock(synth_channel->flite_engine->guard);
synth_channel->flite_engine->iChannels--;
apr_thread_mutex_unlock(synth_channel->flite_engine->guard);
apr_thread_mutex_destroy(synth_channel->channel_guard);
return TRUE;
}
@@ -352,210 +281,30 @@ static apt_bool_t flite_synth_channel_destroy(mrcp_engine_channel_t *channel)
static apt_bool_t flite_synth_channel_open(mrcp_engine_channel_t *channel)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_channel_open - channel %d", synth_channel->iId);
return flite_synth_msg_signal(flite_synth_MSG_OPEN_CHANNEL,channel,NULL);
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_channel_open - channel %d", synth_channel->iId);
synth_channel->voice = synth_channel->flite_engine->voices.awb;
return mrcp_engine_channel_open_respond(channel,TRUE);
}
/** Close engine channel (asynchronous response MUST be sent)*/
static apt_bool_t flite_synth_channel_close(mrcp_engine_channel_t *channel)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_channel_close - channel %d", synth_channel->iId);
return flite_synth_msg_signal(flite_synth_MSG_CLOSE_CHANNEL,channel,NULL);
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_channel_close - channel %d", synth_channel->iId);
// create thread to wait for speak thread to terminate
flite_synth_channel_close_t(channel);
return TRUE;
}
/** Process MRCP channel request (asynchronous response MUST be sent)*/
static apt_bool_t flite_synth_channel_request_process(mrcp_engine_channel_t *channel, mrcp_message_t *request)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_channel_request_process - channel %d", synth_channel->iId);
return flite_synth_msg_signal(flite_synth_MSG_REQUEST_PROCESS,channel,request);
}
/** Open engine channel */
static apt_bool_t flite_synth_channel_open_t(mrcp_engine_channel_t *channel)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_channel_open_t - channel %d", synth_channel->iId);
synth_channel->voice = voices.awb;
return TRUE;
}
static apt_bool_t flite_synth_channel_close_t(mrcp_engine_channel_t *channel)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_channel_close_t - channel %d", synth_channel->iId);
if (synth_channel->task)
{
apt_task_t *task = apt_consumer_task_base_get(synth_channel->task);
if (!apt_task_terminate(task,TRUE))
{
apt_log(APT_LOG_MARK, APT_PRIO_WARNING, "Speak task terminate failed - channel %d", synth_channel->iId);
}
else
{
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "Speak task terminated - channel %d", synth_channel->iId);
apt_task_destroy(task);
synth_channel->task = 0;
}
}
if (synth_channel->wave)
{
delete_wave(synth_channel->wave);
synth_channel->wave = 0;
}
else
{
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "No wave buffer to delete - channel %d", synth_channel->iId);
}
return TRUE;
}
/** Process SPEAK request */
static apt_bool_t flite_synth_channel_speak(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_channel_speak - channel %d", synth_channel->iId);
if (!synth_channel->speak_request)
{
apt_task_msg_pool_t *msg_pool = apt_task_msg_pool_create_dynamic( sizeof(flite_speak_msg_t),synth_channel->pool);
apt_task_vtable_t *task_vtable = 0;
apt_task_t * task = 0;
apt_task_msg_t *msg = 0;
flite_speak_msg_t *flite_msg = 0;
/* create task/thread to run flite so this function is not blocking */
apt_log(APT_LOG_MARK,APT_PRIO_NOTICE,"Create flite speak task - channel: %d", synth_channel->iId);
synth_channel->task = apt_consumer_task_create(synth_channel, msg_pool, synth_channel->pool);
if (!synth_channel->task)
{
apt_log(APT_LOG_MARK,APT_PRIO_ERROR, "flite_synth_channel_speak failed to create flite speak task - channel:%d", synth_channel->iId);
return FALSE;
}
task_vtable = apt_consumer_task_vtable_get(synth_channel->task);
if (!task_vtable)
{
apt_log(APT_LOG_MARK,APT_PRIO_ERROR, "flite_synth_channel_speak cannot use flite speak task vtable - channel:%d", synth_channel->iId);
return FALSE;
}
task_vtable->process_msg = flite_speak_msg_process;
synth_channel->speak_request = request;
apt_log(APT_LOG_MARK,APT_PRIO_INFO, "Start task - channel %d", synth_channel->iId);
task = apt_consumer_task_base_get(synth_channel->task);
if (apt_task_start(task) == FALSE)
{
apt_log(APT_LOG_MARK,APT_PRIO_ERROR, "flite_synth_channel_speak failed to start task - channel: %d", synth_channel->iId);
apt_task_destroy(task);
return FALSE;
}
msg = apt_task_msg_acquire(msg_pool);
msg->type = TASK_MSG_USER;
flite_msg = (flite_speak_msg_t*) msg->data;
flite_msg->channel = synth_channel;
flite_msg->request = request;
apt_log(APT_LOG_MARK,APT_PRIO_INFO, "Send signal to start speech synthesis - channel:%d", synth_channel->iId);
if (apt_task_msg_signal(task,msg))
{
response->start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
mrcp_engine_channel_message_send(channel,response);
}
else
{
apt_log(APT_LOG_MARK,APT_PRIO_INFO, "Failed to send signal to start speech synthesis - channel:%d", synth_channel->iId);
apt_task_destroy(task);
return FALSE;
}
}
return TRUE;
}
static apt_bool_t flite_speak_msg_process(apt_task_t *task, apt_task_msg_t *msg)
{
flite_speak_msg_t *flite_msg = (flite_speak_msg_t*)msg->data;
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) flite_msg->channel;
apr_time_t start = 0;
apr_time_t elapsed = 0;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "< flite_speak_msg_process speak - channel %d", synth_channel->iId);
// probably not necessary !?
mpf_buffer_restart(synth_channel->audio_buffer);
// just sequential stuff
start = apr_time_now(); // in microsec
if (synth_channel->speak_request->body.length)
{
cst_wave * wave = synth_channel->wave;
wave = flite_text_to_wave(synth_channel->speak_request->body.buf, synth_channel->voice);
}
elapsed = (apr_time_now() - start)/1000;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "TTS (chan %d) took %ld millisec", synth_channel->iId, elapsed);
if (!synth_channel->stop_response)
{
// this will notify the callback that feeds the client that synthesis is complete
mpf_buffer_event_write(synth_channel->audio_buffer, MEDIA_FRAME_TYPE_EVENT);
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "> flite_speak_msg_process speak - end of TTS - %d", synth_channel->iId);
}
else
{
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "> flite_speak_msg_process speak - channel %d", synth_channel->iId);
}
return TRUE;
}
/** Process STOP request */
static apt_bool_t flite_synth_channel_stop(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_channel_stop - channel %d", synth_channel->iId);
/* store the request, make sure there is no more activity and only then send the response */
/* TODO this should probably be mutexed */
synth_channel->stop_response = response;
return TRUE;
}
/** Process PAUSE request */
static apt_bool_t flite_synth_channel_pause(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_channel_pause - channel %d", synth_channel->iId);
synth_channel->paused = TRUE;
/* send asynchronous response */
mrcp_engine_channel_message_send(channel,response);
return TRUE;
}
/** Process RESUME request */
static apt_bool_t flite_synth_channel_resume(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_channel_resume - channel %d", synth_channel->iId);
synth_channel->paused = FALSE;
/* send asynchronous response */
mrcp_engine_channel_message_send(channel,response);
return TRUE;
}
/** Dispatch MRCP request */
static apt_bool_t flite_synth_channel_request_dispatch(mrcp_engine_channel_t *channel, mrcp_message_t *request)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
apt_bool_t processed = FALSE;
mrcp_message_t *response = mrcp_response_create(request,request->pool);
apt_bool_t processed = FALSE;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_channel_request_dispatch - channel %d", synth_channel->iId);
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_channel_request_process - channel %d", synth_channel->iId);
switch(request->start_line.method_id) {
case SYNTHESIZER_SET_PARAMS:
@@ -563,13 +312,13 @@ static apt_bool_t flite_synth_channel_request_dispatch(mrcp_engine_channel_t *ch
// if (!strcasecmp(voice_name, "awb")) {
// synth_channel->voice = voices.awb;
// } else if (!strcasecmp(voice_name, "kal")) {
// synth_channel->voice = voices.awb;
// synth_channel->voice = voices.kal;
// } else if (!strcasecmp(voice_name, "rms")) {
// synth_channel->voice = voices.awb;
// synth_channel->voice = voices.rms;
// } else if (!strcasecmp(voice_name, "slt")) {
// synth_channel->voice = voices.awb;
// synth_channel->voice = voices.slt;
// } else {
// apt_log(APT_LOG_MARK, APT_PRIO_INFO, "Valid voice names are awb, kal, rms or slt");
// apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "Valid voice names are awb, kal, rms or slt");
// }
break;
case SYNTHESIZER_GET_PARAMS:
@@ -601,6 +350,195 @@ static apt_bool_t flite_synth_channel_request_dispatch(mrcp_engine_channel_t *ch
mrcp_engine_channel_message_send(channel,response);
}
return TRUE;
}
static apt_bool_t flite_synth_channel_close_t(mrcp_engine_channel_t *channel)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_channel_close_t - channel %d", synth_channel->iId);
if (synth_channel->task)
{
apt_task_t *task = apt_consumer_task_base_get(synth_channel->task);
if (!apt_task_terminate(task,TRUE))
{
apt_log(APT_LOG_MARK, APT_PRIO_WARNING, "Speak task terminate failed - channel %d", synth_channel->iId);
}
else
{
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "Speak task terminated - channel %d", synth_channel->iId);
apt_task_destroy(task);
synth_channel->task = 0;
}
}
mrcp_engine_channel_close_respond(channel);
return TRUE;
}
/** Process SPEAK request */
static apt_bool_t flite_synth_channel_speak(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_channel_speak - channel %d", synth_channel->iId);
if (!synth_channel->speak_request)
{
apt_task_msg_pool_t *msg_pool = apt_task_msg_pool_create_dynamic( sizeof(flite_speak_msg_t),synth_channel->pool);
apt_task_vtable_t *task_vtable = 0;
apt_task_t * task = 0;
apt_task_msg_t *msg = 0;
flite_speak_msg_t *flite_msg = 0;
/* create task/thread to run flite so this function is not blocking */
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "Create flite speak task - channel: %d", synth_channel->iId);
synth_channel->task = apt_consumer_task_create(synth_channel, msg_pool, synth_channel->pool);
if (!synth_channel->task)
{
apt_log(APT_LOG_MARK,APT_PRIO_ERROR, "flite_synth_channel_speak failed to create flite speak task - channel:%d", synth_channel->iId);
return FALSE;
}
task_vtable = apt_consumer_task_vtable_get(synth_channel->task);
if (!task_vtable)
{
apt_log(APT_LOG_MARK,APT_PRIO_ERROR, "flite_synth_channel_speak cannot use flite speak task vtable - channel:%d", synth_channel->iId);
return FALSE;
}
task_vtable->process_msg = flite_speak;
synth_channel->speak_request = request;
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG, "Start task - channel %d", synth_channel->iId);
task = apt_consumer_task_base_get(synth_channel->task);
if (apt_task_start(task) == FALSE)
{
apt_log(APT_LOG_MARK,APT_PRIO_ERROR, "flite_synth_channel_speak failed to start task - channel: %d", synth_channel->iId);
apt_task_destroy(task);
return FALSE;
}
msg = apt_task_msg_acquire(msg_pool);
msg->type = TASK_MSG_USER;
flite_msg = (flite_speak_msg_t*) msg->data;
flite_msg->channel = synth_channel;
flite_msg->request = request;
apt_log(APT_LOG_MARK,APT_PRIO_DEBUG, "Send signal to start speech synthesis - channel:%d", synth_channel->iId);
if (apt_task_msg_signal(task,msg))
{
response->start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
mrcp_engine_channel_message_send(channel,response);
}
else
{
apt_log(APT_LOG_MARK,APT_PRIO_WARNING, "Failed to send signal to start speech synthesis - channel:%d", synth_channel->iId);
apt_task_destroy(task);
return FALSE;
}
}
return TRUE;
}
static apt_bool_t flite_speak(apt_task_t *task, apt_task_msg_t *msg)
{
flite_speak_msg_t *flite_msg = (flite_speak_msg_t*)msg->data;
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) flite_msg->channel;
apr_time_t start = 0;
apr_time_t elapsed = 0;
apr_time_t stamp = 0;
mrcp_message_t *stop_response = 0;
mpf_codec_t * codec = mrcp_engine_source_stream_codec_get(synth_channel->channel);
apr_uint16_t rate = codec->descriptor->sampling_rate;
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "< flite_speak_msg_process speak - channel %d", synth_channel->iId);
// just sequential stuff
start = apr_time_now(); // in microsec
if (synth_channel->speak_request->body.length)
{
// TODO
// create small units of text from synth_channel->speak_request->body.buf ( , . ? ! but ...
// synthesize small unit and store in audio_buffer
// check for stop
// pause resume state could improve performance
// you can "pause" generating new speech from a unit of text
// by checking the (decreasing) size of the audio_buffer
// no need to generate more speech samples than can be listened to...
cst_wave *wave = 0;
wave = flite_text_to_wave(synth_channel->speak_request->body.buf, synth_channel->voice);
if (wave && cst_wave_num_samples(wave))
{
int generated = (cst_wave_num_samples(wave)/cst_wave_sample_rate(wave)*1000);
stamp = apr_time_now();
elapsed = (stamp - start)/1000;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "TTS (chan %d) took %"APR_TIME_T_FMT" to generate %d of speech (in millisec)", synth_channel->iId, elapsed, generated);
if (rate != 16000)
{
cst_wave_resample(wave, rate);
elapsed = (apr_time_now() - stamp)/1000;
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "TTS resampling to %d on (chan %d) took %"APR_TIME_T_FMT" millisec", rate, synth_channel->iId, elapsed);
}
mpf_buffer_audio_write(synth_channel->audio_buffer, cst_wave_samples(wave), cst_wave_num_samples(wave) * 2);
delete_wave(wave);
}
}
apr_thread_mutex_lock(synth_channel->channel_guard);
stop_response = synth_channel->stop_response;
apr_thread_mutex_unlock(synth_channel->channel_guard);
if (!stop_response)
{
// this will notify the callback that feeds the client that synthesis is complete
mpf_buffer_event_write(synth_channel->audio_buffer, MEDIA_FRAME_TYPE_EVENT);
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "> flite_speak_msg_process speak - end of TTS - %d", synth_channel->iId);
}
else
{
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "> flite_speak_msg_process speak - channel %d", synth_channel->iId);
}
return TRUE;
}
/** Process STOP request */
static apt_bool_t flite_synth_channel_stop(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_channel_stop - channel %d", synth_channel->iId);
/* store the request, make sure there is no more activity and only then send the response */
apr_thread_mutex_lock(synth_channel->channel_guard);
synth_channel->stop_response = response;
apr_thread_mutex_unlock(synth_channel->channel_guard);
return TRUE;
}
/** Process PAUSE request */
static apt_bool_t flite_synth_channel_pause(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_channel_pause - channel %d", synth_channel->iId);
synth_channel->paused = TRUE;
/* send asynchronous response */
mrcp_engine_channel_message_send(channel,response);
return TRUE;
}
/** Process RESUME request */
static apt_bool_t flite_synth_channel_resume(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_channel_resume - channel %d", synth_channel->iId);
synth_channel->paused = FALSE;
/* send asynchronous response */
mrcp_engine_channel_message_send(channel,response);
return TRUE;
}
/** Callback is called from MPF engine context to destroy any additional data associated with audio stream */
@@ -613,16 +551,16 @@ static apt_bool_t flite_synth_stream_destroy(mpf_audio_stream_t *stream)
/** Callback is called from MPF engine context to perform any action before open */
static apt_bool_t flite_synth_stream_open(mpf_audio_stream_t *stream)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) stream->obj;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_stream_open - channel %d", synth_channel->iId);
// flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) stream->obj;
// apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_stream_open - channel %d", synth_channel->iId);
return TRUE;
}
/** Callback is called from MPF engine context to perform any action after close */
static apt_bool_t flite_synth_stream_close(mpf_audio_stream_t *stream)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) stream->obj;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_stream_close - channel %d", synth_channel->iId);
// flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) stream->obj;
// apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_stream_close - channel %d", synth_channel->iId);
return TRUE;
}
@@ -631,7 +569,7 @@ static apt_bool_t flite_synth_speak_complete_raise(flite_synth_channel_t *synth_
{
mrcp_message_t *message = 0;
mrcp_synth_header_t * synth_header = 0;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_speak_complete_raise - channel %d", synth_channel->iId);
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_speak_complete_raise - channel %d", synth_channel->iId);
if (!synth_channel->speak_request) {
return FALSE;
@@ -664,7 +602,6 @@ static apt_bool_t flite_synth_speak_complete_raise(flite_synth_channel_t *synth_
static apt_bool_t flite_synth_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) stream->obj;
cst_wave * wave = synth_channel->wave;
if (synth_channel->stop_response && synth_channel->speak_request)
{
/* send asynchronous response to STOP request */
@@ -674,17 +611,12 @@ static apt_bool_t flite_synth_stream_read(mpf_audio_stream_t *stream, mpf_frame_
return TRUE;
}
if (wave && cst_wave_num_samples(wave))
{
mpf_buffer_audio_write(synth_channel->audio_buffer, cst_wave_samples(wave), cst_wave_num_samples(wave) * 2);
}
/* check if there is active SPEAK request and it isn't in paused state */
if (synth_channel->speak_request && synth_channel->paused == FALSE)
{
/* normal processing */
mpf_buffer_frame_read(synth_channel->audio_buffer,frame);
// apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_stream_read - channel %d - size %d", synth_channel->iId, mpf_buffer_get_size(synth_channel->audio_buffer));
// apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_stream_read - channel %d - size %d", synth_channel->iId, mpf_buffer_get_size(synth_channel->audio_buffer));
if((frame->type & MEDIA_FRAME_TYPE_EVENT) == MEDIA_FRAME_TYPE_EVENT)
{
@@ -692,58 +624,4 @@ static apt_bool_t flite_synth_stream_read(mpf_audio_stream_t *stream, mpf_frame_
}
}
return TRUE;
}
static apt_bool_t flite_synth_msg_signal(flite_synth_msg_type_e type, mrcp_engine_channel_t *channel, mrcp_message_t *request)
{
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
apt_bool_t status = FALSE;
flite_synth_engine_t *flite_engine = synth_channel->flite_engine;
apt_task_t *task = apt_consumer_task_base_get(flite_engine->task);
apt_task_msg_t *msg = apt_task_msg_get(task);
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_msg_signal - channel %d", synth_channel->iId);
if (msg) {
flite_synth_msg_t *flite_msg;
msg->type = TASK_MSG_USER;
flite_msg = (flite_synth_msg_t*) msg->data;
flite_msg->type = type;
flite_msg->channel = channel;
flite_msg->request = request;
status = apt_task_msg_signal(task,msg);
}
else
{
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_msg_signal - task msg not found %d", synth_channel->iId);
}
return status;
}
static apt_bool_t flite_synth_msg_process(apt_task_t *task, apt_task_msg_t *msg)
{
flite_synth_msg_t *flite_msg = (flite_synth_msg_t*)msg->data;
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) flite_msg->channel->method_obj;
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_msg_process - channel %d", synth_channel->iId);
switch(flite_msg->type) {
case flite_synth_MSG_OPEN_CHANNEL:
/* open channel and send asynch response */
flite_synth_channel_open_t(flite_msg->channel);
mrcp_engine_channel_open_respond(flite_msg->channel,TRUE);
break;
case flite_synth_MSG_CLOSE_CHANNEL:
/* close channel, make sure there is no activity and send asynch response */
flite_synth_channel_close_t(flite_msg->channel);
mrcp_engine_channel_close_respond(flite_msg->channel);
break;
case flite_synth_MSG_REQUEST_PROCESS:
flite_synth_channel_request_dispatch(flite_msg->channel,flite_msg->request);
break;
default:
break;
}
return TRUE;
}
}