uint32_t client_render_voice(srs_client_t *c, const char *msg,
- const char *voice, int timeout, int notify_events)
+ const char *voice, double rate, double pitch,
+ int timeout, int notify_events)
{
srs_context_t *srs = c->srs;
const char *tags[] = { "media.role=speech", NULL };
req->c = c;
req->notify_events = notify_events;
- req->id = srs_render_voice(srs, msg, (char **)tags, voice, timeout,
- notify_events | forced, client_voice_event,
- req);
+ if (rate == 0)
+ rate = 1;
+ if (pitch == 0)
+ pitch = 1;
+
+ req->id = srs_render_voice(srs, msg, (char **)tags, voice, rate, pitch,
+ timeout, notify_events | forced,
+ client_voice_event, req);
if (req->id != SRS_VOICE_INVALID) {
mrp_list_append(&c->voices, &req->hook);
/** Request synthesizing a message. */
uint32_t client_render_voice(srs_client_t *c, const char *msg,
- const char *voice, int timeout, int notify_events);
+ const char *voice, double rate, double pitch,
+ int timeout, int notify_events);
/** Cancel/stop a synthesizing request. */
void client_cancel_voice(srs_client_t *c, uint32_t id);
char *msg; /* message to render */
char **tags; /* stream tags */
uint32_t actor; /* actor id */
+ double rate; /* synthesis rate (1 = normal) */
+ double pitch; /* synthesis pitch (1 = default) */
int timeout; /* timeout */
} queued_t;
static request_t *enqueue_request(state_t *state, const char *msg, char **tags,
- renderer_t *r, uint32_t actor, int timeout,
- int notify_mask, srs_voice_notify_t notify,
- void *notify_data)
+ renderer_t *r, uint32_t actor, double rate,
+ double pitch, int timeout, int notify_mask,
+ srs_voice_notify_t notify, void *notify_data)
{
queued_t *qr;
qr->req.timer = NULL;
r = qr->req.r;
- qr->req.vid = r->api.render(qr->msg, qr->tags, qr->actor,
- qr->req.notify_mask, r->api_data);
+ qr->req.vid = r->api.render(qr->msg, qr->tags, qr->actor, qr->rate,
+ qr->pitch, qr->req.notify_mask, r->api_data);
mrp_free(qr->msg);
qr->msg = NULL;
request_t *render_request(state_t *state, const char *msg, char **tags,
- renderer_t *r, uint32_t actor, int timeout,
- int notify_mask, srs_voice_notify_t notify,
- void *notify_data)
+ renderer_t *r, uint32_t actor, double rate,
+ double pitch, int timeout, int notify_mask,
+ srs_voice_notify_t notify, void *notify_data)
{
request_t *req;
mrp_list_init(&req->hook);
req->id = state->nextid++;
req->r = r;
- req->vid = r->api.render(msg, tags, actor, notify_mask, r->api_data);
+ req->vid = r->api.render(msg, tags, actor, rate, pitch,
+ notify_mask, r->api_data);
if (req->vid == SRS_VOICE_INVALID) {
mrp_free(req);
uint32_t srs_render_voice(srs_context_t *srs, const char *msg,
- char **tags, const char *voice, int timeout,
- int notify_mask, srs_voice_notify_t notify,
- void *user_data)
+ char **tags, const char *voice, double rate,
+ double pitch, int timeout, int notify_mask,
+ srs_voice_notify_t notify, void *user_data)
{
state_t *state = (state_t *)srs->synthesizer;
renderer_t *r;
}
if (state->active == NULL)
- req = render_request(state, msg, tags, r, actid, timeout,
+ req = render_request(state, msg, tags, r, actid, rate, pitch, timeout,
notify_mask, notify, user_data);
else {
if (timeout == SRS_VOICE_IMMEDIATE) {
req = NULL;
}
else
- req = enqueue_request(state, msg, tags, r, actid, timeout,
- notify_mask, notify, user_data);
+ req = enqueue_request(state, msg, tags, r, actid, rate, pitch,
+ timeout, notify_mask, notify, user_data);
}
if (req != NULL)
*/
typedef struct {
/** Render the given message. */
- uint32_t (*render)(const char *msg, char **tags, int actor,
- int notify_events, void *api_data);
+ uint32_t (*render)(const char *msg, char **tags, int actor, double rate,
+ double pitch, int notify_events, void *api_data);
/** Cancel the given rendering, notify cancellation if asked for. */
void (*cancel)(uint32_t id, void *api_data);
} srs_voice_api_t;
/** Render the given message using the given parameters. */
uint32_t srs_render_voice(srs_context_t *srs, const char *msg,
- char **tags, const char *voice, int timeout,
- int notify_events, srs_voice_notify_t notify,
- void *user_data);
+ char **tags, const char *voice, double rate,
+ double pitch, int timeout, int notify_events,
+ srs_voice_notify_t notify, void *user_data);
/** Cancel the given voice rendering. */
void srs_cancel_voice(srs_context_t *srs, uint32_t id, int notify);
static int parse_render_voice(mrp_dbus_msg_t *req, const char **id,
const char **msg, const char **voice,
- int *timeout, int *notify_events,
- const char **errmsg)
+ double *rate, double *pitch, int *timeout,
+ int *notify_events, const char **errmsg)
{
char **events, *e;
int i;
if (*id == NULL)
return EINVAL;
+ *rate = *pitch = 1;
+
if (!mrp_dbus_msg_read_basic(req, MRP_DBUS_TYPE_STRING, msg) ||
!mrp_dbus_msg_read_basic(req, MRP_DBUS_TYPE_STRING, voice) ||
+ (mrp_dbus_msg_arg_type(req, NULL) != MRP_DBUS_TYPE_DOUBLE ||
+ !(mrp_dbus_msg_read_basic(req, MRP_DBUS_TYPE_DOUBLE, &rate) &&
+ mrp_dbus_msg_read_basic(req, MRP_DBUS_TYPE_DOUBLE, &pitch))) ||
!mrp_dbus_msg_read_basic(req, MRP_DBUS_TYPE_INT32 , &to) ||
!mrp_dbus_msg_read_array(req, MRP_DBUS_TYPE_STRING,
(void **)&events, &nevent)) {
dbusif_t *bus = (dbusif_t *)user_data;
srs_context_t *srs = bus->self->srs;
const char *id, *msg, *voice, *errmsg;
+ double rate, pitch;
int timeout, events, err;
uint32_t reqid;
srs_client_t *c;
- err = parse_render_voice(req, &id, &msg, &voice, &timeout, &events,
- &errmsg);
+ err = parse_render_voice(req, &id, &msg, &voice, &rate, &pitch, &timeout,
+ &events, &errmsg);
if (err != 0) {
reply_error(dbus, req, err, errmsg);
return TRUE;
}
- reqid = client_render_voice(c, msg, voice, timeout, events);
+ reqid = client_render_voice(c, msg, voice, rate, pitch, timeout, events);
if (reqid != SRS_VOICE_INVALID)
reply_render(dbus, req, reqid);
uint32_t srs_render_voice(srs_t *srs, const char *msg, const char *voice,
- int timeout, int events, srs_render_notify_t cb,
- void *cb_data)
+ double rate, double pitch, int timeout, int events,
+ srs_render_notify_t cb, void *cb_data)
{
srs_req_voice_t req;
request_data_t data;
req.type = SRS_REQUEST_RENDERVOICE;
req.msg = (char *)msg;
req.voice = (char *)voice;
+ req.rate = rate;
+ req.pitch = pitch;
req.timeout = timeout;
req.events = events;
/** Request rendering the given message, subscribing for the given events. */
uint32_t srs_render_voice(srs_t *srs, const char *msg, const char *voice,
- int timeout, int events, srs_render_notify_t cb,
- void *cb_data);
+ double rate, double pitch, int timeout,
+ int events, srs_render_notify_t cb, void *cb_data);
/** Cancel an ongoing voice render request. */
int srs_cancel_voice(srs_t *srs, uint32_t id);
MRP_UINT32(srs_req_voice_t, reqno , DEFAULT),
MRP_STRING(srs_req_voice_t, msg , DEFAULT),
MRP_STRING(srs_req_voice_t, voice , DEFAULT),
+ MRP_DOUBLE(srs_req_voice_t, rate , DEFAULT),
+ MRP_DOUBLE(srs_req_voice_t, pitch , DEFAULT),
MRP_UINT32(srs_req_voice_t, timeout , DEFAULT),
MRP_UINT32(srs_req_voice_t, events , DEFAULT));
uint32_t reqno; /* request number */
char *msg; /* message to render */
char *voice; /* voice to use */
+ double rate; /* voice pitch (0 or 1 = default) */
+ double pitch; /* voice pitch (0 or 1 = default) */
uint32_t timeout; /* message timeout */
uint32_t events; /* mask of events to notify about */
} srs_req_voice_t;
{
const char *msg = req->msg;
const char *voice = req->voice;
+ double rate = req->rate;
+ double pitch = req->pitch;
int timeout = req->timeout;
int events = req->events;
uint32_t reqid;
mrp_debug("received voice render request from native client #%d", c->id);
- reqid = client_render_voice(c->c, msg, voice, timeout, events);
+ reqid = client_render_voice(c->c, msg, voice, rate, pitch, timeout, events);
if (reqid != SRS_VOICE_INVALID)
reply_render(c, req->reqno, reqid);
print(c, "Requesting TTS for message: '%s'.", msg);
- c->vreq = srs_render_voice(c->srs, msg, voice, timeout,
+ c->vreq = srs_render_voice(c->srs, msg, voice, 0, 0, timeout,
events ? SRS_VOICE_MASK_ALL:SRS_VOICE_MASK_NONE,
render_notify, NULL);
}
mrp_log_info("WRT media client: relaying TTS request '%s' in '%s' from %s.",
msg, voice, sender);
- id = client_render_voice(wrtc->c, msg, voice, timeout, events);
+ id = client_render_voice(wrtc->c, msg, voice, 0, 0, timeout, events);
g_dbus_method_invocation_return_value(inv, g_variant_new("(u)", id));
}
static uint32_t festival_render(const char *msg, char **tags, int actor,
- int notify_events, void *api_data)
+ double rate, double pitch, int notify_events,
+ void *api_data)
{
festival_t *f = (festival_t *)api_data;
void *samples;
uint32_t nsample, id;
int srate, nchannel;
+ MRP_UNUSED(rate);
+ MRP_UNUSED(pitch);
+
if (0 <= actor && actor < f->nactor)
carnival_select_voice(f->actors[actor].name);
else