0

I am looking a way to know when espeak ended it's speaking. Somebody told use the espeakEVENT_MSG_TERMINATED. But when I try to put this part to my code it gives me this error:

#include <espeak/speak_lib.h>

espeak_EVENT_TYPE;

    if( espeak_EVENT_TYPE == espeakEVENT_MSG_TERMINATED)
    {
    do something;
    }

application.cpp:31:1: error: declaration does not declare anything [-fpermissive] espeak_EVENT_TYPE; ^ application.cpp: In function ‘void speech(char*)’: application.cpp:116:27: error: expected primary-expression before ‘==’ token if( espeak_EVENT_TYPE == espeakEVENT_MSG_TERMINATED)

EDIT: I use this simple code to use espeak:

#include <string.h>
#include <malloc.h>
#include <espeak/speak_lib.h>


espeak_POSITION_TYPE position_type;
espeak_AUDIO_OUTPUT output;
char *path=NULL;
int Buflength = 1000, Options=0;
void* user_data;
t_espeak_callback *SynthCallback;
espeak_PARAMETER Parm;



char Voice[] = {"English"};


char text[30] = {"this is an english text"};
unsigned int Size,position=0, end_position=0, flags=espeakCHARS_AUTO, *unique_identifier;




int main(int argc, char* argv[] ) 
{
    output = AUDIO_OUTPUT_PLAYBACK;
    espeak_Initialize(output, Buflength, path, AUDIO_OUTPUT_SYNCHRONOUS ); //Options ); 
    espeak_SetVoiceByName(Voice);
    const char *langNativeString = "en";
    espeak_VOICE voice = {0};
  //  memset(&voice, 0, sizeof(espeak_VOICE));
        voice.languages = langNativeString;
        voice.name = "US";
        voice.variant = 2;
        voice.gender = 1;
        espeak_SetVoiceByProperties(&voice);
    Size = strlen(text)+1;    

    espeak_Synth( text, Size, position, position_type, end_position, flags,unique_identifier, user_data );
    espeak_Synchronize( );

    return 0;
}

Edit2:

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

#include <sphinxbase/err.h>
#include <sphinxbase/ad.h>

#include <espeak/speak_lib.h>
#include <string>
#include <iostream>
using namespace std;

#include "pocketsphinx.h"
static ps_decoder_t *ps;
static cmd_ln_t *config;
static FILE *rawfd;

ad_rec_t *ad;

espeak_POSITION_TYPE position_type;
espeak_AUDIO_OUTPUT output;
char *path=NULL;
int Buflength = 1000, Options=0;
void* user_data;
char Voice[] = {"English"};
unsigned int Size,position=0, end_position=0, flags=espeakCHARS_AUTO, *unique_identifier;
t_espeak_callback *SynthCallback;
espeak_PARAMETER Parm;

static void initFuncs()
{

    output = AUDIO_OUTPUT_PLAYBACK;
    espeak_Initialize(output, Buflength, path, AUDIO_OUTPUT_SYNCHRONOUS ); 
    espeak_SetVoiceByName(Voice);
    const char *langNativeString = "en";
    espeak_VOICE voice;
    memset(&voice, 0, sizeof(espeak_VOICE));
        voice.languages = langNativeString;
        voice.name = "US";
        voice.variant = 2;
        voice.gender = 1;
        espeak_SetVoiceByProperties(&voice);

}

int receive_espeak_events(short *wav, int numsamples, espeak_EVENT *event)
{
    while (event->type != espeakEVENT_LIST_TERMINATED) {
        if (event->type == espeakEVENT_MSG_TERMINATED) {
            /* do something */
            ad_start_rec(ad);
        }
        ++event; // Examine the next event.
    }
    return 0; // Continue speaking.
}

static void sleep_msec(int32 ms)
{
    struct timeval tmo;

    tmo.tv_sec = 0;
    tmo.tv_usec = ms * 1000;

    select(0, NULL, NULL, NULL, &tmo);

}

static void speech(char* hyp)
{      
    Size = strlen(hyp)+1;
    espeak_SetSynthCallback(receive_espeak_events);
    espeak_Synth( hyp, Size, position, position_type, end_position, flags,unique_identifier, user_data );
    espeak_Synchronize( );    
}


static void recognize_from_microphone()
{

    ad_rec_t *ad;
    int16 adbuf[2048];
    uint8 utt_started, in_speech;
    int32 k;
    char  *hyp=0;

    if ((ad = ad_open_dev(cmd_ln_str_r(config, "-adcdev"),(int) cmd_ln_float32_r(config,"-samprate"))) == NULL)
        E_FATAL("Failed to open audio device\n");
    if (ad_start_rec(ad) < 0)
        E_FATAL("Failed to start recording\n");

    if (ps_start_utt(ps) < 0)
        E_FATAL("Failed to start utterance\n");


    utt_started = FALSE;
    E_INFO("Ready....\n");

    for (;;) 
    {

        if ((k = ad_read(ad, adbuf, 2048)) < 0)
            E_FATAL("Failed to read audio\n");
        ps_process_raw(ps, adbuf, k, FALSE, FALSE);
        in_speech = ps_get_in_speech(ps);
        if (in_speech && !utt_started) 
        {
            utt_started = TRUE;
            E_INFO("Listening...\n");
        }
        if (!in_speech && utt_started) 
        {

            ps_end_utt(ps);
            hyp = (char*)ps_get_hyp(ps, NULL );
            if (hyp != NULL) 
            {
///////////////////I am passing hyp to espeak heere ////////////////////
             ad_stop_rec(ad);
             speech(hyp);

                printf("%s\n",hyp);
                fflush(stdout);
            //    sleep_msec(3000);

            }

            if (ps_start_utt(ps) < 0)
                E_FATAL("Failed to start utterance\n");
            utt_started = FALSE;
            E_INFO("Ready....\n");

        }
    }//for
    ad_close(ad);
}

