2010-04-18 20 views
6

Frage: Ich versuche, die espeak Text-zu-Sprache-Engine zu verwenden. Also ich habe es funktioniert wunderbar auf Linux (Code unten). Nun wollte ich dieses Basisprogramm in dem Hafen Fenster auch, aber es ist fast unmöglich ...Espeak SAPI/DLL-Nutzung unter Windows?

Ein Teil des Problems ist, dass die Fenster nur DLL für AUDIO_OUTPUT_SYNCHRONOUS erlaubt, was bedeutet es einen Rückruf erfordert, aber ich kann‘ Ich finde heraus, wie man das Audio vom Callback spielt ... Zuerst ist es abgestürzt, dann habe ich gemerkt, ich brauche eine Callback-Funktion, jetzt bekomme ich die Daten in der Callback-Funktion, aber ich weiß nicht, wie ich es spielen soll. Es ist weder eine WAV-Datei noch spielt es automatisch wie auf Linux.

Die Source Website ziemlich nutzlos ist, weil es im Grunde sagt die SAPI-Version verwenden, aber dann gibt es kein Beispiel dafür, wie die sapi espeak DLL verwenden ...

Wie auch immer, hier ist mein Code, kann jemand helfen ?

#ifdef __cplusplus 
#include <cstdio> 
#include <cstdlib> 
#include <cstring> 
#else 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#endif 

#include <assert.h> 
#include <ctype.h> 

//#include "speak_lib.h" 
#include "espeak/speak_lib.h" 

// libespeak-dev: /usr/include/espeak/speak_lib.h 
// apt-get install libespeak-dev 
// apt-get install libportaudio-dev 

// g++ -o mine mine.cpp -lespeak 
// g++ -o mine mine.cpp -I/usr/include/espeak/ -lespeak 
// gcc -o mine mine.cpp -I/usr/include/espeak/ -lespeak 


char voicename[40]; 
int samplerate; 
int quiet = 0; 
static char genders[4] = {' ','M','F',' '}; 

//const char *data_path = "/usr/share/"; // /usr/share/espeak-data/ 
const char *data_path = NULL; // use default path for espeak-data 


int strrcmp(const char *s, const char *sub) 
{ 
int slen = strlen(s); 
int sublen = strlen(sub); 
return memcmp(s + slen - sublen, sub, sublen); 
} 


char * strrcpy(char *dest, const char *source) 
{ 
// Pre assertions 
assert(dest != NULL); 
assert(source != NULL); 
assert(dest != source); 

// tk: parentheses 
while((*dest++ = *source++)) 
    ; 
return(--dest); 
} 

const char* GetLanguageVoiceName(const char* pszShortSign) 
{ 
#define LANGUAGE_LENGTH 30 
static char szReturnValue[LANGUAGE_LENGTH] ; 
memset(szReturnValue, 0, LANGUAGE_LENGTH); 

for (int i = 0; pszShortSign[i] != '\0'; ++i) 
    szReturnValue[i] = (char) tolower(pszShortSign[i]); 

const espeak_VOICE **voices; 
espeak_VOICE voice_select; 
voices = espeak_ListVoices(NULL); 

const espeak_VOICE *v; 
for(int ix=0; (v = voices[ix]) != NULL; ix++) 
{ 
    if(!strrcmp(v->languages, szReturnValue)) 
    { 
     strcpy(szReturnValue, v->name); 
     return szReturnValue; 
    } 
} // End for 

strcpy(szReturnValue, "default"); 
return szReturnValue; 
} // End function getvoicename 


void ListVoices() 
{ 
const espeak_VOICE **voices; 
espeak_VOICE voice_select; 
voices = espeak_ListVoices(NULL); 

const espeak_VOICE *v; 
for(int ix=0; (v = voices[ix]) != NULL; ix++) 
{ 
    printf("Shortsign: %s\n", v->languages); 
    printf("age: %d\n", v->age); 
    printf("gender: %c\n", genders[v->gender]); 
    printf("name: %s\n", v->name); 
    printf("\n\n"); 
} // End for 
} // End function getvoicename 


