/** Open engine channel (asynchronous response MUST be sent)*/ static apt_bool_t mrcp_swift_channel_open(mrcp_engine_channel_t *channel) { /* open channel and send asynch response */ apt_bool_t status = FALSE; mrcp_swift_channel_t *synth_channel = channel->method_obj; mrcp_swift_engine_t *synth_engine = channel->engine->obj; const mpf_codec_descriptor_t *descriptor = mrcp_engine_source_stream_codec_get(synth_channel->channel); if(descriptor) { swift_params *params; swift_port *port; params = swift_params_new(NULL); swift_params_set_string(params, "audio/encoding", "pcm16"); swift_params_set_int(params, "audio/sampling-rate", descriptor->sampling_rate); /* open swift port */ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Open Swift Port"); port = swift_port_open(synth_engine->swift,params); if(port) { /* set swift_write_audio as a callback, with the output file as its param */ swift_port_set_callback(port, &mrcp_swift_write_audio, SWIFT_EVENT_AUDIO | SWIFT_EVENT_END, synth_channel); synth_channel->port = port; status = TRUE; } else { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Open Swift Port"); } } return mrcp_engine_channel_open_respond(channel,status); }
/** Create demo synthesizer channel derived from engine channel base */ static mrcp_engine_channel_t* mrcp_swift_engine_channel_create(mrcp_resource_engine_t *engine, apr_pool_t *pool) { swift_engine *synth_engine = engine->obj; mrcp_swift_channel_t *synth_channel; mrcp_engine_channel_t *channel; swift_params *params; swift_port *port; mpf_codec_descriptor_t *codec_descriptor; codec_descriptor = apr_palloc(pool,sizeof(mpf_codec_descriptor_t)); mpf_codec_descriptor_init(codec_descriptor); codec_descriptor->channel_count = 1; codec_descriptor->payload_type = 96; apt_string_set(&codec_descriptor->name,"L16"); codec_descriptor->sampling_rate = 8000; params = swift_params_new(NULL); swift_params_set_string(params, "audio/encoding", "pcm16"); swift_params_set_int(params, "audio/sampling-rate", codec_descriptor->sampling_rate); /* open swift port */ apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Open Swift Port"); if((port = swift_port_open(synth_engine,params)) == NULL) { apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Open Swift Port"); return NULL; } /* create swift synth channel */ synth_channel = apr_palloc(pool,sizeof(mrcp_swift_channel_t)); synth_channel->speak_request = NULL; synth_channel->stop_response = NULL; synth_channel->paused = FALSE; synth_channel->channel = NULL; synth_channel->port = port; synth_channel->tts_stream = 0; /* create engine channel base */ channel = mrcp_engine_source_channel_create( engine, /* resource engine */ &channel_vtable, /* virtual methods table of engine channel */ &audio_stream_vtable, /* virtual methods table of audio stream */ synth_channel, /* object to associate */ codec_descriptor, /* codec descriptor might be NULL by default */ pool); /* pool to allocate memory from */ if(!channel) { swift_port_close(port); synth_channel->port = NULL; return NULL; } synth_channel->audio_buffer = mpf_buffer_create(pool); /* set swift_write_audio as a callback, with the output file as its param */ swift_port_set_callback(port, &mrcp_swift_write_audio, SWIFT_EVENT_AUDIO | SWIFT_EVENT_END, synth_channel); synth_channel->channel = channel; return channel; }
static int app_exec(struct ast_channel *chan, void *data) { int res = 0, argc = 0, max_digits = 0, timeout = 0, alreadyran = 0, old_writeformat = 0; int ms, len, availatend; char *argv[3], *parse = NULL, *text = NULL, *rc = NULL; char tmp_exten[2], results[20]; struct ast_module_user *u; struct ast_frame *f; struct timeval next; struct stuff *ps; struct myframe { struct ast_frame f; unsigned char offset[AST_FRIENDLY_OFFSET]; unsigned char frdata[framesize]; } myf; swift_engine *engine; swift_port *port = NULL; swift_voice *voice; swift_params *params; swift_result_t sresult; swift_background_t tts_stream; unsigned int event_mask; memset(results, 0 ,20); memset(tmp_exten, 0, 2); memset(argv, 0, 3); parse = ast_strdupa(data); u = ast_module_user_add(chan); argc = ast_app_separate_args(parse, ',', argv, 3); text = argv[0]; if (!ast_strlen_zero(argv[1])) { timeout = strtol(argv[1], NULL, 0); } if (!ast_strlen_zero(argv[2])) { max_digits = strtol(argv[2], NULL, 0); } if (ast_strlen_zero(text)) { ast_log(LOG_WARNING, "%s requires text to speak!\n", app); return -1; } if (!ast_strlen_zero(text)) { ast_log(LOG_DEBUG, "Text to Speak : %s\n", text); } if (timeout > 0) { ast_log(LOG_DEBUG, "Timeout : %d\n", timeout); } if (max_digits > 0) { ast_log(LOG_DEBUG, "Max Digits : %d\n", max_digits); } ps = malloc(sizeof(struct stuff)); swift_init_stuff(ps); /* Setup synthesis */ if ((engine = swift_engine_open(NULL)) == NULL) { ast_log(LOG_ERROR, "Failed to open Swift Engine.\n"); goto exception; } params = swift_params_new(NULL); swift_params_set_string(params, "audio/encoding", "ulaw"); swift_params_set_string(params, "audio/sampling-rate", "8000"); swift_params_set_string(params, "audio/output-format", "raw"); swift_params_set_string(params, "tts/text-encoding", "utf-8"); /* Additional swift parameters * * swift_params_set_float(params, "speech/pitch/shift", 1.0); * swift_params_set_int(params, "speech/rate", 150); * swift_params_set_int(params, "audio/volume", 110); * swift_params_set_int(params, "audio/deadair", 0); */ if ((port = swift_port_open(engine, params)) == NULL) { ast_log(LOG_ERROR, "Failed to open Swift Port.\n"); goto exception; } if ((voice = swift_port_set_voice_by_name(port, cfg_voice)) == NULL) { ast_log(LOG_ERROR, "Failed to set voice.\n"); goto exception; } event_mask = SWIFT_EVENT_AUDIO | SWIFT_EVENT_END; swift_port_set_callback(port, &swift_cb, event_mask, ps); if (SWIFT_FAILED(swift_port_speak_text(port, text, 0, NULL, &tts_stream, NULL))) { ast_log(LOG_ERROR, "Failed to speak.\n"); goto exception; } if (chan->_state != AST_STATE_UP) { ast_answer(chan); } ast_stopstream(chan); old_writeformat = chan->writeformat; if (ast_set_write_format(chan, AST_FORMAT_ULAW) < 0) { ast_log(LOG_WARNING, "Unable to set write format.\n"); goto exception; } res = 0; /* Wait 100ms first for synthesis to start crankin'; if that's not * enough the */ next = ast_tvadd(ast_tvnow(), ast_tv(0, 100000)); while (swift_generator_running(ps)) { ms = ast_tvdiff_ms(next, ast_tvnow()); if (ms <= 0) { if (swift_bytes_available(ps) > 0) { ASTOBJ_WRLOCK(ps); len = fmin(framesize, ps->qc); availatend = cfg_buffer_size - (ps->pq_r - ps->q); if (len > availatend) { /* read #1: to end of q buf */ memcpy(myf.frdata, ps->pq_r, availatend); ps->qc -= availatend; /* read #2: reset to start of q buf and get rest */ ps->pq_r = ps->q; memcpy(myf.frdata + availatend, ps->pq_r, len - availatend); ps->qc -= len - availatend; ps->pq_r += len - availatend; } else { ast_log(LOG_DEBUG, "Easy read; %d bytes and %d at end, %d free\n", len, availatend, cfg_buffer_size - ps->qc); memcpy(myf.frdata, ps->pq_r, len); ps->qc -= len; ps->pq_r += len; } myf.f.frametype = AST_FRAME_VOICE; myf.f.subclass = AST_FORMAT_ULAW; myf.f.datalen = len; myf.f.samples = len; myf.f.data.ptr = myf.frdata; myf.f.mallocd = 0; myf.f.offset = AST_FRIENDLY_OFFSET; myf.f.src = __PRETTY_FUNCTION__; myf.f.delivery.tv_sec = 0; myf.f.delivery.tv_usec = 0; if (ast_write(chan, &myf.f) < 0) { ast_log(LOG_DEBUG, "ast_write failed\n"); } ast_log(LOG_DEBUG, "wrote a frame of %d\n", len); if (ps->qc < 0) { ast_log(LOG_DEBUG, "queue claims to contain negative bytes. Huh? qc < 0\n"); } ASTOBJ_UNLOCK(ps); next = ast_tvadd(next, ast_samp2tv(myf.f.samples, samplerate)); } else { next = ast_tvadd(next, ast_samp2tv(framesize / 2, samplerate)); ast_log(LOG_DEBUG, "Whoops, writer starved for audio\n"); } } else { ms = ast_waitfor(chan, ms); if (ms < 0) { ast_log(LOG_DEBUG, "Hangup detected\n"); res = -1; ASTOBJ_WRLOCK(ps); ps->immediate_exit = 1; ASTOBJ_UNLOCK(ps); } else if (ms) { f = ast_read(chan); if (!f) { ast_log(LOG_DEBUG, "Null frame == hangup() detected\n"); res = -1; ASTOBJ_WRLOCK(ps); ps->immediate_exit = 1; ASTOBJ_UNLOCK(ps); } else if (f->frametype == AST_FRAME_DTMF && timeout > 0 && max_digits > 0) { char originDTMF = f->subclass; alreadyran = 1; res = 0; ASTOBJ_WRLOCK(ps); ps->immediate_exit = 1; ASTOBJ_UNLOCK(ps); if (max_digits > 1) { rc = listen_for_dtmf(chan, timeout, max_digits - 1); } if (rc) { sprintf(results, "%c%s", originDTMF, rc); } else { sprintf(results, "%c", originDTMF); } ast_log(LOG_NOTICE, "DTMF = %s\n", results); pbx_builtin_setvar_helper(chan, "SWIFT_DTMF", results); } ast_frfree(f); } } ASTOBJ_RDLOCK(ps); if (ps->immediate_exit && !ps->generating_done) { if (SWIFT_FAILED(sresult = swift_port_stop(port, tts_stream, SWIFT_EVENT_NOW))) { ast_log(LOG_NOTICE, "Early top of swift port failed\n"); } } ASTOBJ_UNLOCK(ps); } if (alreadyran == 0 && timeout > 0 && max_digits > 0) { rc = listen_for_dtmf(chan, timeout, max_digits); if (rc != NULL) { sprintf(results, "%s", rc); ast_log(LOG_NOTICE, "DTMF = %s\n", results); pbx_builtin_setvar_helper(chan, "SWIFT_DTMF", results); } } if (max_digits >= 1 && results != NULL) { if (cfg_goto_exten) { ast_log(LOG_NOTICE, "GoTo(%s|%s|%d) : ", chan->context, results, 1); if (ast_exists_extension (chan, chan->context, results, 1, chan->cid.cid_num)) { ast_log(LOG_NOTICE, "OK\n"); ast_copy_string(chan->exten, results, sizeof(chan->exten) - 1); chan->priority = 0; } else { ast_log(LOG_NOTICE, "FAILED\n"); } } } exception: if (port != NULL) { swift_port_close(port); } if (engine != NULL) { swift_engine_close(engine); } if (ps && ps->q) { ast_free(ps->q); ps->q = NULL; } if (ps) { ast_free(ps); ps = NULL; } if (!res && old_writeformat) { ast_set_write_format(chan, old_writeformat); } ast_module_user_remove(u); return res; }
static switch_status_t cepstral_speech_open(switch_speech_handle_t *sh, const char *voice_name, int rate, switch_speech_flag_t *flags) { cepstral_t *cepstral = switch_core_alloc(sh->memory_pool, sizeof(*cepstral)); char srate[25]; if (!cepstral) { return SWITCH_STATUS_MEMERR; } if (switch_buffer_create_dynamic(&cepstral->audio_buffer, MY_BLOCK_SIZE, MY_BUF_LEN, 0) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Write Buffer Failed!\n"); return SWITCH_STATUS_MEMERR; } switch_mutex_init(&cepstral->audio_lock, SWITCH_MUTEX_NESTED, sh->memory_pool); cepstral->params = swift_params_new(NULL); swift_params_set_string(cepstral->params, "audio/encoding", "pcm16"); switch_snprintf(srate, sizeof(srate), "%d", rate); swift_params_set_string(cepstral->params, "audio/sampling-rate", srate); /* Open a Swift Port through which to make TTS calls */ if (!(cepstral->port = swift_port_open(engine, cepstral->params))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to open Swift Port.\n"); goto all_done; } if (voice_name && SWIFT_FAILED(swift_port_set_voice_by_name(cepstral->port, voice_name))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Invalid voice %s!\n", voice_name); voice_name = NULL; } if (zstr(voice_name)) { /* Find the first voice on the system */ if ((cepstral->voice = swift_port_find_first_voice(cepstral->port, NULL, NULL)) == NULL) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to find any voices!\n"); goto all_done; } /* Set the voice found by find_first_voice() as the port's current voice */ if (SWIFT_FAILED(swift_port_set_voice(cepstral->port, cepstral->voice))) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to set voice.\n"); goto all_done; } voice_name = (char *) swift_voice_get_attribute(cepstral->voice, "name"); } if (voice_name) { switch_copy_string(sh->voice, voice_name, sizeof(sh->voice)); } swift_port_set_callback(cepstral->port, &write_audio, SWIFT_EVENT_AUDIO, cepstral); sh->private_info = cepstral; return SWITCH_STATUS_SUCCESS; all_done: return SWITCH_STATUS_FALSE; }