int main(int argc, char *argv[])
{
    initFuncs();

                 config = cmd_ln_init(NULL, ps_args(), TRUE,
                 "-hmm", "/home/m/myrobot3/robot/model_parameters/robot.cd_cont_1000",
                     "-lm","/home/m/myrobot3/robot/etc/robot.lm.bin",
                     "-dict", "/home/m/myrobot3/robot/etc/robot.dic",
                     NULL);

    ps = ps_init(config);
    recognize_from_microphone();

    ps_free(ps);
    cmd_ln_free_r(config);

    return 0;
}

ERROR:

FATAL: "application.cpp", line 163: Failed to read audio

Hasani
  • 3,543
  • 14
  • 65
  • 125

1 Answers1

2
espeak_EVENT_TYPE;

This line is not sensible to the compiler. espeak_EVENT_TYPE is a data type. It is not a variable that can be compared to a value like espeakEVENT_MSG_TERMINATED. In order to declare a variable, the syntax would be:

espeak_EVENT_TYPE an_event_type {};
if (an_event_type == espeakEVENT_MSG_TERMINATED) {
/* ... */

However, if we do this, then the variable an_event_type that we just created will not actually contain any information about any real espeak event. And it certainly won't say anything about whether any actual message is terminated or not.

Receiving real event information from espeak

In order to get information about whether a message is terminated, the program needs to obtain a variable of type espeak_EVENT_TYPE from the espeak library.

Looking through this header, espeak_EVENT_TYPE is used as part of the espeak_EVENT struct. To receive espeak_EVENT notifications, it is necessary to write a function which will be called by the espeak library. (This is known as a "callback" function). Then the callback function is registered with the library by calling espeak_SetSynthCallback.

From the same header, the prototype of the callback function must be as follows:

int SynthCallback(short *wav, int numsamples, espeak_EVENT *events);

wav: is the speech sound data which has been produced. NULL indicates that the synthesis has been completed.

numsamples: is the number of entries in wav. This number may vary, may be less than the value implied by the buflength parameter given in > espeak_Initialize, and may sometimes be zero (which does NOT indicate end of synthesis).

events: an array of espeak_EVENT items which indicate word and sentence events, and also the occurance if and elements within the text. The list of events is terminated by an event of type > = 0.

Callback returns: 0=continue synthesis, 1=abort synthesis.

Putting this together, we need a function that loops through the events variable as if it is an array, until it encounters an event of type 0. Then the function needs to return 0 to continue speech activities.

int receive_espeak_events(short *wav, int numsamples, espeak_EVENT *event)
{
    while (event->type != espeakEVENT_LIST_TERMINATED) {
        if (event->type == espeakEVENT_MSG_TERMINATED) {
            /* do something */
        }
        ++event; // Examine the next event.
    }
    return 0; // Continue speaking.
}

To tell espeak to call this function, pass the function to espeak_SetSynthCallback before starting any synthesis operations.

espeak_SetSynthCallback(receive_espeak_events);
Jack C.
  • 744
  • 3
  • 7
  • Thank you so much Jack! I tried your code and put my complete code and updated my question, but still gives me error. I don't know if you know `pocketsphinx` or not, but the important part is that, I get the recognized text from the user speech and collect it inside `char* hyp` and try to pass it through `espeak` to say what tha text is collected inside `hyp`. Also you can see this question to exactly find what I wanted to do? https://stackoverflow.com/questions/50062009/how-to-find-if-espeak-ended-the-speech?noredirect=1#comment87168322_50062009 – Hasani Apr 29 '18 at 12:42
  • I tested your code, but I think there is a problem. The sequence of my interesting things is like this : 1.pocketsphinx recognizes a word and stores it within `hyp`. 2.I pass the `hyp` to `espeak` by `speech()` function. 3. `espeak` reads the `hyp` and the rest of the code after `speech()` function is on pause. But when I must call `espeak_SetSynthCallback()` before the `espeak_Synth` I can not reach my purpose in step 3, and the program will not be paused till espeak ends speaking! – Hasani Apr 29 '18 at 20:20
  • `espeak_SetSynthCallback()` should probably be called once after `espeak_Initialize` in `initFuncs`. There is no need to call `espeak_SetSynthCallback` for each time through `espeak_Synth`. Also, if all you want to do is wait for synthesis to complete, `espeak_Synchronize` should already be doing that for you. – Jack C. Apr 30 '18 at 03:02
  • I tried to put `espeak_SetSynthCallback()` inside the `initFuncs()` and remove it from `speech()` but result is the same error! – Hasani Apr 30 '18 at 19:19
  • You know, the `pocketsphinx` is a real-time app, it uses `ad_rec_start(ad);` to start the listening to microphone, then recognizes the voices and stores what it recognizes within the `hyp` variable. But when I try to pass the `hyp` to `espeak` to say what it recognized, `pocketsphinx` is still listening and it's causes an ultimate repeating the first word it recognized, because it listens to what `espeak` says after the first recognized voice from the user. – Hasani Apr 30 '18 at 19:26
  • So I must use `ad_rec_stop(ad);` function to stop the `pocketsphinx's` listening untill the espeak ends the espeaking, to avoid the above problem! But I don't know how to do it and my app crashes :( – Hasani Apr 30 '18 at 19:27