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

//
//#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