Skip to content
Browse files

support adapters using the acsint module

  • Loading branch information...
1 parent 70f7465 commit c06f18c4544a6e9e3d28b8f037bc40588fbff3f5 @CMB CMB committed with May 1, 2011
Showing with 181 additions and 7 deletions.
  1. +5 −1 cli.c
  2. +25 −2 espeak.c
  3. +2 −1 espeakup.c
  4. +6 −0 espeakup.h
  5. +143 −3 softsynth.c
View
6 cli.c
@@ -31,10 +31,11 @@ extern char *pidPath;
extern char *defaultVoice;
/* command line options */
-const char *shortOptions = "P:V:dhv";
+const char *shortOptions = "P:V:adhv";
const struct option longOptions[] = {
{"pid-path", required_argument, NULL, 'P'},
{"default-voice", required_argument, NULL, 'V'},
+ {"acsint", no_argument, NULL, 'a'},
{"debug", no_argument, NULL, 'd'},
{"help", no_argument, NULL, 'h'},
{"version", no_argument, NULL, 'v'},
@@ -79,6 +80,9 @@ void process_cli(int argc, char **argv)
case 'V':
defaultVoice = strdup(optarg);
break;
+ case 'a':
+ espeakup_mode = ESPEAKUP_MODE_ACSINT;
+ break;
case 'd':
debug = 1;
break;
View
27 espeak.c
@@ -40,6 +40,21 @@ const int volumeMultiplier = 22;
volatile int stop_requested = 0;
+static int acsint_callback(short *wav, int numsamples, espeak_EVENT * events)
+{
+ int i;
+ for (i = 0; events[i].type != espeakEVENT_LIST_TERMINATED; i++) {
+ if (events[i].type == espeakEVENT_MARK) {
+ int mark = atoi(events[i].id.name);
+ if ((mark < 0) || (mark > 255))
+ continue;
+ putchar(mark);
+ fflush(stdout);
+ }
+ }
+ return 0;
+}
+
static espeak_ERROR set_frequency(struct synth_t *s, int freq,
enum adjust_t adj)
{
@@ -139,9 +154,13 @@ static espeak_ERROR stop_speech(void)
static espeak_ERROR speak_text(struct synth_t *s)
{
espeak_ERROR rc;
+ int synth_mode = 0;
- rc = espeak_Synth(s->buf, s->len + 1, 0, POS_CHARACTER, 0, 0, NULL,
- NULL);
+ if (espeakup_mode == ESPEAKUP_MODE_ACSINT)
+ synth_mode |= espeakSSML;
+
+ rc = espeak_Synth(s->buf, s->len + 1, 0, POS_CHARACTER, 0, synth_mode,
+ NULL, NULL);
return rc;
}
@@ -219,6 +238,10 @@ int initialize_espeak(struct synth_t *s)
return -1;
}
+ /* We need a callback in acsint mode, but not in speakup mode. */
+ if (espeakup_mode == ESPEAKUP_MODE_ACSINT)
+ espeak_SetSynthCallback(acsint_callback);
+
/* Setup initial voice parameters */
if (defaultVoice) {
set_voice(s, defaultVoice);
View
3 espeakup.c
@@ -30,6 +30,7 @@
char *pidPath = "/var/run/espeakup.pid";
int debug = 0;
+enum espeakup_mode_t espeakup_mode = ESPEAKUP_MODE_SPEAKUP;
struct queue_t *synth_queue = NULL;
int self_pipe_fds[2];
@@ -99,7 +100,7 @@ int main(int argc, char **argv)
/*
* If we are not in debug mode, become a daemon and store the pid.
*/
- if (!debug) {
+ if (espeakup_mode != ESPEAKUP_MODE_ACSINT && !debug) {
daemon(0, 1);
if (create_pid_file() < 0) {
perror("Unable to create pid file");
View
6 espeakup.h
@@ -31,6 +31,11 @@
#define PACKAGE_VERSION "0.80-dev"
#define PACKAGE_BUGREPORT "http://github.com/williamh/espeakup/issues"
+enum espeakup_mode_t {
+ ESPEAKUP_MODE_SPEAKUP,
+ ESPEAKUP_MODE_ACSINT
+};
+
enum command_t {
CMD_SET_FREQUENCY,
CMD_SET_PITCH,
@@ -70,6 +75,7 @@ struct synth_t {
extern struct queue_t *synth_queue;
extern int debug;
+extern enum espeakup_mode_t espeakup_mode;
extern void process_cli(int argc, char **argv);
extern void *signal_thread(void *arg);
View
146 softsynth.c
@@ -28,13 +28,103 @@
#include "espeakup.h"
/* max buffer size */
-static const size_t maxBufferSize = 1025;
+/* A big fat buffer. */
+static const size_t maxBufferSize = 16 * 1024 + 1;
/* synth flush character */
static const int synthFlushChar = 0x18;
+
static int softFD = 0;
+/* Text accumulator: */
+char *textAccumulator;
+int textAccumulator_l;
+
+/* String routines, borrowed from edbrowse: */
+char *EMPTYSTRING = "";
+
+void *allocMem(size_t n)
+{
+ void *s;
+ if (!n)
+ return EMPTYSTRING;
+ if (!(s = malloc(n))) {
+ fprintf(stderr, "Out of memory!\n");
+ exit(1);
+ }
+ return s;
+} /* allocMem */
+
+void *reallocMem(void *p, size_t n)
+{
+ void *s;
+ if (!n) {
+ fprintf(stderr, "Trying to reallocate memory with size of 0.\n");
+ exit(1);
+ }
+ if (!p) {
+ fprintf(stderr, "realloc called with a NULL pointer!\n");
+ exit(1);
+ }
+ if (p == EMPTYSTRING)
+ return allocMem(n);
+ if (!(s = realloc(p, n))) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ exit(1);
+ }
+ return s;
+} /* reallocMem */
+
+char *initString(int *l)
+{
+ *l = 0;
+ return EMPTYSTRING;
+}
+
+void stringAndString(char **s, int *l, const char *t)
+{
+ char *p = *s;
+ int oldlen, newlen, x;
+ oldlen = *l;
+ newlen = oldlen + strlen(t);
+ *l = newlen;
+ ++newlen; /* room for the 0 */
+ x = oldlen ^ newlen;
+ if (x > oldlen) { /* must realloc */
+ newlen |= (newlen >> 1);
+ newlen |= (newlen >> 2);
+ newlen |= (newlen >> 4);
+ newlen |= (newlen >> 8);
+ newlen |= (newlen >> 16);
+ p = reallocMem(p, newlen);
+ *s = p;
+ }
+ strcpy(p + oldlen, t);
+} /* stringAndString */
+
+void stringAndBytes(char **s, int *l, const char *t, int cnt)
+{
+ char *p = *s;
+ int oldlen, newlen, x;
+ oldlen = *l;
+ newlen = oldlen + cnt;
+ *l = newlen;
+ ++newlen;
+ x = oldlen ^ newlen;
+ if (x > oldlen) { /* must realloc */
+ newlen |= (newlen >> 1);
+ newlen |= (newlen >> 2);
+ newlen |= (newlen >> 4);
+ newlen |= (newlen >> 8);
+ newlen |= (newlen >> 16);
+ p = reallocMem(p, newlen);
+ *s = p;
+ }
+ memcpy(p + oldlen, t, cnt);
+ p[oldlen + cnt] = 0;
+} /* stringAndBytes */
+
static void queue_add_cmd(enum command_t cmd, enum adjust_t adj, int value)
{
struct espeak_entry_t *entry;
@@ -147,8 +237,15 @@ static int process_command(struct synth_t *s, char *buf, int start)
break;
}
- if (cmd != CMD_FLUSH && cmd != CMD_UNKNOWN)
+ if (cmd != CMD_FLUSH && cmd != CMD_UNKNOWN) {
+ if (espeakup_mode == ESPEAKUP_MODE_ACSINT
+ && textAccumulator_l != 0) {
+ queue_add_text(textAccumulator, textAccumulator_l);
+ free(textAccumulator);
+ textAccumulator = initString(&textAccumulator_l);
+ }
queue_add_cmd(cmd, adj, value);
+ }
return cp - (buf + start);
}
@@ -178,6 +275,38 @@ static void process_buffer(struct synth_t *s, char *buf, ssize_t length)
}
}
+static void process_buffer_acsint(struct synth_t *s, char *buf,
+ ssize_t length)
+{
+ int start = 0;
+ int i;
+ int flushIt = 0;
+
+ while (start < length) {
+ for (i = start; i < length; i++) {
+ if (buf[i] == '\r' || buf[i] == '\n')
+ flushIt = 1;
+ if (buf[i] >= 0 && buf[i] < ' ')
+ break;
+ }
+ if (i > start)
+ stringAndBytes(&textAccumulator, &textAccumulator_l,
+ buf + start, i - start);
+ if (flushIt) {
+ if (textAccumulator != EMPTYSTRING) {
+ queue_add_text(textAccumulator, textAccumulator_l);
+ free(textAccumulator);
+ textAccumulator = initString(&textAccumulator_l);
+ }
+ flushIt = 0;
+ }
+ if (i < length)
+ start = i = i + process_command(s, buf, i);
+ else
+ start = length;
+ }
+}
+
static void request_espeak_stop(void)
{
pthread_mutex_lock(&queue_guard);
@@ -191,6 +320,12 @@ static void request_espeak_stop(void)
int open_softsynth(void)
{
int rc = 0;
+ /* If we're in acsint mode, we read from stdin. No need to open. */
+ if (espeakup_mode == ESPEAKUP_MODE_ACSINT) {
+ softFD = STDIN_FILENO;
+ return 0;
+ }
+
/* open the softsynth. */
softFD = open("/dev/softsynth", O_RDWR | O_NONBLOCK);
if (softFD < 0) {
@@ -216,6 +351,8 @@ void *softsynth_thread(void *arg)
int terminalFD = PIPE_READ_FD;
int greatestFD;
+ textAccumulator = initString(&textAccumulator_l);
+
if (terminalFD > softFD)
greatestFD = terminalFD;
else
@@ -264,7 +401,10 @@ void *softsynth_thread(void *arg)
memmove(buf, cp + 1, strlen(cp + 1) + 1);
length = strlen(buf);
}
- process_buffer(s, buf, length);
+ if (espeakup_mode == ESPEAKUP_MODE_SPEAKUP)
+ process_buffer(s, buf, length);
+ else
+ process_buffer_acsint(s, buf, length);
pthread_mutex_lock(&queue_guard);
}
pthread_cond_signal(&runner_awake);

0 comments on commit c06f18c

Please sign in to comment.
Something went wrong with that request. Please try again.