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.
569 lines
15 KiB
569 lines
15 KiB
|
|
//
|
|
//#define CPP_DLL_API __declspec(dllexport)
|
|
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <chrono>
|
|
#include <thread>
|
|
#include <codecvt>
|
|
|
|
#include <stdlib.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
|
|
#include <iostream>
|
|
#include <string>
|
|
|
|
#include <mutex>
|
|
|
|
#include <WinSock2.h>
|
|
#include <windows.h>
|
|
|
|
#include "RecognitionCppDll.h"
|
|
|
|
#pragma comment(lib, "ws2_32" )
|
|
#pragma comment(lib, "pthreadVC2.lib")
|
|
#pragma comment(lib, "vsdllsdk6.lib")
|
|
|
|
//extern std::string gTtsStrGlobal;
|
|
//extern std::string gSdkConfigBasePath;
|
|
//extern std::vector<char> gWaveData;
|
|
//extern volatile bool gFinishRecording;
|
|
//extern std::string GBKToUTF8(const std::string& strGBK);
|
|
|
|
extern std::string GBKToUTF8(const std::string& strGBK);
|
|
extern std::string UTF8ToGBK(const char* strUTF8);
|
|
|
|
std::string gTtsStrGlobal="";
|
|
std::string gSdkConfigBasePath = "D:\\sdktest\\config";
|
|
std::vector<char> gWaveData;
|
|
volatile bool gFinishRecording = false;
|
|
|
|
std::mutex gMutex;
|
|
std::condition_variable gCondition;
|
|
pthread_mutex_t gPMutex;
|
|
pthread_cond_t gPCondition;
|
|
|
|
//extern "C" int recordAndSaveWav();
|
|
extern int recordAndSaveWav();
|
|
#define INSTANT_RECORD_DATA 1
|
|
#define VECTOR_SIZE 640 * 1000 //20ms--640k, 20s--1000*640
|
|
|
|
namespace mobvoi {
|
|
namespace sds {
|
|
|
|
class OnlineRecognizerDemo::RecognizerCallBack : public CallBackBase {
|
|
|
|
public:
|
|
explicit RecognizerCallBack(OnlineRecognizerDemo* recognizer)
|
|
: recognizer_(recognizer) {}
|
|
|
|
virtual void CallBack(const Parameter& param) {
|
|
|
|
|
|
std::string cb_type = param[MOBVOI_SDS_CB_TYPE].AsString();
|
|
std::string cb_typeDisp= UTF8ToGBK(cb_type.c_str());
|
|
|
|
int cb_ec = 0;
|
|
std::string cb_info;
|
|
std::string cb_info_temp;
|
|
|
|
if (param.HasParam(MOBVOI_SDS_ERROR_CODE)) {
|
|
cb_ec = param[MOBVOI_SDS_ERROR_CODE].AsInt();
|
|
}
|
|
|
|
gTtsStrGlobal = "";
|
|
if (param.HasParam(MOBVOI_SDS_CB_INFO)) {
|
|
//cb_info = param[MOBVOI_SDS_CB_INFO].AsString();
|
|
cb_info_temp = param[MOBVOI_SDS_CB_INFO].AsString();
|
|
cb_info = UTF8ToGBK(cb_info_temp.c_str());
|
|
}
|
|
|
|
std::cerr << "RecognizerCallBack::CallBack() invoked: type:" << cb_typeDisp.c_str()<<" info:" << cb_info<< std::endl << std::flush;
|
|
//std::cerr << param << std::endl;
|
|
|
|
/////////type//////
|
|
if (MOBVOI_SDS_CB_ERROR == cb_type) {
|
|
gFinishRecording = true;
|
|
std::cout << "识别异常, 错误码是: " << cb_ec << std::endl;
|
|
|
|
std::string temp1;
|
|
std::stringstream ss;
|
|
ss << cb_ec;
|
|
ss >> temp1;
|
|
std::string temp2 = cb_typeDisp + ": " + temp1;
|
|
recognizer_->callCSharp(-1, cb_typeDisp.c_str(), temp2.c_str());
|
|
//recognizer_->callCSharp(1, cb_typeDisp.c_str());
|
|
recognizer_->Notify();
|
|
}
|
|
else if (MOBVOI_SDS_CB_FINAL_TRANSCRIPT == cb_type) {
|
|
gFinishRecording = true;
|
|
std::cout << "语音识别结果: " << cb_info << std::endl;
|
|
recognizer_->callCSharp(0, cb_typeDisp.c_str(), cb_info.c_str());
|
|
}
|
|
else if (MOBVOI_SDS_CB_PARTIAL_TRANSCRIPT == cb_type) {
|
|
gFinishRecording = false;
|
|
std::cout << std::endl;
|
|
std::cout << "中间识别结果: " << cb_info << std::endl;
|
|
recognizer_->callCSharp(0, cb_typeDisp.c_str(),cb_info.c_str());
|
|
}
|
|
else if (MOBVOI_SDS_CB_REMOTE_SILENCE == cb_type) {
|
|
//gFinishRecording = true;
|
|
std::cout << "检测不到声音了:" << std::endl;
|
|
//recognizer_->callCSharp(0, cb_typeDisp.c_str(), "silence detected");
|
|
}
|
|
else if (MOBVOI_SDS_CB_RESULT == cb_type) {
|
|
gFinishRecording = true;
|
|
std::cout << std::endl;
|
|
std::cout << "语义分析查询结果: " << cb_info << std::endl;
|
|
|
|
//播放displayText内容
|
|
gTtsStrGlobal = "";
|
|
int index = cb_info_temp.find("displayText");
|
|
if (index > 0) {
|
|
int start = index + 14;
|
|
int len = cb_info_temp.length() - index - 15;
|
|
std::string sub1 = cb_info_temp.substr(start, len);
|
|
|
|
index = sub1.find("\",\"");
|
|
if (index > 0) {
|
|
std::string sub2 = sub1.substr(0, index);
|
|
//if (sub2.length() > 200) {
|
|
// gTtsStrGlobal = sub2.substr(0, 200);
|
|
//}
|
|
//else {
|
|
gTtsStrGlobal = sub2;
|
|
//}
|
|
|
|
}
|
|
}
|
|
if (gTtsStrGlobal == "") {
|
|
std::string temp = "未找到合适的查询结果";//以.结束
|
|
gTtsStrGlobal = GBKToUTF8(temp);
|
|
}
|
|
//
|
|
recognizer_->callCSharp(0, cb_typeDisp.c_str(),cb_info.c_str());
|
|
recognizer_->Notify();
|
|
}
|
|
else if (MOBVOI_SDS_CB_NLU == cb_type) {
|
|
gFinishRecording = true;
|
|
std::cout << "MOBVOI_SDS_CB_NLU: " << cb_info << std::endl;
|
|
|
|
}
|
|
else if (MOBVOI_SDS_CB_VOLUME == cb_type) {
|
|
gFinishRecording = false;
|
|
std::cout << "MOBVOI_SDS_CB_VOLUME: " << cb_info << std::endl;
|
|
|
|
}
|
|
else {
|
|
gFinishRecording = true;
|
|
std::cerr << "Error: Unknown callback type " << cb_type << std::endl;
|
|
//recognizer_->callCSharp(3, "Unknown error");
|
|
recognizer_->callCSharp(-1, cb_typeDisp.c_str(),cb_typeDisp.c_str());
|
|
recognizer_->Notify();////
|
|
}
|
|
}
|
|
|
|
OnlineRecognizerDemo* recognizer_;
|
|
//private:
|
|
|
|
};
|
|
|
|
|
|
#ifdef UNICODE
|
|
std::string tchar2string(TCHAR *STR)
|
|
{
|
|
int iLen = WideCharToMultiByte(CP_ACP, 0, STR, -1, NULL, 0, NULL, NULL);
|
|
char* chRtn = new char[iLen * sizeof(char)];
|
|
WideCharToMultiByte(CP_ACP, 0, STR, -1, chRtn, iLen, NULL, NULL);
|
|
std::string str(chRtn);
|
|
delete chRtn;
|
|
return str;
|
|
}
|
|
#endif
|
|
|
|
std::string getCurrentDir() {
|
|
|
|
TCHAR currentPath[MAX_PATH]; // Full path
|
|
GetCurrentDirectory(MAX_PATH, currentPath);
|
|
#ifdef UNICODE
|
|
return tchar2string(currentPath);
|
|
#else
|
|
return currentPath;
|
|
#endif
|
|
}
|
|
|
|
OnlineRecognizerDemo::OnlineRecognizerDemo()
|
|
: service_(nullptr),
|
|
service_type_(""),
|
|
stop_(false),
|
|
enablePartial_(false),
|
|
mutex_(PTHREAD_MUTEX_INITIALIZER),
|
|
cond_(PTHREAD_COND_INITIALIZER),
|
|
sds_(nullptr) {
|
|
sds_ = SpeechSDS::MakeInstance();
|
|
|
|
gSdkConfigBasePath = getCurrentDir() + "\\config";
|
|
|
|
WSADATA data;
|
|
if (WSAStartup(MAKEWORD(1, 1), &data) != 0)
|
|
{
|
|
std::cerr << "Could not initialise Winsock:" << stderr << std::endl;
|
|
}
|
|
gWaveData.reserve(VECTOR_SIZE);
|
|
|
|
}
|
|
|
|
OnlineRecognizerDemo::~OnlineRecognizerDemo() {
|
|
pthread_mutex_destroy(&mutex_);
|
|
pthread_cond_destroy(&cond_);
|
|
SpeechSDS::DestroyInstance(sds_);
|
|
|
|
WSACleanup();
|
|
}
|
|
|
|
void RecordTask()
|
|
{
|
|
recordAndSaveWav();
|
|
}
|
|
|
|
void OnlineRecognizerDemo::setRecognitionParams(bool enablePartial) {
|
|
enablePartial_ = enablePartial;
|
|
std::cerr << "setRecognitionParams:" << enablePartial_ << std::endl;
|
|
}
|
|
|
|
bool OnlineRecognizerDemo::startRecognition() {
|
|
bool res = false;
|
|
gWaveData.clear();
|
|
gFinishRecording = false;
|
|
|
|
std::thread recorderThread(RecordTask);
|
|
Sleep(100);
|
|
//recordAndSaveWav();
|
|
res = Run(0, NULL);
|
|
|
|
if (recorderThread.joinable()) {
|
|
recorderThread.join();
|
|
}
|
|
|
|
std::cerr << "Recognition finished" << std::endl;
|
|
pCallback->recognizer_ = NULL;
|
|
return res;
|
|
}
|
|
|
|
bool OnlineRecognizerDemo::startRecognition(void* Function) {
|
|
cSharpCallback = (ResultCallbackType)(Function);
|
|
|
|
bool res = startRecognition();
|
|
return res;
|
|
}
|
|
|
|
void OnlineRecognizerDemo::callCSharp(int code, const char * type, const char * info ) {
|
|
if (cSharpCallback != nullptr) {
|
|
std::cerr << " code:" << code <<" type:"<<type << " info:" << info << std::endl;
|
|
cSharpCallback(code,type, info);
|
|
}
|
|
}
|
|
|
|
//test
|
|
int OnlineRecognizerDemo::Add(int a, int b) {
|
|
return a + b;
|
|
}
|
|
|
|
void OnlineRecognizerDemo::WriteMessage(int number , void* Function)
|
|
{
|
|
WriteMessageType WriteMessageFunc = (WriteMessageType)(Function);
|
|
std::cerr <<" before callback" << std::endl;
|
|
WriteMessageFunc(number);
|
|
std::cerr << " after callback" << std::endl;
|
|
}
|
|
|
|
bool OnlineRecognizerDemo::Run(int argc, char* argv[]) {
|
|
if (!ParseCmdArgs(argc, argv)) {
|
|
return false;
|
|
}
|
|
|
|
if (!InitEnv()) {
|
|
std::cerr << "InitEnv failed." << std::endl;
|
|
return false;
|
|
}
|
|
|
|
if (!GetService()) {
|
|
std::cerr << "GetService failed." << std::endl;
|
|
return false;
|
|
}
|
|
|
|
if (!InvokeService()) {
|
|
std::cerr << "InvokeService failed." << std::endl;
|
|
return false;
|
|
}
|
|
|
|
if (!ReleaseService()) {
|
|
std::cerr << "ReleaseService failed." << std::endl;
|
|
return false;
|
|
}
|
|
|
|
if (!ReleaseEnv()) {
|
|
std::cerr << "ReleaseEnv failed." << std::endl;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void OnlineRecognizerDemo::Notify() {
|
|
pthread_mutex_lock(&mutex_);
|
|
stop_ = true;
|
|
pthread_cond_signal(&cond_);
|
|
pthread_mutex_unlock(&mutex_);
|
|
}
|
|
|
|
const std::string& OnlineRecognizerDemo::GetType() const {
|
|
return service_type_;
|
|
}
|
|
|
|
void OnlineRecognizerDemo::SetType(const std::string& type) {
|
|
service_type_ = "MOBVOI_SDS_ONLINE_" + type;
|
|
}
|
|
|
|
|
|
bool OnlineRecognizerDemo::ParseCmdArgs(int argc, char* argv[]) {
|
|
|
|
const char* path = gSdkConfigBasePath.c_str();
|
|
struct stat info;
|
|
if (stat(path, &info) != 0) {
|
|
std::cerr << "Error: Cannot access " << path << std::endl;
|
|
return false;
|
|
}
|
|
else if (!(info.st_mode & S_IFDIR)) {
|
|
std::cerr << "Error: " << path << " is not a directory" << std::endl;
|
|
return false;
|
|
}
|
|
base_dir_ = path;
|
|
|
|
//std::string type = argv[2];
|
|
std::string type = "ONEBOX";
|
|
//if (type != "ASR" && type != "ONEBOX" && type != "SEMANTIC") {
|
|
// return false;
|
|
//}
|
|
SetType(type);
|
|
|
|
//path = argv[3];
|
|
|
|
std::string filename;
|
|
filename = base_dir_ + "\\recordTest.wav";
|
|
|
|
path = filename.c_str();
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OnlineRecognizerDemo::InitEnv() {
|
|
Parameter params(MOBVOI_SDS_INIT);
|
|
params[MOBVOI_SDS_BASE_DIR] = base_dir_.c_str();
|
|
//params[MOBVOI_SDS_BASE_DIR] = GBKToUTF8(base_dir_).c_str();
|
|
|
|
|
|
params[MOBVOI_SDS_LOG_LEVEL] = 0;
|
|
params[MOBVOI_SDS_VLOG_LEVEL] = 4;
|
|
std::string filename = gSdkConfigBasePath + "\\asr_log.txt";
|
|
|
|
std::cerr << "config basedir is: " << base_dir_ <<std::endl;
|
|
//params[MOBVOI_SDS_LOG_FILE] = GBKToUTF8(filename).c_str();
|
|
params[MOBVOI_SDS_LOG_FILE] = filename.c_str();
|
|
|
|
return sds_->Init(params);
|
|
}
|
|
|
|
bool OnlineRecognizerDemo::GetService() {
|
|
service_ = sds_->GetService(service_type_);
|
|
|
|
return (service_ != nullptr);
|
|
}
|
|
|
|
bool OnlineRecognizerDemo::InvokeService() {
|
|
bool res1 = InvokeSetParamService();
|
|
|
|
bool res2 = InvokeStartService();
|
|
|
|
bool res3 = InvokeFeedSpeech();
|
|
bool res4 = InvokeStopService();
|
|
|
|
return (res1 && res2 && res3 && res4);
|
|
}
|
|
|
|
bool OnlineRecognizerDemo::InvokeSetParamService() {
|
|
Parameter params(MOBVOI_SDS_SET_PARAM);
|
|
static RecognizerCallBack callback(NULL);
|
|
pCallback = &callback;
|
|
pCallback->recognizer_ = this;
|
|
params[MOBVOI_SDS_CALLBACK] = &callback;
|
|
|
|
//params[MOBVOI_SDS_REMOTE_START_SILENCE] = 5000;
|
|
//params[MOBVOI_SDS_REMOTE_END_SILENCE] = 1000;
|
|
//params[MOBVOI_SDS_ENABLE_CB_PARTIAL] = true;
|
|
//params[MOBVOI_SDS_ENABLE_CB_VOLUME] = false;
|
|
|
|
params[MOBVOI_SDS_REMOTE_START_SILENCE] = 5000;
|
|
params[MOBVOI_SDS_REMOTE_END_SILENCE] = 1000;
|
|
std::cerr << "InvokeSetParamService setRecognitionParams:" << enablePartial_ << std::endl;
|
|
params[MOBVOI_SDS_ENABLE_CB_PARTIAL] = enablePartial_;
|
|
params[MOBVOI_SDS_ENABLE_CB_VOLUME] = false;
|
|
|
|
Parameter result = service_->Invoke(params);
|
|
if (result[MOBVOI_SDS_ERROR_CODE].AsInt() != MOBVOI_SDS_SUCCESS) {
|
|
std::cerr << "Set parameter error: "
|
|
<< result[MOBVOI_SDS_ERROR_CODE].AsInt()
|
|
<< std::endl;
|
|
gTtsStrGlobal = "设置参数失败";
|
|
callCSharp(-1, "SDK_INIT_ERROR", "设置参数失败");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OnlineRecognizerDemo::InvokeStartService() {
|
|
Parameter params(MOBVOI_SDS_START);
|
|
|
|
Parameter result = service_->Invoke(params);
|
|
if (result[MOBVOI_SDS_ERROR_CODE].AsInt() != MOBVOI_SDS_SUCCESS) {
|
|
std::cerr << "Start error: "
|
|
<< result[MOBVOI_SDS_ERROR_CODE].AsInt()
|
|
<< std::endl;
|
|
gTtsStrGlobal = "启动识别失败,授权可能过期";
|
|
callCSharp(-1, "SDK_INIT_ERROR", "MOBVOI_SDS_START失败,license可能过期了");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool OnlineRecognizerDemo::InvokeFeedSpeech() {
|
|
Parameter params(MOBVOI_SDS_FEED_SPEECH);
|
|
|
|
const int kBatchSize = 640;
|
|
const int kSleepTime =10 * 1000;
|
|
|
|
gPMutex = PTHREAD_MUTEX_INITIALIZER;
|
|
gPCondition = PTHREAD_COND_INITIALIZER;
|
|
|
|
size_t pos = 0;
|
|
//size_t length = waves_.size();
|
|
//auto* start = &waves_[0];
|
|
size_t length = gWaveData.size();
|
|
char* start = NULL;
|
|
if (length > 0) {
|
|
start = &gWaveData[0];
|
|
}
|
|
while ((pos < length)/* && (!gFinishRecording)*/ ) {
|
|
pthread_mutex_lock(&mutex_);
|
|
if (stop_) {
|
|
pthread_mutex_unlock(&mutex_);
|
|
break;
|
|
}
|
|
pthread_mutex_unlock(&mutex_);
|
|
|
|
size_t stride = (pos + kBatchSize < length) ? kBatchSize : (length - pos);
|
|
Buf audio_buf(start + pos, stride);
|
|
params[MOBVOI_SDS_AUDIO_BUF] = audio_buf;
|
|
Parameter result = service_->Invoke(params);
|
|
if (result[MOBVOI_SDS_ERROR_CODE].AsInt() != MOBVOI_SDS_SUCCESS) {
|
|
std::cerr << "Error: service->Invoke: "
|
|
<< result[MOBVOI_SDS_ERROR_CODE].AsInt()
|
|
<< std::endl;
|
|
return false;
|
|
}
|
|
|
|
//std::this_thread::sleep_for(std::chrono::milliseconds(kSleepTime / 1000));
|
|
|
|
if (!gFinishRecording) {
|
|
std::unique_lock<std::mutex> lock(gMutex);
|
|
gCondition.wait(lock);
|
|
lock.unlock();
|
|
}
|
|
|
|
/*
|
|
while (!gFinishRecording) {
|
|
|
|
std::unique_lock<std::mutex> lock(gMutex);
|
|
|
|
size_t lengthTemp = gWaveData.size();
|
|
if (lengthTemp - length < 640) {
|
|
gCondition.wait(lock);
|
|
}
|
|
else {
|
|
break;
|
|
lock.unlock();
|
|
}
|
|
|
|
lock.unlock();
|
|
}
|
|
|
|
|
|
if (!gFinishRecording) {
|
|
std::unique_lock<std::mutex> lock(gMutex);
|
|
gCondition.wait(lock);
|
|
lock.unlock();
|
|
}
|
|
|
|
pthread_mutex_lock(&gPMutex);
|
|
if (!gFinishRecording) {
|
|
pthread_cond_wait(&gPCondition, &gPMutex);
|
|
}
|
|
pthread_mutex_unlock(&gPMutex);
|
|
*/
|
|
|
|
|
|
length = gWaveData.size();
|
|
|
|
|
|
|
|
pos += stride;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool OnlineRecognizerDemo::InvokeStopService() {
|
|
Parameter params(MOBVOI_SDS_STOP);
|
|
Parameter result = service_->Invoke(params);
|
|
if (result[MOBVOI_SDS_ERROR_CODE].AsInt() != MOBVOI_SDS_SUCCESS) {
|
|
std::cerr << "Invoke SDS_ASR_STOP error: "
|
|
<< result[MOBVOI_SDS_ERROR_CODE].AsInt()
|
|
<< std::endl;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool OnlineRecognizerDemo::ReleaseService() {
|
|
pthread_mutex_lock(&mutex_);
|
|
if (!stop_) {
|
|
pthread_cond_wait(&cond_, &mutex_);
|
|
}
|
|
pthread_mutex_unlock(&mutex_);
|
|
|
|
if (sds_->ReleaseService(service_)) {
|
|
service_ = nullptr;
|
|
return true;
|
|
}
|
|
else {
|
|
std::cout << "Failed releasing service " << service_type_ << std::endl;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool OnlineRecognizerDemo::ReleaseEnv() {
|
|
return sds_->CleanUp();
|
|
}
|
|
|
|
void OnlineRecognizerDemo::ShowUsage(const std::string& exe) {
|
|
std::cerr << "Usage: "<< std::endl;
|
|
}
|
|
|
|
} // namespace sds
|
|
} // namespace mobvoi
|
|
|
|
|