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

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;
}
}
}