Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7918902
  • 博文数量: 701
  • 博客积分: 2150
  • 博客等级: 上尉
  • 技术积分: 13233
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-29 16:28
个人简介

天行健,君子以自强不息!

文章分类

全部博文(701)

文章存档

2019年(2)

2018年(12)

2017年(76)

2016年(120)

2015年(178)

2014年(129)

2013年(123)

2012年(61)

分类: 云计算

2018-10-24 17:43:27

1. speex的降噪模块的简介
speex的语音处理模块要使用独立于 speex codec库的libspeexdsp 库。
这个分离的库是在1.2版本后实现;
它这库包括了: 预处理,回声消除,jitter buffer 和重采样模块;
在Unix/Linux环境下,使用 -lspeexdsp -lm 来编译和链接。

和libspeex一样,库libspeexdsp的库函数都是可重入函数。
但它不是线程安全的,所以在多个线程中使用同一个实例时,必须加个线程安全锁。

NOTE:
所谓就是允许被的函数。
函数的递归调用是 指当一个函数正被调用尚未返回时,又直接或间接调用函数本身。
一般的函数不能做到这样,只有重入函数才允许递归调用.



2. 下载与编译
$ tar -zxvf
$ cd speexdsp-1.2rc3
$./configure --prefix=/data/speexdsp-1.2rc3-install/ --enable-static --disable-shared --with-pic
$ make && make install


3. API简介
预处理模块需要添加头文件:
#include

创建实例:
SpeexPreprocessState *preprocess_state = speex_preprocess_state_init(frame_size,sampling_rate);
参数: frame_size , 建议设置成编码器相同的值。

对于每一个输入帧,调用处理的函数:
speex_preprocess_run(preprocess_state, audio_frame);
参数: audio_frame , 即是输入,也是输出。


在某些场景下,有些降噪的数据并不想输出,可以下面的API:
它会更新处理器内部的状态,但不会将降噪后的数据输出,这样可以节省一些计算量:
speex_preprocess_estimate_update(preprocess_state, audio_frame);


使用下面API来改变进行预处理器的状态设置,更多的参数见下面的一节:
speex_preprocess_ctl(preprocess_state, request, ptr);

实例销毁 :
speex_preprocess_state_destroy(preprocess_state);

3.1 Preprocessor options
As with the codec, the preprocessor also has options that can be controlled using an ioctl()-like call. The available options are:
SPEEX_PREPROCESS_SET_DENOISE Turns denoising on(1) or off(2) (spx_int32_t)
SPEEX_PREPROCESS_GET_DENOISE Get denoising status (spx_int32_t)
SPEEX_PREPROCESS_SET_AGC Turns automatic gain control (AGC) on(1) or off(2) (spx_int32_t)
SPEEX_PREPROCESS_GET_AGC Get AGC status (spx_int32_t)
SPEEX_PREPROCESS_SET_VAD Turns voice activity detector (VAD) on(1) or off(2) (spx_int32_t)
SPEEX_PREPROCESS_GET_VAD Get VAD status (spx_int32_t)
SPEEX_PREPROCESS_SET_AGC_LEVEL
SPEEX_PREPROCESS_GET_AGC_LEVEL
SPEEX_PREPROCESS_SET_DEREVERB Turns reverberation removal on(1) or off(2) (spx_int32_t)
SPEEX_PREPROCESS_GET_DEREVERB Get reverberation removal status (spx_int32_t)
SPEEX_PREPROCESS_SET_DEREVERB_LEVEL Not working yet, do not use
SPEEX_PREPROCESS_GET_DEREVERB_LEVEL Not working yet, do not use
SPEEX_PREPROCESS_SET_DEREVERB_DECAY Not working yet, do not use
SPEEX_PREPROCESS_GET_DEREVERB_DECAY Not working yet, do not use
SPEEX_PREPROCESS_SET_PROB_START
SPEEX_PREPROCESS_GET_PROB_START
SPEEX_PREPROCESS_SET_PROB_CONTINUE
SPEEX_PREPROCESS_GET_PROB_CONTINUE
SPEEX_PREPROCESS_SET_NOISE_SUPPRESS Setmaximumattenuation of the noise in dB (negativespx_int32_t)
SPEEX_PREPROCESS_GET_NOISE_SUPPRESS Getmaximumattenuation of the noise in dB (negativespx_int32_t)
SPEEX_PREPROCESS_SET_ECHO_SUPPRESS Setmaximumattenuation of the residual echo in dB (negative spx_int32_t)
SPEEX_PREPROCESS_GET_ECHO_SUPPRESS Setmaximumattenuation of the residual echo in dB (negativespx_int32_t)
SPEEX_PREPROCESS_SET_ECHO_SUPPRESS_ACTIVE Set maximum attenuation of the echo in dB when near
end is active (negative spx_int32_t)
SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE Set maximum attenuation of the echo in dB when near
end is active (negative spx_int32_t)
SPEEX_PREPROCESS_SET_ECHO_STATE Set the associated echo canceller for residual echo suppression (pointer
or NULL for no residual echo suppression)
SPEEX_PREPROCESS_GET_ECHO_STATE Get the associated echo canceller (pointer)

