C++ Espeak SAPI/dll在Windows上的使用情况?

C++ Espeak SAPI/dll在Windows上的使用情况?,c++,c,text-to-speech,espeak,C++,C,Text To Speech,Espeak,问题:我正在尝试使用espeak文本到语音引擎。 因此,我让它在linux上正常工作(代码如下)。 现在我也想把这个基本程序移植到windows上,但这几乎是不可能的 部分问题是windows dll只允许音频输出同步,这意味着它需要回调,但我不知道如何从回调播放音频。。。首先它崩溃了,然后我意识到,我需要一个回调函数,现在我得到了回调函数中的数据,但我不知道如何播放它。。。因为它既不是wav文件,也不像在Linux上那样自动播放 sourceforge站点是相当无用的,因为它基本上说使用SAP

问题:我正在尝试使用espeak文本到语音引擎。 因此,我让它在linux上正常工作(代码如下)。 现在我也想把这个基本程序移植到windows上,但这几乎是不可能的

部分问题是windows dll只允许音频输出同步,这意味着它需要回调,但我不知道如何从回调播放音频。。。首先它崩溃了,然后我意识到,我需要一个回调函数,现在我得到了回调函数中的数据,但我不知道如何播放它。。。因为它既不是wav文件,也不像在Linux上那样自动播放

sourceforge站点是相当无用的,因为它基本上说使用SAPI版本,但是没有关于如何使用SAPI espeak dll的示例

不管怎样,这是我的密码,有人能帮忙吗

#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);
    }
}
*/
\ifdef\uuucplusplus
#包括
#包括
#包括
#否则
#包括
#包括
#包括
#恩迪夫
#包括
#包括
//#包括“speak_lib.h”
#包括“espeak/speak_lib.h”
//libespeak dev:/usr/include/espeak/speak_lib.h
//apt get安装libespeak dev
//apt get安装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采样器;
int安静=0;
静态字符性别[4]={'','M','F',''};
//const char*data_path=“/usr/share/”;///usr/share/espeak数据/
const char*data_path=NULL;//使用espeak数据的默认路径
int strrcmp(常量字符*s,常量字符*sub)
{
int slen=strlen(s);
int SUBELN=strlen(sub);
返回memcmp(s+slen-子项,子项,子项);
}
char*strrcpy(char*dest,const char*source)
{
//预断言
断言(dest!=NULL);
断言(源!=NULL);
断言(dest!=源);
//tk:括号
而((*dest++=*source++)
;
返回(--dest);
}
常量字符*GetLanguageVoiceName(常量字符*pszShortSign)
{
#定义语言长度30
静态字符返回值[语言长度];
memset(szReturnValue,0,语言长度);
for(int i=0;pszShortSign[i]!='\0';++i)
szReturnValue[i]=(char)tolower(pszShortSign[i]);
const espeak_VOICE**voices;
espeak_VOICE_选择;
voices=espeak_ListVoices(空);
const espeak_VOICE*v;
for(int ix=0;(v=voices[ix])!=NULL;ix++)
{
如果(!strrcmp(v->languages,szReturnValue))
{
strcpy(szReturnValue,v->name);
返回值;
}
}//结束
strcpy(szReturnValue,默认值);
返回值;
}//结束函数getvoicename
void ListVoices()
{
const espeak_VOICE**voices;
espeak_VOICE_选择;
voices=espeak_ListVoices(空);
const espeak_VOICE*v;
for(int ix=0;(v=voices[ix])!=NULL;ix++)
{
printf(“短符号:%s\n”,v->语言);
printf(“年龄:%d\n”,v->age);
printf(“性别:%c\n”,性别[v->gender]);
printf(“名称:%s\n”,v->name);
printf(“\n\n”);
}//结束
}//结束函数getvoicename
int main()
{
printf(“你好,世界!\n”);
const char*szVersionInfo=espeak_Info(空);
printf(“Espeak版本:%s\n”,szVersionInfo);
samplerate=espeak\u Initialize(音频输出播放,0,数据路径,0);
strcpy(voicename,“默认”);
//埃斯皮克——声音
strcpy(语音名称,“德语”);
strcpy(voicename,GetLanguageVoiceName(“DE”));
如果(espeak_SetVoiceByName(voicename)!=EE_OK)
{
printf(“Espeak setvoice错误…\n”);
}
静态字符字[200]=“你好世界”;
strcpy(单词“TV-fäns aufgepasst,es ist 20 Uhr 15.Zeit für Rambo 3”);
strcpy(单词,“无名球员wurde zum Opfer von GSG9”);
内速度=220;
int volume=500;//0-100范围内的音量0=静音
int-pitch=50;//基音节,范围0-100.50=正常
//espeak.cpp 625
espeak_设置参数(espeakRATE,速度,0);
espeak_设置参数(espeakVOLUME,volume,0);
espeak_设置参数(espeakPITCH,pitch,0);
//espeakRANGE:音高范围,范围0-100。0-单调,50=正常
//Espeak标点符号:要宣布的标点符号:
//espeak_PUNCT_类型中的值(无、全部、部分),
espeak_VOICE*VOICE_spec=espeak_GetCurrentVoice();
声音规格->性别=2;//0=无1=男性,2=女性,
//语音规格->年龄=年龄;
espeak_SetVoiceByProperties(语音规范);
espeak_Synth((char*)字,strlen(word)+1,0,POS_字符,0,espeak_自动,NULL,NULL);
espeak_Synchronize();
strcpy(voicename,GetLanguageVoiceName(“EN”));
espeak_SetVoiceByName(语音名称);
strcpy(单词“Geany被GSG9谷歌机器人折磨”);
strcpy(单词“谷歌机器人”);
espeak_Synth((char*)字,strlen(word)+1,0,POS_字符,0,espeak_自动,NULL,NULL);
espeak_Synchronize();
espeak_Terminate();
printf(“Espeak终止\n”);
返回退出成功;
}
/*
如果(espeak_SetVoiceByName(voicename)!=EE_OK)
{
memset(&voice_-select,0,sizeof(voice_-select));
voice_select.languages=语音名称;
如果(espeak_设置VoiceByProperties(&voice_select)!=EE_OK)
{
fprintf(标准,“%s声音“%s”\n”,错误加载,语音名称);
出口(2);
}
}
*/
上面的代码是针对Linux的。 下面的代码是我在Vista x64(32位emu)上得到的代码:
\ifdef\uuucplusplus
#包括
#包括
#包括
#否则
#包括
#包括
#包括
#恩迪夫
#包括
#包括
#包括“speak_lib.h”
//#包括“espeak/speak_lib.h”
//libespeak dev:/usr/include/espeak/speak_lib.h
//apt get安装libespeak dev
//apt get安装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安静=0;
静态字符性别[4]={'','M','F',''};
//const char*data_path=“/usr/share/”;///usr/share/espeak数据/
//const char*data_path=NULL;//使用espeak数据的默认路径
const char*data_path=“C:\\Users\\Username\\Desktop\\espeak-1.43-source\\espeak-1.43-source\\”;
int strrcmp(常量字符*s,常量字符*sub)
{
int slen=strlen(s);
int SUBELN=strlen(sub);
返回memcmp(s+slen-子项,子项,子项);
}
char*strrcpy(char*dest,const
#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; 
}
Declare Function sndPlaySound Lib "winmm.dll" Alias "sndPlaySoundA" (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
  sndPlaySound(buffer[0], SND_ASYNC | SND_MEMORY)
  sndPlaySound(filename, SND_ASYNC)