int main() 
{ 
printf("Hello World!\n"); 
const char* szVersionInfo = espeak_Info(NULL); 

printf("Espeak version: %s\n", szVersionInfo); 
samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,0,data_path,0); 

strcpy(voicename, "default"); 
// espeak --voices 
strcpy(voicename, "german"); 
strcpy(voicename, GetLanguageVoiceName("DE")); 

if(espeak_SetVoiceByName(voicename) != EE_OK) 
{ 
    printf("Espeak setvoice error...\n"); 
} 

static char word[200] = "Hello World" ; 
strcpy(word, "TV-fäns aufgepasst, es ist 20 Uhr 15. Zeit für Rambo 3"); 
strcpy(word, "Unnamed Player wurde zum Opfer von GSG9"); 
int speed = 220; 
int volume = 500; // volume in range 0-100 0=silence 
int pitch = 50; // base pitch, range 0-100. 50=normal 

// espeak.cpp 625 
espeak_SetParameter(espeakRATE, speed, 0); 
espeak_SetParameter(espeakVOLUME,volume,0); 
espeak_SetParameter(espeakPITCH,pitch,0); 
// espeakRANGE: pitch range, range 0-100. 0-monotone, 50=normal 
// espeakPUNCTUATION: which punctuation characters to announce: 
    // value in espeak_PUNCT_TYPE (none, all, some), 
espeak_VOICE *voice_spec = espeak_GetCurrentVoice(); 
voice_spec->gender=2; // 0=none 1=male, 2=female, 
//voice_spec->age = age; 

espeak_SetVoiceByProperties(voice_spec); 


espeak_Synth((char*) word, strlen(word)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL); 
espeak_Synchronize(); 

strcpy(voicename, GetLanguageVoiceName("EN")); 
espeak_SetVoiceByName(voicename); 
strcpy(word, "Geany was fragged by GSG9 Googlebot"); 
strcpy(word, "Googlebot"); 

espeak_Synth((char*) word, strlen(word)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL); 
espeak_Synchronize(); 


espeak_Terminate(); 
printf("Espeak terminated\n"); 
return EXIT_SUCCESS; 
} 

/* 
if(espeak_SetVoiceByName(voicename) != EE_OK) 
{ 
    memset(&voice_select,0,sizeof(voice_select)); 
    voice_select.languages = voicename; 
    if(espeak_SetVoiceByProperties(&voice_select) != EE_OK) 
    { 
     fprintf(stderr,"%svoice '%s'\n",err_load,voicename); 
     exit(2); 
    } 
} 
*/ 

Der obige Code ist für Linux. Der Code unten ist etwa so weit, wie ich auf Vista x64 (32 Bit emu) bekam:

#ifdef __cplusplus 
#include <cstdio> 
#include <cstdlib> 
#include <cstring> 
#else 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#endif 

#include <assert.h> 
#include <ctype.h> 

#include "speak_lib.h" 
//#include "espeak/speak_lib.h" 

// libespeak-dev: /usr/include/espeak/speak_lib.h 
// apt-get install libespeak-dev 
// apt-get install libportaudio-dev 

// g++ -o mine mine.cpp -lespeak 
// g++ -o mine mine.cpp -I/usr/include/espeak/ -lespeak 
// gcc -o mine mine.cpp -I/usr/include/espeak/ -lespeak 


char voicename[40]; 
int iSampleRate; 
int quiet = 0; 
static char genders[4] = {' ','M','F',' '}; 

//const char *data_path = "/usr/share/"; // /usr/share/espeak-data/ 
//const char *data_path = NULL; // use default path for espeak-data 
const char *data_path = "C:\\Users\\Username\\Desktop\\espeak-1.43-source\\espeak-1.43-source\\"; 


int strrcmp(const char *s, const char *sub) 
{ 
int slen = strlen(s); 
int sublen = strlen(sub); 
return memcmp(s + slen - sublen, sub, sublen); 
} 


char * strrcpy(char *dest, const char *source) 
{ 
// Pre assertions 
assert(dest != NULL); 
assert(source != NULL); 
assert(dest != source); 

// tk: parentheses 
while((*dest++ = *source++)) 
    ; 
return(--dest); 
} 

