内容简介:在最近的项目中,需要完成这样一个功能,要求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目录:
说明编译成功。若为成功,请详细检查 两个 binding.gyp中的目录是否对应正确,注:使用node-gyp需要 python27环境,必须为此版本
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 模块
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
实用Common Lisp编程
Peter Seibel / 田春 / 人民邮电出版社 / 2011-10 / 89.00元
由塞贝尔编著的《实用Common Lisp编程》是一本不同寻常的Common Lisp入门书。《实用Common Lisp编程》首先从作者的学习经过及语言历史出发,随后用21个章节讲述了各种基础知识,主要包括:REPL及Common Lisp的各种实现、S-表达式、函数与变量、标准宏与自定义宏、数字与字符以及字符串、集合与向量、列表处理、文件与文件I/O处理、类、FORMAT格式、符号与包,等等。......一起来看看 《实用Common Lisp编程》 这本书的介绍吧!
Markdown 在线编辑器
Markdown 在线编辑器
正则表达式在线测试
正则表达式在线测试