4. 应用实例
C语言实现的音频降噪代码如下。
代码中采样率、音频帧大小需要根据实际情况设置,
HEADLEN是WAV格式的文件头,占44个字节,这44个字节是不需要处理的,不然文件头会损坏,
导致得到的结果无法播放。
如果是PCM数据,则没有这个头,直接输入指定长度的数据就行;

noiseSuppress的值可以控制减除的噪声强度,负值越小,噪声去除的强度越大,
同时会造成原声的失真,需要作出权衡。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4. #include <assert.h>
  5. #include <string.h>
  6. #include <speex/speex_preprocess.h>

  7. #define HEADLEN 44
  8. #define SAMPLE_RATE (48000)
  9. #define SAMPLES_PER_FRAME (1024)
  10. #define FRAME_SIZE (SAMPLES_PER_FRAME * 1000/ SAMPLE_RATE)
  11. #define FRAME_BYTES (SAMPLES_PER_FRAME)
  12. int main()
  13. {
  14.     size_t n = 0;
  15.     FILE *inFile, *outFile;
  16.     fopen_s(&inFile, "./audio/input01L.wav", "rb");
  17.     fopen_s(&outFile, "./audio/output01L.wav", "wb");

  18.     char *headBuf = (char*)malloc(HEADLEN);
  19.     char *dataBuf = (char*)malloc(FRAME_BYTES * 2 );
  20.     memset(headBuf, 0, HEADLEN);
  21.     memset(dataBuf, 0, FRAME_BYTES);
  22.     assert(headBuf != NULL);
  23.     assert(dataBuf != NULL);

  24.     SpeexPreprocessState *state = speex_preprocess_state_init(1024, SAMPLE_RATE);
  25.     int denoise = 1;
  26.     int noiseSuppress = -25;
  27.     speex_preprocess_ctl(state, SPEEX_PREPROCESS_SET_DENOISE, &denoise);
  28.     speex_preprocess_ctl(state, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &noiseSuppress);
  29.     
  30.     int i;
  31.     i = 0;
  32.     speex_preprocess_ctl(state, SPEEX_PREPROCESS_SET_AGC, &i);
  33.     i = 80000;
  34.     speex_preprocess_ctl(state, SPEEX_PREPROCESS_SET_AGC_LEVEL, &i);
  35.     i = 0;
  36.     speex_preprocess_ctl(state, SPEEX_PREPROCESS_SET_DEREVERB, &i);
  37.     float f = 0;
  38.     speex_preprocess_ctl(state, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &f);
  39.     f = 0;
  40.     speex_preprocess_ctl(state, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &f);

  41.     //静音检测,效果一般
  42.     /*
  43.     int vad = 1;
  44.     int vadProbStart = 80;
  45.     int vadProbContinue = 65;
  46.     speex_preprocess_ctl(state, SPEEX_PREPROCESS_SET_VAD, &vad);
  47.     speex_preprocess_ctl(state, SPEEX_PREPROCESS_SET_PROB_START, &vadProbStart);
  48.     speex_preprocess_ctl(state, SPEEX_PREPROCESS_SET_PROB_CONTINUE, &vadProbContinue);
  49.     */

  50.     bool flag = true;

  51.     while (1)
  52.     {
  53.         if (flag == true)
  54.         {
  55.             flag = false;
  56.             n = fread(headBuf, 1, HEADLEN, inFile);
  57.             if (n == 0)
  58.                 break;
  59.             fwrite(headBuf, 1, HEADLEN, outFile);
  60.         }
  61.         else
  62.         {
  63.             n = fread(dataBuf, 1, SAMPLES_PER_FRAME, inFile);
  64.             if (n == 0)
  65.                 break;
  66.             speex_preprocess_run(state, (spx_int16_t*)(dataBuf));
  67.             fwrite(dataBuf, 1, SAMPLES_PER_FRAME, outFile);
  68.         }
  69.     }

  70.     free(headBuf);
  71.     free(dataBuf);
  72.     fclose(inFile);
  73.     fclose(outFile);
  74.     speex_preprocess_state_destroy(state);
  75.     return 0;
  76. }


阅读(6825) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~