const char* GetLanguageVoiceName(const char* pszShortSign) 
{ 
#define LANGUAGE_LENGTH 30 
static char szReturnValue[LANGUAGE_LENGTH] ; 
memset(szReturnValue, 0, LANGUAGE_LENGTH); 

for (int i = 0; pszShortSign[i] != '\0'; ++i) 
    szReturnValue[i] = (char) tolower(pszShortSign[i]); 

const espeak_VOICE **voices; 
espeak_VOICE voice_select; 
voices = espeak_ListVoices(NULL); 

const espeak_VOICE *v; 
for(int ix=0; (v = voices[ix]) != NULL; ix++) 
{ 
    if(!strrcmp(v->languages, szReturnValue)) 
    { 
     strcpy(szReturnValue, v->name); 
     return szReturnValue; 
    } 
} // End for 

strcpy(szReturnValue, "default"); 
return szReturnValue; 
} // End function getvoicename 


void ListVoices() 
{ 
const espeak_VOICE **voices; 
espeak_VOICE voice_select; 
voices = espeak_ListVoices(NULL); 

const espeak_VOICE *v; 
for(int ix=0; (v = voices[ix]) != NULL; ix++) 
{ 
    printf("Shortsign: %s\n", v->languages); 
    printf("age: %d\n", v->age); 
    printf("gender: %c\n", genders[v->gender]); 
    printf("name: %s\n", v->name); 
    printf("\n\n"); 
} // End for 
} // End function getvoicename 


/* Callback from espeak. Directly speaks using AudioTrack. */ 
#define LOGI(x) printf("%s\n", x) 
static int AndroidEspeakDirectSpeechCallback(short *wav, int numsamples, espeak_EVENT *events) 
{ 
    char buf[100]; 
    sprintf(buf, "AndroidEspeakDirectSpeechCallback: %d samples", numsamples); 
    LOGI(buf); 

    if (wav == NULL) 
{ 
     LOGI("Null: speech has completed"); 
    } 

    if (numsamples > 0) 
{ 
     //audout->write(wav, sizeof(short) * numsamples); 
     sprintf(buf, "AudioTrack wrote: %d bytes", sizeof(short) * numsamples); 
     LOGI(buf); 
    } 

    return 0; // continue synthesis (1 is to abort) 
} 


static int AndroidEspeakSynthToFileCallback(short *wav, int numsamples,espeak_EVENT *events) 
{ 
    char buf[100]; 
    sprintf(buf, "AndroidEspeakSynthToFileCallback: %d samples", numsamples); 
    LOGI(buf); 

    if (wav == NULL) 
{ 
     LOGI("Null: speech has completed"); 
    } 

    // The user data should contain the file pointer of the file to write to 
    //void* user_data = events->user_data; 
FILE* user_data = fopen ("myfile1.wav" , "ab"); 

    FILE* fp = static_cast<FILE *>(user_data); 

    // Write all of the samples 
    fwrite(wav, sizeof(short), numsamples, fp); 
    return 0; // continue synthesis (1 is to abort) 
} 



int main() 
{ 
printf("Hello World!\n"); 
const char* szVersionInfo = espeak_Info(NULL); 

printf("Espeak version: %s\n", szVersionInfo); 

iSampleRate = espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 4096, data_path, 0); 
if (iSampleRate <= 0) 
{ 
    printf("Unable to initialize espeak"); 
    return EXIT_FAILURE; 
} 

//samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,0,data_path,0); 

//ListVoices(); 

strcpy(voicename, "default"); 
// espeak --voices 
//strcpy(voicename, "german"); 
//strcpy(voicename, GetLanguageVoiceName("DE")); 

if(espeak_SetVoiceByName(voicename) != EE_OK) 
{ 
    printf("Espeak setvoice error...\n"); 
} 

static char word[200] = "Hello World" ; 
strcpy(word, "TV-fäns aufgepasst, es ist 20 Uhr 15. Zeit für Rambo 3"); 
strcpy(word, "Unnamed Player wurde zum Opfer von GSG9"); 
int speed = 220; 
int volume = 500; // volume in range 0-100 0=silence 
int pitch = 50; // base pitch, range 0-100. 50=normal 


