第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > 接口调用-【4】讯飞离线语音合成Windows/Linux

接口调用-【4】讯飞离线语音合成Windows/Linux

时间:2019-04-17 01:21:49

相关推荐

接口调用-【4】讯飞离线语音合成Windows/Linux

1、离线语音合成调用主函数(离线语音合成调用属于简单的,无回调函数)

package com.iflytek;import com.iflytek.util.Step2_tts_thread;import com.iflytek.util.Step3_audioFormat;import java.util.Scanner;import javax.sound.sampled.*;/*** 请注意!!!* 1.首选到控制台/services/aisound下载普通离线语音合成的Windows MSC。* 2.普通离线语音合成Windows MSC解压后,把bin目录下msc文件夹与dll文件拷贝到res目录下。* 3.最后请替换Step2_tts_thread中的appid值,appid值在下载页面控制台可以看到。*/public class OfflineTtsMain {//录音相关参数public static AudioFormat audioFormat;public static SourceDataLine sourceDataLine;public static void main(String[] args) throws Exception {System.out.println("输入y开始体验普通离线语音合成...");Scanner myScanner = new Scanner(System.in);String userCommand = myScanner.next();long startTime = System.currentTimeMillis();if(userCommand.equals("y")){audioFormat = Step3_audioFormat.getAudioFormat(audioFormat);//构造具有线性 PCM 编码和给定参数的 AudioFormat。DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class,audioFormat, AudioSystem.NOT_SPECIFIED);sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);Step2_tts_thread myThread=new Step2_tts_thread();myThread.start();}}}

2、根据MSC文档用JAVA重写方法

package com.iflytek.service;import com.sun.jna.Library;import com.sun.jna.Native;import com.sun.jna.Pointer;import com.sun.jna.ptr.IntByReference;public interface Step1_tts_dll extends Library {/*** 重点:* 1.char * 对应 String* 2.int * 对应 IntByReference* 3.void * 对应 byte[]/Pointer,回调函数里此类型需用String来对应。* 4.int对应 int* 5.无参对应 void* 6.回调函数 对应 根据文档自定义回调函数,实现接口Callback,离线语音合成无回调*///加载dll动态库并实例化,从而使用其内部的方法Step1_tts_dll INSTANCE = (Step1_tts_dll) Native.loadLibrary("res/msc_x64.dll", Step1_tts_dll.class);//定义登录方法public int MSPLogin(String usr, String pwd, String params);//开始一次普通离线语音合成public String QTTSSessionBegin(String params, IntByReference errorCode);//写入需要合成的文本public int QTTSTextPut(String sessionID,String textString,int textLen,String params);//获取离线合成的音频public Pointer QTTSAudioGet(String sessionID, IntByReference audioLen, IntByReference synthStatus, IntByReference errorCode);//结束本次普通离线语音合成public int QTTSSessionEnd(String sessionID, String hints);//定义退出方法public int MSPLogout();}

3、把调用步骤依次写进线程类

package com.iflytek.util;import com.iflytek.OfflineTtsMain;import com.iflytek.service.Step1_tts_dll;import com.sun.jna.Pointer;import com.sun.jna.ptr.IntByReference;import java.io.ByteArrayOutputStream;import java.util.Scanner;public class Step2_tts_thread extends Thread{public static int total_audio_length=0;public static ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();public void run() {while (true) {//登录参数String login_params = "appid = 替换你的appid, work_dir = ./res";//第一个参数为用户名,第二个参数为密码,传null即可int ret = Step1_tts_dll.INSTANCE.MSPLogin(null, null, login_params);if (ret != 0) {//登录成功标志ret为0System.out.println("登录失败...请检查");System.exit(1);} else {//System.out.println("登录成功...");}//请让一让,A02-02-03//开始一次普通离线语音合成会话String session_begin_params = "engine_type = local, voice_name = xiaoyan, text_encoding = UTF8, tts_res_path = fo|res/tts/xiaoyan.jet;fo|res/tts/common.jet, sample_rate = 16000, speed = 50, volume = 50, pitch = 50, rdn = 2";IntByReference errorCode = new IntByReference(-100);String session_id = Step1_tts_dll.INSTANCE.QTTSSessionBegin(session_begin_params,errorCode);if(errorCode.getValue()==0){//System.out.println("开启普通离线语音合成成功,session_id是:"+session_id);}else{System.out.println("开启普通离线语音合成失败:"+errorCode.getValue());}//写入需要合成的文本System.out.println("\033[43;34;4m"+"请输入你要合成的文本并回车"+"\033[0m");Scanner myScanner = new Scanner(System.in);String tts_text =myScanner.nextLine();//System.out.println(tts_text);//注意获取的文本是否完整ret= Step1_tts_dll.INSTANCE.QTTSTextPut(session_id, tts_text, tts_text.getBytes().length,null);if(ret==0){//System.out.println("写入合成文本成功...");}else{System.out.println("写入合成文本失败:"+ret);}//循环获取离线合成的音频,并实时进行播放IntByReference audio_len=new IntByReference(-100);IntByReference synth_status=new IntByReference(-100);errorCode=new IntByReference(-100);try{//实时播放OfflineTtsMain.sourceDataLine.open(OfflineTtsMain.audioFormat);OfflineTtsMain.sourceDataLine.start();}catch (Exception e){e.printStackTrace();}//int i=0;while (true) {Pointer audioPointer = Step1_tts_dll.INSTANCE.QTTSAudioGet(session_id,audio_len,synth_status,errorCode);byte[] audioDataByteArray=null;if(audioPointer!=null){audioDataByteArray=audioPointer.getByteArray(0,audio_len.getValue());}if (errorCode.getValue()==0){//System.out.println("正常获取音频中...");}else{System.out.println("获取音频发生错误:"+errorCode);break;}if (audioDataByteArray!=null ){try{//实时播放OfflineTtsMain.sourceDataLine.write(audioDataByteArray, 0, audio_len.getValue());/*i=i+1;//实现暂停的效果System.out.println(i);if(i==5){OfflineTtsMain.sourceDataLine.stop();Thread.sleep(5000);}if(i==6){OfflineTtsMain.sourceDataLine.start();}*///将数据写入字节数组的输出流,用来生成音频文件byteArrayOutputStream.write(audioDataByteArray, 0, audio_len.getValue());}catch(Exception e){e.printStackTrace();}//计算总音频长度,用来生成音频文件total_audio_length=total_audio_length+audio_len.getValue();}if (synth_status.getValue()==2){//说明音频已经取完,退出本次循环try{OfflineTtsMain.sourceDataLine.drain();OfflineTtsMain.sourceDataLine.close();byteArrayOutputStream.flush();byteArrayOutputStream.close();}catch (Exception e){e.printStackTrace();}break;}}//把合成的音频存放为wav格式String dateAsFileName= String.valueOf(System.currentTimeMillis());//用当前时间标记文件名Boolean waveProductFlag=Step4_wave_product.waveProduct(total_audio_length,byteArrayOutputStream,"./res/"+dateAsFileName+".wav");if(waveProductFlag){System.out.println("生成音频文件成功:"+dateAsFileName+".wav");}else{System.out.println("生成音频文件失败...");}//结束本次普通离线语音合成ret=Step1_tts_dll.INSTANCE.QTTSSessionEnd(session_id, "正常退出");if(ret==0){//System.out.println("离线语音合成正常退出...");}else{System.out.println("离线语音合成退出异常:"+ret);}//执行最终退出ret = Step1_tts_dll.INSTANCE.MSPLogout();if (ret == 0) {//System.out.println("正常退出...");} else {System.out.println("异常退出:"+ret);}//是否退出Java程序System.out.println("\33[43;31;4m"+"结束合成:输入n,继续合成:输入其他内容"+"\33[0m");Scanner myScanner2 = new Scanner(System.in);String userCommand = myScanner2.nextLine();if(userCommand.equals("n")){OfflineTtsMain.sourceDataLine.stop();OfflineTtsMain.sourceDataLine.close();System.exit(0);}}}}

4、生成16K、16BIT单声道音频流

package com.iflytek.util;import javax.sound.sampled.AudioFormat;public class Step3_audioFormat {//构造线程参数//16k采样率的16bit音频,一帧的大小为640B, 时长20ms/**sampleRate - 每秒样品数sampleSizeInBits - 每个样本中的位数channels - 通道数(1为mono,2为立体声等)signed - 表示数据是签名还是无符号bigEndian - 指示单个样本的数据是否以大字节顺序存储( false表示小端)*/public static AudioFormat getAudioFormat(AudioFormat audioFormat) {audioFormat=new AudioFormat(16000F, 16, 1,true,false);// true,false 指示是以 big-endian 顺序还是以 little-endian 顺序存储音频数据。return audioFormat;//构造具有线性 PCM 编码和给定参数的 AudioFormat。}}

5、生成WAV音频所需的文件头

package com.iflytek.util;import java.io.BufferedOutputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileOutputStream;public class Step4_wave_product {public static byte[] RIFF = "RIFF".getBytes();public static byte[] RIFF_SIZE = new byte[8];public static byte[] RIFF_TYPE = "WAVE".getBytes();public static byte[] FORMAT = "fmt ".getBytes();public static byte[] FORMAT_SIZE = new byte[4];public static byte[] FORMAT_TAG = new byte[2];public static byte[] CHANNELS = new byte[2];public static byte[] SamplesPerSec = new byte[4];public static byte[] AvgBytesPerSec = new byte[4];public static byte[] BlockAlign = new byte[2];public static byte[] BitsPerSample = new byte[2];public static byte[] Data = "data".getBytes();public static byte[] DataSize = new byte[4];public static boolean waveProduct(int audioLength, ByteArrayOutputStream byteArrayOutputStream, String outputFilePath){Step4_wave_product.DataSize = Step4_wave_product.revers(Step4_wave_product.intToBytes(audioLength));Step4_wave_product.RIFF_SIZE = Step4_wave_product.revers(Step4_wave_product.intToBytes(audioLength + 36 - 8));File waveFile = new File(outputFilePath);FileOutputStream fileOutputStream = null;try {fileOutputStream = new FileOutputStream(waveFile);BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);init();bufferedOutputStream.write(RIFF);bufferedOutputStream.write(RIFF_SIZE);bufferedOutputStream.write(RIFF_TYPE);bufferedOutputStream.write(FORMAT);bufferedOutputStream.write(FORMAT_SIZE);bufferedOutputStream.write(FORMAT_TAG);bufferedOutputStream.write(CHANNELS);bufferedOutputStream.write(SamplesPerSec);bufferedOutputStream.write(AvgBytesPerSec);bufferedOutputStream.write(BlockAlign);bufferedOutputStream.write(BitsPerSample);bufferedOutputStream.write(Data);bufferedOutputStream.write(DataSize);bufferedOutputStream.write(byteArrayOutputStream.toByteArray());bufferedOutputStream.flush();bufferedOutputStream.close();return true;} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();return false;}}public static void init() {FORMAT_SIZE = new byte[]{(byte) 16, (byte) 0, (byte) 0, (byte) 0};byte[] tmp = revers(intToBytes(1));FORMAT_TAG = new byte[]{tmp[0], tmp[1]};CHANNELS = new byte[]{tmp[0], tmp[1]};SamplesPerSec = revers(intToBytes(16000));AvgBytesPerSec = revers(intToBytes(32000));tmp = revers(intToBytes(2));BlockAlign = new byte[]{tmp[0], tmp[1]};tmp = revers(intToBytes(16));BitsPerSample = new byte[]{tmp[0], tmp[1]};}public static byte[] revers(byte[] tmp) {byte[] reversed = new byte[tmp.length];for (int i = 0; i < tmp.length; i++) {reversed[i] = tmp[tmp.length - i - 1];}return reversed;}public static byte[] intToBytes(int num) {byte[] bytes = new byte[4];bytes[0] = (byte) (num >> 24);bytes[1] = (byte) ((num >> 16) & 0x000000FF);bytes[2] = (byte) ((num >> 8) & 0x000000FF);bytes[3] = (byte) (num & 0x000000FF);return bytes;}}

6、放置讯飞开放平台下载Linux/Windows中所带的资源

7、Linux代码基本类似,离线合成普通版,注意资源放置

package com.iflytek.service;import com.iflytek.OfflineTtsMain;import com.sun.jna.Library;import com.sun.jna.Native;import com.sun.jna.Pointer;import com.sun.jna.ptr.IntByReference;public interface Step1_tts_so extends Library {/*** 重点:* 1.char * 对应 String* 2.int * 对应 IntByReference* 3.void * 对应 byte[]/Pointer,回调函数里此类型需用String来对应。* 4.int对应 int* 5.无参对应 void* 6.回调函数 对应 根据文档自定义回调函数,实现接口Callback,离线语音合成无回调*///加载dll动态库并实例化,从而使用其内部的方法Step1_tts_so INSTANCE = (Step1_tts_so) Native.loadLibrary(OfflineTtsMain.userPath+"res/libmsc.so", Step1_tts_so.class);//定义登录方法public int MSPLogin(String usr, String pwd, String params);//开始一次普通离线语音合成public String QTTSSessionBegin(String params, IntByReference errorCode);//写入需要合成的文本public int QTTSTextPut(String sessionID,String textString,int textLen,String params);//获取离线合成的音频public Pointer QTTSAudioGet(String sessionID, IntByReference audioLen, IntByReference synthStatus, IntByReference errorCode);//结束本次普通离线语音合成public int QTTSSessionEnd(String sessionID, String hints);//定义退出方法public int MSPLogout();}

8、Linux代码基本类似,离线合成高品质,注意资源放置

package com.iflytek.service;import com.iflytek.OfflineHighQualityTtsMain;import com.sun.jna.Library;import com.sun.jna.Native;import com.sun.jna.Pointer;import com.sun.jna.ptr.IntByReference;public interface Step1_tts_so extends Library {/*** 重点:* 1.char * 对应 String* 2.int * 对应 IntByReference* 3.void * 对应 byte[]/Pointer,回调函数里此类型需用String来对应。* 4.int对应 int* 5.无参对应 void* 6.回调函数 对应 根据文档自定义回调函数,实现接口Callback,离线语音合成无回调*///加载so动态库并实例化,从而使用其内部的方法Step1_tts_so INSTANCE = (Step1_tts_so) Native.loadLibrary(OfflineHighQualityTtsMain.userPath+"res/libmsc.so", Step1_tts_so.class);//定义登录方法public int MSPLogin(String usr, String pwd, String params);//开始一次高品质离线语音合成public String QTTSSessionBegin(String params, IntByReference errorCode);//写入需要合成的文本public int QTTSTextPut(String sessionID,String textString,int textLen,String params);//获取离线合成的音频public Pointer QTTSAudioGet(String sessionID, IntByReference audioLen, IntByReference synthStatus, IntByReference errorCode);//结束本次高品质离线语音合成public int QTTSSessionEnd(String sessionID, String hints);//定义退出方法public int MSPLogout();}

9、普通版与高品质版对内存的消耗也不同,请根据实际所需进行选择

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。