bool UmcScenario::InitCapabilities(mpf_stream_capabilities_t* pCapabilities) const { if(m_pCapabilities) { int i; mpf_codec_attribs_t *pAttribs; for(i=0; i<m_pCapabilities->attrib_arr->nelts; i++) { pAttribs = &APR_ARRAY_IDX(m_pCapabilities->attrib_arr,i,mpf_codec_attribs_t); mpf_codec_capabilities_add( &pCapabilities->codecs, pAttribs->sample_rates, pAttribs->name.buf); } } else { /* add default codec capabilities (Linear PCM) */ mpf_codec_capabilities_add( &pCapabilities->codecs, MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000, "LPCM"); } return true; }
bool UmcScenario::LoadCapabilities(const apr_xml_elem* pElem, apr_pool_t* pool) { const apr_xml_elem* pChildElem; /* Load Child Elements */ m_pCapabilities = (mpf_codec_capabilities_t*) apr_palloc(pool,sizeof(mpf_codec_capabilities_t)); mpf_codec_capabilities_init(m_pCapabilities,1,pool); for(pChildElem = pElem->first_child; pChildElem; pChildElem = pChildElem->next) { if(strcasecmp(pChildElem->name,"codec") != 0) continue; const char* pName = NULL; const char* pRates = NULL; const apr_xml_attr* pAttr; for(pAttr = pChildElem->attr; pAttr; pAttr = pAttr->next) { if(strcasecmp(pAttr->name,"name") == 0) { pName = pAttr->value; } else if(strcasecmp(pAttr->name,"rates") == 0) { pRates = pAttr->value; } } if(pName) { int rates = ParseRates(pRates,pool); mpf_codec_capabilities_add(m_pCapabilities,rates,pName); } } return true; }
static mpf_termination_t *speech_channel_create_mpf_termination(speech_channel_t *schannel) { mpf_termination_t *termination = NULL; mpf_stream_capabilities_t *capabilities = NULL; int sample_rates; if (schannel->type == SPEECH_CHANNEL_SYNTHESIZER) capabilities = mpf_sink_stream_capabilities_create(schannel->unimrcp_session->pool); else capabilities = mpf_source_stream_capabilities_create(schannel->unimrcp_session->pool); if (capabilities == NULL) ast_log(LOG_ERROR, "(%s) Unable to create capabilities\n", schannel->name); /* UniMRCP should transcode whatever the MRCP server wants to use into LPCM * (host-byte ordered L16) for us. Asterisk may not support all of these. */ if (schannel->rate == 16000) sample_rates = MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000; else if (schannel->rate == 32000) sample_rates = MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000 | MPF_SAMPLE_RATE_32000; else if (schannel->rate == 48000) sample_rates = MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000 | MPF_SAMPLE_RATE_48000; else sample_rates = MPF_SAMPLE_RATE_8000; /* TO DO : Check if all of these are supported on Asterisk for all codecs. */ if (strcasecmp(schannel->codec, "L16") == 0) mpf_codec_capabilities_add(&capabilities->codecs, sample_rates, "LPCM"); else mpf_codec_capabilities_add(&capabilities->codecs, sample_rates, schannel->codec); termination = mrcp_application_audio_termination_create( schannel->unimrcp_session, /* Session, termination belongs to. */ &schannel->application->audio_stream_vtable, /* Virtual methods table of audio stream. */ capabilities, /* Capabilities of audio stream. */ schannel); /* Object to associate. */ if (termination == NULL) ast_log(LOG_ERROR, "(%s) Unable to create termination\n", schannel->name); return termination; }
/** Create demo recognizer channel */ static mrcp_channel_t* recog_application_channel_create(mrcp_session_t *session) { mrcp_channel_t *channel; mpf_termination_t *termination; mpf_stream_capabilities_t *capabilities; /* create channel */ recog_app_channel_t *recog_channel = apr_palloc(session->pool,sizeof(recog_app_channel_t)); recog_channel->streaming = FALSE; recog_channel->audio_in = NULL; recog_channel->time_to_complete = 0; /* create source stream capabilities */ capabilities = mpf_source_stream_capabilities_create(session->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 */ recog_channel); /* 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) */ recog_channel); /* object to associate */ return channel; }
/** 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; }
/** Create engine channel and sink media termination */ mrcp_engine_channel_t* mrcp_engine_sink_channel_create( mrcp_engine_t *engine, const mrcp_engine_channel_method_vtable_t *channel_vtable, const mpf_audio_stream_vtable_t *stream_vtable, void *method_obj, mpf_codec_descriptor_t *codec_descriptor, apr_pool_t *pool) { mpf_stream_capabilities_t *capabilities; mpf_audio_stream_t *audio_stream; mpf_termination_t *termination; capabilities = mpf_sink_stream_capabilities_create(pool); if(codec_descriptor) { mpf_codec_capabilities_add( &capabilities->codecs, mpf_sample_rate_mask_get(codec_descriptor->sampling_rate), codec_descriptor->name.buf); } else { mpf_codec_default_capabilities_add(&capabilities->codecs); } /* create audio stream */ audio_stream = mpf_audio_stream_create( method_obj, /* object to associate */ stream_vtable, /* virtual methods table of audio stream */ capabilities, /* stream capabilities */ pool); /* pool to allocate memory from */ if(!audio_stream) { return NULL; } audio_stream->tx_descriptor = codec_descriptor; /* create media termination */ termination = mpf_raw_termination_create( NULL, /* no object to associate */ audio_stream, /* audio stream */ NULL, /* no video stream */ pool); /* pool to allocate memory from */ /* create engine channel base */ return mrcp_engine_channel_create( engine, /* engine */ channel_vtable, /* virtual methods table of engine channel */ method_obj, /* object to associate */ termination, /* media termination, used to terminate audio stream */ pool); /* pool to allocate memory from */ }
/** Create demo synthesizer channel derived from engine channel base */ static mrcp_engine_channel_t* mrcp_swift_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool) { mrcp_swift_engine_t *synth_engine = engine->obj; mpf_stream_capabilities_t *capabilities; mpf_termination_t *termination; mrcp_engine_channel_t *channel; /* create swift synth channel */ mrcp_swift_channel_t *synth_channel = apr_palloc(pool,sizeof(mrcp_swift_channel_t)); synth_channel->port = NULL; synth_channel->tts_stream = 0; synth_channel->channel = NULL; synth_channel->audio_buffer = NULL; synth_channel->speak_request = NULL; synth_channel->stop_response = NULL; synth_channel->paused = FALSE; capabilities = mpf_source_stream_capabilities_create(pool); mpf_codec_capabilities_add( &capabilities->codecs, synth_engine->sample_rates, "LPCM"); /* create media termination */ termination = mrcp_engine_audio_termination_create( synth_channel, /* object to associate */ &audio_stream_vtable, /* virtual methods table of audio stream */ capabilities, /* stream capabilities */ pool); /* pool to allocate memory from */ /* create engine channel base */ channel = mrcp_engine_channel_create( engine, /* engine */ &channel_vtable, /* virtual methods table of engine channel */ synth_channel, /* object to associate */ termination, /* associated media termination */ pool); /* pool to allocate memory from */ if(channel) { synth_channel->audio_buffer = mpf_buffer_create(pool); } synth_channel->channel = channel; return channel; }
/** Create source media termination */ MRCP_DECLARE(mpf_termination_t*) mrcp_application_source_termination_create( mrcp_session_t *session, const mpf_audio_stream_vtable_t *stream_vtable, mpf_codec_descriptor_t *codec_descriptor, void *obj) { mpf_stream_capabilities_t *capabilities; mpf_audio_stream_t *audio_stream; capabilities = mpf_source_stream_capabilities_create(session->pool); if(codec_descriptor) { mpf_codec_capabilities_add( &capabilities->codecs, mpf_sample_rate_mask_get(codec_descriptor->sampling_rate), codec_descriptor->name.buf); } else { mpf_codec_default_capabilities_add(&capabilities->codecs); } /* create audio stream */ audio_stream = mpf_audio_stream_create( obj, /* object to associate */ stream_vtable, /* virtual methods table of audio stream */ capabilities, /* stream capabilities */ session->pool); /* memory pool to allocate memory from */ if(!audio_stream) { return NULL; } audio_stream->rx_descriptor = codec_descriptor; /* create raw termination */ return mpf_raw_termination_create( NULL, /* no object to associate */ audio_stream, /* audio stream */ NULL, /* no video stream */ session->pool); /* memory pool to allocate memory from */ }
static mrcp_engine_channel_t* recorder_engine_channel_create(mrcp_engine_t *engine, apr_pool_t *pool) { mpf_stream_capabilities_t *capabilities; mpf_termination_t *termination; /* create recorder channel */ recorder_channel_t *recorder_channel = apr_palloc(pool,sizeof(recorder_channel_t)); recorder_channel->record_request = NULL; recorder_channel->stop_response = NULL; recorder_channel->detector = mpf_activity_detector_create(pool); recorder_channel->max_time = 0; recorder_channel->cur_time = 0; recorder_channel->cur_size = 0; recorder_channel->file_name = NULL; recorder_channel->audio_out = NULL; capabilities = mpf_sink_stream_capabilities_create(pool); mpf_codec_capabilities_add( &capabilities->codecs, MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000, "LPCM"); /* create media termination */ termination = mrcp_engine_audio_termination_create( recorder_channel, /* object to associate */ &audio_stream_vtable, /* virtual methods table of audio stream */ capabilities, /* stream capabilities */ pool); /* pool to allocate memory from */ /* create engine channel base */ recorder_channel->channel = mrcp_engine_channel_create( engine, /* engine */ &channel_vtable, /* virtual methods table of engine channel */ recorder_channel, /* object to associate */ termination, /* associated media termination */ pool); /* pool to allocate memory from */ return recorder_channel->channel; }
/** Create demo synthesizer channel derived from engine channel base */ 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; /* create demo synth channel */ 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; capabilities = mpf_source_stream_capabilities_create(pool); mpf_codec_capabilities_add( &capabilities->codecs, MPF_SAMPLE_RATE_8000 | MPF_SAMPLE_RATE_16000, "LPCM"); /* create media termination */ termination = mrcp_engine_audio_termination_create( synth_channel, /* object to associate */ &audio_stream_vtable, /* virtual methods table of audio stream */ capabilities, /* stream capabilities */ pool); /* pool to allocate memory from */ /* create engine channel base */ synth_channel->channel = mrcp_engine_channel_create( engine, /* engine */ &channel_vtable, /* virtual methods table of engine channel */ synth_channel, /* object to associate */ termination, /* associated media termination */ pool); /* pool to allocate memory from */ return synth_channel->channel; }
/** \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; }
/** Add default (liear PCM) capabilities */ MPF_DECLARE(apt_bool_t) mpf_codec_default_capabilities_add(mpf_codec_capabilities_t *capabilities) { return mpf_codec_capabilities_add(capabilities,MPF_SAMPLE_RATE_8000,lpcm_attribs.name.buf); }
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; }