// espeak.cpp 625 
espeak_SetParameter(espeakRATE, speed, 0); 
espeak_SetParameter(espeakVOLUME,volume,0); 
espeak_SetParameter(espeakPITCH,pitch,0); 
// espeakRANGE: pitch range, range 0-100. 0-monotone, 50=normal 
// espeakPUNCTUATION: which punctuation characters to announce: 
    // value in espeak_PUNCT_TYPE (none, all, some), 
//espeak_VOICE *voice_spec = espeak_GetCurrentVoice(); 
//voice_spec->gender=2; // 0=none 1=male, 2=female, 
//voice_spec->age = age; 

//espeak_SetVoiceByProperties(voice_spec); 

//espeak_SetSynthCallback(AndroidEspeakDirectSpeechCallback); 
espeak_SetSynthCallback(AndroidEspeakSynthToFileCallback); 

unsigned int unique_identifier; 
espeak_ERROR err = espeak_Synth((char*) word, strlen(word)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, &unique_identifier, NULL); 

err = espeak_Synchronize(); 



/* 
strcpy(voicename, GetLanguageVoiceName("EN")); 
espeak_SetVoiceByName(voicename); 
strcpy(word, "Geany was fragged by GSG9 Googlebot"); 
strcpy(word, "Googlebot"); 

espeak_Synth((char*) word, strlen(word)+1, 0, POS_CHARACTER, 0, espeakCHARS_AUTO, NULL, NULL); 
espeak_Synchronize(); 
*/ 

// espeak_Cancel(); 
espeak_Terminate(); 
printf("Espeak terminated\n"); 
system("pause"); 
return EXIT_SUCCESS; 
} 
+1

+1 für einige Beispielcode, wie espeak als eine Bibliothek zu verwenden. Ich hatte Schwierigkeiten, Beispiele zu finden. Vielen Dank. – Noremac

Antwort

1

Haben Sie versucht, das Bestehen der Puffer Sie in Ihrer Callback() zu sndplaysnd erhalten ??

Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long 

Sein Standard winapi ist wie folgt:

sndPlaySound(buffer[0], SND_ASYNC | SND_MEMORY) 

Alternativ kann, wenn Sie eine WAV-Datei, die die Audio-spielen hat:

sndPlaySound(filename, SND_ASYNC) 

Playsound hat eine ASYNC Modus, der die Ausführung Ihres Programms nicht blockiert, während das Audio abgespielt wird.

HINWEIS: Ich habe es in VB verwendet und die obigen Snippets sind für den Einsatz in VB. Wenn Sie in VC++ codieren, müssen Sie sie möglicherweise entsprechend ändern. Aber die Grundabsicht bleibt dieselbe; Übergeben des Puffers an sndPlaySound mit gesetztem ASYNC-Flag.

Gute GLÜCK !!

+0

sndPlaySound (wav, SND_ASYNC | SND_MEMORY); Danke, es erfordert eine Verbindung zu winmm.lib in C++, aber ich habe es versucht und es funktioniert nicht (kein Absturz, aber auch kein Ton, ich habe auch versucht SND _) ... sndPlaySound (wav [0], SND_ASYNC | SND_MEMORY); Abstürze –

+0

Da U dies verwenden, FILE * user_data = fopen ("myfile1.wav", "ab"); Liegt die Ausgabe in myfile1.wav?Versucht das Abspielen mit SndPlaySound (Dateiname, SND_ASYNC) ??. Versuchen Sie, die Datei myfile1.wav in Ihrem Media-Payer abzuspielen und prüfen Sie, ob darin Sprachdaten enthalten sind. Ich bin neugierig ... – TheCodeArtist

+0

Es ist nicht eine WAV-Datei, es ist nur die Daten ... es spielt nicht einmal in Mediaplayer –

3

Mehrere Änderungen im Quellcode sind erforderlich, damit die Windows-Bibliothek dieselbe Funktionalität wie die unter Linux hat. Ich habe die Änderungen here aufgelistet. Die fertige Binärdatei ist ebenfalls verfügbar.

Alle Patches und die Beschreibung wurden auch an espeak maintainer (öffentlich, über die Mailingliste und den Patch-Tracker) gesendet, damit sie in Zukunft vielleicht direkt verfügbar sein werden.