1. 下载讯飞基于Linux的语音文档Linux_tts_online
demo链接https://download.csdn.net/download/weixin_39841821/10568834
里面的目录如下:
bin: 一些用来测试的文件
doc:技术文档
include:将使用的头文件
lib:qt编译需要加入的库文件
samples:使用demo
2. 新建widgt窗体项目,这里我的项目名是TTLSpeech_Demo,右击项目名,选择add Library->Browse加入lib中libmsc.so 库文件,选择Framework(静态库)确定
3. pro加入multimedia 用于播放合成后的语音QSound类
==TTLSpeech_Demo.pro如下==
#-------------------------------------------------
#
# Project created by QtCreator 2018-07-26T09:24:48
#
#-------------------------------------------------
QT += core gui multimedia
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = TTLSpeech_Demo
TEMPLATE = app
SOURCES += main.cpp\
widget.cpp \
myttlfunction.cpp
HEADERS += widget.h \
ttl_h/msp_cmn.h \
ttl_h/msp_errors.h \
ttl_h/msp_types.h \
ttl_h/qise.h \
ttl_h/qisr.h \
ttl_h/qtts.h \
myttlfunction.h
FORMS += widget.ui
win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../../ttlsdk/libs/x86/release/ -lmsc
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../../ttlsdk/libs/x86/debug/ -lmsc
else:mac: LIBS += -F$$PWD/../../ttlsdk/libs/x86/ -framework msc
else:unix: LIBS += -L$$PWD/../../ttlsdk/libs/x86/ -lmsc
INCLUDEPATH += $$PWD/../../ttlsdk/libs/x86
DEPENDPATH += $$PWD/../../ttlsdk/libs/x86
RESOURCES += \
testfile.qrc
4.把Linux_tts_online->include复制到项目目录下,然后右击项目头文件Header->add Existing File,将所有.h文件加入
5. 右击项目选择add New->c++->c++ class->object,新建一个object类,我这个类的名字为myttfunction,然后会生成myttlfunction.h和myttlfunction.cpp
myttlfunction.h
#ifndef MYTTLFUNCTION_H
#define MYTTLFUNCTION_H
#include "ttl_h/qtts.h"
#include "ttl_h/msp_cmn.h"
#include "ttl_h/msp_errors.h"
#include <QObject>
class myttlFunction : public QObject
{
Q_OBJECT
public:
explicit myttlFunction(QObject *parent = 0);
int text_to_speech(const char* src_text, const char* des_path, const char* params);
QString TextToVoice_Speak(const char * src_text,const char * des_path,const char* session_begin_params);
/* wav音频头部格式 */
typedef struct _wave_pcm_hdr
{
char riff[4]; // = "RIFF"
int size_8; // = FileSize - 8
char wave[4]; // = "WAVE"
char fmt[4]; // = "fmt "
int fmt_size; // = 下一个结构体的大小 : 16
short int format_tag; // = PCM : 1
short int channels; // = 通道数 : 1
int samples_per_sec; // = 采样率 : 8000 | 6000 | 11025 | 16000
int avg_bytes_per_sec; // = 每秒字节数 : samples_per_sec * bits_per_sample / 8
short int block_align; // = 每采样点字节数 : wBitsPerSample / 8
short int bits_per_sample; // = 量化比特数: 8 | 16
char data[4]; // = "data";
int data_size; // = 纯数据长度 : FileSize - 44
} wave_pcm_hdr;
signals:
public slots:
};
#endif // MYTTLFUNCTION_H
myttlfunction.cpp
#include "myttlfunction.h"
#include <QtDebug>
#include <QThread>
#include "include/qtts.h"
#include "include/msp_cmn.h"
#include "include/msp_errors.h"
myttlFunction::myttlFunction(QObject *parent) : QObject(parent)
{
}
/* 默认wav音频头部数据 */
myttlFunction::wave_pcm_hdr default_wav_hdr =
{
{ 'R', 'I', 'F', 'F' },
0,
{'W', 'A', 'V', 'E'},
{'f', 'm', 't', ' '},
16,
1,
1,
16000,
32000,
2,
16,
{'d', 'a', 't', 'a'},
0
};
int myttlFunction::text_to_speech(const char *src_text, const char *des_path, const char *params)
{
int ret = -1;
FILE* fp = NULL;
const char* sessionID = NULL;
unsigned int audio_len = 0;
wave_pcm_hdr wav_hdr = default_wav_hdr;
int synth_status = MSP_TTS_FLAG_STILL_HAVE_DATA;
if (NULL == src_text || NULL == des_path)
{
qDebug("params is error!\n");
return ret;
}
fp = fopen(des_path, "wb");
if (NULL == fp)
{
printf("open %s error.\n", des_path);
return ret;
}
/* 开始合成 */
sessionID = QTTSSessionBegin(params, &ret);
if (MSP_SUCCESS != ret)
{
qDebug("QTTSSessionBegin failed, error code: %d.\n", ret);
fclose(fp);
return ret;
}
ret = QTTSTextPut(sessionID, src_text, (unsigned int)strlen(src_text), NULL);
if (MSP_SUCCESS != ret)
{
qDebug("QTTSTextPut failed, error code: %d.\n",ret);
QTTSSessionEnd(sessionID, "TextPutError");
fclose(fp);
return ret;
}
qDebug("正在合成 ...\n");
fwrite(&wav_hdr, sizeof(wav_hdr) ,1, fp); //添加wav音频头,使用采样率为16000
while (1)
{
/* 获取合成音频 */
const void* data = QTTSAudioGet(sessionID, &audio_len, &synth_status, &ret);
if (MSP_SUCCESS != ret)
break;
if (NULL != data)
{
fwrite(data, audio_len, 1, fp);
wav_hdr.data_size += audio_len; //计算data_size大小
}
if (MSP_TTS_FLAG_DATA_END == synth_status)
break;
printf(">");
QThread::usleep(150*1000); //防止频繁占用CPU
}
printf("\n");
if (MSP_SUCCESS != ret)
{
printf("QTTSAudioGet failed, error code: %d.\n",ret);
QTTSSessionEnd(sessionID, "AudioGetError");
fclose(fp);
return ret;
}
/* 修正wav文件头数据的大小 */
wav_hdr.size_8 += wav_hdr.data_size + (sizeof(wav_hdr) - 8);
/* 将修正过的数据写回文件头部,音频文件为wav格式 */
fseek(fp, 4, 0);
fwrite(&wav_hdr.size_8,sizeof(wav_hdr.size_8), 1, fp); //写入size_8的值
fseek(fp, 40, 0); //将文件指针偏移到存储data_size值的位置
fwrite(&wav_hdr.data_size,sizeof(wav_hdr.data_size), 1, fp); //写入data_size的值
fclose(fp);
fp = NULL;
/* 合成完毕 */
ret = QTTSSessionEnd(sessionID, "Normal");
if (MSP_SUCCESS != ret)
{
printf("QTTSSessionEnd failed, error code: %d.\n",ret);
}
return ret;
}
QString myttlFunction::TextToVoice_Speak(const char *src_text, const char *des_path,const char *session_begin_params)
{
qDebug()<<"dd";
QString errorWarn;
int ret = MSP_SUCCESS;
const char* login_params = "appid = 5b586f68, work_dir = .";//登录参数,appid与msc库绑定,请勿随意改动
ret = MSPLogin("[email protected]", "hong1996", login_params);//第一个参数是用户名,第二个参数是密码,第三个参数是登录参数,用户名和密码可在http://www.xfyun.cn注册获取
if (MSP_SUCCESS != ret)
{
errorWarn="MSPLogin failed, error code: " +QString::number(ret);
return errorWarn;
}
qDebug("开始合成 ...\n");
ret = text_to_speech(src_text, des_path, session_begin_params);
if (MSP_SUCCESS != ret)
{
errorWarn="text_to_speech failed, error code: " +QString::number(ret);
return errorWarn;
}
qDebug("合成完毕\n");
errorWarn="finish";
return errorWarn;
}
==widge.h==
#ifndef WIDGET_H
#define WIDGET_H
#include "myttlfunction.h"
#include <QWidget>
#include <QSound>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::Widget *ui;
myttlFunction *ttlAsk;
QSound *sound;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <QtDebug>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
sound = new QSound("/home/csgec/Videos/10.wav");
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
QString result;
const char* session_begin_params = "voice_name = yanping, text_encoding = utf8, sample_rate = 16000, speed = 50, volume = 50, pitch = 50, rdn = 2";
ttlAsk = new myttlFunction;
result=ttlAsk->TextToVoice_Speak("第一个参数是用户名","/home/csgec/Videos/10.wav",session_begin_params);
qDebug()<<result<<"my";
}
void Widget::on_pushButton_2_clicked()
{
sound->play();
sound->setLoops(2);
qDebug() << "loops:" << sound->loops() ;
}
==main.cpp==
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
6. widget 里托两个button,用来生成音频文件和播放音频文件
==widget.ui==
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Widget</class>
<widget class="QWidget" name="Widget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Widget</string>
</property>
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>50</x>
<y>260</y>
<width>99</width>
<height>27</height>
</rect>
</property>
<property name="text">
<string>transform</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_2">
<property name="geometry">
<rect>
<x>220</x>
<y>260</y>
<width>99</width>
<height>27</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>