mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-08-13 01:26:58 +00:00
commit dbea6143d6b63765f2d0eba26728c3903d3d2606
Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8> Date: Wed Jul 8 17:37:24 2009 +0000 Added yet another buffer of media frames mpf_frame_buffer. There are a number of similar buffers (mpf_jitter_buffer, mpf_buffer, mpf_frame_buffer). All of them produce mpf_frames as output, but input is somewhat dif ferent. Input is RTP payload in case of mpf_jitter_buffer, synthesized chunks of voice in case of mpf_buffer, and mpf_frame in case of mpf_frame_buffer git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1043 f001bc3a-424a-0410-80a0-a715b8f413a8 commit 1bf7a66012180649bd1f01fd72e483a9e5de3495 Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8> Date: Wed Jul 8 16:33:36 2009 +0000 Fixed termination of client and server stacks (Issue-28) Network client/server stacks generated double TERMINATE_COMPLETE event, while mpf engine generated no TERMINATE_COMPLETE event. git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1042 f001bc3a-424a-0410-80a0-a715b8f413a8 commit 0327cf17779430b51290d22cc7d51130f997f2f2 Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8> Date: Sun Jul 5 19:22:31 2009 +0000 Enhanced flite plugin to - support more than one SPEAK requests in a session (SPEAK -> STOP -> SPEAK or SPEAK-> SPEAK-COMPLETE->SPEAK), task is created upon channel creation and is waiting for consecutive SPEAK requests to process - properly handle race between STOP request and SPEAK-COMPLETE event - respond with IN-PROGRESS, when all the required parameters are checked to be valid and synthesizing is due to start git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1037 f001bc3a-424a-0410-80a0-a715b8f413a8 commit e2f73f9279e54ef3a40cb637a38ab1ff485ea5d3 Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8> Date: Sun Jul 5 03:46:13 2009 +0000 Separated flite voices (unified voice register/unregister routine, select voice by name) git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1036 f001bc3a-424a-0410-80a0-a715b8f413a8 commit 694783a527cb795ca45982c2388895da06dd6009 Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8> Date: Sat Jul 4 05:06:17 2009 +0000 Checked content-type to be "text/plain" as flite doesn't support SSML yet. git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1035 f001bc3a-424a-0410-80a0-a715b8f413a8 commit aafdc6e30e77c40e5470cce844f48ec28a254786 Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8> Date: Fri Jul 3 14:55:10 2009 +0000 Enhanced float value generation to use the precision (digits after decimal sign) user provides by removing optional trailing 0s (if any) Issue-35 git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1034 f001bc3a-424a-0410-80a0-a715b8f413a8 commit bcc2f137956f5c532c0256b064c8a3d1015a46d0 Author: achaloyan <achaloyan@f001bc3a-424a-0410-80a0-a715b8f413a8> Date: Fri Jul 3 07:04:07 2009 +0000 Enhanced RTP port management (Issue-34, Thanks cpsoares) git-svn-id: https://unimrcp.googlecode.com/svn/trunk@1033 f001bc3a-424a-0410-80a0-a715b8f413a8 git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@14166 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
@@ -14,6 +14,6 @@ INCLUDES = -Iinclude \
|
||||
|
||||
plugin_LTLIBRARIES = mrcpflite.la
|
||||
|
||||
mrcpflite_la_SOURCES = src/mrcp_flite.c
|
||||
mrcpflite_la_SOURCES = src/mrcp_flite.c src/flite_voices.c
|
||||
mrcpflite_la_LDFLAGS = -module $(PLUGIN_LT_VERSION)
|
||||
mrcpflite_la_LIBADD = $(UNIMRCP_FLITE_LIBS) -lm
|
||||
|
41
libs/unimrcp/plugins/mrcp-flite/include/flite_voices.h
Normal file
41
libs/unimrcp/plugins/mrcp-flite/include/flite_voices.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __FLITE_VOICES_H__
|
||||
#define __FLITE_VOICES_H__
|
||||
|
||||
/**
|
||||
* @file flite_voices.h
|
||||
* @brief Flite Voices
|
||||
*/
|
||||
|
||||
#include <flite.h>
|
||||
#include <apr_hash.h>
|
||||
#include "mrcp_message.h"
|
||||
|
||||
APT_BEGIN_EXTERN_C
|
||||
|
||||
|
||||
typedef struct flite_voices_t flite_voices_t;
|
||||
|
||||
flite_voices_t* flite_voices_load(apr_pool_t *pool);
|
||||
void flite_voices_unload(flite_voices_t *voices);
|
||||
|
||||
cst_voice* flite_voices_best_match_get(flite_voices_t *voices, mrcp_message_t *message);
|
||||
|
||||
APT_END_EXTERN_C
|
||||
|
||||
#endif /*__FLITE_VOICES_H__*/
|
@@ -149,11 +149,19 @@
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\include\flite_voices.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="src"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\src\flite_voices.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\src\mrcp_flite.c"
|
||||
>
|
||||
|
160
libs/unimrcp/plugins/mrcp-flite/src/flite_voices.c
Normal file
160
libs/unimrcp/plugins/mrcp-flite/src/flite_voices.c
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright 2008 Arsen Chaloyan
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "flite_voices.h"
|
||||
#include "mrcp_synth_header.h"
|
||||
|
||||
typedef struct flite_voice_t flite_voice_t;
|
||||
|
||||
/** Declaration of flite voice */
|
||||
struct flite_voice_t {
|
||||
const char *name;
|
||||
cst_voice *self;
|
||||
cst_voice* (*register_voice)(void);
|
||||
void (*unregister_voice)(cst_voice *);
|
||||
};
|
||||
|
||||
struct flite_voices_t {
|
||||
apr_hash_t *table;
|
||||
apr_pool_t *pool;
|
||||
};
|
||||
|
||||
|
||||
/* declarations for flite voices */
|
||||
cst_voice *register_cmu_us_awb(void);
|
||||
cst_voice *register_cmu_us_kal(void);
|
||||
cst_voice *register_cmu_us_rms(void);
|
||||
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);
|
||||
|
||||
|
||||
static apt_bool_t flite_voices_init(flite_voices_t *voices, apr_pool_t *pool)
|
||||
{
|
||||
flite_voice_t *voice;
|
||||
|
||||
voice = apr_palloc(pool,sizeof(flite_voice_t));
|
||||
voice->name = "awb";
|
||||
voice->self = NULL;
|
||||
voice->register_voice = register_cmu_us_awb;
|
||||
voice->unregister_voice = unregister_cmu_us_awb;
|
||||
apr_hash_set(voices->table,voice->name,APR_HASH_KEY_STRING,voice);
|
||||
|
||||
voice = apr_palloc(pool,sizeof(flite_voice_t));
|
||||
voice->name = "kal";
|
||||
voice->self = NULL;
|
||||
voice->register_voice = register_cmu_us_kal;
|
||||
voice->unregister_voice = unregister_cmu_us_kal;
|
||||
apr_hash_set(voices->table,voice->name,APR_HASH_KEY_STRING,voice);
|
||||
|
||||
voice = apr_palloc(pool,sizeof(flite_voice_t));
|
||||
voice->name = "rms";
|
||||
voice->self = NULL;
|
||||
voice->register_voice = register_cmu_us_rms;
|
||||
voice->unregister_voice = unregister_cmu_us_rms;
|
||||
apr_hash_set(voices->table,voice->name,APR_HASH_KEY_STRING,voice);
|
||||
|
||||
voice = apr_palloc(pool,sizeof(flite_voice_t));
|
||||
voice->name = "slt";
|
||||
voice->self = NULL;
|
||||
voice->register_voice = register_cmu_us_slt;
|
||||
voice->unregister_voice = unregister_cmu_us_slt;
|
||||
apr_hash_set(voices->table,voice->name,APR_HASH_KEY_STRING,voice);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
flite_voices_t* flite_voices_load(apr_pool_t *pool)
|
||||
{
|
||||
flite_voice_t *voice;
|
||||
apr_hash_index_t *it;
|
||||
void *val;
|
||||
|
||||
flite_voices_t *voices = apr_palloc(pool,sizeof(flite_voices_t));
|
||||
voices->pool = pool;
|
||||
voices->table = apr_hash_make(pool);
|
||||
|
||||
/* init voices */
|
||||
flite_voices_init(voices,pool);
|
||||
|
||||
/* register voices */
|
||||
it = apr_hash_first(pool,voices->table);
|
||||
/* walk through the voices and register them */
|
||||
for(; it; it = apr_hash_next(it)) {
|
||||
apr_hash_this(it,NULL,NULL,&val);
|
||||
voice = val;
|
||||
if(voice) {
|
||||
voice->self = voice->register_voice();
|
||||
}
|
||||
}
|
||||
|
||||
return voices;
|
||||
}
|
||||
|
||||
void flite_voices_unload(flite_voices_t *voices)
|
||||
{
|
||||
flite_voice_t *voice;
|
||||
apr_hash_index_t *it;
|
||||
void *val;
|
||||
|
||||
/* unregister voices */
|
||||
it = apr_hash_first(voices->pool,voices->table);
|
||||
/* walk through the voices and register them */
|
||||
for(; it; it = apr_hash_next(it)) {
|
||||
apr_hash_this(it,NULL,NULL,&val);
|
||||
voice = val;
|
||||
if(voice && voice->self) {
|
||||
voice->unregister_voice(voice->self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cst_voice* flite_voices_best_match_get(flite_voices_t *voices, mrcp_message_t *message)
|
||||
{
|
||||
cst_voice *voice = NULL;
|
||||
const char *voice_name = NULL;
|
||||
mrcp_synth_header_t *synth_header = mrcp_resource_header_get(message);
|
||||
if(synth_header) {
|
||||
if(mrcp_resource_header_property_check(message,SYNTHESIZER_HEADER_VOICE_NAME) == TRUE) {
|
||||
voice_name = synth_header->voice_param.name.buf;
|
||||
}
|
||||
}
|
||||
|
||||
if(voice_name) {
|
||||
/* get voice by name */
|
||||
flite_voice_t *flite_voice;
|
||||
flite_voice = apr_hash_get(voices->table,voice_name,APR_HASH_KEY_STRING);
|
||||
if(flite_voice) {
|
||||
voice = flite_voice->self;
|
||||
}
|
||||
}
|
||||
|
||||
if(!voice) {
|
||||
/* still no voice found, get the default one */
|
||||
flite_voice_t *flite_voice = NULL;
|
||||
void *val;
|
||||
apr_hash_index_t *it = apr_hash_first(voices->pool,voices->table);
|
||||
apr_hash_this(it,NULL,NULL,&val);
|
||||
if(val) {
|
||||
flite_voice = val;
|
||||
voice = flite_voice->self;
|
||||
}
|
||||
}
|
||||
return voice;
|
||||
}
|
@@ -24,6 +24,7 @@
|
||||
* 4. Methods (callbacks) of the MPF engine stream MUST not block.
|
||||
*/
|
||||
|
||||
#include "flite_voices.h"
|
||||
#include "mrcp_resource_engine.h"
|
||||
#include "mrcp_synth_resource.h"
|
||||
#include "mrcp_synth_header.h"
|
||||
@@ -33,7 +34,6 @@
|
||||
#include "apr_time.h"
|
||||
#include "apt_consumer_task.h"
|
||||
#include "apt_log.h"
|
||||
#include "flite.h"
|
||||
|
||||
typedef struct flite_synth_engine_t flite_synth_engine_t;
|
||||
typedef struct flite_synth_channel_t flite_synth_channel_t;
|
||||
@@ -57,8 +57,6 @@ 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);
|
||||
@@ -75,15 +73,12 @@ static const struct mrcp_engine_channel_method_vtable_t channel_vtable = {
|
||||
};
|
||||
|
||||
/** Declaration of synthesizer audio stream methods */
|
||||
static apt_bool_t flite_synth_stream_destroy(mpf_audio_stream_t *stream);
|
||||
static apt_bool_t flite_synth_stream_open(mpf_audio_stream_t *stream);
|
||||
static apt_bool_t flite_synth_stream_close(mpf_audio_stream_t *stream);
|
||||
static apt_bool_t flite_synth_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame);
|
||||
|
||||
static const mpf_audio_stream_vtable_t audio_stream_vtable = {
|
||||
flite_synth_stream_destroy,
|
||||
flite_synth_stream_open,
|
||||
flite_synth_stream_close,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
flite_synth_stream_read,
|
||||
NULL,
|
||||
NULL,
|
||||
@@ -92,39 +87,25 @@ static const mpf_audio_stream_vtable_t audio_stream_vtable = {
|
||||
|
||||
/** Declaration of flite synthesizer engine */
|
||||
struct flite_synth_engine_t {
|
||||
int iChannels;
|
||||
struct {
|
||||
cst_voice *awb;
|
||||
cst_voice *kal;
|
||||
cst_voice *rms;
|
||||
cst_voice *slt;
|
||||
} voices;
|
||||
/** Table of flite voices */
|
||||
flite_voices_t *voices;
|
||||
int iChannels;
|
||||
};
|
||||
|
||||
/** declarations for flite voices **/
|
||||
cst_voice *register_cmu_us_awb(void);
|
||||
cst_voice *register_cmu_us_kal(void);
|
||||
cst_voice *register_cmu_us_rms(void);
|
||||
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);
|
||||
|
||||
|
||||
/** Declaration of flite synthesizer channel */
|
||||
struct flite_synth_channel_t {
|
||||
flite_synth_engine_t *flite_engine; // Back pointer to engine
|
||||
mrcp_engine_channel_t *channel; // Engine channel base
|
||||
mrcp_message_t *speak_request; // Active (in-progress) speak request
|
||||
mrcp_message_t *stop_response; // Pending stop response
|
||||
apt_bool_t paused; // Is paused
|
||||
mpf_buffer_t *audio_buffer; // Audio buffer
|
||||
int iId; // Synth channel simultaneous reference count
|
||||
cst_voice *voice;
|
||||
apr_pool_t *pool;
|
||||
apt_consumer_task_t *task;
|
||||
apr_thread_mutex_t *channel_guard;
|
||||
flite_synth_engine_t *flite_engine; /* Back pointer to engine */
|
||||
mrcp_engine_channel_t *channel; /* Engine channel base */
|
||||
mrcp_message_t *speak_request; /* Active (in-progress) speak request */
|
||||
mrcp_message_t *speak_response;/* Pending speak response */
|
||||
mrcp_message_t *stop_response; /* Pending stop response */
|
||||
apt_bool_t synthesizing; /* Is synthesizer task processing speak request */
|
||||
apt_bool_t paused; /* Is paused */
|
||||
mpf_buffer_t *audio_buffer; /* Audio buffer */
|
||||
int iId; /* Synth channel simultaneous reference count */
|
||||
apr_pool_t *pool;
|
||||
apt_task_t *task;
|
||||
apt_task_msg_pool_t *msg_pool;
|
||||
};
|
||||
|
||||
/** Declaration of flite synthesizer task message */
|
||||
@@ -135,8 +116,8 @@ struct flite_speak_msg_t {
|
||||
|
||||
typedef struct flite_speak_msg_t flite_speak_msg_t;
|
||||
|
||||
// we have a special task for the actual synthesis -
|
||||
// the task is created when a mrcp speak message is received
|
||||
/* 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(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 */
|
||||
@@ -147,7 +128,6 @@ 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));
|
||||
|
||||
flite_engine->iChannels = 0;
|
||||
|
||||
/* create resource engine base */
|
||||
@@ -172,13 +152,10 @@ static apt_bool_t flite_synth_engine_open(mrcp_resource_engine_t *engine)
|
||||
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_engine_open");
|
||||
|
||||
flite_init();
|
||||
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();
|
||||
|
||||
flite_engine->voices = flite_voices_load(engine->pool);
|
||||
|
||||
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite init success");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -188,14 +165,36 @@ 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_DEBUG, "flite_synth_engine_close");
|
||||
|
||||
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);
|
||||
flite_voices_unload(flite_engine->voices);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static apt_bool_t flite_synth_task_create(flite_synth_channel_t *synth_channel)
|
||||
{
|
||||
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_consumer_task_t *consumer_task = 0;
|
||||
|
||||
/* create task/thread to run flite synthesizer in */
|
||||
consumer_task = apt_consumer_task_create(synth_channel, msg_pool, synth_channel->pool);
|
||||
if(!consumer_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(consumer_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->msg_pool = msg_pool;
|
||||
synth_channel->task = apt_consumer_task_base_get(consumer_task);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Create flite synthesizer channel derived from engine channel base */
|
||||
static mrcp_engine_channel_t* flite_synth_engine_channel_create(mrcp_resource_engine_t *engine, apr_pool_t *pool)
|
||||
{
|
||||
@@ -204,30 +203,31 @@ static mrcp_engine_channel_t* flite_synth_engine_channel_create(mrcp_resource_en
|
||||
mpf_codec_descriptor_t *codec_descriptor = NULL;
|
||||
|
||||
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));
|
||||
// mpf_codec_descriptor_init(codec_descriptor);
|
||||
// codec_descriptor->channel_count = 1;
|
||||
// codec_descriptor->payload_type = 96;
|
||||
// apt_string_set(&codec_descriptor->name,"LPCM");
|
||||
// codec_descriptor->sampling_rate = 16000;
|
||||
#if 0
|
||||
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,"LPCM");
|
||||
codec_descriptor->sampling_rate = 16000;
|
||||
#endif
|
||||
|
||||
synth_channel->flite_engine = (flite_synth_engine_t *) engine->obj;
|
||||
synth_channel->speak_request = NULL; // no active speak request in progress
|
||||
synth_channel->speak_response = NULL;
|
||||
synth_channel->stop_response = NULL;
|
||||
synth_channel->synthesizing = FALSE;
|
||||
synth_channel->paused = FALSE;
|
||||
synth_channel->pool = pool;
|
||||
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");
|
||||
synth_channel->task = NULL;
|
||||
synth_channel->msg_pool = NULL;
|
||||
if(flite_synth_task_create(synth_channel) != TRUE) {
|
||||
apt_log(APT_LOG_MARK, APT_PRIO_WARNING, "flite_synth_task_create failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* create engine channel base */
|
||||
synth_channel->channel = mrcp_engine_source_channel_create(
|
||||
engine, /* resource engine */
|
||||
@@ -237,9 +237,9 @@ static mrcp_engine_channel_t* flite_synth_engine_channel_create(mrcp_resource_en
|
||||
codec_descriptor, /* codec descriptor might be NULL by default */
|
||||
pool); /* pool to allocate memory from */
|
||||
|
||||
if (!synth_channel->channel)
|
||||
{
|
||||
if(!synth_channel->channel) {
|
||||
apt_log(APT_LOG_MARK, APT_PRIO_WARNING, "flite_synth_engine_channel_create failed");
|
||||
apt_task_destroy(synth_channel->task);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -247,7 +247,6 @@ static mrcp_engine_channel_t* flite_synth_engine_channel_create(mrcp_resource_en
|
||||
synth_channel->iId = ++synth_channel->flite_engine->iChannels;
|
||||
|
||||
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "flite_synth_engine_channel_create created channel %d", synth_channel->iId);
|
||||
|
||||
return synth_channel->channel;
|
||||
}
|
||||
|
||||
@@ -256,24 +255,12 @@ 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_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 (!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_DEBUG, "Speak task destroyed - channel %d", synth_channel->iId);
|
||||
}
|
||||
if(synth_channel->task) {
|
||||
apt_task_destroy(synth_channel->task);
|
||||
synth_channel->task = NULL;
|
||||
}
|
||||
|
||||
synth_channel->task = NULL;
|
||||
synth_channel->flite_engine->iChannels--;
|
||||
|
||||
apr_thread_mutex_destroy(synth_channel->channel_guard);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -283,7 +270,15 @@ 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_DEBUG, "flite_synth_channel_open - channel %d", synth_channel->iId);
|
||||
|
||||
synth_channel->voice = synth_channel->flite_engine->voices.awb;
|
||||
if(synth_channel->task) {
|
||||
if(apt_task_start(synth_channel->task) == TRUE) {
|
||||
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "Speak task started - channel %d", synth_channel->iId);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK, APT_PRIO_WARNING, "Speak task start failed - channel %d", synth_channel->iId);
|
||||
}
|
||||
}
|
||||
|
||||
return mrcp_engine_channel_open_respond(channel,TRUE);
|
||||
}
|
||||
|
||||
@@ -292,8 +287,16 @@ 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_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);
|
||||
|
||||
if(synth_channel->task) {
|
||||
if(apt_task_terminate(synth_channel->task,TRUE) == TRUE) {
|
||||
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "Speak task terminated - channel %d", synth_channel->iId);
|
||||
}
|
||||
else {
|
||||
apt_log(APT_LOG_MARK, APT_PRIO_WARNING, "Speak task terminate failed - channel %d", synth_channel->iId);
|
||||
}
|
||||
}
|
||||
mrcp_engine_channel_close_respond(channel);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -308,18 +311,6 @@ static apt_bool_t flite_synth_channel_request_process(mrcp_engine_channel_t *cha
|
||||
|
||||
switch(request->start_line.method_id) {
|
||||
case SYNTHESIZER_SET_PARAMS:
|
||||
// TODO set voices
|
||||
// if (!strcasecmp(voice_name, "awb")) {
|
||||
// synth_channel->voice = voices.awb;
|
||||
// } else if (!strcasecmp(voice_name, "kal")) {
|
||||
// synth_channel->voice = voices.kal;
|
||||
// } else if (!strcasecmp(voice_name, "rms")) {
|
||||
// synth_channel->voice = voices.rms;
|
||||
// } else if (!strcasecmp(voice_name, "slt")) {
|
||||
// synth_channel->voice = voices.slt;
|
||||
// } else {
|
||||
// apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "Valid voice names are awb, kal, rms or slt");
|
||||
// }
|
||||
break;
|
||||
case SYNTHESIZER_GET_PARAMS:
|
||||
break;
|
||||
@@ -350,92 +341,67 @@ static apt_bool_t flite_synth_channel_request_process(mrcp_engine_channel_t *cha
|
||||
mrcp_engine_channel_message_send(channel,response);
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
static apt_bool_t flite_synth_channel_close_t(mrcp_engine_channel_t *channel)
|
||||
/** Process SPEAK request */
|
||||
static apt_bool_t synth_response_construct(mrcp_message_t *response, mrcp_status_code_e status_code, mrcp_synth_completion_cause_e completion_cause)
|
||||
{
|
||||
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_synth_header_t *synth_header = mrcp_resource_header_prepare(response);
|
||||
if(!synth_header) {
|
||||
return FALSE;
|
||||
}
|
||||
mrcp_engine_channel_close_respond(channel);
|
||||
|
||||
response->start_line.status_code = status_code;
|
||||
synth_header->completion_cause = completion_cause;
|
||||
mrcp_resource_header_property_add(response,SYNTHESIZER_HEADER_COMPLETION_CAUSE);
|
||||
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)
|
||||
{
|
||||
mrcp_generic_header_t *generic_header;
|
||||
const char *content_type = NULL;
|
||||
flite_synth_channel_t *synth_channel = (flite_synth_channel_t *) channel->method_obj;
|
||||
apt_task_msg_t *msg = 0;
|
||||
flite_speak_msg_t *flite_msg = 0;
|
||||
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;
|
||||
generic_header = mrcp_generic_header_get(request);
|
||||
if(generic_header) {
|
||||
/* content-type must be specified */
|
||||
if(mrcp_generic_header_property_check(request,GENERIC_HEADER_CONTENT_TYPE) == TRUE) {
|
||||
content_type = generic_header->content_type.buf;
|
||||
}
|
||||
}
|
||||
if(!content_type) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Missing Content-Type");
|
||||
synth_response_construct(response,MRCP_STATUS_CODE_MISSING_PARAM,SYNTHESIZER_COMPLETION_CAUSE_ERROR);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
/* Flite currently supports only text/plain (no SSML) */
|
||||
if(strstr(content_type,"text") == NULL) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Not Supported Content-Type [%s]",content_type);
|
||||
synth_response_construct(response,MRCP_STATUS_CODE_UNSUPPORTED_PARAM_VALUE,SYNTHESIZER_COMPLETION_CAUSE_ERROR);
|
||||
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;
|
||||
}
|
||||
synth_channel->speak_request = request;
|
||||
synth_channel->speak_response = response;
|
||||
|
||||
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;
|
||||
}
|
||||
msg = apt_task_msg_acquire(synth_channel->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(synth_channel->task,msg) != TRUE) {
|
||||
apt_log(APT_LOG_MARK,APT_PRIO_WARNING, "Failed to send signal to start speech synthesis - channel:%d", synth_channel->iId);
|
||||
synth_channel->speak_request = NULL;
|
||||
synth_channel->speak_response = NULL;
|
||||
synth_response_construct(response,MRCP_STATUS_CODE_METHOD_FAILED,SYNTHESIZER_COMPLETION_CAUSE_ERROR);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
@@ -444,62 +410,80 @@ 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;
|
||||
cst_wave *wave = NULL;
|
||||
cst_voice *voice = NULL;
|
||||
apr_time_t start = 0;
|
||||
apr_time_t elapsed = 0;
|
||||
apr_time_t stamp = 0;
|
||||
apt_str_t *body;
|
||||
mrcp_message_t *response;
|
||||
|
||||
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;
|
||||
apr_uint16_t rate = codec->descriptor->sampling_rate;
|
||||
body = &synth_channel->speak_request->body;
|
||||
|
||||
response = synth_channel->speak_response;
|
||||
synth_channel->speak_response = NULL;
|
||||
|
||||
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "< flite_speak_msg_process speak - channel %d", synth_channel->iId);
|
||||
|
||||
// just sequential stuff
|
||||
/* 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(!body->length) {
|
||||
synth_channel->speak_request = NULL;
|
||||
synth_response_construct(response,MRCP_STATUS_CODE_MISSING_PARAM,SYNTHESIZER_COMPLETION_CAUSE_ERROR);
|
||||
mrcp_engine_channel_message_send(synth_channel->channel,response);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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);
|
||||
voice = flite_voices_best_match_get(
|
||||
synth_channel->flite_engine->voices,
|
||||
synth_channel->speak_request);
|
||||
if(!voice) {
|
||||
/* error case: no voice found, appropriate respond must be sent */
|
||||
synth_channel->speak_request = NULL;
|
||||
synth_response_construct(response,MRCP_STATUS_CODE_METHOD_FAILED,SYNTHESIZER_COMPLETION_CAUSE_ERROR);
|
||||
mrcp_engine_channel_message_send(synth_channel->channel,response);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
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...
|
||||
*/
|
||||
|
||||
/* send in-progress response and start synthesizing */
|
||||
response->start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS;
|
||||
mrcp_engine_channel_message_send(synth_channel->channel,response);
|
||||
|
||||
synth_channel->synthesizing = TRUE;
|
||||
wave = flite_text_to_wave(body->buf, 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);
|
||||
// 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);
|
||||
synth_channel->synthesizing = FALSE;
|
||||
|
||||
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);
|
||||
}
|
||||
apt_log(APT_LOG_MARK, APT_PRIO_DEBUG, "> flite_speak_msg_process speak - end of TTS - %d", synth_channel->iId);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -510,10 +494,7 @@ static apt_bool_t flite_synth_channel_stop(mrcp_engine_channel_t *channel, mrcp_
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -541,29 +522,6 @@ static apt_bool_t flite_synth_channel_resume(mrcp_engine_channel_t *channel, mrc
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Callback is called from MPF engine context to destroy any additional data associated with audio stream */
|
||||
static apt_bool_t flite_synth_stream_destroy(mpf_audio_stream_t *stream)
|
||||
{
|
||||
apt_log(APT_LOG_MARK, APT_PRIO_INFO, "flite_synth_stream_destroy");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** 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_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_DEBUG, "flite_synth_stream_close - channel %d", synth_channel->iId);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Raise SPEAK-COMPLETE event */
|
||||
static apt_bool_t flite_synth_speak_complete_raise(flite_synth_channel_t *synth_channel)
|
||||
{
|
||||
@@ -602,26 +560,25 @@ 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;
|
||||
if (synth_channel->stop_response && synth_channel->speak_request)
|
||||
{
|
||||
if(synth_channel->stop_response && synth_channel->synthesizing == FALSE) {
|
||||
/* send asynchronous response to STOP request */
|
||||
mrcp_engine_channel_message_send(synth_channel->channel, synth_channel->stop_response);
|
||||
mrcp_message_t *stop_response = synth_channel->stop_response;
|
||||
synth_channel->stop_response = NULL;
|
||||
synth_channel->speak_request = NULL;
|
||||
synth_channel->paused = FALSE;
|
||||
mrcp_engine_channel_message_send(synth_channel->channel,stop_response);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* check if there is active SPEAK request and it isn't in paused state */
|
||||
if (synth_channel->speak_request && synth_channel->paused == FALSE)
|
||||
{
|
||||
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_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)
|
||||
{
|
||||
if((frame->type & MEDIA_FRAME_TYPE_EVENT) == MEDIA_FRAME_TYPE_EVENT) {
|
||||
flite_synth_speak_complete_raise(synth_channel);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user