awaken_offline.cpp
Go to the documentation of this file.
2 #include <thread>
3 #include "common_config.h"
4 #include "linuxrec.h"
5 #include "asr/xunfei/msp_cmn.h"
7 #include "asr/xunfei/msp_types.h"
8 #include "asr/xunfei/qivw.h"
9 #include <cstring>
10 
12 bool AwakenOffline::is_awaken = false;
14 {
15  while (true)
16  {
17  if (is_awaken)
18  {
19  //播放“嘟”声提示音.
20  std::string dialogue_prompt_wav = "play " + base_path_ + "/defaultconfig/audio/call.wav";
21  system(dialogue_prompt_wav.c_str());
22 
23  is_awaken = false;
24  break;
25  }
26  else
27  {
28  continue;
29  }
30  }
31 }
32 
33 // 科大讯飞登录以及语音唤醒相关参数的设置
34 void AwakenOffline::loginAndSetParams(const std::string base_path, const std::string pcm_file, const int channel)
35 {
36  // 公司只买了语音合成以及离线关键词识别,appid对应的语音唤醒设备已经超出免费版范围(3台设备),
37  // 于是自己注册了科大讯飞申请了新的appid,于是对应的libmsc.so和msc都需要重新的资源。
38  // FIXME:购买语音唤醒功能后需替换appid和sdk资源
39  std::string login_parameters = "appid = 5ade9569, work_dir = " + base_path + "/defaultconfig";
40  int error_code = MSPLogin(NULL, NULL, login_parameters.c_str());
41  if (MSP_SUCCESS != error_code)
42  {
43  std::cout << "MSPLogin failed ! errorcode:" << error_code << std::endl;
45  }
46  awaken_params_ = "ivw_threshold=0:1450,sst=wakeup,ivw_res_path "
47  "=fo|res/ivw/wakeupresource.jet";
49  pcm_file_ = pcm_file;
50  channel_ = channel;
51 }
52 
53 // 一次对话结束后释放资源
55 {
56  // 结束本次语音唤醒
57  int ret = QIVWSessionEnd(session_id_, "normal end");
58  if (MSP_SUCCESS != ret)
59  {
60  std::cout << "QIVWSessionEnd failed !errorcode:" << ret << std::endl;
61  }
62 }
63 
64 // 从双声道的音频数据中分离出单声道数据
66 {
67  struct DataBuff pcm_two_channel = pcm_data_;
68  pcm_data_ = { NULL, 0 };
69  pcm_data_.size = pcm_two_channel.size / 2;
70 
71  pcm_data_.data = new char[pcm_data_.size];
72  for (int i = 0; i < pcm_data_.size / 2; i++)
73  {
74  memcpy((uint16_t*)pcm_data_.data + i, ((uint32_t*)(pcm_two_channel.data)) + i, 2);
75  }
76  return pcm_data_;
77 }
78 
79 // 从用于语音唤醒的pcm音频文件中读取数据
81 {
82  FileOperation pcm_file;
84 }
85 
86 void AwakenOffline::writeAudioData(const char* audio_data, unsigned int audio_len)
87 {
88  int err_code;
89  err_code = QIVWAudioWrite(session_id_, (const void*)audio_data, audio_len, audio_stat_);
90  if (MSP_SUCCESS != err_code)
91  {
92  std::cout << "QIVWAudioWrite failed! error code:" << err_code << std::endl;
94  }
95 }
96 void sleep_ms(int ms)
97 {
98  usleep(ms * 1000);
99 }
100 
101 // 调用回调函数通知唤醒成功息同时给出相应唤醒数据。
102 // 如果出错,msc 调用回调函数给出错误信息。
103 int AwakenOffline::cb_ivw_msg_proc(const char* sessionID, int msg, int param1, int param2, const void* info,
104  void* userData)
105 {
106  //唤醒出错消息
107  if (MSP_IVW_MSG_ERROR == msg)
108  {
109  std::cout << "\nMSP_IVW_MSG_ERROR errCode = " << param1 << std::endl;
111  }
112  //唤醒成功消息
113  else if (MSP_IVW_MSG_WAKEUP == msg)
114  {
115  std::cout << "\nMSP_IVW_MSG_WAKEUP result = " << (const char*)info << std::endl;
116  awaken_result_ = (char*)info;
117  is_awaken = true;
118  awaken_result_ = NULL;
119  }
120  return 0;
121 }
122 
124 {
125  int err_code = MSP_SUCCESS;
126  session_id_ = QIVWSessionBegin(NULL, awaken_params_, &err_code);
127  if (err_code != MSP_SUCCESS)
128  {
129  std::cout << "QIVWSessionBegin failed! error code:" << err_code << std::endl;
131  }
132 
134  if (err_code != MSP_SUCCESS)
135  {
136  std::cout << "QIVWRegisterNotify failed! error code:" << err_code << std::endl;
138  }
139 }
140 
141 // 把一段长pcm音频数据循环写入qivw
143 {
144  long real_read = 0;
145  long audio_count = 0;
146  int count = 0;
148  // 根据音频数据是单声道还是双声道选择接口
149  if (channel_ == 2)
150  {
152  }
153  while (1)
154  {
155  long len = 10 * FRAME_LEN; // 16k音频,10帧 (时长200ms)
157  if (pcm_data_.size <= len)
158  {
159  len = pcm_data_.size;
160  audio_stat_ = MSP_AUDIO_SAMPLE_LAST; //最后一块
161  }
162  if (0 == audio_count)
163  {
165  }
166  writeAudioData(&pcm_data_.data[audio_count], len);
168  {
169  break;
170  }
171  audio_count += len;
172  pcm_data_.size -= len;
173  sleep_ms(200); //模拟人说话时间间隙,10帧的音频时长为200ms
174  }
175  free(pcm_data_.data);
176 }
177 
179 {
180  std::string save_file_name = file_operation.setFileName("-awaken.pcm");
181  std::string save_file = base_path_ + "/cache/pcm" + save_file_name;
182  std::ofstream pcm_file(save_file, std::ofstream::binary);
183  pcm_file.write(pcm_data_.data, pcm_data_.size);
184  pcm_file.close();
185 }
186 
187 void AwakenOffline::recordThroughMIC(const float record_time, bool enable_audio_save)
188 {
189  int success_code = 0;
190  int errorcode;
191  pcm_data_.data = NULL;
192  pcm_data_.size = 0;
193  std::cout << "-----------Start Voice Wake up Thread --------" << std::endl;
194  // 采用默认设备获取音频
195  record_dev_id device_id = getDefaultInputDevice();
196  int errcode = 0;
197  // 使用WAVEFORMATEX结构指定pcm数据格式。
198  WAVEFORMATEX wavfmt = { WAVE_FORMAT_PCM, 1, 16000, 32000, 2, 16, sizeof(WAVEFORMATEX) };
199  if (getInputDeviceNum() == 0)
200  {
201  std::cout << "\nNo active record device find! ";
202  }
203  else
204  {
205  std::cout << "The total number of active input devices is : " << getInputDeviceNum() << std::endl;
206  }
207  // 设置myrec用于存储录音信息.
208  awaken_record_ = (struct recorder*)malloc(sizeof(struct recorder));
209 
210  memset(awaken_record_, 0, sizeof(struct recorder));
211 
213 
214  awaken_record_->pcm_file_path = base_path_ + "/cache/pcm";
216 
217  record_alsa.initRecord(awaken_record_, device_id, &wavfmt);
219 
220  int buf_count = 0; //分段录音计数
221  struct DataBuff record_pcm;
222  while (record_loops_ > 0)
223  {
224  record_pcm = record_alsa.startRecord();
225  writeAudioData(record_pcm.data, record_pcm.size);
226  record_loops_--;
227  pcm_data_.data = (char*)realloc(pcm_data_.data, record_pcm.size * (buf_count + 1));
228 
229  if (pcm_data_.data == NULL)
230  {
231  std::cout << "ERROR:buf_new realloc error!" << std::endl;
233  }
234  std::memcpy(&pcm_data_.data[record_pcm.size * buf_count], record_pcm.data, record_pcm.size);
235  buf_count += 1;
236  pcm_data_.size = record_pcm.size * buf_count;
237  }
238 }
239 
241 {
242  record_loops_ = 0;
244 }
static bool is_awaken
int MSPAPI QIVWRegisterNotify(const char *sessionID, ivw_ntf_handler msgProcCb, void *userData)
volatile int state
Definition: linuxrec.h:46
std::string base_path_
void checkIsAwaken()
检测是否唤醒.
struct DataBuff startRecord()
Definition: linuxrec.cpp:188
void closeRecord()
Definition: linuxrec.cpp:215
const char * session_id_
std::string pcm_file_
void recordThroughMIC(const float record_time, bool enable_audio_save)
录音并进行语音唤醒.
int MSPAPI MSPLogin(const char *usr, const char *pwd, const char *params)
unsigned short uint16_t
Definition: stdint.h:125
科大讯飞离线唤醒模块接口定义头文件. TODO: 还需要添加版权、版本等信息
int getInputDeviceNum()
Definition: linuxrec.cpp:693
void writeAudioData(const char *audio_data, unsigned int audio_len)
将pcm音频写入科大讯飞QIVWAudioWrite接口.
void dataLoopAwaken()
将音频数据循环写入科大讯飞接口进行离线唤醒.
int setRecordDuration(const float duration_time)
Definition: linuxrec.cpp:181
void uninitAsr()
一次离线唤醒结束后释放资源.
void awakenInit()
科大讯飞离线唤醒模块的初始化.
std::string setFileName(std::string file_type)
int MSPAPI QIVWSessionEnd(const char *sessionID, const char *hints)
struct recorder * awaken_record_
unsigned int uint32_t
Definition: stdint.h:126
Mobile Speech Platform Common Interface Header File.
const int FRAME_LEN
void initRecord(struct recorder *rec, record_dev_id dev, WAVEFORMATEX *fmt)
Definition: linuxrec.cpp:80
char * data
Definition: file_operation.h:8
int MSPAPI QIVWAudioWrite(const char *sessionID, const void *audioData, unsigned int audioLen, int audioStatus)
void getPcmFileData()
读取pcm文件里的音频数据,并将数据的内容和数据大小存入pcm_data_结构体.
const char * awaken_params_
record_dev_id getDefaultInputDevice()
Definition: linuxrec.cpp:680
void loginAndSetParams(const std::string base_path, const std::string pcm_file, const int channel)
科大讯飞离线唤醒登录以及参数设置.
static int cb_ivw_msg_proc(const char *sessionID, int msg, int param1, int param2, const void *info, void *userData)
static char * awaken_result_
void saveRecordDataToFile()
把录音数据存入/cache/pcm/目录下的pcm文件里,以次序和时间命名.
const std::string base_path
void stopRecordThroughMIC()
关闭录音设备.
struct DataBuff getOneChannelData()
void sleep_ms(int ms)
#define WAVE_FORMAT_PCM
Definition: formats.h:5
FileOperation file_operation
struct tWAVEFORMATEX WAVEFORMATEX
const char *MSPAPI QIVWSessionBegin(const char *grammarList, const char *params, int *errorCode)
RecordAlsaAPI record_alsa
std::string pcm_file_path
Definition: linuxrec.h:60
struct DataBuff pcm_data_
struct DataBuff readFileAsDatabuffer(const std::string file_path)


xbot_talker
Author(s): wangxiaoyun
autogenerated on Sat Oct 10 2020 03:27:53