/** Create DEFINE-GRAMMAR request */ static mrcp_message_t* define_grammar_message_create(asr_session_t *asr_session, const char *grammar_file) { /* create MRCP message */ mrcp_message_t *mrcp_message = mrcp_application_message_create( asr_session->mrcp_session, asr_session->mrcp_channel, RECOGNIZER_DEFINE_GRAMMAR); if(mrcp_message) { mrcp_generic_header_t *generic_header; /* set message body */ const apt_dir_layout_t *dir_layout = mrcp_application_dir_layout_get(asr_session->engine->mrcp_app); apr_pool_t *pool = mrcp_application_session_pool_get(asr_session->mrcp_session); char *grammar_file_path = apt_datadir_filepath_get(dir_layout,grammar_file,pool); if(grammar_file_path) { apr_finfo_t finfo; apr_file_t *grammar_file; apt_str_t *content = &mrcp_message->body; if(apr_file_open(&grammar_file,grammar_file_path,APR_FOPEN_READ|APR_FOPEN_BINARY,0,pool) != APR_SUCCESS) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Open Grammar File %s",grammar_file_path); return NULL; } if(apr_file_info_get(&finfo,APR_FINFO_SIZE,grammar_file) != APR_SUCCESS) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Get Grammar File Info %s",grammar_file_path); apr_file_close(grammar_file); return NULL; } content->length = (apr_size_t)finfo.size; content->buf = (char*) apr_palloc(pool,content->length+1); apt_log(APT_LOG_MARK,APT_PRIO_DEBUG,"Load Grammar File Content size [%"APR_SIZE_T_FMT" bytes] %s", content->length,grammar_file_path); if(apr_file_read(grammar_file,content->buf,&content->length) != APR_SUCCESS) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Read Grammar File Content %s",grammar_file_path); apr_file_close(grammar_file); return NULL; } content->buf[content->length] = '\0'; apr_file_close(grammar_file); } /* get/allocate generic header */ generic_header = mrcp_generic_header_prepare(mrcp_message); if(generic_header) { /* set generic header fields */ if(mrcp_message->start_line.version == MRCP_VERSION_2) { apt_string_assign(&generic_header->content_type,"application/srgs+xml",mrcp_message->pool); } else { apt_string_assign(&generic_header->content_type,"application/grammar+xml",mrcp_message->pool); } mrcp_generic_header_property_add(mrcp_message,GENERIC_HEADER_CONTENT_TYPE); apt_string_assign(&generic_header->content_id,"demo-grammar",mrcp_message->pool); mrcp_generic_header_property_add(mrcp_message,GENERIC_HEADER_CONTENT_ID); } } return mrcp_message; }
/** \brief Activate a loaded grammar */ static int uni_recog_activate_grammar(struct ast_speech *speech, ast_compat_const char *grammar_name) { uni_speech_t *uni_speech = speech->data; apr_pool_t *pool = mrcp_application_session_pool_get(uni_speech->session); const char *entry; ast_log(LOG_NOTICE, "(%s) Activate grammar name: %s\n",uni_speech->name,grammar_name); entry = apr_pstrdup(pool,grammar_name); apr_hash_set(uni_speech->active_grammars,entry,APR_HASH_KEY_STRING,entry); return 0; }
/** Create demo channel */ static mrcp_channel_t* demo_application_channel_create(mrcp_session_t *session) { mrcp_channel_t *channel; apr_pool_t *pool = mrcp_application_session_pool_get(session); /* create channel */ demo_app_channel_t *demo_channel = apr_palloc(pool,sizeof(demo_app_channel_t)); mpf_rtp_termination_descriptor_t *rtp_descriptor = demo_rtp_descriptor_create(pool); channel = mrcp_application_channel_create( session, /* session, channel belongs to */ MRCP_SYNTHESIZER_RESOURCE, /* MRCP resource identifier */ NULL, /* no termination (not to use internal media processing) */ rtp_descriptor, /* RTP descriptor, used to create RTP termination */ demo_channel); /* object to associate */ return channel; }
/** Create DEFINE-GRAMMAR request */ static mrcp_message_t* define_grammar_message_create(asr_session_t *asr_session, const char *grammar_file) { /* create MRCP message */ mrcp_message_t *mrcp_message = mrcp_application_message_create( asr_session->mrcp_session, asr_session->mrcp_channel, RECOGNIZER_DEFINE_GRAMMAR); if(mrcp_message) { mrcp_generic_header_t *generic_header; /* set message body */ const apt_dir_layout_t *dir_layout = mrcp_application_dir_layout_get(asr_session->engine->mrcp_app); apr_pool_t *pool = mrcp_application_session_pool_get(asr_session->mrcp_session); char *grammar_file_path = apt_datadir_filepath_get(dir_layout,grammar_file,pool); if(grammar_file_path) { char text[1024]; apr_size_t size; FILE *grammar = fopen(grammar_file_path,"r"); if(!grammar) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot Open [%s]",grammar_file_path); return NULL; } size = fread(text,1,sizeof(text),grammar); apt_string_assign_n(&mrcp_message->body,text,size,mrcp_message->pool); fclose(grammar); } /* get/allocate generic header */ generic_header = mrcp_generic_header_prepare(mrcp_message); if(generic_header) { /* set generic header fields */ if(mrcp_message->start_line.version == MRCP_VERSION_2) { apt_string_assign(&generic_header->content_type,"application/srgs+xml",mrcp_message->pool); } else { apt_string_assign(&generic_header->content_type,"application/grammar+xml",mrcp_message->pool); } mrcp_generic_header_property_add(mrcp_message,GENERIC_HEADER_CONTENT_TYPE); apt_string_assign(&generic_header->content_id,"demo-grammar",mrcp_message->pool); mrcp_generic_header_property_add(mrcp_message,GENERIC_HEADER_CONTENT_ID); } } return mrcp_message; }
/** \brief Preload grammar */ static apt_bool_t uni_recog_grammars_preload(uni_speech_t *uni_speech) { apr_table_t *grammars = uni_engine.grammars; if(grammars && uni_speech->session) { int i; char *grammar_name; char *grammar_path; apr_pool_t *pool = mrcp_application_session_pool_get(uni_speech->session); const apr_array_header_t *header = apr_table_elts(grammars); apr_table_entry_t *entry = (apr_table_entry_t *) header->elts; for(i=0; i<header->nelts; i++) { grammar_name = apr_pstrdup(pool,entry[i].key); grammar_path = apr_pstrdup(pool,entry[i].val); uni_recog_load_grammar(uni_speech->speech_base,grammar_name,grammar_path); } } return TRUE; }
/** \brief Try to get result */ struct ast_speech_result* uni_recog_get(struct ast_speech *speech) { mrcp_recog_header_t *recog_header; uni_speech_t *uni_speech = speech->data; if(uni_speech->is_inprogress) { uni_recog_stop(speech); } ast_log(LOG_NOTICE, "Get result '%s'\n",uni_speech_id_get(uni_speech)); if(!uni_speech->mrcp_event) { ast_log(LOG_WARNING, "No RECOGNITION-COMPLETE message received\n"); return NULL; } /* Get recognizer header */ recog_header = mrcp_resource_header_get(uni_speech->mrcp_event); if(!recog_header || mrcp_resource_header_property_check(uni_speech->mrcp_event,RECOGNIZER_HEADER_COMPLETION_CAUSE) != TRUE) { ast_log(LOG_WARNING, "Missing Completion-Cause in RECOGNITION-COMPLETE message\n"); return NULL; } if(recog_header->completion_cause != RECOGNIZER_COMPLETION_CAUSE_SUCCESS) { ast_log(LOG_WARNING, "Unsuccessful completion cause:%d reason:%s\n", recog_header->completion_cause, recog_header->completion_reason.buf ? recog_header->completion_reason.buf : "none"); return NULL; } if(speech->results) { ast_speech_results_free(speech->results); } speech->results = uni_recog_speech_result_build( &uni_speech->mrcp_event->body, uni_speech->mrcp_event->start_line.version, mrcp_application_session_pool_get(uni_speech->session)); if(speech->results) { ast_set_flag(speech,AST_SPEECH_HAVE_RESULTS); } return speech->results; }
/** Create demo synthesizer channel */ static mrcp_channel_t* synth_application_channel_create(mrcp_session_t *session) { mrcp_channel_t *channel; mpf_termination_t *termination; mpf_stream_capabilities_t *capabilities; apr_pool_t *pool = mrcp_application_session_pool_get(session); /* create channel */ synth_app_channel_t *synth_channel = apr_palloc(pool,sizeof(synth_app_channel_t)); synth_channel->audio_out = NULL; /* create sink stream capabilities */ capabilities = mpf_sink_stream_capabilities_create(pool); /* add codec capabilities (Linear PCM) */ mpf_codec_capabilities_add( &capabilities->codecs, MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000, "LPCM"); #if 0 /* more capabilities can be added or replaced */ mpf_codec_capabilities_add( &capabilities->codecs, MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000, "PCMU"); #endif termination = mrcp_application_audio_termination_create( session, /* session, termination belongs to */ &audio_stream_vtable, /* virtual methods table of audio stream */ capabilities, /* capabilities of audio stream */ synth_channel); /* object to associate */ channel = mrcp_application_channel_create( session, /* session, channel belongs to */ MRCP_SYNTHESIZER_RESOURCE, /* MRCP resource identifier */ termination, /* media termination, used to terminate audio stream */ NULL, /* RTP descriptor, used to create RTP termination (NULL by default) */ synth_channel); /* object to associate */ return channel; }
/** Open audio input file */ static apt_bool_t asr_input_file_open(asr_session_t *asr_session, const char *input_file) { const apt_dir_layout_t *dir_layout = mrcp_application_dir_layout_get(asr_session->engine->mrcp_app); apr_pool_t *pool = mrcp_application_session_pool_get(asr_session->mrcp_session); char *input_file_path = apt_datadir_filepath_get(dir_layout,input_file,pool); if(!input_file_path) { return FALSE; } if(asr_session->audio_in) { fclose(asr_session->audio_in); asr_session->audio_in = NULL; } asr_session->audio_in = fopen(input_file_path,"rb"); if(!asr_session->audio_in) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Cannot Open [%s]",input_file_path); return FALSE; } return TRUE; }
/** Handle the responses sent to channel add requests */ static apt_bool_t synth_application_on_channel_add(mrcp_application_t *application, mrcp_session_t *session, mrcp_channel_t *channel, mrcp_sig_status_code_e status) { if(status == MRCP_SIG_STATUS_CODE_SUCCESS) { mrcp_message_t *mrcp_message; synth_app_channel_t *synth_channel = mrcp_application_channel_object_get(channel); apr_pool_t *pool = mrcp_application_session_pool_get(session); const apt_dir_layout_t *dir_layout = mrcp_application_dir_layout_get(application); const mpf_codec_descriptor_t *descriptor = mrcp_application_sink_descriptor_get(channel); if(!descriptor) { /* terminate the demo */ apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Get Media Sink Descriptor"); return mrcp_application_session_terminate(session); } /* create and send SPEAK request */ mrcp_message = demo_speak_message_create(session,channel,dir_layout); if(mrcp_message) { mrcp_application_message_send(session,channel,mrcp_message); } if(synth_channel) { const apt_str_t *id = mrcp_application_session_id_get(session); char *file_name = apr_psprintf(pool,"synth-%dkHz-%s.pcm", descriptor->sampling_rate/1000, id->buf); char *file_path = apt_datadir_filepath_get(dir_layout,file_name,pool); if(file_path) { synth_channel->audio_out = fopen(file_path,"wb"); } } } else { /* error case, just terminate the demo */ mrcp_application_session_terminate(session); } return TRUE; }
/** \brief Create recognition channel */ static apt_bool_t uni_recog_channel_create(uni_speech_t *uni_speech, ast_format_compat *format) { mrcp_channel_t *channel; mpf_termination_t *termination; mpf_stream_capabilities_t *capabilities; apr_pool_t *pool = mrcp_application_session_pool_get(uni_speech->session); /* Create source stream capabilities */ capabilities = mpf_source_stream_capabilities_create(pool); /* Add codec capabilities (Linear PCM) */ mpf_codec_capabilities_add( &capabilities->codecs, MPF_SAMPLE_RATE_8000, "LPCM"); /* Create media termination */ termination = mrcp_application_audio_termination_create( uni_speech->session, /* session, termination belongs to */ &audio_stream_vtable, /* virtual methods table of audio stream */ capabilities, /* stream capabilities */ uni_speech); /* object to associate */ /* Create MRCP channel */ channel = mrcp_application_channel_create( uni_speech->session, /* session, channel belongs to */ MRCP_RECOGNIZER_RESOURCE, /* MRCP resource identifier */ termination, /* media termination, used to terminate audio stream */ NULL, /* RTP descriptor, used to create RTP termination (NULL by default) */ uni_speech); /* object to associate */ if(!channel) { return FALSE; } uni_speech->channel = channel; return TRUE; }
/** Create ASR session */ ASR_CLIENT_DECLARE(asr_session_t*) asr_session_create(asr_engine_t *engine, const char *profile) { mpf_termination_t *termination; mrcp_channel_t *channel; mrcp_session_t *session; const mrcp_app_message_t *app_message; apr_pool_t *pool; asr_session_t *asr_session; mpf_stream_capabilities_t *capabilities; /* create session */ session = mrcp_application_session_create(engine->mrcp_app,profile,NULL); if(!session) { return NULL; } pool = mrcp_application_session_pool_get(session); asr_session = apr_palloc(pool,sizeof(asr_session_t)); mrcp_application_session_object_set(session,asr_session); /* create source stream capabilities */ capabilities = mpf_source_stream_capabilities_create(pool); /* add codec capabilities (Linear PCM) */ mpf_codec_capabilities_add( &capabilities->codecs, MPF_SAMPLE_RATE_8000, "LPCM"); termination = mrcp_application_audio_termination_create( session, /* session, termination belongs to */ &audio_stream_vtable, /* virtual methods table of audio stream */ capabilities, /* capabilities of audio stream */ asr_session); /* object to associate */ channel = mrcp_application_channel_create( session, /* session, channel belongs to */ MRCP_RECOGNIZER_RESOURCE, /* MRCP resource identifier */ termination, /* media termination, used to terminate audio stream */ NULL, /* RTP descriptor, used to create RTP termination (NULL by default) */ asr_session); /* object to associate */ if(!channel) { mrcp_application_session_destroy(session); return NULL; } asr_session->engine = engine; asr_session->mrcp_session = session; asr_session->mrcp_channel = channel; asr_session->recog_complete = NULL; asr_session->input_mode = INPUT_MODE_NONE; asr_session->streaming = FALSE; asr_session->audio_in = NULL; asr_session->media_buffer = NULL; asr_session->mutex = NULL; asr_session->wait_object = NULL; asr_session->app_message = NULL; /* Create cond wait object and mutex */ apr_thread_mutex_create(&asr_session->mutex,APR_THREAD_MUTEX_DEFAULT,pool); apr_thread_cond_create(&asr_session->wait_object,pool); /* Create media buffer */ asr_session->media_buffer = mpf_frame_buffer_create(160,20,pool); /* Send add channel request and wait for the response */ apr_thread_mutex_lock(asr_session->mutex); app_message = NULL; if(mrcp_application_channel_add(asr_session->mrcp_session,asr_session->mrcp_channel) == TRUE) { apr_thread_cond_wait(asr_session->wait_object,asr_session->mutex); app_message = asr_session->app_message; asr_session->app_message = NULL; } apr_thread_mutex_unlock(asr_session->mutex); if(sig_response_check(app_message) == FALSE) { asr_session_destroy_ex(asr_session,TRUE); return NULL; } return asr_session; }
int main(int argc, char const* argv[]) { apr_pool_t* pool = NULL; apr_pool_t* spool = NULL; int i; struct iovec cattext[101]; static char const SP = ' '; char const* outfile; apr_status_t status; apt_dir_layout_t* dirLayout = NULL; mrcp_client_t* client = NULL; mrcp_application_t* app = NULL; mrcp_session_t* sess = NULL; mpf_stream_capabilities_t* caps = NULL; mpf_termination_t* term = NULL; mrcp_channel_t* chan = NULL; struct stat info; if (argc < 2) { puts("Usage:"); printf("\t%s \"This is a synthetic voice.\"", argv[0]); exit(1); } /* Just detect various directory layout constellations */ if (stat(ROOT_DIR, &info)) ROOT_DIR = ROOT_DIR2; if (stat(ROOT_DIR, &info)) ROOT_DIR = ROOT_DIR3; /* Initialize platform first */ if (apr_initialize() != APR_SUCCESS) FAIL("Cannot initialize APR platform"); pool = apt_pool_create(); if (!pool) FAIL("Not enough memory"); for (i = 0; (i < argc - 2) && (i < 50); i += 2) { cattext[2 * i].iov_base = (void*) argv[i + 1]; cattext[2 * i].iov_len = strlen(argv[i + 1]); cattext[2 * i + 1].iov_base = (void*) &SP; cattext[2 * i + 1].iov_len = 1; } cattext[2 * i].iov_base = (void*) argv[i + 1]; cattext[2 * i].iov_len = strlen(argv[i + 1]); text = apr_pstrcatv(pool, cattext, 2 * i + 1, NULL); if (!text) FAIL("Not enough memory"); outfile = apr_pstrcat(pool, ROOT_DIR, "/data/", PCM_OUT_FILE, NULL); printf("This is a sample C UniMRCP client synthesizer scenario.\n"); printf("Use client configuration from %s/conf/unimrcpclient.xml\n", ROOT_DIR); printf("Use profile %s\n", MRCP_PROFILE); printf("Synthesize text: `%s'\n", text); printf("Write output to file: %s\n", outfile); printf("\n"); printf("Press enter to start the session...\n"); (void) getchar(); apt_log_instance_create(APT_LOG_OUTPUT_NONE, APT_PRIO_DEBUG, pool); apt_log_ext_handler_set(UniSynth_logger); dirLayout = apt_default_dir_layout_create(ROOT_DIR, pool); /* Create and start the client in a root dir */ client = unimrcp_client_create(dirLayout); if (!client) FAIL("Cannot create UniMRCP client"); app = mrcp_application_create(UniSynthAppMsgHandler, NULL, mrcp_client_memory_pool_get(client)); if (!app) FAIL("Cannot create MRCP application"); if (!mrcp_client_application_register(client, app, "Sample C app")) FAIL("Cannot register MRCP application"); if (!mrcp_client_start(client)) FAIL("Cannot start MRCP client"); /* Create a session using MRCP profile MRCP_PROFILE */ sess = mrcp_application_session_create(app, MRCP_PROFILE, NULL); if (!sess) FAIL("Cannot create session"); spool = mrcp_application_session_pool_get(sess); /* Create audio termination with capabilities */ caps = mpf_stream_capabilities_create(STREAM_DIRECTION_SEND, spool); if (!caps) FAIL("Error creating capabilities"); if (!mpf_codec_capabilities_add(&caps->codecs, MPF_SAMPLE_RATE_8000, "LPCM")) FAIL("Error adding codec capabilities"); term = mrcp_application_audio_termination_create(sess, &stream_vtable, caps, NULL); if (!term) FAIL("Cannot create audio termination"); /* Add signaling channel (and start processing in OnAdd method */ f = fopen(outfile, "wb"); if (!f) FAIL("Cannot open output file"); status = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, pool); if (status != APR_SUCCESS) FAIL("Cannot create mutex"); status = apr_thread_cond_create(&cond, pool); if (status != APR_SUCCESS) FAIL("Cannot create condition variable"); chan = mrcp_application_channel_create(sess, MRCP_SYNTHESIZER_RESOURCE, term, NULL, NULL); if (!chan) FAIL("Cannot create channel"); if (!mrcp_application_channel_add(sess, chan)) FAIL("Cannot add channel"); /* Now wait until the processing finishes */ apr_thread_mutex_lock(mutex); while (err < 0) apr_thread_cond_wait(cond, mutex); apr_thread_mutex_unlock(mutex); cleanup: if (sess) mrcp_application_session_terminate(sess); if (f) fclose(f); if (client) mrcp_client_shutdown(client); if (app) mrcp_application_destroy(app); if (client) mrcp_client_destroy(client); apt_log_instance_destroy(); if (pool) apr_pool_destroy(pool); apr_terminate(); puts("Program finished, memory released. Press any key to exit."); (void) getchar(); return err; }
/** \brief Set up the speech structure within the engine */ static int uni_recog_create_internal(struct ast_speech *speech, ast_format_compat *format) { uni_speech_t *uni_speech; mrcp_session_t *session; apr_pool_t *pool; const mpf_codec_descriptor_t *descriptor; /* Create session instance */ session = mrcp_application_session_create(uni_engine.application,uni_engine.profile,speech); if(!session) { ast_log(LOG_ERROR, "Failed to create session\n"); return -1; } pool = mrcp_application_session_pool_get(session); uni_speech = apr_palloc(pool,sizeof(uni_speech_t)); uni_speech->session = session; uni_speech->channel = NULL; uni_speech->wait_object = NULL; uni_speech->mutex = NULL; uni_speech->media_buffer = NULL; uni_speech->active_grammars = apr_hash_make(pool); uni_speech->is_sm_request = FALSE; uni_speech->is_inprogress = FALSE; uni_speech->sm_request = 0; uni_speech->sm_response = MRCP_SIG_STATUS_CODE_SUCCESS; uni_speech->mrcp_request = NULL; uni_speech->mrcp_response = NULL; uni_speech->mrcp_event = NULL; uni_speech->speech_base = speech; speech->data = uni_speech; /* Create cond wait object and mutex */ apr_thread_mutex_create(&uni_speech->mutex,APR_THREAD_MUTEX_DEFAULT,pool); apr_thread_cond_create(&uni_speech->wait_object,pool); /* Create recognition channel instance */ if(uni_recog_channel_create(uni_speech,format) != TRUE) { ast_log(LOG_ERROR, "Failed to create channel\n"); uni_recog_cleanup(uni_speech); return -1; } /* Send add channel request and wait for response */ if(uni_recog_sm_request_send(uni_speech,MRCP_SIG_COMMAND_CHANNEL_ADD) != TRUE) { ast_log(LOG_WARNING, "Failed to send add channel request\n"); uni_recog_cleanup(uni_speech); return -1; } /* Check received response */ if(uni_speech->sm_response != MRCP_SIG_STATUS_CODE_SUCCESS) { ast_log(LOG_WARNING, "Failed to add channel\n"); uni_recog_sm_request_send(uni_speech,MRCP_SIG_COMMAND_SESSION_TERMINATE); uni_recog_cleanup(uni_speech); return -1; } descriptor = mrcp_application_source_descriptor_get(uni_speech->channel); if(descriptor) { mpf_frame_buffer_t *media_buffer; apr_size_t frame_size = mpf_codec_linear_frame_size_calculate(descriptor->sampling_rate,descriptor->channel_count); /* Create media buffer */ ast_log(LOG_DEBUG, "Create media buffer frame_size:%"APR_SIZE_T_FMT"\n",frame_size); media_buffer = mpf_frame_buffer_create(frame_size,20,pool); uni_speech->media_buffer = media_buffer; } if(!uni_speech->media_buffer) { ast_log(LOG_WARNING, "Failed to create media buffer\n"); uni_recog_sm_request_send(uni_speech,MRCP_SIG_COMMAND_SESSION_TERMINATE); uni_recog_cleanup(uni_speech); return -1; } ast_log(LOG_NOTICE, "Created speech instance '%s'\n",uni_speech_id_get(uni_speech)); /* Set properties for session */ uni_recog_properties_set(uni_speech); /* Preload grammars */ uni_recog_grammars_preload(uni_speech); return 0; }
apr_pool_t* UmcSession::GetSessionPool() const { if(!m_pMrcpSession) return NULL; return mrcp_application_session_pool_get(m_pMrcpSession); }
/** \brief Build ast_speech_result based on the NLSML result */ static struct ast_speech_result* uni_recog_speech_result_build(uni_speech_t *uni_speech, const apt_str_t *nlsml_result, mrcp_version_e mrcp_version) { float confidence; const char *grammar; const char *text; struct ast_speech_result *speech_result; struct ast_speech_result *first_speech_result; nlsml_interpretation_t *interpretation; nlsml_instance_t *instance; nlsml_input_t *input; int interpretation_count; int instance_count; apr_pool_t *pool = mrcp_application_session_pool_get(uni_speech->session); nlsml_result_t *result = nlsml_result_parse(nlsml_result->buf, nlsml_result->length, pool); if(!result) { ast_log(LOG_WARNING, "(%s) Failed to parse NLSML result: %s\n",uni_speech->name,nlsml_result->buf); return NULL; } #if 1 /* enable/disable debug output of parsed results */ nlsml_result_trace(result, pool); #endif first_speech_result = NULL; #if AST_VERSION_AT_LEAST(1,6,0) AST_LIST_HEAD_NOLOCK(, ast_speech_result) speech_results; AST_LIST_HEAD_INIT_NOLOCK(&speech_results); #else struct ast_speech_result *last_speech_result = NULL; #endif interpretation_count = 0; interpretation = nlsml_first_interpretation_get(result); while(interpretation) { input = nlsml_interpretation_input_get(interpretation); if(!input) { ast_log(LOG_WARNING, "(%s) Failed to get NLSML input\n",uni_speech->name); continue; } instance_count = 0; instance = nlsml_interpretation_first_instance_get(interpretation); if(!instance) { ast_log(LOG_WARNING, "(%s) Failed to get NLSML instance\n",uni_speech->name); continue; } confidence = nlsml_interpretation_confidence_get(interpretation); grammar = nlsml_interpretation_grammar_get(interpretation); if(grammar) { const char session_token[] = "session:"; char *str = strstr(grammar,session_token); if(str) { grammar = str + sizeof(session_token) - 1; } } do { nlsml_instance_swi_suppress(instance); text = nlsml_instance_content_generate(instance, pool); speech_result = ast_calloc(sizeof(struct ast_speech_result), 1); if(text) speech_result->text = strdup(text); speech_result->score = confidence * 100; if(grammar) speech_result->grammar = strdup(grammar); speech_result->nbest_num = interpretation_count; if(!first_speech_result) first_speech_result = speech_result; #if AST_VERSION_AT_LEAST(1,6,0) AST_LIST_INSERT_TAIL(&speech_results, speech_result, list); #else speech_result->next = last_speech_result; last_speech_result = speech_result; #endif ast_log(LOG_NOTICE, "(%s) Speech result[%d/%d]: %s, score: %d, grammar: %s\n", uni_speech->name, interpretation_count, instance_count, speech_result->text, speech_result->score, speech_result->grammar); instance_count++; instance = nlsml_interpretation_next_instance_get(interpretation, instance); } while(instance); interpretation_count++; interpretation = nlsml_next_interpretation_get(result, interpretation); } return first_speech_result; }