Example #1
0
/** Create Swift synthesizer engine */
MRCP_PLUGIN_DECLARE(mrcp_resource_engine_t*) mrcp_plugin_create(apr_pool_t *pool)
{
	swift_engine *synth_engine;
	mrcp_resource_engine_t *engine;
	/* open swift engine */
	apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Open Swift Engine [%s]",swift_version);
	if((synth_engine = swift_engine_open(NULL)) ==  NULL) {
		apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Open Swift Engine");
		return NULL;
	}
	swift_speech_language_table = mrcp_swift_language_table_create(pool);
	mrcp_swift_voices_show(synth_engine);

	/* create resource engine base */
	engine = mrcp_resource_engine_create(
					MRCP_SYNTHESIZER_RESOURCE, /* MRCP resource identifier */
					synth_engine,              /* object to associate */
					&engine_vtable,            /* virtual methods table of resource engine */
					pool);                     /* pool to allocate memory from */
	if(!engine) {
		apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Create Resource Engine");
		swift_engine_close(synth_engine);
	}
	return engine;
}
Example #2
0
static int
spk_construct (volatile SpeechSynthesizer *spk, char **parameters) {
  swift_result_t result;

  spk->setVolume = spk_setVolume;
  spk->setRate = spk_setRate;

  if (setEnvironmentVariable("SWIFT_HOME", SWIFT_ROOT)) {
    swift_params *engineParameters;

    if ((engineParameters = swift_params_new(NULL))) {
      if ((swiftEngine = swift_engine_open(engineParameters))) {
        if ((swiftPort = swift_port_open(swiftEngine, NULL))) {
          {
            const char *name = parameters[PARM_NAME];
            if (name && *name) {
              swift_voice *voice;
              if (*name == '/') {
                logMessage(LOG_DEBUG, "setting swift voice directory: %s", name);
                voice = swift_port_set_voice_from_dir(swiftPort, name);
              } else {
                logMessage(LOG_DEBUG, "setting swift voice name: %s", name);
                voice = swift_port_set_voice_by_name(swiftPort, name);
              }

              if (!voice) {
                 logMessage(LOG_WARNING, "Swift voice set error: %s", name);
              }
            }
          }

          setStringParameter("tts/content-type", "text/plain");

          logMessage(LOG_INFO, "Swift Engine: %s for %s, version %s, %s",
                     swift_engine_name, swift_platform, swift_version, swift_date);
          return 1;
        } else {
          logMessage(LOG_ERR, "Swift port open error.");
        }

        if ((result = swift_engine_close(swiftEngine)) != SWIFT_SUCCESS) {
          speechError(result, "engine close");
        }
        swiftEngine = NULL;
      } else {
        logMessage(LOG_ERR, "Swift engine open error.");
      }
    } else {
      logMessage(LOG_ERR, "Swift engine parameters allocation error.");
    }
  }

  return 0;
}
Example #3
0
/** Destroy synthesizer engine */
static apt_bool_t mrcp_swift_engine_destroy(mrcp_resource_engine_t *engine)
{
	swift_engine *synth_engine = engine->obj;
	/* close swift engine */
	apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Close Swift Engine");
	if(synth_engine) {
		swift_engine_close(synth_engine);
		engine->obj = NULL;
	}
	return TRUE;
}
Example #4
0
/** Close synthesizer engine */
static apt_bool_t mrcp_swift_engine_close(mrcp_engine_t *engine)
{
	mrcp_swift_engine_t *synth_engine = engine->obj;

	/* close swift engine */
	apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Close Swift Engine");
	if(synth_engine->swift) {
		swift_engine_close(synth_engine->swift);
		synth_engine->swift = NULL;
	}
	return TRUE;
}
Example #5
0
static void
spk_destruct (volatile SpeechSynthesizer *spk) {
  swift_result_t result;

  if (swiftPort) {
    if ((result = swift_port_close(swiftPort)) != SWIFT_SUCCESS) {
      speechError(result, "port close");
    }
    swiftPort = NULL;
  }

  if (swiftEngine) {
    if ((result = swift_engine_close(swiftEngine)) != SWIFT_SUCCESS) {
      speechError(result, "engine close");
    }
    swiftEngine = NULL;
  }
}
Example #6
0
/** Open synthesizer engine */
static apt_bool_t mrcp_swift_engine_open(mrcp_engine_t *engine)
{
	mrcp_swift_engine_t *synth_engine = engine->obj;
	
	/* open swift engine */
	apt_log(APT_LOG_MARK,APT_PRIO_INFO,"Open Swift Engine [%s]",swift_version);
	if((synth_engine->swift = swift_engine_open(NULL)) ==  NULL) {
		apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Open Swift Engine");
		return FALSE;
	}

	if(mrcp_swift_voices_scan(synth_engine) == FALSE) {
		apt_log(APT_LOG_MARK,APT_PRIO_WARNING,"Failed to Scan Swift Voices");
		swift_engine_close(synth_engine->swift);
		synth_engine->swift = NULL;
		return FALSE;
	}
	return TRUE;
}
Example #7
0
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;
}