/* * Copyright 2008-2015 Arsen Chaloyan * * 遵循Apache License 2.0协议开源,使用前请阅读协议条款 * 协议地址:http://www.apache.org/licenses/LICENSE-2.0 */ /* * MRCP插件实现的强制规则: * 1. 每个插件必须实现一个插件/引擎创建函数,签名和名称必须严格匹配(主入口点) * MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool) * 2. 每个插件必须声明版本号,通过宏 MRCP_PLUGIN_VERSION_DECLARE * 3. 接收到的每个请求必须且只能返回一个响应 * 4. MRCP引擎通道的方法(回调函数)不能阻塞(异步响应可从其他线程上下文发送) * 5. MPF引擎流的方法(回调函数)不能阻塞 */ #include "mrcp_synth_engine.h" // MRCP合成引擎核心头文件 #include "apt_consumer_task.h" // 消费者任务(异步处理)头文件 #include "apt_log.h" // 日志工具头文件 #define SYNTH_ENGINE_TASK_NAME "Demo Synth Engine" // 合成引擎任务名称 // 前置声明:核心数据结构 typedef struct demo_synth_engine_t demo_synth_engine_t; // 演示合成引擎结构体 typedef struct demo_synth_channel_t demo_synth_channel_t; // 演示合成通道结构体 typedef struct demo_synth_msg_t demo_synth_msg_t; // 演示合成任务消息结构体 /** 合成引擎方法声明(引擎级别的生命周期管理) */ static apt_bool_t demo_synth_engine_destroy(mrcp_engine_t *engine); // 销毁引擎 static apt_bool_t demo_synth_engine_open(mrcp_engine_t *engine); // 打开引擎 static apt_bool_t demo_synth_engine_close(mrcp_engine_t *engine); // 关闭引擎 static mrcp_engine_channel_t* demo_synth_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool); // 创建引擎通道 // 合成引擎虚函数表(绑定引擎生命周期方法) static const struct mrcp_engine_method_vtable_t engine_vtable = { demo_synth_engine_destroy, // 销毁引擎回调 demo_synth_engine_open, // 打开引擎回调 demo_synth_engine_close, // 关闭引擎回调 demo_synth_engine_channel_create // 创建通道回调 }; /** 合成通道方法声明(通道级别的生命周期和请求处理) */ static apt_bool_t demo_synth_channel_destroy(mrcp_engine_channel_t *channel); // 销毁通道 static apt_bool_t demo_synth_channel_open(mrcp_engine_channel_t *channel); // 打开通道 static apt_bool_t demo_synth_channel_close(mrcp_engine_channel_t *channel); // 关闭通道 static apt_bool_t demo_synth_channel_request_process(mrcp_engine_channel_t *channel, mrcp_message_t *request); // 处理通道请求 // 合成通道虚函数表(绑定通道生命周期和请求处理方法) static const struct mrcp_engine_channel_method_vtable_t channel_vtable = { demo_synth_channel_destroy, // 销毁通道回调 demo_synth_channel_open, // 打开通道回调 demo_synth_channel_close, // 关闭通道回调 demo_synth_channel_request_process // 处理请求回调 }; /** 合成音频流方法声明(媒体流级别的数据读写) */ static apt_bool_t demo_synth_stream_destroy(mpf_audio_stream_t *stream); // 销毁音频流 static apt_bool_t demo_synth_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec); // 打开音频流 static apt_bool_t demo_synth_stream_close(mpf_audio_stream_t *stream); // 关闭音频流 static apt_bool_t demo_synth_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame); // 读取音频帧 // 音频流虚函数表(绑定媒体流操作方法) static const mpf_audio_stream_vtable_t audio_stream_vtable = { demo_synth_stream_destroy, // 销毁流回调 demo_synth_stream_open, // 打开流回调 demo_synth_stream_close, // 关闭流回调 demo_synth_stream_read, // 读取音频帧回调 NULL, // 写入音频帧(当前仅作为音频源,无需实现) NULL, NULL, NULL }; /** 演示合成引擎结构体定义(引擎核心上下文) */ struct demo_synth_engine_t { apt_consumer_task_t *task; // 异步处理任务(避免阻塞主线程) }; /** 演示合成通道结构体定义(每个通道独立上下文) */ struct demo_synth_channel_t { demo_synth_engine_t *demo_engine; // 指向所属引擎的回指指针 mrcp_engine_channel_t *channel; // 基础引擎通道对象 mrcp_message_t *speak_request; // 正在处理的SPEAK请求 mrcp_message_t *stop_response; // 待发送的STOP响应 apr_size_t time_to_complete; // 合成完成预估时间(毫秒) apt_bool_t paused; // 是否暂停合成(TRUE/FALSE) FILE *audio_file; // 音频文件句柄(模拟合成数据来源) }; // 任务消息类型枚举(标识异步处理的消息类型) typedef enum { DEMO_SYNTH_MSG_OPEN_CHANNEL, // 打开通道消息 DEMO_SYNTH_MSG_CLOSE_CHANNEL, // 关闭通道消息 DEMO_SYNTH_MSG_REQUEST_PROCESS // 处理请求消息 } demo_synth_msg_type_e; /** 演示合成任务消息结构体(异步任务的消息载体) */ struct demo_synth_msg_t { demo_synth_msg_type_e type; // 消息类型 mrcp_engine_channel_t *channel; // 关联的通道 mrcp_message_t *request; // 关联的请求(可选) }; // 内部函数声明(异步消息处理) static apt_bool_t demo_synth_msg_signal(demo_synth_msg_type_e type, mrcp_engine_channel_t *channel, mrcp_message_t *request); static apt_bool_t demo_synth_msg_process(apt_task_t *task, apt_task_msg_t *msg); /** 声明插件版本号(强制要求) */ MRCP_PLUGIN_VERSION_DECLARE /** * 声明日志源(使用服务器的日志机制) * 需要在logger.xml中配置对应日志源: * <source name="SYNTH-PLUGIN" priority="DEBUG" masking="NONE"/> */ MRCP_PLUGIN_LOG_SOURCE_IMPLEMENT(SYNTH_PLUGIN,"SYNTH-PLUGIN") /** 自定义日志标记(简化日志输出) */ #define SYNTH_LOG_MARK APT_LOG_MARK_DECLARE(SYNTH_PLUGIN) /** * MRCP插件入口函数:创建演示合成引擎 * @param pool 内存池(用于内存分配,避免内存泄漏) * @return 创建成功的mrcp_engine_t对象,失败返回NULL */ MRCP_PLUGIN_DECLARE(mrcp_engine_t*) mrcp_plugin_create(apr_pool_t *pool) { // 分配演示引擎对象内存 demo_synth_engine_t *demo_engine = apr_palloc(pool,sizeof(demo_synth_engine_t)); apt_task_t *task; // 基础任务对象 apt_task_vtable_t *vtable; // 任务虚函数表 apt_task_msg_pool_t *msg_pool; // 任务消息池 // 创建动态消息池(存储异步处理的消息) msg_pool = apt_task_msg_pool_create_dynamic(sizeof(demo_synth_msg_t),pool); // 创建消费者任务(异步处理引擎逻辑) demo_engine->task = apt_consumer_task_create(demo_engine,msg_pool,pool); if(!demo_engine->task) { return NULL; // 任务创建失败,返回NULL } // 初始化任务基础属性 task = apt_consumer_task_base_get(demo_engine->task); // 获取基础任务对象 apt_task_name_set(task,SYNTH_ENGINE_TASK_NAME); // 设置任务名称 vtable = apt_task_vtable_get(task); // 获取任务虚函数表 if(vtable) { vtable->process_msg = demo_synth_msg_process; // 绑定消息处理回调 } // 创建MRCP引擎基础对象并返回 return mrcp_engine_create( MRCP_SYNTHESIZER_RESOURCE, // MRCP资源类型(合成器) demo_engine, // 关联的自定义引擎对象 &engine_vtable, // 引擎方法虚函数表 pool); // 内存池 } /** * 销毁合成引擎(引擎生命周期结束) * @param engine MRCP引擎基础对象 * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_engine_destroy(mrcp_engine_t *engine) { demo_synth_engine_t *demo_engine = engine->obj; // 获取自定义引擎对象 if(demo_engine->task) { apt_task_t *task = apt_consumer_task_base_get(demo_engine->task); apt_task_destroy(task); // 销毁异步任务 demo_engine->task = NULL; } return TRUE; } /** * 打开合成引擎(引擎启动) * @param engine MRCP引擎基础对象 * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_engine_open(mrcp_engine_t *engine) { demo_synth_engine_t *demo_engine = engine->obj; if(demo_engine->task) { apt_task_t *task = apt_consumer_task_base_get(demo_engine->task); apt_task_start(task); // 启动异步任务 } return mrcp_engine_open_respond(engine,TRUE); // 发送引擎打开成功的响应 } /** * 关闭合成引擎(引擎停止) * @param engine MRCP引擎基础对象 * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_engine_close(mrcp_engine_t *engine) { demo_synth_engine_t *demo_engine = engine->obj; if(demo_engine->task) { apt_task_t *task = apt_consumer_task_base_get(demo_engine->task); apt_task_terminate(task,TRUE); // 终止异步任务(等待任务完成) } return mrcp_engine_close_respond(engine); // 发送引擎关闭响应 } /** * 创建演示合成通道(每个会话对应一个通道) * @param engine MRCP引擎基础对象 * @param pool 内存池 * @return 创建成功的引擎通道对象 */ static mrcp_engine_channel_t* demo_synth_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool) { mpf_stream_capabilities_t *capabilities; // 媒体流能力集 mpf_termination_t *termination; // 媒体终结点(关联音频流) // 分配自定义通道对象内存 demo_synth_channel_t *synth_channel = apr_palloc(pool,sizeof(demo_synth_channel_t)); // 初始化通道基础属性 synth_channel->demo_engine = engine->obj; synth_channel->speak_request = NULL; synth_channel->stop_response = NULL; synth_channel->time_to_complete = 0; synth_channel->paused = FALSE; synth_channel->audio_file = NULL; // 创建音频源流能力集(支持8kHz/16kHz采样率的LPCM编码) capabilities = mpf_source_stream_capabilities_create(pool); mpf_codec_capabilities_add( &capabilities->codecs, MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000, "LPCM"); // 创建媒体终结点(关联音频流处理逻辑) termination = mrcp_engine_audio_termination_create( synth_channel, // 关联的自定义通道对象 &audio_stream_vtable, // 音频流方法虚函数表 capabilities, // 流能力集 pool); // 内存池 // 创建MRCP引擎通道基础对象 synth_channel->channel = mrcp_engine_channel_create( engine, // 所属引擎 &channel_vtable, // 通道方法虚函数表 synth_channel, // 关联的自定义通道对象 termination, // 关联的媒体终结点 pool); // 内存池 return synth_channel->channel; } /** * 销毁引擎通道(通道生命周期结束) * @param channel 引擎通道对象 * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_channel_destroy(mrcp_engine_channel_t *channel) { // 本示例无额外需要销毁的资源,直接返回成功 return TRUE; } /** * 打开引擎通道(异步处理,必须发送响应) * @param channel 引擎通道对象 * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_channel_open(mrcp_engine_channel_t *channel) { // 发送打开通道的异步消息 return demo_synth_msg_signal(DEMO_SYNTH_MSG_OPEN_CHANNEL,channel,NULL); } /** * 关闭引擎通道(异步处理,必须发送响应) * @param channel 引擎通道对象 * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_channel_close(mrcp_engine_channel_t *channel) { // 发送关闭通道的异步消息 return demo_synth_msg_signal(DEMO_SYNTH_MSG_CLOSE_CHANNEL,channel,NULL); } /** * 处理MRCP通道请求(异步处理,必须发送响应) * @param channel 引擎通道对象 * @param request MRCP请求消息 * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_channel_request_process(mrcp_engine_channel_t *channel, mrcp_message_t *request) { // 发送处理请求的异步消息 return demo_synth_msg_signal(DEMO_SYNTH_MSG_REQUEST_PROCESS,channel,request); } /** * 处理SPEAK请求(核心合成逻辑) * @param channel 引擎通道对象 * @param request SPEAK请求消息 * @param response 待发送的响应消息 * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_channel_speak(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response) { char *file_path = NULL; demo_synth_channel_t *synth_channel = channel->method_obj; // 获取自定义通道对象 // 获取音频流编码描述符(采样率、编码格式等) const mpf_codec_descriptor_t *descriptor = mrcp_engine_source_stream_codec_get(channel); if(!descriptor) { // 编码描述符获取失败,记录日志并返回方法失败 apt_log(SYNTH_LOG_MARK,APT_PRIO_WARNING,"获取编码描述符失败 " APT_SIDRES_FMT, MRCP_MESSAGE_SIDRES(request)); response->start_line.status_code = MRCP_STATUS_CODE_METHOD_FAILED; return FALSE; } synth_channel->time_to_complete = 0; if(channel->engine) { // 构造音频文件名(根据采样率区分:8kHz/16kHz) char *file_name = apr_psprintf(channel->pool,"demo-%dkHz.pcm",descriptor->sampling_rate/1000); // 获取音频文件的完整路径(从引擎数据目录) file_path = apt_datadir_filepath_get(channel->engine->dir_layout,file_name,channel->pool); } if(file_path) { // 打开音频文件(模拟合成数据来源) synth_channel->audio_file = fopen(file_path,"rb"); if(synth_channel->audio_file) { // 音频文件打开成功,记录日志 apt_log(SYNTH_LOG_MARK,APT_PRIO_INFO,"设置音频源文件: [%s] " APT_SIDRES_FMT, file_path, MRCP_MESSAGE_SIDRES(request)); } else { // 音频文件不存在,记录日志并计算预估合成时间 apt_log(SYNTH_LOG_MARK,APT_PRIO_INFO,"未找到音频源文件: [%s] " APT_SIDRES_FMT, file_path, MRCP_MESSAGE_SIDRES(request)); // 从请求头中获取内容长度,估算合成时间(每字符10毫秒) if(mrcp_generic_header_property_check(request,GENERIC_HEADER_CONTENT_LENGTH) == TRUE) { mrcp_generic_header_t *generic_header = mrcp_generic_header_get(request); if(generic_header) { synth_channel->time_to_complete = generic_header->content_length * 10; } } } } // 设置响应状态为"处理中" response->start_line.request_state = MRCP_REQUEST_STATE_INPROGRESS; // 发送异步响应(告知客户端请求已开始处理) mrcp_engine_channel_message_send(channel,response); // 保存当前SPEAK请求(后续合成完成时使用) synth_channel->speak_request = request; return TRUE; } /** * 处理STOP请求(停止合成) * @param channel 引擎通道对象 * @param request STOP请求消息 * @param response 待发送的响应消息 * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_channel_stop(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response) { demo_synth_channel_t *synth_channel = channel->method_obj; // 保存STOP响应(等待音频流停止后再发送,避免数据不一致) synth_channel->stop_response = response; return TRUE; } /** * 处理PAUSE请求(暂停合成) * @param channel 引擎通道对象 * @param request PAUSE请求消息 * @param response 待发送的响应消息 * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_channel_pause(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response) { demo_synth_channel_t *synth_channel = channel->method_obj; synth_channel->paused = TRUE; // 设置暂停标记 // 发送异步响应(告知客户端暂停成功) mrcp_engine_channel_message_send(channel,response); return TRUE; } /** * 处理RESUME请求(恢复合成) * @param channel 引擎通道对象 * @param request RESUME请求消息 * @param response 待发送的响应消息 * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_channel_resume(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response) { demo_synth_channel_t *synth_channel = channel->method_obj; synth_channel->paused = FALSE; // 取消暂停标记 // 发送异步响应(告知客户端恢复成功) mrcp_engine_channel_message_send(channel,response); return TRUE; } /** * 处理SET-PARAMS请求(设置合成参数) * @param channel 引擎通道对象 * @param request SET-PARAMS请求消息 * @param response 待发送的响应消息 * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_channel_set_params(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response) { mrcp_synth_header_t *req_synth_header; // 获取合成器请求头(包含语音参数等) req_synth_header = mrcp_resource_header_get(request); if(req_synth_header) { // 检查并记录"语音年龄"参数 if(mrcp_resource_header_property_check(request,SYNTHESIZER_HEADER_VOICE_AGE) == TRUE) { apt_log(SYNTH_LOG_MARK,APT_PRIO_INFO,"设置语音年龄: [%"APR_SIZE_T_FMT"]", req_synth_header->voice_param.age); } // 检查并记录"语音名称"参数 if(mrcp_resource_header_property_check(request,SYNTHESIZER_HEADER_VOICE_NAME) == TRUE) { apt_log(SYNTH_LOG_MARK,APT_PRIO_INFO,"设置语音名称: [%s]", req_synth_header->voice_param.name.buf); } } // 发送异步响应(告知客户端参数设置成功) mrcp_engine_channel_message_send(channel,response); return TRUE; } /** * 处理GET-PARAMS请求(获取合成参数) * @param channel 引擎通道对象 * @param request GET-PARAMS请求消息 * @param response 待发送的响应消息 * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_channel_get_params(mrcp_engine_channel_t *channel, mrcp_message_t *request, mrcp_message_t *response) { mrcp_synth_header_t *req_synth_header; // 获取合成器请求头(确认需要获取的参数) req_synth_header = mrcp_resource_header_get(request); if(req_synth_header) { // 准备响应头(分配内存并初始化) mrcp_synth_header_t *res_synth_header = mrcp_resource_header_prepare(response); // 填充"语音年龄"参数(固定返回25) if(mrcp_resource_header_property_check(request,SYNTHESIZER_HEADER_VOICE_AGE) == TRUE) { res_synth_header->voice_param.age = 25; mrcp_resource_header_property_add(response,SYNTHESIZER_HEADER_VOICE_AGE); } // 填充"语音名称"参数(固定返回David) if(mrcp_resource_header_property_check(request,SYNTHESIZER_HEADER_VOICE_NAME) == TRUE) { apt_string_set(&res_synth_header->voice_param.name,"David"); mrcp_resource_header_property_add(response,SYNTHESIZER_HEADER_VOICE_NAME); } } // 发送异步响应(返回参数值) mrcp_engine_channel_message_send(channel,response); return TRUE; } /** * 分发MRCP请求(根据请求类型路由到对应处理函数) * @param channel 引擎通道对象 * @param request MRCP请求消息 * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_channel_request_dispatch(mrcp_engine_channel_t *channel, mrcp_message_t *request) { apt_bool_t processed = FALSE; // 创建响应消息(基于请求初始化) mrcp_message_t *response = mrcp_response_create(request,request->pool); // 根据请求方法ID分发处理 switch(request->start_line.method_id) { case SYNTHESIZER_SET_PARAMS: // 设置参数 processed = demo_synth_channel_set_params(channel,request,response); break; case SYNTHESIZER_GET_PARAMS: // 获取参数 processed = demo_synth_channel_get_params(channel,request,response); break; case SYNTHESIZER_SPEAK: // 开始合成 processed = demo_synth_channel_speak(channel,request,response); break; case SYNTHESIZER_STOP: // 停止合成 processed = demo_synth_channel_stop(channel,request,response); break; case SYNTHESIZER_PAUSE: // 暂停合成 processed = demo_synth_channel_pause(channel,request,response); break; case SYNTHESIZER_RESUME: // 恢复合成 processed = demo_synth_channel_resume(channel,request,response); break; case SYNTHESIZER_BARGE_IN_OCCURRED: // 打断合成(同STOP处理) processed = demo_synth_channel_stop(channel,request,response); break; case SYNTHESIZER_CONTROL: // 控制合成(未实现) break; case SYNTHESIZER_DEFINE_LEXICON: // 定义词典(未实现) break; default: // 未知请求 break; } if(processed == FALSE) { // 未处理的请求,发送默认响应 mrcp_engine_channel_message_send(channel,response); } return TRUE; } /** * 销毁音频流(MPF引擎回调) * @param stream 音频流对象 * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_stream_destroy(mpf_audio_stream_t *stream) { // 本示例无额外需要销毁的资源,直接返回成功 return TRUE; } /** * 打开音频流(MPF引擎回调) * @param stream 音频流对象 * @param codec 编码格式 * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_stream_open(mpf_audio_stream_t *stream, mpf_codec_t *codec) { // 本示例无需额外初始化,直接返回成功 return TRUE; } /** * 关闭音频流(MPF引擎回调) * @param stream 音频流对象 * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_stream_close(mpf_audio_stream_t *stream) { // 本示例无需额外清理,直接返回成功 return TRUE; } /** * 读取音频帧(MPF引擎回调,核心媒体数据输出逻辑) * @param stream 音频流对象 * @param frame 音频帧(输出参数) * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_stream_read(mpf_audio_stream_t *stream, mpf_frame_t *frame) { demo_synth_channel_t *synth_channel = stream->obj; // 获取自定义通道对象 // 检查是否有STOP请求待处理 if(synth_channel->stop_response) { // 发送STOP响应(告知客户端停止成功) mrcp_engine_channel_message_send(synth_channel->channel,synth_channel->stop_response); // 清理状态 synth_channel->stop_response = NULL; synth_channel->speak_request = NULL; synth_channel->paused = FALSE; if(synth_channel->audio_file) { fclose(synth_channel->audio_file); // 关闭音频文件 synth_channel->audio_file = NULL; } return TRUE; } // 检查是否有活跃的SPEAK请求且未暂停 if(synth_channel->speak_request && synth_channel->paused == FALSE) { apt_bool_t completed = FALSE; // 合成是否完成标记 if(synth_channel->audio_file) { // 从音频文件读取数据(模拟合成输出) apr_size_t size = frame->codec_frame.size; if(fread(frame->codec_frame.buffer,1,size,synth_channel->audio_file) == size) { frame->type |= MEDIA_FRAME_TYPE_AUDIO; // 标记为音频帧 } else { completed = TRUE; // 文件读取完毕,合成完成 } } else { // 无音频文件,填充静音数据(模拟合成) if(synth_channel->time_to_complete >= CODEC_FRAME_TIME_BASE) { memset(frame->codec_frame.buffer,0,frame->codec_frame.size); // 静音数据(全0) frame->type |= MEDIA_FRAME_TYPE_AUDIO; // 标记为音频帧 synth_channel->time_to_complete -= CODEC_FRAME_TIME_BASE; // 减少剩余时间 } else { completed = TRUE; // 预估时间耗尽,合成完成 } } if(completed) { // 合成完成,创建SPEAK-COMPLETE事件(告知客户端合成结束) mrcp_message_t *message = mrcp_event_create( synth_channel->speak_request, SYNTHESIZER_SPEAK_COMPLETE, synth_channel->speak_request->pool); if(message) { // 准备合成器事件头 mrcp_synth_header_t *synth_header = mrcp_resource_header_prepare(message); if(synth_header) { // 设置完成原因(正常完成) synth_header->completion_cause = SYNTHESIZER_COMPLETION_CAUSE_NORMAL; mrcp_resource_header_property_add(message,SYNTHESIZER_HEADER_COMPLETION_CAUSE); } // 设置请求状态为"完成" message->start_line.request_state = MRCP_REQUEST_STATE_COMPLETE; // 清理状态 synth_channel->speak_request = NULL; if(synth_channel->audio_file) { fclose(synth_channel->audio_file); synth_channel->audio_file = NULL; } // 发送合成完成事件 mrcp_engine_channel_message_send(synth_channel->channel,message); } } } return TRUE; } /** * 发送异步任务消息(封装消息并触发处理) * @param type 消息类型 * @param channel 关联的通道 * @param request 关联的请求(可选) * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_msg_signal(demo_synth_msg_type_e type, mrcp_engine_channel_t *channel, mrcp_message_t *request) { apt_bool_t status = FALSE; demo_synth_channel_t *demo_channel = channel->method_obj; demo_synth_engine_t *demo_engine = demo_channel->demo_engine; apt_task_t *task = apt_consumer_task_base_get(demo_engine->task); // 获取任务消息(从消息池分配) apt_task_msg_t *msg = apt_task_msg_get(task); if(msg) { demo_synth_msg_t *demo_msg; msg->type = TASK_MSG_USER; // 标记为用户自定义消息 demo_msg = (demo_synth_msg_t*) msg->data; // 填充消息内容 demo_msg->type = type; demo_msg->channel = channel; demo_msg->request = request; // 发送消息(触发异步处理) status = apt_task_msg_signal(task,msg); } return status; } /** * 处理异步任务消息(任务线程上下文) * @param task 任务对象 * @param msg 任务消息 * @return 操作结果(TRUE成功/FALSE失败) */ static apt_bool_t demo_synth_msg_process(apt_task_t *task, apt_task_msg_t *msg) { demo_synth_msg_t *demo_msg = (demo_synth_msg_t*)msg->data; // 根据消息类型分发处理 switch(demo_msg->type) { case DEMO_SYNTH_MSG_OPEN_CHANNEL: // 发送通道打开成功的响应 mrcp_engine_channel_open_respond(demo_msg->channel,TRUE); break; case DEMO_SYNTH_MSG_CLOSE_CHANNEL: // 发送通道关闭响应 mrcp_engine_channel_close_respond(demo_msg->channel); break; case DEMO_SYNTH_MSG_REQUEST_PROCESS: // 分发并处理MRCP请求 demo_synth_channel_request_dispatch(demo_msg->channel,demo_msg->request); break; default: break; } return TRUE; }
浙公网安备 33010602011771号