speechd-discuss
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

No subject


From: trev . saunders
Subject: No subject
Date: Sun, 17 Jan 2010 16:16:10 -0500

Hi,

In trying to fix seg faults in sd_espeak I decided that rewritting was probably 
the best option.  Seeattached my first attempt.  Please note this is very 
experimental, and needswork.  However I believe it to be a lot cleaner than the 
old code too!  

If you want to work on this you need only compile espeak2.c linking  against 
espeak and sdaudio.  

Unfortunetly the machine that holds my public repo is down for upgrades, I will 
soon post the name of a   machine that has this module in git, and when it's 
closer to stable provide a patch.

Trev
-------------- next part --------------
#include"spd_audio.h"


#include<espeak/speak_lib.h>

#include<stdlib.h>
#include<sys/stat.h>

#define _GNU_SOURCE

#include<stdio.h>
#include<string.h>

/*
helper functions
*/

static int set_rate(char *value);
static int set_pitch( char * value);
static int set_punct_mode(char *value);
static int set_voice(char *value);
int synthCallback(short *data, int samples, espeak_EVENT *events);
int soundIconCallback(int type, const  char * file,  const char *base);
static int set_defaults();
static int set_language(char *value);
static int set_cap_recogn(char *value);
static int set_spell_mode(char *value);


/* global bars */
int voice;
int toPause;

AudioID *audio_output;
int freq;
/*
functions  for each command
*/

/*
init is valid command 
just for the future
*/
int init(){
return(0);
}
int speak()
{
unsigned int buffLength = 50; /*length of the buffer*/
unsigned int textLength = 0; // length of the message
unsigned int lineLen;  //length of cur line
char *curLine = NULL;
char *toSpeak = malloc(buffLength*sizeof(char));

printf("202 OK SEND DATA");
while( 1 ){
curLine = NULL;
lineLen = 0;
getline( &curLine, &lineLen, stdin);

if( 0 == strcmp(curLine, ".\n")) {
free(curLine);
 break;
}
if(0 == strcmp(curLine, "..\n")){
strcpy(curLine,  ".\n");
lineLen = 2;
}

if( textLength + lineLen + 1 > buffLength ){
buffLength = 2* (textLength + lineLen + 1);
toSpeak = realloc(toSpeak, buffLength);
}

strcat(toSpeak, curLine);
free(curLine);
}

espeak_Synth(toSpeak, textLength+1, 0, POS_CHARACTER, 0, 
espeakCHARS_AUTO | espeakSSML, NULL, NULL);
free(toSpeak);
return(0);
}

int sayChar( )
{
char buff[10];
char buff2[5];
wchar_t theChar;

fgets(buff, sizeof(buff), stdin);
fgets(buff2, sizeof(buff2), stdin);
if( 0 != strcmp(buff2, ".\n")){
printf("301 syntax error");
}

if(0 != strcmp(buff, "space")){
mbrtowc(&theChar, buff, sizeof(buff), NULL);
} else {
theChar = ' ';
}

espeak_Char(theChar);
return(0);
}

int sayKey(){
char key[50];
char buff[5];
fgets(key, sizeof(key), stdin);
fgets(buff, sizeof(buff), stdin);

if(0 != strcmp(buff, ".\n")){
printf("301 syntax error");
}

espeak_Key(key);
return(0);
}

