From 9bbee350c23b472215df149ff6f537985bd6a43a Mon Sep 17 00:00:00 2001 From: Jeff Lenk Date: Wed, 10 Oct 2012 14:20:07 -0500 Subject: [PATCH] FS-4527 --resolve add resample core support for asr. This code is very isolated and only effects mod_unimrcp at this time. --- src/include/switch_module_interfaces.h | 8 ++++++ src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c | 12 +++++++++ src/switch_core_asr.c | 33 +++++++++++++++++++++++ 3 files changed, 53 insertions(+) diff --git a/src/include/switch_module_interfaces.h b/src/include/switch_module_interfaces.h index b3dddc7171..e92e1a1366 100644 --- a/src/include/switch_module_interfaces.h +++ b/src/include/switch_module_interfaces.h @@ -408,6 +408,14 @@ struct switch_asr_handle { char *param; /*! the handle's memory pool */ switch_memory_pool_t *memory_pool; + switch_buffer_t *buffer; + switch_byte_t *dbuf; + switch_size_t dbuflen; + switch_audio_resampler_t *resampler; + /*! the current samplerate */ + uint32_t samplerate; + /*! the current native samplerate */ + uint32_t native_rate; /*! private data for the format module to store handle specific info */ void *private_info; }; diff --git a/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c b/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c index aaf8f8764a..91b9943805 100644 --- a/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c +++ b/src/mod/asr_tts/mod_unimrcp/mod_unimrcp.c @@ -339,6 +339,7 @@ struct speech_channel { switch_hash_t *params; /** app specific data */ void *data; + void *fsh; }; typedef struct speech_channel speech_channel_t; @@ -1591,6 +1592,7 @@ static switch_status_t synth_speech_open(switch_speech_handle_t *sh, const char goto done; } sh->private_info = schannel; + schannel->fsh = sh; /* Open the channel */ if (zstr(profile_name)) { @@ -1835,7 +1837,16 @@ static apt_bool_t speech_on_channel_add(mrcp_application_t *application, mrcp_se if (!descriptor) { goto error; } + schannel->rate = descriptor->sampling_rate; + + /* report negotiated sample rate back to FreeSWITCH */ + if (schannel->type == SPEECH_CHANNEL_SYNTHESIZER) { + ((switch_speech_handle_t*)schannel->fsh)->native_rate = schannel->rate; + } else { + ((switch_asr_handle_t*)schannel->fsh)->native_rate = schannel->rate; + } + if (descriptor->name.length) { strncpy(codec_name, descriptor->name.buf, sizeof(codec_name)); } @@ -2914,6 +2925,7 @@ static switch_status_t recog_asr_open(switch_asr_handle_t *ah, const char *codec status = SWITCH_STATUS_FALSE; goto done; } + schannel->fsh = ah; ah->private_info = schannel; r = (recognizer_data_t *) switch_core_alloc(ah->memory_pool, sizeof(recognizer_data_t)); schannel->data = r; diff --git a/src/switch_core_asr.c b/src/switch_core_asr.c index e10928f29d..a8a9521b87 100644 --- a/src/switch_core_asr.c +++ b/src/switch_core_asr.c @@ -77,6 +77,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_asr_open(switch_asr_handle_t *ah, } ah->rate = rate; ah->name = switch_core_strdup(ah->memory_pool, module_name); + ah->samplerate = rate; + ah->native_rate = rate; status = ah->asr_interface->asr_open(ah, codec, rate, dest, flags); @@ -223,6 +225,8 @@ SWITCH_DECLARE(switch_status_t) switch_core_asr_close(switch_asr_handle_t *ah, s status = ah->asr_interface->asr_close(ah, flags); switch_set_flag(ah, SWITCH_ASR_FLAG_CLOSED); + switch_resample_destroy(&ah->resampler); + UNPROTECT_INTERFACE(ah->asr_interface); if (switch_test_flag(ah, SWITCH_ASR_FLAG_FREE_POOL)) { @@ -234,8 +238,37 @@ SWITCH_DECLARE(switch_status_t) switch_core_asr_close(switch_asr_handle_t *ah, s SWITCH_DECLARE(switch_status_t) switch_core_asr_feed(switch_asr_handle_t *ah, void *data, unsigned int len, switch_asr_flag_t *flags) { + switch_size_t orig_len = len; switch_assert(ah != NULL); + if (ah->native_rate && ah->samplerate && ah->native_rate != ah->samplerate) { + if (!ah->resampler) { + if (switch_resample_create(&ah->resampler, + ah->samplerate, ah->native_rate, (uint32_t) orig_len, SWITCH_RESAMPLE_QUALITY, 1) != SWITCH_STATUS_SUCCESS) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to create resampler!\n"); + return SWITCH_STATUS_GENERR; + } + } + + switch_resample_process(ah->resampler, data, len / 2); + if (ah->resampler->to_len > orig_len) { + if (!ah->dbuf) { + void *mem; + ah->dbuflen = ah->resampler->to_len * 2; + mem = realloc(ah->dbuf, ah->dbuflen); + switch_assert(mem); + ah->dbuf = mem; + } + switch_assert(ah->resampler->to_len * 2 <= ah->dbuflen); + memcpy(ah->dbuf, ah->resampler->to, ah->resampler->to_len * 2); + data = ah->dbuf; + } else { + memcpy(data, ah->resampler->to, ah->resampler->to_len * 2); + } + + len = ah->resampler->to_len; + } + return ah->asr_interface->asr_feed(ah, data, len, flags); }