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; /// /// 单例模式 /// 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; } } /// /// 录音信息初始化 /// 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"); } } /// /// 开始录音 /// /// 保存的文件名 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; } /// /// 录音回调函数,写入数据 /// /// /// 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"); } } /// /// 录音结束回调函数 /// /// /// 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); } } } } /// /// 结束录音 /// /// internal bool StopRecorder() { waveIn.StopRecording(); return true; } } }