PerKins Zhu

Le vent se lève,il faut tenter de vivre.

导航

unimrcp_plugin_demo_synth_engine.c 源码解析

Posted on 2026-01-09 17:18  PerKins.Zhu  阅读(3)  评论(0)    收藏  举报
/*
 * 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;
}