Qt 国产嵌入式操作系统实现文字转语音功能(TTS)

发布时间:2024年01月15日

1.简介

本示例使用的CPU:rk3588。

操作系统:kylin V10

架构:aarch64

在Windows端,我们很容易想到使用Qt自带的类QTextToSpeech来实现文字转语音功能,Qt版本得在5.11.0以上才支持。但是在嵌入式平台,尤其是在国产的操作系统中,我们需要编译Qt源码,使得Qt能够支持文字转语音功能,我使用的Qt版本5.12.8,我的想法是在编译配置中将文字转语音功能编译进去,但是我并没有找到相关的配置选项,如果有知道的大佬,请指教。

Qt 文字转语音_qt 文本转语音-CSDN博客

查看系统的版本:

lsb_release -a

查看系统架构:

uname -m

查看Qt的编译选项,生成makefile。

./configure -help

后来我采用了另外的三方库eSpeak,来实现了文字转语音。

2.QTextToSpeech使用方法

  • setRate(double):可以设置 速率 高低音 音量,此属性保存当前语音速率,范围从-1.0到1.0。默认值0.0是正常的语音流。
  • setPitch(double):此属性保存语音音高,范围从-1.0到1.0。默认的0.0是正常的语音音高。
  • setVolume(double):此属性保存当前音量,范围从0.0到1.0。默认值是平台的默认音量
  • setVoice(const QVoice &voice):设置声音使用。注意:在某些平台上,设置语音会更改其他语音属性,如地区、音高等。这些变化触发了信号的发射。
  • void setLocale(const QLocale &locale);设置语言的语种 有中文 英文啥的
  • void say(const QString &text);播放语音 传入 字符串比如 say(“hello world”) 语音里就说 hello world

3.eSpeak编译

这里我并不是使用的交叉编译,我直接放到将源码放到平台上编译。

eSpeak依赖PortAudio进行播放音频,所以在编译eSpeak前需要准备好PortAudio的库。

PortAudio是一个免费、跨平台、开源的音频I/O库。它能够简化C/C++的音频程序的设计实现,能够运行在Windows、Macintosh OS X和UNIX之上(Linux的各种版本也不在话下)。

PortAudio下载:我下载的如下图所示的包。

PortAudio - an Open-Source Cross-Platform Audio API

PortAudio编译:

解压完后在portaudio目录下创建build目录用于安装。生成makefile。

./configure --prefix=/home/kylin/wzz/build

编译:make -j8 && make install

在build目录下就有了安装好的头文件和库。

eSpeak下载地址:

espeak: Downloads

解压完成后,进入到src中。

cd src && cp portaudio19.h portaudio.h?

修改Makefile内容:

vi Makefile

修改3-7行,根据自己的路径来修改。

注释掉30行:AUDIO = portaudio

打开31行:AUDIO = portaudio0

注释掉53行:LIB_AUDIO=/usr/lib/libportaudio.so.0

添加LIB_AUDIO=$(PREFIX)/lib/libportaudio.so?(刚刚编译生成的portaudio库)

?

保存后执行:

make -j8 && make install

生成的库在/home/kylin/wzz/build下。

4.eSpeak使用

在bin目录下生成espeak可执行程序。

执行命令:

./espeak "你好" -v zh

嵌入到Qt代码中:源码示例。

espeak_Initialize:初始化。

espeak_SetVoiceByName:设置声音。

espeak_SetSynthCallback:设置回调。

espeak_Synth:语音合成。

espeak_Cancel:停止合成。

espeak_Terminate:终止。

#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QList>
#include <QMutex>

class MyThread : public QThread
{
public:
    MyThread(QObject *parent = nullptr);

public:
    void stop();
    void add(QString text);
    void cancel();
protected:
    void run();

private:
    QString m_text;
    bool m_isStart = false;
    QMutex m_mutex;
    bool m_isNewText;
};

#endif // MYTHREAD_H


#include "mythread.h"
#include <QDebug>

#ifdef __LINUX__
extern "C"
{
#include "espeak/speak_lib.h"
}

int speakCallback(short *wav, int numsamples, espeak_EVENT *events)
{
	fwrite(wav, sizeof(short), numsamples, stdout);
}
#endif // __LINUX__


MyThread::MyThread(QObject *parent)
    : QThread(parent)
{
#ifdef __LINUX__
    if(espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,0,NULL,0) != EE_OK)
    {
        qDebug()<<"espeak_Initialize error";
    }

    espeak_SetVoiceByName("zh+f2");
#endif // __LINUX__
    //espeak_SetSynthCallback(speakCallback);

}

void MyThread::stop()
{
    m_isStart = false;
}

void MyThread::add(QString text)
{
#ifdef __LINUX__
    m_mutex.lock();
    if(espeak_IsPlaying())
        espeak_Cancel();
    m_text = text;

    m_isNewText = true;
    m_mutex.unlock();
#endif // __LINUX__
}

void MyThread::cancel()
{
#ifdef __LINUX__
    espeak_Cancel();
#endif // __LINUX__
}

void MyThread::run()
{
#ifdef __LINUX__
    m_isStart = true;
    while(m_isStart)
    {

        if(m_isNewText)
        {
            QString text = m_text;
            QByteArray byte = text.toUtf8();

            if(espeak_Synth(byte.data(),byte.length(),0,POS_CHARACTER,0,espeakCHARS_UTF8,NULL,NULL) != EE_OK)
            {
                qDebug()<<"espeak_Synth error";
            }
            m_isNewText = false;
        }
        else
        {
            msleep(50);
        }
    }
    espeak_Terminate();

#endif // __LINUX__
}

文章来源:https://blog.csdn.net/wzz953200463/article/details/135605318
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。