/***********
not sure how right this is taken directly  from espeak.c
it seems decent though
*********/


 int play_file(char *filename)
{
int result = 0;
#if HAVE_SNDFILE
        int subformat;
        sf_count_t items;
        sf_count_t readcount;
        SNDFILE* sf;
        SF_INFO sfinfo;

//      DBG("Espeak: Playing |%s|", filename);
        memset (&sfinfo, 0, sizeof (sfinfo));
        sf = sf_open(filename, SFM_READ, &sfinfo);
        subformat = sfinfo.format & SF_FORMAT_SUBMASK ;
        items = sfinfo.channels * sfinfo.frames;
//      DBG("Espeak: frames = %ld, channels = %d", sfinfo.frames, 
sfinfo.channels);
//      DBG("Espeak: samplerate = %i, items = %Ld", sfinfo.samplerate, (long 
long) items);
//      DBG("Espeak: major format = 0x%08X, subformat = 0x%08X, endian = 
0x%08X",
//              sfinfo.format & SF_FORMAT_TYPEMASK, subformat, sfinfo.format & 
SF_FORMAT_ENDMASK);
        if (sfinfo.channels < 1 || sfinfo.channels > 2) {
//              DBG("Espeak: ERROR: channels = %d.\n", sfinfo.channels);
                result = -1;
                goto cleanup1;
        }
        if (sfinfo.frames > 0x7FFFFFFF) {
//              DBG("Espeak: ERROR: Unknown number of frames.");
                result = -1;
                goto cleanup1;
        }
        if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) {
                /* Set scaling for float to integer conversion. */
                sf_command (sf, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
        }
        AudioTrack track;
        track.num_samples = sfinfo.frames;
        track.num_channels = sfinfo.channels;
        track.sample_rate = sfinfo.samplerate;
        track.bits = 16;
        track.samples = malloc(items * sizeof(short));
        if (NULL == track.samples) {
//              DBG("Espeak: ERROR: Cannot allocate audio buffer.");
                result = -1;
                goto cleanup1;
        }
        readcount = sf_read_short(sf, (short *) track.samples, items);
//      DBG("Espeak: read %Ld items from audio file.", (long long) readcount);

        if (readcount > 0) {
                track.num_samples = readcount / sfinfo.channels;
//              DBG("Espeak: Sending %i samples to audio.", track.num_samples);
                /* Volume is controlled by the synthesizer.  Always play at 
normal on audio device. */
                spd_audio_set_volume(module_audio_id, EspeakSoundIconVolume);
                int ret = spd_audio_play(module_audio_id, track, SPD_AUDIO_LE);
                if (ret < 0) {
//                      DBG("ERROR: Can't play track for unknown reason.");
                        result = -1;
                        goto cleanup2;
                }
//              DBG("Espeak: Sent to audio.");
        }
 cleanup2:
        xfree(track.samples);
 cleanup1:
        sf_close(sf);
#endif
        return result;
}

int stop(){
espeak_Cancel();
printf("703 EVENT STOP");
return(0);
}

int pause(){
if( 1==  espeak_IsPlaying()){
toPause = 1;
}
return(0);
}

static int set(){
int lineLength = 100, errors = 0;
char line[lineLength];
char  *var, *value, * context;

printf("203 OK RECIEVING SETTINGS");

set_defaults();

while(1){
fgets(line, lineLength, stdin);

if(0 == strcmp(line, ".\n"))
break;

value = strtok_r(line, "=", &context);
var = line;

if(0 == strcasecmp(value, "null"))
continue;
/*decide what we're setting*/
if( 0 == strcasecmp(var, "rate"))
        set_rate(value);
else if( 0 == strcasecmp(var, "pitch"))
        set_pitch(value);
else if( 0 == strcasecmp(var, "punctation_mode"))
        set_punct_mode(value);
else if(0 == strcasecmp(var, "spelling_mode"))
set_spell_mode(value);
else  if( 0 == strcasecmp(var, "cap_let_recogn"))
set_cap_recogn(value);
else if( 0 == strcasecmp(var, "voice"))
set_voice(value);
else if( 0 == strcasecmp(var, "langauge"))
set_language(value);
else {
errors++;
continue;
}
}

if(errors != 0){
printf("300 SYNTAX ERROR");
return(-1);
}

printf("203 SETTINGS RECIEVED");
return(0);
}

static int set_defaults(){
/*
deal with this later
*/
return(0);
}

/* set helper functions*/
static int set_rate(char *value){
int  standard = 185; //middle
double incroment = 105.0/100.0;
int spd_rate = atoi(value);
int espeak_rate =  standard + spd_rate *incroment;

if( espeak_rate < 80 || espeak_rate > 390 )
espeak_rate = standard;
int ret = espeak_SetParameter(espeakRATE, (int)  espeak_rate, 0);
if (ret != 0 ){
return(-1);
}

return(0);
}

static int set_pitch( char * value){
int spd_pitch = atoi(value);
int espeak_pitch = (spd_pitch+100)/2;
int ret = espeak_SetParameter(espeakPITCH, espeak_pitch, 0);
return(ret);
}

static int set_volume(char *volume){
int spd_volume = atoi(volume);
int ret = espeak_SetParameter(espeakVOLUME, (100+spd_volume)/2, 0);
return(ret);
}

static int set_punct_mode(char *value){
int ret;
if( 0 == strcasecmp(value, "all"))
         ret = espeak_SetParameter(espeakPUNCTUATION, espeakPUNCT_ALL, 0);
else if( 0 == strcasecmp(value, "none"))
ret = espeak_SetParameter(espeakPUNCTUATION, espeakPUNCT_NONE, 0);
else 
ret = espeak_SetParameter(espeakPUNCTUATION, espeakPUNCT_SOME, 0);
return(ret);
}

