2010-04-18 22 views
6

Câu hỏi: Tôi đang cố gắng sử dụng công cụ chuyển văn bản thành giọng nói đặc biệt. Vì vậy, đối với tôi đã nhận nó làm việc một cách nghiêm túc trên linux (mã dưới đây). Bây giờ tôi cũng muốn chuyển chương trình cơ bản này sang cửa sổ, nhưng gần như không thể ...Sử dụng Espeak SAPI/dll trên Windows?

Một phần của sự cố là dll windows chỉ cho phép AUDIO_OUTPUT_SYNCHRONOUS, có nghĩa là nó yêu cầu gọi lại, nhưng tôi có thể ' t tìm ra cách để phát âm thanh từ cuộc gọi lại ... Đầu tiên nó bị hỏng, sau đó tôi nhận ra, tôi cần một hàm gọi lại, bây giờ tôi nhận được dữ liệu trong chức năng gọi lại, nhưng tôi không biết làm thế nào để chơi nó .. vì nó không phải là một tệp wav cũng không tự động phát như trên Linux.

Các trang web SourceForge là khá vô dụng, bởi vì nó về cơ bản nói sử dụng phiên bản SAPI, nhưng sau đó không có ví dụ về cách sử dụng dll SAPI eSpeak ...

Dù sao, đây là mã của tôi, bất cứ ai có thể giúp ?

#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); 
    } 
} 
*/ 

Mã trên là dành cho Linux. Mã dưới đây là về như xa như tôi có trên Vista x64 (32 bit emu):

#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 để đăng một số mã ví dụ về cách sử dụng espeak làm thư viện. Tôi đã gặp khó khăn trong việc tìm kiếm các ví dụ. Cảm ơn. – Noremac

Trả lời

1

Bạn đã cố gắng vượt qua đệm bạn có được trong callback của bạn để sndplaysnd() ??

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

WINAPI tiêu chuẩn của nó là như sau:

sndPlaySound(buffer[0], SND_ASYNC | SND_MEMORY) 

Cách khác, nếu bạn có một wav file có âm thanh to play:

sndPlaySound(filename, SND_ASYNC) 

PlaySound có ASYNC chế độ sẽ không chặn thực thi chương trình của bạn trong khi âm thanh đang được phát.

LƯU Ý: Tôi đã sử dụng nó trong VB và các đoạn mã trên được sử dụng trong VB. Nếu bạn đang mã hóa trong VC++, bạn có thể phải sửa đổi chúng cho phù hợp. Nhưng ý định cơ bản vẫn như cũ; để chuyển bộ đệm tới sndPlaySound với bộ cờ ASYNC.

Good LUCK !!

+0

sndPlaySound (wav, SND_ASYNC | SND_MEMORY); Cảm ơn, nó đòi hỏi phải liên kết với winmm.lib trong C++, nhưng tôi đã thử và nó không hoạt động (không có sự cố, nhưng không có âm thanh nào cả, tôi cũng đã thử SND _) ... sndPlaySound (wav [0], SND_ASYNC | SND_MEMORY); treo –

+0

Vì U đang sử dụng, FILE * user_data = fopen ("myfile1.wav", "ab"); hiện đầu ra nằm trong myfile1.wav.Đã cố chơi bằng sndPlaySound (tên tệp, SND_ASYNC) ??. Hãy thử chơi myfile1.wav trong phương tiện truyền thông-payer ur và kiểm tra xem nó có bất kỳ dữ liệu lời nói trong đó. Tôi tò mò ... – TheCodeArtist

+0

Nó không phải là một tập tin wav, đó là dữ liệu duy nhất ... nó thậm chí không chơi trong mediaplayer –

3

Một số thay đổi trong mã nguồn là cần thiết để làm cho thư viện cửa sổ có chức năng tương tự như chức năng trên Linux. Tôi đã liệt kê các thay đổi here. Sẵn sàng để sử dụng nhị phân cũng có sẵn.

Tất cả các bản vá và mô tả cũng được gửi đến người bảo trì độc lập (công khai, thông qua danh sách gửi thư và bản vá lỗi), vì vậy có thể trong tương lai nó sẽ có sẵn trực tiếp.

Các vấn đề liên quan