[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);
}
- No subject,
trev . saunders <=
your mail, trev . saunders, 2010/01/17