static int set_language(char *value){
espeak_VOICE buff;

if( 0 == strcasecmp(value, "null")) 
        return(0);

memset(&buff, 0, sizeof(buff));
buff.languages = value;
espeak_SetVoiceByProperties( & buff);

return(0);
}

static int set_voice(char *value){
espeak_VOICE buff;

if( 0 == strcasecmp( value, "null"))
return(0);


memset(&buff, 0, sizeof(buff));
buff.name = value;
espeak_SetVoiceByProperties(&buff);

return(0);
}

static int set_cap_recogn(char *value){
/* 
the hard coded values here are defined in some enum, but I be a lazy fuck...
*/
if( 0 == strcasecmp(value, "icon")){
espeak_SetParameter(espeakCAPITALS, 1, 0);
} else if ( 0 == strcasecmp(value,  "none")) {
espeak_SetParameter(espeakCAPITALS, 0, 0);
} else { 
espeak_SetParameter(espeakCAPITALS, 2, 0);
}

 return(0);
}

static int set_spell_mode(char *value){
//to do fix this 
return(0);
}

/*
this function needs a lot of help
*/
int audio(){
char line[100];
/* I have no idea how or why this is this way but this is how odule utils does 
it, so ...
*/

char *err; 
char *value;
char *context;
void * audioArgs[10];
AudioOutputType output;


printf("207 RECIEVING AUDIO SETTINGS");
fflush(stdout);

while(1){
fgets(line, 100, stdin);
if(0 == strcmp(".\n", line)){
break;
}
strtok_r(line, "=", &context);
value = strtok_r(NULL, "\n", &context);

if(0 == strcasecmp("audio_alsa_device", line)){
        audioArgs[0] = strdup(value);
audioArgs[1] = NULL;
output =  AUDIO_ALSA;
}
/*
a bunch of pulse / oss / nas / libao shit should go here!!!
*/
}

audio_output = spd_audio_open( output, audioArgs, &err);
return(0);
}

int main(int argc, char ** argv){
int lineLength = 100;
char line[lineLength];

freq = espeak_Initialize( AUDIO_OUTPUT_RETRIEVAL, 4400,  NULL, 0);

if(freq == 0){
printf("400 ESPEAK failed to INITIALIZE");
perror("failed to start espeak terminating");
exit(1);
}

espeak_SetUriCallback(soundIconCallback);
espeak_SetSynthCallback(synthCallback);

fgets(line, lineLength, stdin);
if( 0 != strcasecmp("init\n", line)){
perror("need to call init");
exit(1);
}

        init();
while(1){
fgets(line, lineLength, stdin);

if (  0 == strcasecmp(line, "speak\n"))
        speak();
else if(0 == strcasecmp(line, "character\n"))
        sayChar();
else if (0 == strcasecmp(line, "key\n"))
        sayKey();
else if (0 == strcasecmp(line, "stop\n"))
stop();
                else if (0 == strcasecmp(line, "pause\n"))
        pause();
        else if( 0 == strcasecmp(line, "set\n"))
        set();
else if( 0 == strcasecmp(line, "audio\n"))
        audio();
else if( 0 == strcasecmp(line, "alive\n"))
        printf("211 YES");
else if(0 == strcasecmp(line, "quit\n"))
break;
else {
printf("300 INALID COMMAND");
}
}

spd_audio_close(audio_output);
espeak_Terminate();

return(0);
}

int synthCallback(short *data, int samples, espeak_EVENT *events){
espeak_EVENT  *event = events;
AudioTrack audio;

if(data == NULL ){
/*synth is over so we'll abort anything else possible.*/
return(1);
}

audio.samples = data;
audio.num_samples = samples;
audio.sample_rate = freq;
audio.bits = 16;
audio.num_channels = 1;

spd_audio_play(audio_output, audio, SPD_AUDIO_LE);

while(event->type != 0 ){
switch(event->type){
case espeakEVENT_MARK:
printf("700-%s\n700 INDEX MARK\n", event->id.name);
break;
case espeakEVENT_MSG_TERMINATED:
printf("702 EVENT END");
break;
case espeakEVENT_PLAY:
play_file( (char*) event->id.name);
break;
default:
/*some other event we don't cae about*/
break;
}

event++;
}

if(toPause != 0 ){
return(1);
}

return(0);
}

int soundIconCallback(int type, const  char * file, const  char *base){
struct stat buff;
/*
some nice stuff check settings etc could go here, but  for now just see if it 
exists
*/

if( 0 == stat(file, &buff))
        return(0);
else 
return(1);
}


reply via email to

[Prev in Thread] Current Thread [Next in Thread]