commit 4e3bbdb0b02eb1f12c087909e6437a31a9c60d7b Author: William Hubbs Date: Mon Jul 28 01:23:43 2008 -0500 initial import diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..643b0c5 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +espeakup diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5e3b7cc --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +LDLIBS = -lespeak + +PROGRAM = espeakup + +all: $(PROGRAM) + +clean: + rm $(PROGRAM) + +install: $(PROGRAM) + install -m 0755 $(PROGRAM) $(DESTDIR)/usr/bin + diff --git a/README b/README new file mode 100644 index 0000000..95a6836 --- /dev/null +++ b/README @@ -0,0 +1,42 @@ +espeakup connector +======================= + +This is very early alpha software, so please keep that in mind if you +use this program. + +espeakup is a program which makes it possible for speakup to use +the espeak software synthesizer. It does this by reading speakup's +softsynth device and passing the text to espeak which actually speaks. + +Requirements +============ + +This program works with the speakup screen reader, which can be obtained +from http://linux-speakup.org, and the espeak software speech +synthesizer which can be obtained from http://espeak.sourceforge.net. +You must have both of these installed and operational. Setting them up +is beyond the scope of this document. + +Installation +============ + +To install espeakup, first cd into the directory where you +unpacked the tarball, then issue make to compile the program. Once this +is done, as root, issue make install. This will install espeakup in /usr/bin. + +Starting up +=========== + +This program should be run after speakup is set up to communicate with a +software synthesizer and after /dev/softsynth exists. Currently it does +not accept any command line options, so invoke it as follows: + +/usr/sbin/espeakup + +Questions +========= + +You can contact me with questions, bugs, patches, etc, at +w.d.hubbs@gmail.com or on the speakup mailing list. + +Thanks, and I hope you find this useful. diff --git a/espeakup.c b/espeakup.c new file mode 100644 index 0000000..b6c001d --- /dev/null +++ b/espeakup.c @@ -0,0 +1,191 @@ +/* + * espeakup - connector so that speakup can use espeak. + * + * Copyright (C) 2008 William Hubbs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* multipliers and offsets */ +const int pitchMultiplier = 10; +const int rateMultiplier = 32; +const int rateOffset = 80; + +struct synth_t { + int fd; + int pitch; + int rate; + char buf[1025]; +}; + +int SynthCallback(short *wav, int numsamples, espeak_EVENT *events) +{ + return 0; +} + +static void set_pitch (struct synth_t *s) +{ + espeak_SetParameter(espeakPITCH, s->pitch * pitchMultiplier, 0); +} + +static void set_rate (struct synth_t *s) +{ +espeak_SetParameter(espeakRATE, s->rate * rateMultiplier + rateOffset, 0); +} + +static void stop_speech(void) +{ + espeak_Cancel(); +} + +static void speak_text(struct synth_t *s) +{ + if (! strlen(s->buf)) + return; + espeak_Synth(s->buf, strlen(s->buf), 0, POS_CHARACTER, 0, 0, NULL, s); + strcpy(s->buf, ""); +} + +static int process_command(struct synth_t *s, char *buf, int start) +{ + char value; + char param; + + switch (buf[start]) { + case 1: + if (buf[start+1] == '+' || buf[start+1] == '-') { + value = buf[start+2]-'0'; + param = buf[start+3]; + if (buf[start+1] == '-') + value = -value; + switch (param) { + case 'p': + s->pitch += value; + set_pitch (s); + break; + case 's': + s->rate += value; + set_rate (s); + break; + } + return 4; + } else if (buf[start+1] >= '0' && buf[start+1] <= '9') { + value = buf[start+1]-'0'; + param = buf[start+2]; + switch (param) { + case 'p': + s->pitch = value; + set_pitch (s); + break; + case 's': + s->rate = value; + set_rate (s); + break; + } + } + return 3; + case 24: + stop_speech(); + return 1; + } + return 1; +} + +static void process_data (struct synth_t *s) +{ + int length; + int start; + int end; + char buf[1025]; + char tmp_buf[1025]; + + length = read (s->fd, buf, 1024); + start = 0; + end = 0; + while (start < length) { + while (buf[end] >= 32 && end < length) + end++; + if (end != start) { + strncpy (tmp_buf, buf + start, end-start); + tmp_buf[end-start] = 0; + strcat(s->buf, tmp_buf); + } + if (end < length) + start = end = end+process_command (s, buf, end); + else + start = length; + } + speak_text (s); +} + +static void main_loop (struct synth_t *s) +{ + fd_set set; + struct timeval tv; + struct timeval timeout = {0, 20000}; + int i; + + while (1) { + FD_ZERO (&set); + FD_SET (s->fd, &set); + tv = timeout; + i = select (s->fd+1, &set, NULL, NULL, &tv); + if (i) + process_data (s); + } +} + +int main () +{ + struct synth_t s; + + /* become a daemon */ + daemon(0, 1); + + /* open the softsynth. */ + s.fd = open ("/dev/softsynth", O_RDWR | O_NONBLOCK); + if (s.fd < 0) { + printf("Unable to open the softsynth device.\n"); + return -1; + } + + /* initialize espeak */ + espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, NULL, 0); + espeak_SetSynthCallback(SynthCallback); + + /* Setup initial voice parameters */ + s.pitch = 5; + s.rate = 5; + strcpy(s.buf,""); + set_pitch (&s); + set_rate (&s); + + /* run the main loop */ + main_loop (&s); + + /* shutdown espeak and close the softsynth */ + espeak_Terminate(); + close(s.fd); + + return 0; +}