node中使用C++模块调用调用speex完成语音文件压缩

栏目: C++ · 发布时间: 5年前

内容简介:在最近的项目中,需要完成这样一个功能,要求app能与硬件进行语音交流,不需要实时,仅仅实现类似微信的按住说话的功能就可以。为了减少网络流量,考虑将音频文件压缩传送。成熟的压缩方式有speex、opus。目前speex已不再维护。考虑到本次需要的功能简单以及网上关于speex的文档较多的情况下,我们决定使用speex完成语音压缩功能。         我们通过node调用c++模块的方法,来实现speex的压缩(仅实现压缩,关于音频格式转换日后再码)。ps: 先水上他一篇 :)

在最近的项目中,需要完成这样一个功能,要求app能与硬件进行语音交流,不需要实时,仅仅实现类似微信的按住说话的功能就可以。为了减少网络流量,考虑将音频文件压缩传送。成熟的压缩方式有speex、opus。目前speex已不再维护。考虑到本次需要的功能简单以及网上关于speex的文档较多的情况下,我们决定使用speex完成语音压缩功能。         我们通过node调用c++模块的方法,来实现speex的压缩(仅实现压缩,关于音频格式转换日后再码)。

ps: 先水上他一篇 :)

github

下载speex

我们选择speex的最新稳定版本进行下载:speex-1.2.0.tar.gz

具体步骤

1、将下载的speex文件放到项目中

  1. 项目根目录下新建deps文件夹,并在deps中新建文件,建好目录如下:
    node中使用C++模块调用调用speex完成语音文件压缩
  2. 图中的speex-1.2.0为下载并解压好的speex。
  3. 在x64文件夹中新加config.h文件 内容如下
    node中使用C++模块调用调用speex完成语音文件压缩
  4. 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++目录,如下图所示

node中使用C++模块调用调用speex完成语音文件压缩

此目录为我们要自己动手实现的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目录:

node中使用C++模块调用调用speex完成语音文件压缩
说明编译成功。若为成功,请详细检查 两个 binding.gyp中的目录是否对应正确,注:使用node-gyp需要 python27

环境,必须为此版本

5 测试:

新建hello.js 文件内容如下

const hello = require('./build/Release/hello');
hello.add('male.wav', "male.test");
复制代码

文件运行后会将male.wav文件压缩,并生成male.test文件 效果如下:

node中使用C++模块调用调用speex完成语音文件压缩

最终文件目录如下

node中使用C++模块调用调用speex完成语音文件压缩

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Essential ActionScript 3.0

Essential ActionScript 3.0

Colin Moock / Adobe Dev Library / June 22, 2007 / $34.64

ActionScript 3.0 is a huge upgrade to Flash's programming language. The enhancements to ActionScript's performance, feature set, ease of use, cleanliness, and sophistication are considerable. Essentia......一起来看看 《Essential ActionScript 3.0》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具