forked from yanw/App_win_iot_V2.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
308 lines
14 KiB
308 lines
14 KiB
using NAudio.Wave;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace IOTContainer.Common
|
|
{
|
|
public class IflytekSpecch
|
|
{
|
|
private int deviceNumber = 0; // 选择的录音设备下标。多个设备时可设置为用户选择
|
|
private WaveInEvent waveIn; // waveIn操作类
|
|
private WaveFormat recordingFormat; // 录音格式
|
|
private WaveFileWriter writer; // 录音文件操作类
|
|
StringBuilder result = new StringBuilder();//存储最终识别的结果
|
|
int totalLength = 0;//用来记录总的识别后的结果的长度,判断是否超过缓存最大值
|
|
private byte[] wavdata;
|
|
private int aud_stat = AudioStatus.MSP_AUDIO_SAMPLE_FIRST;//音频状态
|
|
public event EventHandler StoppedEvent = delegate { }; // 录音结束事件
|
|
public event EventHandler DataAvailableEvent = delegate { }; // 录音过程中接收到数据事件
|
|
static bool flag = true;
|
|
private int ep_stat = EpStatus.MSP_EP_LOOKING_FOR_SPEECH;//端点状态
|
|
private int rec_stat = RecogStatus.MSP_REC_STATUS_SUCCESS;//识别状态
|
|
int errcode = (int)Errors.MSP_SUCCESS;
|
|
bool isClose = false;
|
|
/// <summary>
|
|
/// 单例模式
|
|
/// </summary>
|
|
public static IflytekSpecch iflyteSpeech
|
|
{
|
|
get
|
|
{
|
|
if (_iflyteSpeech == null)
|
|
_iflyteSpeech = new IflytekSpecch();
|
|
return _iflyteSpeech;
|
|
}
|
|
}
|
|
|
|
private static IflytekSpecch _iflyteSpeech = new IflytekSpecch();
|
|
|
|
private IflytekSpecch() { }
|
|
public void startVoice()
|
|
{
|
|
if(flag)
|
|
{
|
|
//InitSpeech();
|
|
|
|
isClose = false;
|
|
flag = false;
|
|
StartRecorder();
|
|
}
|
|
|
|
}
|
|
public void stopVoice()
|
|
{
|
|
if(!flag)
|
|
{
|
|
isClose = true;
|
|
StopRecorder();
|
|
flag = true;
|
|
}
|
|
|
|
}
|
|
/// <summary>
|
|
/// 录音信息初始化
|
|
/// </summary>
|
|
public void InitSpeech()
|
|
{
|
|
try
|
|
{
|
|
IatNativeMethods.initVoice();
|
|
recordingFormat = new WaveFormat(16000, 16, 1);
|
|
// 设置麦克风操作对象
|
|
waveIn = new WaveInEvent();
|
|
waveIn.DeviceNumber = deviceNumber; // 设置使用的录音设备
|
|
waveIn.DataAvailable += OnDataAviailable; // 接收到音频数据时,写入文件
|
|
waveIn.RecordingStopped += OnRecordingStopped; // 录音结束时执行
|
|
waveIn.WaveFormat = recordingFormat;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.MyLog.WriteLogFile("语音初始化失败:" + ex.ToString(), "IflytekSpecch");
|
|
}
|
|
|
|
}
|
|
/// <summary>
|
|
/// 开始录音
|
|
/// </summary>
|
|
/// <param name="filename">保存的文件名</param>
|
|
internal bool StartRecorder(string filename = "voice.wav")
|
|
{
|
|
try
|
|
{
|
|
totalLength = 0;
|
|
// 设置文件操作类
|
|
writer = new WaveFileWriter(filename, recordingFormat);
|
|
result.Clear();
|
|
// 开始录音
|
|
waveIn.StartRecording();
|
|
int errcode = (int)Errors.MSP_SUCCESS;
|
|
string session_begin_params = "sub=iat,domain=iat,language=zh_cn,accent=mandarin,sample_rate=16000,result_type=plain,result_encoding=gb2312";
|
|
IatNativeMethods.session_id = IatNativeMethods.QISRSessionBegin(null, session_begin_params, ref errcode);
|
|
if (errcode != (int)Errors.MSP_SUCCESS)
|
|
{
|
|
IatNativeMethods.initVoice();
|
|
flag = true;
|
|
string result = "{\"code\": \"401\",\"msg\": \"语音系统维护中,请稍后再试!\",\"data\": { \"ModelType\" : \"\", \"ActionType\" : \"\", \"query\":\"???\" , \"ttsMsg\":\"语音系统维护中,请稍后再试!\"}}";
|
|
Log.MyLog.WriteLogFile("StartRecorder:获取结果失败:" + errcode, "IflytekSpecch");
|
|
StopRecorder();
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.MyLog.WriteLogFile("StartRecorder:" + ex.ToString(), "IflytekSpecch");
|
|
}
|
|
return true;
|
|
}
|
|
/// <summary>
|
|
/// 录音回调函数,写入数据
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void OnDataAviailable(object sender, WaveInEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
byte[] buffer = e.Buffer;
|
|
int bytesRecorded = e.BytesRecorded;
|
|
long maxFileLength = this.recordingFormat.AverageBytesPerSecond * 60;
|
|
var toWrite = (int)Math.Min(maxFileLength - writer.Length, bytesRecorded);
|
|
if (toWrite > 0)
|
|
{
|
|
writer.Write(buffer, 0, bytesRecorded);
|
|
run_iat(buffer);
|
|
aud_stat = AudioStatus.MSP_AUDIO_SAMPLE_CONTINUE;
|
|
}
|
|
DataAvailableEvent(this, EventArgs.Empty);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
|
|
Log.MyLog.WriteLogFile("OnDataAviailable:" + ex.ToString(), "IflytekSpecch");
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 录音结束回调函数
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void OnRecordingStopped(object sender, StoppedEventArgs e)
|
|
{
|
|
writer.Dispose();
|
|
run_iatlast();
|
|
// 通知结束事件
|
|
StoppedEvent(this, EventArgs.Empty);
|
|
}
|
|
private void run_iat(byte[] _wavdata)
|
|
{
|
|
try
|
|
{
|
|
wavdata = _wavdata;
|
|
if(wavdata == null || wavdata.Length == 0)
|
|
{
|
|
string result = "{\"code\": \"401\",\"msg\": \"未识别到语音输入\",\"data\": { \"ModelType\" : \"\", \"ActionType\" : \"\", \"query\":\"???\" , \"ttsMsg\":\"未识别到语音输入\"}}";
|
|
ComParameters.Parameters.EdgeWindow.SendVoiceMsg(result);
|
|
}
|
|
else
|
|
{
|
|
int res = IatNativeMethods.QISRAudioWrite(IatNativeMethods.session_id, wavdata, (uint)wavdata.Length, aud_stat, ref ep_stat, ref rec_stat);
|
|
if (res != (int)Errors.MSP_SUCCESS)
|
|
{
|
|
flag = true;
|
|
string result = "{\"code\": \"401\",\"msg\": \"未识别到语音输入\",\"data\": { \"ModelType\" : \"\", \"ActionType\" : \"\", \"query\":\"???\" , \"ttsMsg\":\"未识别到语音输入\"}}";
|
|
ComParameters.Parameters.EdgeWindow.SendVoiceMsg(result);
|
|
Log.MyLog.WriteLogFile("写入识别的音频失败!" + res, "IflytekSpecch");
|
|
StopRecorder();
|
|
return;
|
|
}
|
|
if (RecogStatus.MSP_REC_STATUS_SUCCESS != rec_stat)
|
|
{
|
|
IntPtr now_result = IatNativeMethods.QISRGetResult(IatNativeMethods.session_id, ref rec_stat, 0, ref errcode);
|
|
if (errcode != (int)Errors.MSP_SUCCESS)
|
|
{
|
|
flag = true;
|
|
string result = "{\"code\": \"401\",\"msg\": \"未识别到语音输入\",\"data\": { \"ModelType\" : \"\", \"ActionType\" : \"\", \"query\":\"???\" , \"ttsMsg\":\"未识别到语音输入\"}}";
|
|
ComParameters.Parameters.EdgeWindow.SendVoiceMsg(result);
|
|
Log.MyLog.WriteLogFile("获取结果失败:" + errcode, "IflytekSpecch");
|
|
StopRecorder();
|
|
return;
|
|
}
|
|
if (now_result != null)
|
|
{
|
|
int length = now_result.ToString().Length;
|
|
totalLength += length;
|
|
if (totalLength > 4096)
|
|
{
|
|
flag = true;
|
|
string result = "{\"code\": \"401\",\"msg\": \"未识别到语音输入\",\"data\": { \"ModelType\" : \"\", \"ActionType\" : \"\", \"query\":\"???\" , \"ttsMsg\":\"未识别到语音输入\"}}";
|
|
ComParameters.Parameters.EdgeWindow.SendVoiceMsg(result);
|
|
Log.MyLog.WriteLogFile("缓存空间不够:" + totalLength, "IflytekSpecch");
|
|
StopRecorder();
|
|
return;
|
|
}
|
|
result.Append(Marshal.PtrToStringAnsi(now_result));
|
|
}
|
|
}
|
|
if (EpStatus.MSP_EP_AFTER_SPEECH == ep_stat)
|
|
{
|
|
StopRecorder();
|
|
return;
|
|
}
|
|
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.MyLog.WriteLogFile("run_iat:" + ex.ToString(), "IflytekSpecch");
|
|
}
|
|
}
|
|
private void run_iatlast()
|
|
{
|
|
|
|
var res = IatNativeMethods.QISRAudioWrite(IatNativeMethods.session_id, null, 0, AudioStatus.MSP_AUDIO_SAMPLE_LAST, ref ep_stat, ref rec_stat);
|
|
if (res != (int)Errors.MSP_SUCCESS)
|
|
{
|
|
flag = true;
|
|
string result = "{\"code\": \"401\",\"msg\": \"未识别到语音输入\",\"data\": { \"ModelType\" : \"\", \"ActionType\" : \"\", \"query\":\"???\" , \"ttsMsg\":\"未识别到语音输入\"}}";
|
|
ComParameters.Parameters.EdgeWindow.SendVoiceMsg(result);
|
|
Log.MyLog.WriteLogFile("写入识别的音频失败:" + res, "IflytekSpecch");
|
|
StopRecorder();
|
|
return;
|
|
}
|
|
|
|
while (RecogStatus.MSP_REC_STATUS_COMPLETE != rec_stat)
|
|
{
|
|
IntPtr now_result = IatNativeMethods.QISRGetResult(IatNativeMethods.session_id, ref rec_stat, 0, ref errcode);
|
|
if (errcode != (int)Errors.MSP_SUCCESS)
|
|
{
|
|
flag = true;
|
|
string result = "{\"code\": \"401\",\"msg\": \"未识别到语音输入\",\"data\": { \"ModelType\" : \"\", \"ActionType\" : \"\", \"query\":\"???\" , \"ttsMsg\":\"未识别到语音输入\"}}";
|
|
ComParameters.Parameters.EdgeWindow.SendVoiceMsg(result);
|
|
Log.MyLog.WriteLogFile("获取结果失败:" + errcode, "IflytekSpecch");
|
|
StopRecorder();
|
|
return;
|
|
}
|
|
if (now_result != null)
|
|
{
|
|
int length = now_result.ToString().Length;
|
|
totalLength += length;
|
|
if (totalLength > 4096)
|
|
{
|
|
flag = true;
|
|
string result = "{\"code\": \"401\",\"msg\": \"未识别到语音输入\",\"data\": { \"ModelType\" : \"\", \"ActionType\" : \"\", \"query\":\"???\" , \"ttsMsg\":\"未识别到语音输入\"}}";
|
|
ComParameters.Parameters.EdgeWindow.SendVoiceMsg(result);
|
|
Log.MyLog.WriteLogFile("缓存空间不够:" + totalLength, "IflytekSpecch");
|
|
StopRecorder();
|
|
}
|
|
|
|
result.Append(Marshal.PtrToStringAnsi(now_result));
|
|
}
|
|
Thread.Sleep(150);//防止频繁占用cpu
|
|
}
|
|
QISRSessionEnd();
|
|
}
|
|
private void QISRSessionEnd()
|
|
{
|
|
int ret = IatNativeMethods.QISRSessionEnd(IatNativeMethods.session_id, "normal end");
|
|
if (!isClose)
|
|
{
|
|
if (errcode != (int)Errors.MSP_SUCCESS)
|
|
{
|
|
flag = true;
|
|
string result = "{\"code\": \"401\",\"msg\": \"未识别到语音输入\",\"data\": { \"ModelType\" : \"\", \"ActionType\" : \"\", \"query\":\"???\" , \"ttsMsg\":\"未识别到语音输入\"}}";
|
|
ComParameters.Parameters.EdgeWindow.SendVoiceMsg(result);
|
|
Log.MyLog.WriteLogFile("QISRSessionEnd failed, error code is: %d" + ret, "IflytekSpecch");
|
|
|
|
}
|
|
else
|
|
{
|
|
if (result.Length > 0)
|
|
{
|
|
string resultReturn = "{\"code\": \"200\",\"msg\": \"" + result.ToString() + "\",\"data\": { \"ModelType\" : \"\", \"ActionType\" : \"\", \"query\":\"???\" , \"ttsMsg\":\"录音结束\"}}";
|
|
//最终方法
|
|
ComParameters.Parameters.EdgeWindow.SendVoiceMsg(resultReturn);
|
|
}
|
|
else
|
|
{
|
|
flag = true;
|
|
string resultReturn = "{\"code\": \"401\",\"msg\": \"未识别到语音输入\",\"data\": { \"ModelType\" : \"\", \"ActionType\" : \"\", \"query\":\"???\" , \"ttsMsg\":\"录音结束\"}}";
|
|
ComParameters.Parameters.EdgeWindow.SendVoiceMsg(resultReturn);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 结束录音
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal bool StopRecorder()
|
|
{
|
|
waveIn.StopRecording();
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|