Speex AEC

该博客介绍了如何利用Speex开源库编译并初始化回声消除(AEC)类,包括设置帧大小、滤波器长度和采样率,并展示了如何执行AEC操作。通过创建CSpeexEC类,调用speex_echo_state_init和speex_preprocess_state_init进行初始化,然后在DoAEC方法中执行回声消除。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  
  
下载Speex开源库编译https://www.speex.org/,不做详述!
//------------------------------头文件---------------------------------//

#ifndef SPEEX_EC_H
#define SPEEX_EC_H

#include <stdio.h>
#include <stdlib.h>
#include <speex/speex_echo.h>
#include <speex/speex_preprocess.h>

class CSpeexEC
{
public:
	CSpeexEC();
	~CSpeexEC();
	void Init(int frame_size=160, int filter_length=1280, int sampling_rate=8000); 
	void DoAEC(short *mic, short *ref, short *out);

protected:
	void Reset();

private:
	bool      m_bHasInit;
	SpeexEchoState*   m_pState;
	SpeexPreprocessState* m_pPreprocessorState;
	int      m_nFrameSize;
	int      m_nFilterLen;
	int      m_nSampleRate;
	spx_int32_t*      m_pfNoise;
};

#endif


//-----------------------------AEC----------------------------------//

#include "stdafx.h"
#include "SpeexEC.h"

CSpeexEC::CSpeexEC()
{
	m_bHasInit   = false;
	m_pState   = NULL;
	m_pPreprocessorState  = NULL;
	m_nFrameSize   = 160;
	m_nFilterLen   = 160*8;
	m_nSampleRate   = 8000;
	m_pfNoise   = NULL;
}

CSpeexEC::~CSpeexEC()
{
	Reset();
}

void CSpeexEC::Init(int frame_size, int filter_length, int sampling_rate)
{
	Reset(); 

	if (frame_size<=0 || filter_length<=0 || sampling_rate<=0)
	{
		m_nFrameSize  =160;
		m_nFilterLen  = 160*8;
		m_nSampleRate = 8000;
	}
	else
	{
		m_nFrameSize  =frame_size;
		m_nFilterLen  = filter_length;
		m_nSampleRate = sampling_rate;
	}

	m_pState = speex_echo_state_init(m_nFrameSize, m_nFilterLen);
	m_pPreprocessorState = speex_preprocess_state_init(m_nFrameSize, m_nSampleRate);
	m_pfNoise = new spx_int32_t[m_nFrameSize+1];
	m_bHasInit = true;
}

void CSpeexEC::Reset()
{
	if (m_pState != NULL)
	{
		speex_echo_state_destroy(m_pState);
		m_pState = NULL;
	}
	if (m_pPreprocessorState != NULL)
	{
		speex_preprocess_state_destroy(m_pPreprocessorState);
		m_pPreprocessorState = NULL;
	}
	if (m_pfNoise != NULL)
	{
		delete []m_pfNoise;
		m_pfNoise = NULL;
	}
	m_bHasInit = false;
}


void CSpeexEC::DoAEC(short* mic, short* ref, short* out)
{
	if (!m_bHasInit)
		return;

    /*1.1.9版本中所使用的函数*/
	//speex_echo_cancel(m_pState, mic, ref, out, m_pfNoise);
	//speex_preprocess(m_pPreprocessorState, (__int16 *)out, m_pfNoise);
	/*1.2beta3-win32版本中使用的函数,从参数可以看出最新版本没有参数m_pfNoise,所以CSpeex中可以删除数据成员m_pfNoise*/
	/*本文依然保留,是为了测试两个版本的差别,从结果来看,至少人耳似乎听不出有多大差别*/
	speex_echo_cancellation(m_pState, mic, ref, out);
	speex_preprocess_run(m_pPreprocessorState, (__int16 *)out);

}

//----------------------------Demo-----------------------------------//

#include "stdafx.h"
#include "speexEC.h"
#include <stdio.h>
#include <speex/speex_echo.h>

#define NN 160
void main()
{
	FILE *ref_fd;
	FILE *mic_fd;
	FILE *out_fd;
	short ref[NN];
	short mic[NN];
	short out[NN];
	
	ref_fd = fopen("FarEnd.pcm", "r+b");
	mic_fd = fopen("NearEnd.pcm", "r+b");
	out_fd = fopen("out.pcm", "w+b");


	CSpeexEC ec;
	ec.Init();

	while (fread(mic, 1, NN*2, mic_fd))
	{
		fread(ref, 1, NN*2, ref_fd);  
		ec.DoAEC(mic, ref, out);
		fwrite(out, 1, NN*2, out_fd);
	}

	fclose(ref_fd);
	fclose(mic_fd);
	fclose(out_fd);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值