mirror of
https://github.com/linux-speakup/espeakup.git
synced 2026-08-21 15:24:17 +02:00
added queueing support
I have added queueing support so that when we read from the softsynth we can put the text and commands we have read into a queue. This will allow us to retry calling espeak_synth() if we fill espeak's internal buffer.
This commit is contained in:
parent
86e93edeb0
commit
655894ee2a
6 changed files with 288 additions and 93 deletions
26
Makefile
26
Makefile
|
|
@ -2,26 +2,19 @@ CC = cc
|
|||
INSTALL = /usr/bin/install
|
||||
RM = /bin/rm -f
|
||||
|
||||
PREFIX = /usr
|
||||
BINDIR = $(PREFIX)/bin
|
||||
|
||||
LDLIBS = -lespeak
|
||||
|
||||
SRCS = \
|
||||
espeakup.c \
|
||||
queue.c \
|
||||
softsynth.c \
|
||||
synth.c
|
||||
|
||||
OBJS = $(SRCS:.c=.o)
|
||||
|
||||
ifeq ("$(origin TAG)", "command line")
|
||||
TIMESTAMP := _p$(shell date +%Y%m%d)
|
||||
endif
|
||||
CFLAGS = -ggdb
|
||||
LDLIBS = -lespeak
|
||||
|
||||
VERSION := $(shell grep 'Version.*=' espeakup.c | sed 's/.*"\(.*\)";/\1/')
|
||||
TAG := v$(VERSION)
|
||||
TARPREFIX := espeakup-$(VERSION)
|
||||
TARFILE := $(TARPREFIX)$(TIMESTAMP).tar
|
||||
PREFIX = /usr
|
||||
BINDIR = $(PREFIX)/bin
|
||||
|
||||
all: espeakup
|
||||
|
||||
|
|
@ -37,6 +30,15 @@ distclean: clean
|
|||
|
||||
espeakup: $(OBJS)
|
||||
|
||||
ifeq ("$(origin TAG)", "command line")
|
||||
TIMESTAMP := _p$(shell date +%Y%m%d)
|
||||
endif
|
||||
|
||||
VERSION := $(shell grep 'Version.*=' espeakup.c | sed 's/.*"\(.*\)";/\1/')
|
||||
TAG := v$(VERSION)
|
||||
TARPREFIX := espeakup-$(VERSION)
|
||||
TARFILE := $(TARPREFIX)$(TIMESTAMP).tar
|
||||
|
||||
tarball:
|
||||
git archive --format=tar --prefix=$(TARPREFIX)/ $(TAG) > $(TARFILE)
|
||||
tar f $(TARFILE) --delete $(TARPREFIX)/.gitignore
|
||||
|
|
|
|||
23
espeakup.c
23
espeakup.c
|
|
@ -35,6 +35,12 @@ const char *shortOptions = "dhv";
|
|||
/* path to our pid file */
|
||||
const char *pidPath = "/var/run/espeakup.pid";
|
||||
|
||||
/* default voice settings */
|
||||
const int defaultFrequency = 5;
|
||||
const int defaultPitch = 5;
|
||||
const int defaultRate = 5;
|
||||
const int defaultVolume = 5;
|
||||
|
||||
int debug = 0;
|
||||
|
||||
int espeakup_is_running(void)
|
||||
|
|
@ -123,13 +129,7 @@ void process_cli(int argc, char **argv)
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct synth_t s = {
|
||||
.frequency = 5,
|
||||
.pitch = 5,
|
||||
.rate = 5,
|
||||
.voice = "default",
|
||||
.volume = 5,
|
||||
};
|
||||
struct synth_t s;
|
||||
|
||||
/* process command line options */
|
||||
process_cli(argc, argv);
|
||||
|
|
@ -158,11 +158,10 @@ int main(int argc, char **argv)
|
|||
espeak_SetSynthCallback(SynthCallback);
|
||||
|
||||
/* Setup initial voice parameters */
|
||||
set_voice(&s);
|
||||
set_frequency (&s);
|
||||
set_pitch (&s);
|
||||
set_rate (&s);
|
||||
set_volume(&s);
|
||||
set_frequency (&s, defaultFrequency, ADJ_SET);
|
||||
set_pitch (&s, defaultPitch, ADJ_SET);
|
||||
set_rate (&s, defaultRate, ADJ_SET);
|
||||
set_volume(&s, defaultVolume, ADJ_SET);
|
||||
|
||||
/* register signal handler */
|
||||
signal(SIGINT, espeakup_sighandler);
|
||||
|
|
|
|||
25
espeakup.h
25
espeakup.h
|
|
@ -22,6 +22,23 @@
|
|||
|
||||
#include <espeak/speak_lib.h>
|
||||
|
||||
enum command_t {
|
||||
CMD_SET_FREQUENCY,
|
||||
CMD_SET_PITCH,
|
||||
CMD_SET_RATE,
|
||||
CMD_SET_VOICE,
|
||||
CMD_SET_VOLUME,
|
||||
CMD_SPEAK_TEXT,
|
||||
CMD_FLUSH,
|
||||
CMD_UNKNOWN,
|
||||
};
|
||||
|
||||
enum adjust_t {
|
||||
ADJ_DEC,
|
||||
ADJ_SET,
|
||||
ADJ_INC,
|
||||
};
|
||||
|
||||
struct synth_t {
|
||||
int frequency;
|
||||
int pitch;
|
||||
|
|
@ -35,11 +52,11 @@ struct synth_t {
|
|||
extern int debug;
|
||||
|
||||
extern int SynthCallback(short *wav, int numsamples, espeak_EVENT *events);
|
||||
extern espeak_ERROR set_frequency (struct synth_t *s);
|
||||
extern espeak_ERROR set_pitch (struct synth_t *s);
|
||||
extern espeak_ERROR set_rate (struct synth_t *s);
|
||||
extern espeak_ERROR set_frequency(struct synth_t *s, int freq, enum adjust_t adj);
|
||||
extern espeak_ERROR set_pitch (struct synth_t *s, int pitch, enum adjust_t adj);
|
||||
extern espeak_ERROR set_rate (struct synth_t *s, int rate, enum adjust_t adj);
|
||||
extern espeak_ERROR set_voice(struct synth_t *s);
|
||||
extern espeak_ERROR set_volume (struct synth_t *s);
|
||||
extern espeak_ERROR set_volume (struct synth_t *s, int vol, enum adjust_t adj);
|
||||
extern espeak_ERROR stop_speech(void);
|
||||
extern espeak_ERROR speak_text(struct synth_t *s);
|
||||
extern void open_softsynth(void);
|
||||
|
|
|
|||
139
queue.c
Normal file
139
queue.c
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* espeakup - interface which allows speakup to 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "espeakup.h"
|
||||
|
||||
struct queue_entry_t {
|
||||
enum command_t cmd;
|
||||
enum adjust_t adjust;
|
||||
int value;
|
||||
char *buf;
|
||||
int len;
|
||||
struct queue_entry_t *next;
|
||||
};
|
||||
|
||||
static struct queue_entry_t *first = NULL;
|
||||
static struct queue_entry_t *last = NULL;
|
||||
|
||||
static void queue_add(struct queue_entry_t *entry)
|
||||
{
|
||||
assert(entry);
|
||||
entry->next = NULL;
|
||||
if (! last)
|
||||
last = entry;
|
||||
if (! first) {
|
||||
first = entry;
|
||||
} else {
|
||||
first->next = entry;
|
||||
first = first->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void queue_remove(void)
|
||||
{
|
||||
struct queue_entry_t *temp;
|
||||
|
||||
assert(last);
|
||||
temp = last;
|
||||
last = temp->next;
|
||||
if (temp->cmd == CMD_SPEAK_TEXT)
|
||||
free(temp->buf);
|
||||
free(temp);
|
||||
if (! last)
|
||||
first = last;
|
||||
}
|
||||
|
||||
void queue_clear(void)
|
||||
{
|
||||
while(last)
|
||||
queue_remove();
|
||||
}
|
||||
|
||||
void queue_add_cmd(enum command_t cmd, enum adjust_t adj, int value)
|
||||
{
|
||||
struct queue_entry_t *entry;
|
||||
|
||||
entry = malloc(sizeof(struct queue_entry_t));
|
||||
if (! entry) {
|
||||
perror("unable to allocate memory for queue entry");
|
||||
return;
|
||||
}
|
||||
entry->cmd = cmd;
|
||||
entry->adjust = adj;
|
||||
entry->value = value;
|
||||
queue_add(entry);
|
||||
}
|
||||
|
||||
void queue_add_text(char *txt, size_t length)
|
||||
{
|
||||
struct queue_entry_t *entry;
|
||||
|
||||
entry = malloc(sizeof(struct queue_entry_t));
|
||||
if (! entry) {
|
||||
perror("unable to allocate memory for queue entry");
|
||||
return;
|
||||
}
|
||||
entry->cmd = CMD_SPEAK_TEXT;
|
||||
entry->adjust = ADJ_SET;
|
||||
entry->buf = strdup(txt);
|
||||
if (! entry->buf) {
|
||||
perror("unable to allocate space for text");
|
||||
free(entry);
|
||||
return;
|
||||
}
|
||||
entry->len = length;
|
||||
queue_add(entry);
|
||||
}
|
||||
|
||||
void queue_process_entry(struct synth_t *s)
|
||||
{
|
||||
espeak_ERROR error;
|
||||
|
||||
if(! last)
|
||||
return;
|
||||
|
||||
switch (last->cmd) {
|
||||
case CMD_SET_FREQUENCY:
|
||||
error = set_frequency(s, last->value, last->adjust);
|
||||
break;
|
||||
case CMD_SET_PITCH:
|
||||
error = set_pitch(s, last->value, last->adjust);
|
||||
break;
|
||||
case CMD_SET_RATE:
|
||||
error = set_rate(s, last->value, last->adjust);
|
||||
break;
|
||||
case CMD_SET_VOICE:
|
||||
break;
|
||||
case CMD_SET_VOLUME:
|
||||
error = set_volume(s, last->value, last->adjust);
|
||||
break;
|
||||
case CMD_SPEAK_TEXT:
|
||||
s->buf = last->buf;
|
||||
s->len = last->len;
|
||||
error = speak_text(s);
|
||||
break;
|
||||
}
|
||||
if (error == EE_OK)
|
||||
queue_remove();
|
||||
}
|
||||
120
softsynth.c
120
softsynth.c
|
|
@ -26,72 +26,74 @@
|
|||
#include "espeakup.h"
|
||||
|
||||
/* max buffer size */
|
||||
const int maxBufferSize = 1025;
|
||||
const size_t maxBufferSize = 1025;
|
||||
|
||||
static int softFD = 0;
|
||||
|
||||
static int process_command(struct synth_t *s, char *buf, int start)
|
||||
{
|
||||
int rc;
|
||||
char value;
|
||||
char param;
|
||||
char *cp;
|
||||
int value;
|
||||
enum adjust_t adj;
|
||||
enum command_t cmd;
|
||||
|
||||
rc = 1;
|
||||
switch (buf[start]) {
|
||||
cp = buf+start;
|
||||
switch (*cp) {
|
||||
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 'f':
|
||||
s->frequency += value;
|
||||
set_frequency (s);
|
||||
break;
|
||||
case 'p':
|
||||
s->pitch += value;
|
||||
set_pitch (s);
|
||||
break;
|
||||
case 's':
|
||||
s->rate += value;
|
||||
set_rate (s);
|
||||
break;
|
||||
case 'v':
|
||||
s->volume += value;
|
||||
set_volume (s);
|
||||
break;
|
||||
}
|
||||
rc = 4;
|
||||
} else if (buf[start+1] >= '0' && buf[start+1] <= '9') {
|
||||
value = buf[start+1]-'0';
|
||||
param = buf[start+2];
|
||||
switch (param) {
|
||||
case 'f':
|
||||
s->frequency = value;
|
||||
set_frequency (s);
|
||||
break;
|
||||
case 'p':
|
||||
s->pitch = value;
|
||||
set_pitch (s);
|
||||
break;
|
||||
case 's':
|
||||
s->rate = value;
|
||||
set_rate (s);
|
||||
break;
|
||||
case 'v':
|
||||
s->volume = value;
|
||||
set_volume (s);
|
||||
break;
|
||||
}
|
||||
cp++;
|
||||
switch (*cp) {
|
||||
case '+':
|
||||
adj = ADJ_INC;
|
||||
cp++;
|
||||
break;
|
||||
case '-':
|
||||
adj = ADJ_DEC;
|
||||
cp++;
|
||||
break;
|
||||
default:
|
||||
adj = ADJ_SET;
|
||||
break;
|
||||
}
|
||||
|
||||
value = 0;
|
||||
while(isdigit(*cp)) {
|
||||
value = value * 10 + (*cp - '0');
|
||||
cp++;
|
||||
}
|
||||
|
||||
switch (*cp) {
|
||||
case 'f':
|
||||
cmd = CMD_SET_FREQUENCY;
|
||||
cp++;
|
||||
break;
|
||||
case 'p':
|
||||
cmd = CMD_SET_PITCH;
|
||||
cp++;
|
||||
break;
|
||||
case 's':
|
||||
cmd = CMD_SET_RATE;
|
||||
cp++;
|
||||
break;
|
||||
case 'v':
|
||||
cmd = CMD_SET_VOLUME;
|
||||
cp++;
|
||||
break;
|
||||
}
|
||||
rc = 3;
|
||||
break;
|
||||
case 24:
|
||||
cmd = CMD_FLUSH;
|
||||
stop_speech();
|
||||
queue_clear();
|
||||
cp++;
|
||||
break;
|
||||
default:
|
||||
cmd = CMD_UNKNOWN;
|
||||
cp++;
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
if (cmd != CMD_FLUSH && cmd != CMD_UNKNOWN)
|
||||
queue_add_cmd(cmd, adj, value);
|
||||
return cp - (buf + start);
|
||||
}
|
||||
|
||||
static void process_buffer (struct synth_t *s, char *buf, size_t length)
|
||||
|
|
@ -110,9 +112,7 @@ static void process_buffer (struct synth_t *s, char *buf, size_t length)
|
|||
txtLen = end-start;
|
||||
strncpy (txtBuf, buf + start, txtLen);
|
||||
*(txtBuf+txtLen) = 0;
|
||||
s->buf = txtBuf;
|
||||
s->len = txtLen;
|
||||
speak_text(s);
|
||||
queue_add_text(txtBuf, txtLen);
|
||||
}
|
||||
if (end < length)
|
||||
start = end = end+process_command (s, buf, end);
|
||||
|
|
@ -141,11 +141,13 @@ void main_loop (struct synth_t *s)
|
|||
int i;
|
||||
size_t length;
|
||||
char buf[maxBufferSize];
|
||||
struct timeval tv = {0, 0};
|
||||
|
||||
while (1) {
|
||||
queue_process_entry(s);
|
||||
FD_ZERO (&set);
|
||||
FD_SET (softFD, &set);
|
||||
i = select (softFD+1, &set, NULL, NULL, NULL);
|
||||
i = select (softFD+1, &set, NULL, NULL, &tv);
|
||||
if (i < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
|
@ -153,8 +155,12 @@ void main_loop (struct synth_t *s)
|
|||
break;
|
||||
}
|
||||
|
||||
if (! FD_ISSET(softFD, &set))
|
||||
continue;
|
||||
length = read (softFD, buf, maxBufferSize - 1);
|
||||
if (length < 0) {
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
continue;
|
||||
perror("Read from softsynth failed");
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
48
synth.c
48
synth.c
|
|
@ -31,19 +31,46 @@ int SynthCallback(short *wav, int numsamples, espeak_EVENT *events)
|
|||
return 0;
|
||||
}
|
||||
|
||||
espeak_ERROR set_frequency (struct synth_t *s)
|
||||
espeak_ERROR set_frequency (struct synth_t *s, int freq, enum adjust_t adj)
|
||||
{
|
||||
return (espeak_SetParameter(espeakRANGE, s->frequency * frequencyMultiplier, 0));
|
||||
espeak_ERROR rc;
|
||||
|
||||
if (adj == ADJ_DEC)
|
||||
freq = -freq;
|
||||
if (adj != ADJ_SET)
|
||||
freq += s->frequency;
|
||||
rc = espeak_SetParameter(espeakRANGE, freq * frequencyMultiplier, 0);
|
||||
if (rc == EE_OK)
|
||||
s->frequency = freq;
|
||||
return rc;
|
||||
}
|
||||
|
||||
espeak_ERROR set_pitch (struct synth_t *s)
|
||||
espeak_ERROR set_pitch (struct synth_t *s, int pitch, enum adjust_t adj)
|
||||
{
|
||||
return (espeak_SetParameter(espeakPITCH, s->pitch * pitchMultiplier, 0));
|
||||
espeak_ERROR rc;
|
||||
|
||||
if (adj == ADJ_DEC)
|
||||
pitch = -pitch;
|
||||
if (adj != ADJ_SET)
|
||||
pitch += s->pitch;
|
||||
rc = espeak_SetParameter(espeakPITCH, pitch * pitchMultiplier, 0);
|
||||
if (rc == EE_OK)
|
||||
s->pitch = pitch;
|
||||
return rc;
|
||||
}
|
||||
|
||||
espeak_ERROR set_rate (struct synth_t *s)
|
||||
espeak_ERROR set_rate (struct synth_t *s, int rate, enum adjust_t adj)
|
||||
{
|
||||
return (espeak_SetParameter(espeakRATE, s->rate * rateMultiplier + rateOffset, 0));
|
||||
espeak_ERROR rc;
|
||||
|
||||
if (adj == ADJ_DEC)
|
||||
rate = -rate;
|
||||
if (adj != ADJ_SET)
|
||||
rate += s->rate;
|
||||
rc = espeak_SetParameter(espeakRATE, rate * rateMultiplier + rateOffset, 0);
|
||||
if (rc == EE_OK)
|
||||
s->rate = rate;
|
||||
return rc;
|
||||
}
|
||||
|
||||
espeak_ERROR set_voice(struct synth_t *s)
|
||||
|
|
@ -51,9 +78,14 @@ espeak_ERROR set_voice(struct synth_t *s)
|
|||
return (espeak_SetVoiceByName(s->voice));
|
||||
}
|
||||
|
||||
espeak_ERROR set_volume (struct synth_t *s)
|
||||
espeak_ERROR set_volume (struct synth_t *s, int vol, enum adjust_t adj)
|
||||
{
|
||||
return (espeak_SetParameter(espeakVOLUME, (s->volume+1) * volumeMultiplier, 0));
|
||||
espeak_ERROR rc;
|
||||
|
||||
|
||||
rc = espeak_SetParameter(espeakVOLUME, (vol+1) * volumeMultiplier, 0);
|
||||
if (rc == EE_OK)
|
||||
s->volume = vol;
|
||||
}
|
||||
|
||||
espeak_ERROR stop_speech(void)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue