内容简介:在最近的项目中,需要完成这样一个功能,要求app能与硬件进行语音交流,不需要实时,仅仅实现类似微信的按住说话的功能就可以。为了减少网络流量,考虑将音频文件压缩传送。成熟的压缩方式有speex、opus。目前speex已不再维护。考虑到本次需要的功能简单以及网上关于speex的文档较多的情况下,我们决定使用speex完成语音压缩功能。 我们通过node调用c++模块的方法,来实现speex的压缩(仅实现压缩,关于音频格式转换日后再码)。ps: 先水上他一篇 :)
在最近的项目中,需要完成这样一个功能,要求app能与硬件进行语音交流,不需要实时,仅仅实现类似微信的按住说话的功能就可以。为了减少网络流量,考虑将音频文件压缩传送。成熟的压缩方式有speex、opus。目前speex已不再维护。考虑到本次需要的功能简单以及网上关于speex的文档较多的情况下,我们决定使用speex完成语音压缩功能。 我们通过node调用c++模块的方法,来实现speex的压缩(仅实现压缩,关于音频格式转换日后再码)。
ps: 先水上他一篇 :)
下载speex
我们选择speex的最新稳定版本进行下载:speex-1.2.0.tar.gz
具体步骤
1、将下载的speex文件放到项目中
- 项目根目录下新建deps文件夹,并在deps中新建文件,建好目录如下:
- 图中的speex-1.2.0为下载并解压好的speex。
- 在x64文件夹中新加config.h文件 内容如下
- building.gyp中的内容如下:(此部分主要用于选择性编译speex中的文件并加载到项目中)
{
'variables': { 'target_arch%': 'x64' },
'target_defaults': {
'default_configuration': 'Debug',
'configuration': {
'Debug': {
'defines': [ 'DEBUG', '_DEBUG' ],
'msvs_settings': {
'VSSLCompilerTool': {
'RuntimeLibrary': 1, #static debug
},
},
},
'Release': {
'defines': [ 'NODEBUG' ],
'msvs_settings': {
'VSSLCompilerTool': {
'RuntimeLibrary': 0, #static release
},
},
},
},
'msvs_settings': {
'VCLinkerTool': {
'GenerateDebugInformation': 'true',
},
},
},
'targets': [
{
'target_name': 'libspeexdsp',
'type': 'static_library',
'sources': [
'speex-1.2.0/libspeex/bits.c',
'speex-1.2.0/libspeex/cb_search.c',
'speex-1.2.0/libspeex/exc_5_64_table.c',
'speex-1.2.0/libspeex/exc_5_256_table.c',
'speex-1.2.0/libspeex/exc_8_128_table.c',
'speex-1.2.0/libspeex/exc_10_16_table.c',
'speex-1.2.0/libspeex/exc_10_32_table.c',
'speex-1.2.0/libspeex/exc_20_32_table.c',
'speex-1.2.0/libspeex/filters.c',
'speex-1.2.0/libspeex/gain_table.c',
'speex-1.2.0/libspeex/gain_table_lbr.c',
'speex-1.2.0/libspeex/hexc_10_32_table.c',
'speex-1.2.0/libspeex/hexc_table.c',
'speex-1.2.0/libspeex/high_lsp_tables.c',
'speex-1.2.0/libspeex/kiss_fft.c',
'speex-1.2.0/libspeex/kiss_fftr.c',
'speex-1.2.0/libspeex/lpc.c',
'speex-1.2.0/libspeex/lsp.c',
'speex-1.2.0/libspeex/lsp_tables_nb.c',
'speex-1.2.0/libspeex/ltp.c',
'speex-1.2.0/libspeex/modes.c',
'speex-1.2.0/libspeex/modes_wb.c',
'speex-1.2.0/libspeex/nb_celp.c',
'speex-1.2.0/libspeex/quant_lsp.c',
'speex-1.2.0/libspeex/smallft.c',
'speex-1.2.0/libspeex/speex.c',
'speex-1.2.0/libspeex/speex_callbacks.c',
'speex-1.2.0/libspeex/speex_header.c',
'speex-1.2.0/libspeex/stereo.c',
'speex-1.2.0/libspeex/vbr.c',
'speex-1.2.0/libspeex/vq.c',
'speex-1.2.0/libspeex/window.c'
],
'cflags': [
'-fvisibility=hidden',
'-W',
'-Wstrict-prototypes',
'-Wno-parentheses',
'-Wno-unused-parameter',
'-Wno-sign-compare',
'-Wno-unused-variable',
],
'include_dirs': [
'config/speex-1.2.0/<(OS)/<(target_arch)',
'speex-1.2.0/include',
],
'defines': [
'PIC',
'HAVE_CONFIG_H',
'_USE_MATH_DEFINES',
]
}
]
}
复制代码
2 新加c++目录,如下图所示
此目录为我们要自己动手实现的c++代码,其中hello.cc文件内容如下:(由于编码格式错误,暂时分多段显示代码,一下代码全为hello.cc)
#include <node.h> #include <math.h> #include <stdio.h> #include <stdlib.h> 复制代码
#ifdef __cplusplus
extern "C"
{
#endif
#include <speex/speex.h>
#include <speex/speex_callbacks.h>
#ifdef __cplusplus
}
#endif
复制代码
#ifdef FIXED_DEBUG extern long long spx_mips; #endif 复制代码
#define FRAME_SIZE 160 #ifdef FIXED_DEBUG extern long long spx_mips; #endif 复制代码
using namespace v8; 复制代码
void Add(const FunctionCallbackInfo<Value>& args) {
复制代码
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
void *st;
FILE *fin,*fout;
short in[FRAME_SIZE];
float input[FRAME_SIZE];
char cbits[200];
int nbBytes;
SpeexBits bits;
int i,tmp;
st = speex_encoder_init(&speex_nb_mode);
tmp = 8;
speex_encoder_ctl(st,SPEEX_SET_QUALITY,&tmp);
Local<Value> in_addr = args[0];
Local<String> ss = in_addr->ToString();
String::Utf8Value value(ss);
char* c = *value;
fin = fopen(c,"r");
复制代码
Local<Value> out_addr = args[1];
Local<String> out_addr_str = out_addr->ToString();
String::Utf8Value value1(out_addr_str);
char* o = *value1;
fout = fopen(o,"w");
speex_bits_init(&bits);
while(1){
fread(in,sizeof(short),FRAME_SIZE,fin);
if(feof(fin))
break;
for(i = 0;i<FRAME_SIZE;i++){
input[i] = in[i];
}
speex_bits_reset(&bits);
speex_encode(st,input,&bits);
nbBytes = speex_bits_write(&bits,cbits,200);
fwrite(&nbBytes, sizeof(int), 1, stdout);
fwrite(cbits, 1, nbBytes, stdout);
fwrite(input,sizeof(short),FRAME_SIZE,fout);
}
复制代码
speex_encoder_destroy(st);
/*Destroy the bit-packing struct*/
speex_bits_destroy(&bits);
fclose(fin);
}
void Init(Handle<Object> exports) {
NODE_SET_METHOD(exports, "add", Add);
}
NODE_MODULE(hello, Init)
复制代码
3 根目录下新建binding.gyp
binding.gyp内容如下:
{
"targets": [
{
"target_name": "hello",
"sources": ["./c++/hello.cc", ],
"dependencies":[
"deps/binding.gyp:libspeexdsp"
],
'cflags': [
'-pthread',
'-fno-exceptions',
'-fno-strict-aliasing',
'-Wall',
'-Wno-unused-parameter',
'-Wno-missing-field-initializers',
'-Wextra',
'-pipe',
'-fno-ident',
'-fdata-sections',
'-ffunction-sections',
'-fPIC'
],
'defines': [
'LARGEFILE_SOURCE',
'_FILE_OFFSET_BITS=64',
'WEBRTC_TARGET_PC',
'WEBRTC_LINUX',
'WEBRTC_THREAD_RR',
'EXPAT_RELATIVE_PATH',
'GTEST_RELATIVE_PATH',
'JSONCPP_RELATIVE_PATH',
'WEBRTC_RELATIVE_PATH',
'POSIX',
'__STDC_FORMAT_MACROS',
'DYNAMIC_ANNOTATIONS_ENABLED=0'
],
'include_dirs': [
'deps/speex-1.2.0/include',
'deps/config/speex-1.2.0/<(OS)/<(target_arch)',
],
}
]
}
复制代码
4 编译
在项目根目录下运行命令
node-gyp configure node-gyp build 复制代码
如未报错并且根目录下生成build目录:
环境,必须为此版本
5 测试:
新建hello.js 文件内容如下
const hello = require('./build/Release/hello');
hello.add('male.wav', "male.test");
复制代码
文件运行后会将male.wav文件压缩,并生成male.test文件 效果如下:
最终文件目录如下
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 一种在 Library 模块中调用 Application 模块功能的方法
- Nodejs如何调用Dll模块
- Python中模块互相调用的例子
- 利用 Transform 解决模块化开发服务调用问题
- 『互联网架构』软件架构-Dubbo调用模块(46)
- NW.js 0.28 发布,Web 调用 Node 模块
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Head First HTML5 Programming
Eric Freeman、Elisabeth Robson / O'Reilly Media / 2011-10-18 / USD 49.99
What can HTML5 do for you? If you're a web developer looking to use this new version of HTML, you might be wondering how much has really changed. Head First HTML5 Programming introduces the key featur......一起来看看 《Head First HTML5 Programming》 这本书的介绍吧!
RGB转16进制工具
RGB HEX 互转工具
UNIX 时间戳转换
UNIX 时间戳转换