初识语音合成软件eSpeak

    在医院取药时听到机器叫自己的名字,有点小好奇。应该是使用了文本转语音技术。出于好奇,百度了一下,发现了这个开源软件eSpeak。下载windows安装包,测试了一下,发现微软的语音技术非常成熟,语音流畅清晰,相比下,eSpeak的语音不太流畅,英语要努力才能听,中文效果离实用距离很远。不管怎样,eSpeak是可以工作的,我作为一个小猿,可以把它组装到自己程序中的跑一跑,不是一件有趣的事情吗?
      说干就干,这其中还是有坑的。我用svn检出了eSpeak的最新代码。我主要使用了其中的两个vc6工程,一个用来生成动态库,一个用来生成命令行程序。先说命令行程序,它居然不使用动态库,说明作者的思路不寻常。它依赖一个叫PAStaticWMME.lib的静态库。该库是另一开源软件PortAudio生成的。我在编译PortAudio时一直没有成功。于是决定直接使用PAStaticWMME.lib。我在vc2005下编译命令行程序报错缺少libc.lib,它是vc6的c语言运行时库。于是从网上下载了一个libcd.lib,将它改名为libc.lib也可以使用。再编译时报很多函数重复定义,于是将libc.lib添加到忽略库中,编译通过。命令行程序可以对标准输入中的文本进行语音合成后发音。再说动态库工程,直接编译生成的动态库是没有语音播放功能的。如果需要,则要先修改speech.h文件,将被注释的#define USE_PORTAUDIO放开。编译时需要依赖PAStaticWMME.lib。编译成功后得到espeak_lib.dll和espeak_lib.lib。头文件espeak_lib.h中对每个函数都有注释,有比没有强吧。我在我的QT工程中添加外部库espeak_lib.lib。在对话框构造函数中增加espeak初始化语句,如下。
static int SynthCallback(short *wav, int numsamples, espeak_EVENT *events)
{
    // 你可以根据源码程序里编写这部分代码实现生成语音文件功能,这里忽略掉了
    return(0);
}
// espeak初始化
    int ret = espeak_Initialize(AUDIO_OUTPUT_SYNCH_PLAYBACK, 0, "C:\\Program Files (x86)\\eSpeak", 0);
    if (ret == EE_INTERNAL_ERROR)
    {
        qDebug() << tr("espeak_Initialize fail");
        return;
    }
    qDebug() << tr("espeak_Initialize ok, return") << ret;
    espeak_SetSynthCallback(SynthCallback);   // 设置回调函数
    ret = espeak_SetParameter(espeakRATE, 80, 0); // 语速调慢至每分钟80个字
    if (ret == EE_INTERNAL_ERROR)
    {
        qDebug() << tr("espeak_SetParameter fail");
        return;
    }
    qDebug() << tr("espeak_SetParameter ok");
espeak_Initialize函数的第3个参数是 espeak-data目录。安装espeak的windows安装包后就有该目录。回调函数SynthCallback什么也不做,直接返回0。在播放语音按钮的处理函数中增加以下语句,实现了英文语音合成播放功能。
    espeak_SetVoiceByName("en"); // 使用英语语音
    ret = espeak_Synth(strCode.toUtf8().data(), strlen(strCode.toUtf8().data()),
                       0, POS_CHARACTER, 0, espeakCHARS_UTF8, NULL ,NULL);
    if (ret != EE_OK)
    {
        qDebug() << tr("espeak_Synth error:") << ret;
        return;
    }
    espeak_Synchronize();
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页