基本思想:需要将声纹识别的demo集成到项目中,奈何官方只提供了py版本和java版本,需要c++版本,逐开发和记录一下,只是简单复现其py代码
一、官方代码的和手册的地址声纹识别 API 文档 | 讯飞开放平台文档中心
?这里将py代码贴一下
import base64
import hashlib
import hmac
import json
from datetime import datetime
from time import mktime
from urllib.parse import urlencode
from wsgiref.handlers import format_date_time
import requests
# 填写在开放平台申请的APPID、APIKey、APISecret
# 相应编码音频base64编码后数据(不超过4M)
class Gen_req_url(object):
"""生成请求的url"""
def sha256base64(self, data):
sha256 = hashlib.sha256()
sha256.update(data)
digest = base64.b64encode(sha256.digest()).decode(encoding='utf-8')
return digest
def parse_url(self, requset_url):
stidx = requset_url.index("://")
host = requset_url[stidx + 3:]
# self.schema = requset_url[:stidx + 3]
edidx = host.index("/")
if edidx <= 0:
raise Exception("invalid request url:" + requset_url)
self.path = host[edidx:]
self.host = host[:edidx]
# build websocket auth request url
def assemble_ws_auth_url(self, requset_url, api_key, api_secret, method="GET"):
self.parse_url(requset_url)
now = datetime.now()
date = format_date_time(mktime(now.timetuple()))
#date = "Wed, 12 Oct 2022 09:22:43 GMT"
signature_origin = "host: {}\ndate: {}\n{} {} HTTP/1.1".format(self.host, date, method, self.path)
signature_sha = hmac.new(api_secret.encode('utf-8'), signature_origin.encode('utf-8'),
digestmod=hashlib.sha256).digest()
print(hmac.new(api_secret.encode('utf-8'), signature_origin.encode('utf-8'),
digestmod=hashlib.sha256).hexdigest())
signature_sha = base64.b64encode(signature_sha).decode(encoding='utf-8')
authorization_origin = "api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"" % (
api_key, "hmac-sha256", "host date request-line", signature_sha)
print(authorization_origin)
authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')
values = {
"host": self.host,
"date": date,
"authorization": authorization
}
x=requset_url + "?" + urlencode(values)
print(x)
return x
def gen_req_body(apiname, APPId, file_path=None):
"""
生成请求的body
:param apiname
:param APPId: Appid
:param file_name: 文件路径
:return:
"""
if apiname == 'createFeature':
with open(file_path, "rb") as f:
audioBytes = f.read()
body = {
"header": {
"app_id": APPId,
"status": 3
},
"parameter": {
"s782b4996": {
"func": "createFeature",
"groupId": "iFLYTEK_examples_groupId",
"featureId": "iFLYTEK_examples_featureId",
"featureInfo": "iFLYTEK_examples_featureInfo",
"createFeatureRes": {
"encoding": "utf8",
"compress": "raw",
"format": "json"
}
}
},
"payload": {
"resource": {
"encoding": "lame",
"sample_rate": 16000,
"channels": 1,
"bit_depth": 16,
"status": 3,
"audio": str(base64.b64encode(audioBytes), 'UTF-8')
}
}
}
elif apiname == 'createGroup':
body = {
"header": {
"app_id": APPId,
"status": 3
},
"parameter": {
"s782b4996": {
"func": "createGroup",
"groupId": "iFLYTEK_examples_groupId",
"groupName": "iFLYTEK_examples_groupName",
"groupInfo": "iFLYTEK_examples_groupInfo",
"createGroupRes": {
"encoding": "utf8",
"compress": "raw",
"format": "json"
}
}
}
}
elif apiname == 'deleteFeature':
body = {
"header": {
"app_id": APPId,
"status": 3
},
"parameter": {
"s782b4996": {
"func": "deleteFeature",
"groupId": "iFLYTEK_examples_groupId",
"featureId": "iFLYTEK_examples_featureId",
"deleteFeatureRes": {
"encoding": "utf8",
"compress": "raw",
"format": "json"
}
}
}
}
elif apiname == 'queryFeatureList':
body = {
"header": {
"app_id": APPId,
"status": 3
},
"parameter": {
"s782b4996": {
"func": "queryFeatureList",
"groupId": "iFLYTEK_examples_groupId",
"queryFeatureListRes": {
"encoding": "utf8",
"compress": "raw",
"format": "json"
}
}
}
}
elif apiname == 'searchFea':
with open(file_path, "rb") as f:
audioBytes = f.read()
body = {
"header": {
"app_id": APPId,
"status": 3
},
"parameter": {
"s782b4996": {
"func": "searchFea",
"groupId": "iFLYTEK_examples_groupId",
"topK": 1,
"searchFeaRes": {
"encoding": "utf8",
"compress": "raw",
"format": "json"
}
}
},
"payload": {
"resource": {
"encoding": "lame",
"sample_rate": 16000,
"channels": 1,
"bit_depth": 16,
"status": 3,
"audio": str(base64.b64encode(audioBytes), 'UTF-8')
}
}
}
elif apiname == 'searchScoreFea':
with open(file_path, "rb") as f:
audioBytes = f.read()
body = {
"header": {
"app_id": APPId,
"status": 3
},
"parameter": {
"s782b4996": {
"func": "searchScoreFea",
"groupId": "iFLYTEK_examples_groupId",
"dstFeatureId": "iFLYTEK_examples_featureId",
"searchScoreFeaRes": {
"encoding": "utf8",
"compress": "raw",
"format": "json"
}
}
},
"payload": {
"resource": {
"encoding": "lame",
"sample_rate": 16000,
"channels": 1,
"bit_depth": 16,
"status": 3,
"audio": str(base64.b64encode(audioBytes), 'UTF-8')
}
}
}
elif apiname == 'updateFeature':
with open(file_path, "rb") as f:
audioBytes = f.read()
body = {
"header": {
"app_id": APPId,
"status": 3
},
"parameter": {
"s782b4996": {
"func": "updateFeature",
"groupId": "iFLYTEK_examples_groupId",
"featureId": "iFLYTEK_examples_featureId",
"featureInfo": "iFLYTEK_examples_featureInfo_update",
"updateFeatureRes": {
"encoding": "utf8",
"compress": "raw",
"format": "json"
}
}
},
"payload": {
"resource": {
"encoding": "lame",
"sample_rate": 16000,
"channels": 1,
"bit_depth": 16,
"status": 3,
"audio": str(base64.b64encode(audioBytes), 'UTF-8')
}
}
}
elif apiname == 'deleteGroup':
body = {
"header": {
"app_id": APPId,
"status": 3
},
"parameter": {
"s782b4996": {
"func": "deleteGroup",
"groupId": "iFLYTEK_examples_groupId",
"deleteGroupRes": {
"encoding": "utf8",
"compress": "raw",
"format": "json"
}
}
}
}
else:
raise Exception(
"输入的apiname不在[createFeature, createGroup, deleteFeature, queryFeatureList, searchFea, searchScoreFea,updateFeature]内,请检查")
return body
def req_url(api_name, APPId, APIKey, APISecret, file_path=None):
"""
开始请求
:param APPId: APPID
:param APIKey: APIKEY
:param APISecret: APISecret
:param file_path: body里的文件路径
:return:
"""
gen_req_url = Gen_req_url()
body = gen_req_body(apiname=api_name, APPId=APPId, file_path=file_path)
bodystr = json.dumps(body)
print("body=",body)
print("bodystr=",bodystr)
#https://www.sojson.com/ 添加转移字符
request_url = gen_req_url.assemble_ws_auth_url(requset_url='https://api.xf-yun.com/v1/private/s782b4996', method="POST", api_key=APIKey, api_secret=APISecret)
print(request_url)
headers = {'content-type': "application/json", 'host': 'api.xf-yun.com', 'appid': '$APPID'}
response = requests.post(request_url, data=json.dumps(body), headers=headers)
tempResult = json.loads(response.content.decode('utf-8'))
print(tempResult)
"""
* 1.声纹识别接口,请填写在讯飞开放平台-控制台-对应能力页面获取的APPID、APIKey、APISecret
* 2.groupId要先创建,然后再在createFeature里使用,不然会报错23005,修改时需要注意保持统一
* 3.音频base64编码后数据(不超过4M),音频格式需要16K、16BIT的MP3音频。
* 4.主函数只提供调用示例,其他参数请到对应类去更改,以适应实际的应用场景。
"""
if __name__ == '__main__':
APPId = "sxj"
APISecret = "sxj"
APIKey = "sxj"
file_path = '0.mp3'
# apiname取值:
# 1.创建声纹特征库 createGroup
# 2.添加音频特征 createFeature
# 3.查询特征列表 queryFeatureList
# 4.特征比对1:1 searchScoreFea
# 5.特征比对1:N searchFea
# 6.更新音频特征 updateFeature
# 7.删除指定特征 deleteFeature
# 8.删除声纹特征库 deleteGroup
req_url(api_name='createFeature', APPId=APPId,
APIKey=APIKey, APISecret=APISecret, file_path=file_path)
填入对应的APPId、 APISecret、 APIKey,返回结果
{'header': {'code': 0, 'message': 'success', 'sid': '**@***'}, 'payload': {'createFeatureRes': {'compress': 'raw', 'encoding': 'utf8', 'format': 'json', 'status': '3', 'text': 'eyJmZWF0dXJlSWQiOiJpRkxZVEVLX2V4YW1wbGVzX2ZlYXR1cmVJZCJ9'}}}
二、c++代码复现,自己优化去~
cmakelists.txt
cmake_minimum_required(VERSION 3.16)
project(audio_feature)
set(CMAKE_CXX_STANDARD 14)
include_directories(${CMAKE_SOURCE_DIR}/include)
add_executable(audio_feature main.cpp hmacsha256.cpp hmacsha256.h Base64.cpp Base64.h url.cpp url.h)
target_link_libraries(audio_feature -lcurl)
c++代码的main.cpp函数
#include<stdio.h>
#include<curl/curl.h>
#include "string.h"
#include <locale>
#include <codecvt>
#include <string>
#include <iostream>
#include <fstream>
#include "hmacsha256.h"
#include "Base64.h"
#include "url.h"
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
using namespace rapidjson;
std::string createGroupJson(const char *APPId) {
rapidjson::Document doc;
doc.SetObject();
rapidjson::Document::AllocatorType &allocator = doc.GetAllocator();
rapidjson::Value header(rapidjson::kStringType);
rapidjson::Document header_doc, parameter_doc, s782b4996_doc, createGroupRes_doc;
header_doc.SetObject();
parameter_doc.SetObject();
s782b4996_doc.SetObject();
createGroupRes_doc.SetObject();
rapidjson::Value app_id(rapidjson::kStringType);
std::string app_id_str = APPId;
app_id.SetString(app_id_str.c_str(), app_id_str.length(), allocator);
header_doc.AddMember("app_id", app_id, allocator);
header_doc.AddMember("status", 3, allocator);
doc.AddMember("header", header_doc, allocator);
rapidjson::Value parameter(rapidjson::kStringType);
rapidjson::Value s782b4996(rapidjson::kStringType);
rapidjson::Value func(rapidjson::kStringType);
std::string func_str = "createGroup";
func.SetString(func_str.c_str(), func_str.length(), allocator);
s782b4996_doc.AddMember("func", func, allocator);
rapidjson::Value groupId(rapidjson::kStringType);
std::string groupId_str = "iFLYTEK_examples_groupId";
groupId.SetString(groupId_str.c_str(), groupId_str.length(), allocator);
s782b4996_doc.AddMember("groupId", groupId, allocator);
rapidjson::Value groupName(rapidjson::kStringType);
std::string groupName_str = "iFLYTEK_examples_groupName";
groupName.SetString(groupName_str.c_str(), groupName_str.length(), allocator);
s782b4996_doc.AddMember("groupName", groupName, allocator);
rapidjson::Value groupInfo(rapidjson::kStringType);
std::string groupInfo_str = "iFLYTEK_examples_groupInfo";
groupInfo.SetString(groupInfo_str.c_str(), groupInfo_str.length(), allocator);
s782b4996_doc.AddMember("groupInfo", groupInfo, allocator);
rapidjson::Value encoding(rapidjson::kStringType);
std::string encoding_str = "utf8";
encoding.SetString(encoding_str.c_str(), encoding_str.length(), allocator);
createGroupRes_doc.AddMember("encoding", encoding, allocator);
rapidjson::Value raw(rapidjson::kStringType);
std::string raw_str = "raw";
raw.SetString(raw_str.c_str(), raw_str.length(), allocator);
createGroupRes_doc.AddMember("compress", raw, allocator);
rapidjson::Value json(rapidjson::kStringType);
std::string json_str = "json";
json.SetString(json_str.c_str(), json_str.length(), allocator);
createGroupRes_doc.AddMember("format", json, allocator);
s782b4996_doc.AddMember("createGroupRes", createGroupRes_doc, allocator);
parameter_doc.AddMember("s782b4996", s782b4996_doc, allocator);
doc.AddMember("parameter", parameter_doc, allocator);
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> write(buffer);
doc.Accept(write);
std::string buf_json_str = buffer.GetString();
return buf_json_str.c_str();
}
void acqure_audio_info(const char *file_path, std::string &readStr, int &audio_length) {
readStr="";
FILE *fp = fopen(file_path, "rb");
char c;
audio_length = -1;
while (!feof(fp)) //我们已在文件的末尾加上结束标志-1
{
c = fgetc(fp);
readStr = readStr + c;
audio_length++;
}
fclose(fp);
}
std::string createFeature(const char *APPId, const char *file_path) {
rapidjson::Document doc;
doc.SetObject();
rapidjson::Document::AllocatorType &allocator = doc.GetAllocator();
rapidjson::Value header(rapidjson::kStringType);
rapidjson::Document header_doc, parameter_doc, s782b4996_doc, createFeatureRes_doc, payload_doc, resource_doc;
header_doc.SetObject();
parameter_doc.SetObject();
s782b4996_doc.SetObject();
createFeatureRes_doc.SetObject();
payload_doc.SetObject();
resource_doc.SetObject();
rapidjson::Value app_id(rapidjson::kStringType);
std::string app_id_str = APPId;
app_id.SetString(app_id_str.c_str(), app_id_str.length(), allocator);
header_doc.AddMember("app_id", app_id, allocator);
header_doc.AddMember("status", 3, allocator);
doc.AddMember("header", header_doc, allocator);
rapidjson::Value parameter(rapidjson::kStringType);
rapidjson::Value s782b4996(rapidjson::kStringType);
rapidjson::Value func(rapidjson::kStringType);
std::string func_str = "createFeature";
func.SetString(func_str.c_str(), func_str.length(), allocator);
s782b4996_doc.AddMember("func", func, allocator);
rapidjson::Value groupId(rapidjson::kStringType);
std::string groupId_str = "iFLYTEK_examples_groupId";
groupId.SetString(groupId_str.c_str(), groupId_str.length(), allocator);
s782b4996_doc.AddMember("groupId", groupId, allocator);
rapidjson::Value groupName(rapidjson::kStringType);
std::string groupName_str = "iFLYTEK_examples_featureId";
groupName.SetString(groupName_str.c_str(), groupName_str.length(), allocator);
s782b4996_doc.AddMember("featureId", groupName, allocator);
rapidjson::Value groupInfo(rapidjson::kStringType);
std::string groupInfo_str = "iFLYTEK_examples_featureInfo";
groupInfo.SetString(groupInfo_str.c_str(), groupInfo_str.length(), allocator);
s782b4996_doc.AddMember("featureInfo", groupInfo, allocator);
rapidjson::Value encoding(rapidjson::kStringType);
std::string encoding_str = "utf8";
encoding.SetString(encoding_str.c_str(), encoding_str.length(), allocator);
createFeatureRes_doc.AddMember("encoding", encoding, allocator);
rapidjson::Value raw(rapidjson::kStringType);
std::string raw_str = "raw";
raw.SetString(raw_str.c_str(), raw_str.length(), allocator);
createFeatureRes_doc.AddMember("compress", raw, allocator);
rapidjson::Value json(rapidjson::kStringType);
std::string json_str = "json";
json.SetString(json_str.c_str(), json_str.length(), allocator);
createFeatureRes_doc.AddMember("format", json, allocator);
rapidjson::Value encoding_(rapidjson::kStringType);
std::string encoding__str = "lame";
encoding_.SetString(encoding__str.c_str(), encoding__str.length(), allocator);
resource_doc.AddMember("encoding", encoding_, allocator);
resource_doc.AddMember("sample_rate", 16000, allocator);
resource_doc.AddMember("channels", 1, allocator);
resource_doc.AddMember("bit_depth", 16, allocator);
resource_doc.AddMember("status", 3, allocator);
std::string readStr="";
int length_audo=-1;
acqure_audio_info(file_path,readStr,length_audo);
std::string audio_info = Base64Encode(reinterpret_cast<const unsigned char *>(readStr.c_str()), length_audo);
rapidjson::Value audio(rapidjson::kStringType);
std::string audio_str = audio_info;
audio.SetString(audio_str.c_str(), audio_str.length(), allocator);
resource_doc.AddMember("audio", audio, allocator);
payload_doc.AddMember("resource", resource_doc, allocator);
doc.AddMember("payload", payload_doc, allocator);
s782b4996_doc.AddMember("createFeatureRes", createFeatureRes_doc, allocator);
parameter_doc.AddMember("s782b4996", s782b4996_doc, allocator);
doc.AddMember("parameter", parameter_doc, allocator);
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> write(buffer);
doc.Accept(write);
std::string buf_json_str = buffer.GetString();
return buf_json_str.c_str();
}
std::string gen_req_body(const char *apiname, const char *APPId, const char *file_path) {
std::string body;
if (strcmp(apiname, "createGroup") == 0) {
body = createGroupJson(APPId);
} else if (strcmp(apiname, "createFeature") == 0) {
body = createFeature(APPId, file_path);
}
return body;
}
std::string http_gmtime() {
time_t now = time(0);
tm *gmt = gmtime(&now);
// http://en.cppreference.com/w/c/chrono/strftime
// e.g.: Sat, 22 Aug 2015 11:48:50 GMT
// 5+ 3+4+ 5+ 9+ 3 = 29
const char *fmt = "%a, %d %b %Y %H:%M:%S GMT";
char tstr[30];
strftime(tstr, sizeof(tstr), fmt, gmt);
return tstr;
}
void compute_sha_ex(unsigned char *dest, const uint8_t *msg, uint32_t mlen) {
uint8_t md[SHA256_DIGESTLEN] = {0};
SHA256_CTX sha;
sha256_init(&sha);
sha256_update(&sha, msg, mlen);
sha256_final(&sha, md);
memcpy(dest, md, SHA256_DIGESTLEN);
}
void compute_hmac_ex(unsigned char *dest, const uint8_t *key, uint32_t klen, const uint8_t *msg, uint32_t mlen) {
uint8_t md[SHA256_DIGESTLEN] = {0};
HMAC_SHA256_CTX hmac;
hmac_sha256_init(&hmac, key, klen);
hmac_sha256_update(&hmac, msg, mlen);
hmac_sha256_final(&hmac, md);
memcpy(dest, md, SHA256_DIGESTLEN);
}
std::string base64_add_encode(unsigned char *dest, int length) {
std::string base_64_out = Base64Encode(dest, length);
//std::cout << base_64_out << std::endl;
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
std::wstring wide_string = converter.from_bytes(base_64_out);
std::string signature_sha(wide_string.begin(), wide_string.end());
return signature_sha;
}
std::string make_hmac_sha256(std::string wsignature_origin, std::string wapi_secret_origin, const char *api_key) {
unsigned char dest[1024] = {0};
compute_hmac_ex(dest, (const uint8_t *) wapi_secret_origin.c_str(), wapi_secret_origin.length(),
(const uint8_t *) wsignature_origin.c_str(), wsignature_origin.length());
std::string outdata_str = sha256_toString(dest);
//std::cout << outdata_str <<" "<<outdata_str.size()<<std::endl;
//std::cout << dest << std::endl;
std::string signature_sha = base64_add_encode(dest, outdata_str.size() / 2);
//std::cout << signature_sha <<" "<< signature_sha.size()<<std::endl;
char authorization_origin[1024] = {0};
sprintf(authorization_origin, "api_key=\"%s\", algorithm=\"%s\", headers=\"%s\", signature=\"%s\"", api_key,
"hmac-sha256", "host date request-line", signature_sha.c_str());
//std::cout << authorization_origin << std::endl;
std::string str_authorization_origin = authorization_origin;
int length = str_authorization_origin.size();
std::string authorization = base64_add_encode(reinterpret_cast<unsigned char *>(authorization_origin), length);
//std::cout << authorization << std::endl;
return authorization;
}
std::string
assemble_ws_auth_url(const char *requset_url, const char *api_key, const char *api_secret, const char *method = "GET") {
std::string request_str = requset_url;
int firstPosition = request_str.find_first_of('/'); //window 使用\\ linux 使用/
std::string pre_host = request_str.substr(firstPosition + 2, request_str.size());
int secondPosition = pre_host.find_first_of('/');
std::string host = pre_host.substr(0, secondPosition);
std::string path = pre_host.substr(secondPosition, pre_host.size());
std::string data_time = http_gmtime();
//::string data_time = "Wed, 12 Oct 2022 09:22:43 GMT";
printf("%s\n", data_time.c_str());
char signature[1024];
sprintf(signature, "host: %s\ndate: %s\n%s %s HTTP/1.1", host.c_str(), data_time.c_str(), method, path.c_str());
std::string signature_origin = signature;
std::wstring wsignature(signature_origin.begin(), signature_origin.end());
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
std::string wsignature_origin = converter.to_bytes(wsignature);
std::string s_api_secret = api_secret;
std::wstring wapi_secret(s_api_secret.begin(), s_api_secret.end());
std::string wapi_secret_origin = converter.to_bytes(wapi_secret);
//在线加密测试网站
// http://www.jsons.cn/allencrypt/
std::string authorization = make_hmac_sha256(wsignature_origin, wapi_secret_origin, api_key);
char value[1024] = {0};
sprintf(value, "host=%s&date=%s&authorization=%s", host.c_str(), data_time.c_str(), authorization.c_str());
std::string append_url = UrlEncode(value);
std::string full_request_url = request_str + "?" + append_url;
//std::cout<<append_url<<std::endl;
return full_request_url;
}
void
req_url(const char *api_name, const char *APPId, const char *APIKey, const char *APISecret, const char *requset_url,
const char *file_path) {
char appid[1024] = {0};
sprintf(appid, "appid: %s", APPId);
std::string body = gen_req_body(api_name, APPId, file_path);
const char *method = "POST";
std::string request_url = assemble_ws_auth_url(requset_url, APIKey, APISecret, method);
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method);
curl_easy_setopt(curl, CURLOPT_URL, request_url.c_str());
curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, appid);
headers = curl_slist_append(headers, "content-type: application/json");
headers = curl_slist_append(headers, "host: api.xf-yun.com");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
const char *data = body.c_str();
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
res = curl_easy_perform(curl);
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
curl_easy_cleanup(curl);
}
curl_global_cleanup();
}
int main(int argc, char *argv[]) {
const char *APPId = "sxj";
const char *APISecret = "sxj";
const char *APIKey = "sxj";
//# apiname取值:
//# 1.创建声纹特征库 createGroup
//# 2.添加音频特征 createFeature
//# 3.查询特征列表 queryFeatureList
//# 4.特征比对1:1 searchScoreFea
//# 5.特征比对1:N searchFea
//# 6.更新音频特征 updateFeature
//# 7.删除指定特征 deleteFeature
//# 8.删除声纹特征库 deleteGroup
// 仅实现了两个 其他类似 不重复实现,集成项目中
//const char *api_name = "createGroup";
const char *api_name = "createFeature";
const char *file_path = "../0.mp3";
const char *request_url = "http://api.xf-yun.com/v1/private/s782b4996";
req_url(api_name, APPId, APIKey, APISecret, request_url, file_path);
return 0;
}
Base64.h
#ifndef UNTITLED2_BASE64_H
#define UNTITLED2_BASE64_H
#include <string>
std::string Base64Encode(const unsigned char* Data, int DataByte);
std::string Base64Decode(const char *Data, int DataByte);
#endif //UNTITLED2_BASE64_H
Base.cpp
#include "Base64.h"
std::string Base64Encode(const unsigned char* Data, int DataByte)
{
//编码表
const char EncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//返回值
std::string strEncode;
unsigned char Tmp[4] = { 0 };
int LineLength = 0;
for (int i = 0; i<(int)(DataByte / 3); i++)
{
Tmp[1] = *Data++;
Tmp[2] = *Data++;
Tmp[3] = *Data++;
strEncode += EncodeTable[Tmp[1] >> 2];
strEncode += EncodeTable[((Tmp[1] << 4) | (Tmp[2] >> 4)) & 0x3F];
strEncode += EncodeTable[((Tmp[2] << 2) | (Tmp[3] >> 6)) & 0x3F];
strEncode += EncodeTable[Tmp[3] & 0x3F];
if (LineLength += 4, LineLength == 76) { strEncode += "\r\n"; LineLength = 0; }
}
//对剩余数据进行编码
int Mod = DataByte % 3;
if (Mod == 1)
{
Tmp[1] = *Data++;
strEncode += EncodeTable[(Tmp[1] & 0xFC) >> 2];
strEncode += EncodeTable[((Tmp[1] & 0x03) << 4)];
strEncode += "==";
}
else if (Mod == 2)
{
Tmp[1] = *Data++;
Tmp[2] = *Data++;
strEncode += EncodeTable[(Tmp[1] & 0xFC) >> 2];
strEncode += EncodeTable[((Tmp[1] & 0x03) << 4) | ((Tmp[2] & 0xF0) >> 4)];
strEncode += EncodeTable[((Tmp[2] & 0x0F) << 2)];
strEncode += "=";
}
return strEncode;
}
std::string Base64Decode(const char *Data, int DataByte)
{
//解码表
const char DecodeTable[] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
62, // '+'
0, 0, 0,
63, // '/'
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'
0, 0, 0, 0, 0, 0, 0,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z'
0, 0, 0, 0, 0, 0,
26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z'
};
//返回值
std::string strDecode;
int nValue;
int i = 0;
while (i < DataByte)
{
if (*Data != '\r' && *Data != '\n')
{
nValue = DecodeTable[*Data++] << 18;
nValue += DecodeTable[*Data++] << 12;
strDecode += (nValue & 0x00FF0000) >> 16;
//OutByte++;
if (*Data != '=')
{
nValue += DecodeTable[*Data++] << 6;
strDecode += (nValue & 0x0000FF00) >> 8;
//OutByte++;
if (*Data != '=')
{
nValue += DecodeTable[*Data++];
strDecode += nValue & 0x000000FF;
// OutByte++;
}
}
i += 4;
}
else// 回车换行,跳过
{
Data++;
i++;
}
}
return strDecode;
}
hmachsa256.h
#ifndef _HMAC_SHA_256_H_
#define _HMAC_SHA_256_H_
#define SHA256_BLOCKLEN 64ul //size of message block buffer
#define SHA256_DIGESTLEN 32ul //size of digest in uint8_t
#define SHA256_DIGESTINT 8ul //size of digest in uint32_t
// #ifndef PBKDF2_SHA256_STATIC
// #define PBKDF2_SHA256_DEF extern
// #else
// #define PBKDF2_SHA256_DEF static
// #endif
#include <stdint.h>
#include <string.h>
#include <string>
#include <iomanip>
typedef struct sha256_ctx_t
{
uint64_t len; // processed message length
uint32_t h[SHA256_DIGESTINT]; // hash state
uint8_t buf[SHA256_BLOCKLEN]; // message block buffer
} SHA256_CTX;
void sha256_init(SHA256_CTX *ctx);
void sha256_update(SHA256_CTX *ctx, const uint8_t *m, uint32_t mlen);
// resets state: calls sha256_init
void sha256_final(SHA256_CTX *ctx, uint8_t *md);
typedef struct hmac_sha256_ctx_t
{
uint8_t buf[SHA256_BLOCKLEN]; // key block buffer, not needed after init
uint32_t h_inner[SHA256_DIGESTINT];
uint32_t h_outer[SHA256_DIGESTINT];
SHA256_CTX sha;
} HMAC_SHA256_CTX;
void hmac_sha256_init(HMAC_SHA256_CTX *hmac, const uint8_t *key, uint32_t keylen);
void hmac_sha256_update(HMAC_SHA256_CTX *hmac, const uint8_t *m, uint32_t mlen);
void hmac_sha256_final(HMAC_SHA256_CTX *hmac, uint8_t *md);
std::string sha256_toString(const uint8_t * digest);
void pbkdf2_sha256(HMAC_SHA256_CTX *ctx,const uint8_t *key, uint32_t keylen, const uint8_t *salt, uint32_t saltlen, uint32_t rounds,uint8_t *dk, uint32_t dklen);
#endif // _HMAC_SHA_256_H_
hmachsa256.cpp
#include "hmacsha256.h"
//#define ROR(n,k) ((n >> k) | (n << (32 - k)))
static uint32_t ror(uint32_t n, uint32_t k)
{
return (n >> k) | (n << (32 - k));
}
#define ROR(n,k) ror(n,k)
#define CH(x,y,z) (z ^ (x & (y ^ z)))
#define MAJ(x,y,z) ((x & y) | (z & (x | y)))
#define S0(x) (ROR(x, 2) ^ ROR(x,13) ^ ROR(x,22))
#define S1(x) (ROR(x, 6) ^ ROR(x,11) ^ ROR(x,25))
#define R0(x) (ROR(x, 7) ^ ROR(x,18) ^ (x>>3))
#define R1(x) (ROR(x,17) ^ ROR(x,19) ^ (x>>10))
static const uint32_t K[64] =
{
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
static void sha256_transform(SHA256_CTX *s, const uint8_t *buf)
{
uint32_t t1, t2, a, b, c, d, e, f, g, h, m[64];
uint32_t i, j;
for (i = 0, j = 0; i < 16; i++, j += 4)
{
m[i] = (uint32_t) buf[j] << 24 | (uint32_t) buf[j + 1] << 16 |
(uint32_t) buf[j + 2] << 8 | (uint32_t) buf[j + 3];
}
for (; i < 64; i++)
{
m[i] = R1(m[i - 2]) + m[i - 7] + R0(m[i - 15]) + m[i - 16];
}
a = s->h[0];
b = s->h[1];
c = s->h[2];
d = s->h[3];
e = s->h[4];
f = s->h[5];
g = s->h[6];
h = s->h[7];
for (i = 0; i < 64; i++)
{
t1 = h + S1(e) + CH(e, f, g) + K[i] + m[i];
t2 = S0(a) + MAJ(a, b, c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
s->h[0] += a;
s->h[1] += b;
s->h[2] += c;
s->h[3] += d;
s->h[4] += e;
s->h[5] += f;
s->h[6] += g;
s->h[7] += h;
}
void sha256_init(SHA256_CTX *s)
{
s->len = 0;
s->h[0] = 0x6a09e667;
s->h[1] = 0xbb67ae85;
s->h[2] = 0x3c6ef372;
s->h[3] = 0xa54ff53a;
s->h[4] = 0x510e527f;
s->h[5] = 0x9b05688c;
s->h[6] = 0x1f83d9ab;
s->h[7] = 0x5be0cd19;
}
void sha256_final(SHA256_CTX *s, uint8_t *md)
{
uint32_t r = s->len % SHA256_BLOCKLEN;
int i;
//pad
s->buf[r++] = 0x80;
if (r > 56)
{
memset(s->buf + r, 0, SHA256_BLOCKLEN - r);
r = 0;
sha256_transform(s, s->buf);
}
memset(s->buf + r, 0, 56 - r);
s->len *= 8;
s->buf[56] = s->len >> 56;
s->buf[57] = s->len >> 48;
s->buf[58] = s->len >> 40;
s->buf[59] = s->len >> 32;
s->buf[60] = s->len >> 24;
s->buf[61] = s->len >> 16;
s->buf[62] = s->len >> 8;
s->buf[63] = s->len;
sha256_transform(s, s->buf);
for (i = 0; i < SHA256_DIGESTINT; i++)
{
md[4 * i ] = s->h[i] >> 24;
md[4 * i + 1] = s->h[i] >> 16;
md[4 * i + 2] = s->h[i] >> 8;
md[4 * i + 3] = s->h[i];
}
sha256_init(s);
}
void sha256_update(SHA256_CTX *s, const uint8_t *m, uint32_t len)
{
const uint8_t *p = m;
uint32_t r = s->len % SHA256_BLOCKLEN;
s->len += len;
if (r)
{
if (len + r < SHA256_BLOCKLEN)
{
memcpy(s->buf + r, p, len);
return;
}
memcpy(s->buf + r, p, SHA256_BLOCKLEN - r);
len -= SHA256_BLOCKLEN - r;
p += SHA256_BLOCKLEN - r;
sha256_transform(s, s->buf);
}
for (; len >= SHA256_BLOCKLEN; len -= SHA256_BLOCKLEN, p += SHA256_BLOCKLEN)
{
sha256_transform(s, p);
}
memcpy(s->buf, p, len);
}
#define INNER_PAD '\x36'
#define OUTER_PAD '\x5c'
std::string sha256_toString(const uint8_t * digest) {
std::stringstream s;
s << std::setfill('0') << std::hex;
for(uint8_t i = 0 ; i < 32 ; i++) {
s << std::setw(2) << (unsigned int) digest[i];
}
return s.str();
}
void hmac_sha256_init(HMAC_SHA256_CTX *hmac, const uint8_t *key, uint32_t keylen)
{
SHA256_CTX *sha = &hmac->sha;
uint32_t i;
if (keylen <= SHA256_BLOCKLEN)
{
memcpy(hmac->buf, key, keylen);
memset(hmac->buf + keylen, '\0', SHA256_BLOCKLEN - keylen);
}
else
{
sha256_init(sha);
sha256_update(sha, key, keylen);
sha256_final(sha, hmac->buf);
memset(hmac->buf + SHA256_DIGESTLEN, '\0', SHA256_BLOCKLEN - SHA256_DIGESTLEN);
}
for (i = 0; i < SHA256_BLOCKLEN; i++)
{
hmac->buf[ i ] = hmac->buf[ i ] ^ OUTER_PAD;
}
sha256_init(sha);
sha256_update(sha, hmac->buf, SHA256_BLOCKLEN);
// copy outer state
memcpy(hmac->h_outer, sha->h, SHA256_DIGESTLEN);
for (i = 0; i < SHA256_BLOCKLEN; i++)
{
hmac->buf[ i ] = (hmac->buf[ i ] ^ OUTER_PAD) ^ INNER_PAD;
}
sha256_init(sha);
sha256_update(sha, hmac->buf, SHA256_BLOCKLEN);
// copy inner state
memcpy(hmac->h_inner, sha->h, SHA256_DIGESTLEN);
}
void hmac_sha256_update(HMAC_SHA256_CTX *hmac, const uint8_t *m, uint32_t mlen)
{
sha256_update(&hmac->sha, m, mlen);
}
void hmac_sha256_final(HMAC_SHA256_CTX *hmac, uint8_t *md)
{
SHA256_CTX *sha = &hmac->sha;
sha256_final(sha, md);
// reset sha to outer state
memcpy(sha->h, hmac->h_outer, SHA256_DIGESTLEN);
sha->len = SHA256_BLOCKLEN;
sha256_update(sha, md, SHA256_DIGESTLEN);
sha256_final(sha, md); // md = D(outer || D(inner || msg))
// reset sha to inner state -> reset hmac
memcpy(sha->h, hmac->h_inner, SHA256_DIGESTLEN);
sha->len = SHA256_BLOCKLEN;
}
void pbkdf2_sha256(HMAC_SHA256_CTX *hmac,
const uint8_t *key, uint32_t keylen, const uint8_t *salt, uint32_t saltlen, uint32_t rounds,
uint8_t *dk, uint32_t dklen)
{
uint8_t *U;
uint8_t *T;
uint8_t count[4];
uint32_t i, j, k;
uint32_t len;
uint32_t hlen = SHA256_DIGESTLEN;
uint32_t l = dklen / hlen + ((dklen % hlen) ? 1 : 0);
uint32_t r = dklen - (l - 1) * hlen;
hmac_sha256_init(hmac, key, keylen);
U = hmac->buf;
T = dk;
len = hlen;
for (i = 1; i <= l; i++)
{
if (i == l) { len = r; }
count[0] = (i >> 24) & 0xFF;
count[1] = (i >> 16) & 0xFF;
count[2] = (i >> 8) & 0xFF;
count[3] = (i) & 0xFF;
hmac_sha256_update(hmac, salt, saltlen);
hmac_sha256_update(hmac, count, 4);
hmac_sha256_final(hmac, U);
memcpy(T, U, len);
for (j = 1; j < rounds; j++)
{
hmac_sha256_update(hmac, U, hlen);
hmac_sha256_final(hmac, U);
for (k = 0; k < len; k++)
{
T[k] ^= U[k];
}
}
T += len;
}
}
url.h
#ifndef UNTITLED2_URL_H
#define UNTITLED2_URL_H
#include <cassert>
#include <string>
unsigned char ToHex(unsigned char x);
unsigned char FromHex(unsigned char x);
std::string UrlEncode(const std::string& str);
std::string UrlDecode(const std::string& str);
#endif //UNTITLED2_URL_H
url.cpp
//
// Created by ubuntu on 2022/10/12.
//
#include "url.h"
unsigned char ToHex(unsigned char x)
{
return x > 9 ? x + 55 : x + 48;
}
unsigned char FromHex(unsigned char x)
{
unsigned char y;
if (x >= 'A' && x <= 'Z') y = x - 'A' + 10;
else if (x >= 'a' && x <= 'z') y = x - 'a' + 10;
else if (x >= '0' && x <= '9') y = x - '0';
else assert(0);
return y;
}
std::string UrlEncode(const std::string& str)
{
std::string strTemp = "";
size_t length = str.length();
for (size_t i = 0; i < length; i++)
{
if (isalnum((unsigned char)str[i]) ||
(str[i] == '-') ||
(str[i] == '_') ||
(str[i] == '.') ||
(str[i] == '~'))
strTemp += str[i];
else if (str[i] == ' ')
strTemp += "+";
///sxj731533730 添加
else if(str[i]=='\r')
continue;
else if(str[i]=='\n')
continue;
else if(str[i]=='=')
strTemp +='=';
else if(str[i]=='&')
strTemp+='&';
///sxj731533730 添加
else
{
strTemp += '%';
strTemp += ToHex((unsigned char)str[i] >> 4);
strTemp += ToHex((unsigned char)str[i] % 16);
}
}
return strTemp;
}
std::string UrlDecode(const std::string& str)
{
std::string strTemp = "";
size_t length = str.length();
for (size_t i = 0; i < length; i++)
{
if (str[i] == '+') strTemp += ' ';
else if (str[i] == '%')
{
assert(i + 2 < length);
unsigned char high = FromHex((unsigned char)str[++i]);
unsigned char low = FromHex((unsigned char)str[++i]);
strTemp += high*16 + low;
}
else strTemp += str[i];
}
return strTemp;
}
测试结果
/home/ubuntu/audio_feature/cmake-build-debug/audio_feature
Thu, 13 Oct 2022 02:09:36 GMT
{"header":{"code":0,"message":"success","sid":"××@×××"},"payload":{"createFeatureRes":{"compress":"raw","encoding":"utf8","format":"json","status":"3","text":"eyJmZWF0dXJlSWQiOiJpRkxZVEVLX2V4YW1wbGVzX2ZlYXR1cmVJZCJ9"}}}
Process finished with exit code 0
附上clion的文件目录
?
参考:
https://cplusplus.com/
声纹识别 API 文档 | 讯飞开放平台文档中心
|