Sample to use AEC

"Vishal Parmar" <[email protected]> Thu, 29 Jan 2015 17:48:54 +0530
Newsgroups gmane.comp.audio.compression.speex.devel
Message-ID <[email protected]>
This is a multipart message in MIME format.


------=_NextPart_000_0003_01D03BEB.DC18A3A0
Content-Type: multipart/alternative;
	boundary="----=_NextPart_001_0004_01D03BEB.DC18A3A0"



------=_NextPart_001_0004_01D03BEB.DC18A3A0
Content-Type: text/plain;
	charset="us-ascii"
Content-Transfer-Encoding: 7bit

Hi,

 

I am using speex lib (libspeexdsp.lib) to implement AEC.

I used mmsystem api to open speaker for my application (waveoutopen)  then I
used callback method to write data on speaker.

 

1 want to remove echo by using speex lib. Now can you provide me a sample to
remove echo  .

 

Kindly find the attached file where I am doing this job to remov echo .

 

 

Regards,

Vishal Parmar


------=_NextPart_001_0004_01D03BEB.DC18A3A0
Content-Type: text/html;
	charset="us-ascii"
Content-Transfer-Encoding: quoted-printable

<html xmlns:v=3D"urn:schemas-microsoft-com:vml" =
xmlns:o=3D"urn:schemas-microsoft-com:office:office" =
xmlns:w=3D"urn:schemas-microsoft-com:office:word" =
xmlns:m=3D"http://schemas.microsoft.com/office/2004/12/omml" =
xmlns=3D"http://www.w3.org/TR/REC-html40"><head><meta =
http-equiv=3DContent-Type content=3D"text/html; =
charset=3Dus-ascii"><meta name=3DGenerator content=3D"Microsoft Word 15 =
(filtered medium)"><style><!--
/* Font Definitions */
@font-face
	{font-family:"Cambria Math";
	panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
	{font-family:Calibri;
	panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
	{font-family:Consolas;
	panose-1:2 11 6 9 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
	{margin:0in;
	margin-bottom:.0001pt;
	font-size:11.0pt;
	font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
	{mso-style-priority:99;
	color:#0563C1;
	text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
	{mso-style-priority:99;
	color:#954F72;
	text-decoration:underline;}
span.EmailStyle17
	{mso-style-type:personal-compose;
	font-family:"Calibri","sans-serif";
	color:windowtext;}
.MsoChpDefault
	{mso-style-type:export-only;
	font-family:"Calibri","sans-serif";}
@page WordSection1
	{size:8.5in 11.0in;
	margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
	{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext=3D"edit" spidmax=3D"1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext=3D"edit">
<o:idmap v:ext=3D"edit" data=3D"1" />
</o:shapelayout></xml><![endif]--></head><body lang=3DEN-US =
link=3D"#0563C1" vlink=3D"#954F72"><div class=3DWordSection1><p =
class=3DMsoNormal>Hi,<o:p></o:p></p><p =
class=3DMsoNormal><o:p>&nbsp;</o:p></p><p class=3DMsoNormal>I am using =
speex lib (libspeexdsp.lib) to implement AEC.<o:p></o:p></p><p =
class=3DMsoNormal>I used <span =
style=3D'font-size:9.5pt;font-family:Consolas;color:#A31515;background:wh=
ite;mso-highlight:white'>mmsystem</span><span =
style=3D'font-size:9.5pt;font-family:Consolas;color:#A31515'> api =
</span>to open speaker for my application (waveoutopen) &nbsp;then I =
used callback method to write data on speaker.<o:p></o:p></p><p =
class=3DMsoNormal><o:p>&nbsp;</o:p></p><p class=3DMsoNormal>1 want to =
remove echo by using speex lib. Now can you provide me a sample to =
remove echo&nbsp; .<o:p></o:p></p><p =
class=3DMsoNormal><o:p>&nbsp;</o:p></p><p class=3DMsoNormal>Kindly find =
the attached file where I am doing this job to remov echo =
.<o:p></o:p></p><p class=3DMsoNormal><o:p>&nbsp;</o:p></p><p =
class=3DMsoNormal><o:p>&nbsp;</o:p></p><p =
class=3DMsoNormal>Regards,<o:p></o:p></p><p class=3DMsoNormal>Vishal =
Parmar<o:p></o:p></p></div></body></html>
------=_NextPart_001_0004_01D03BEB.DC18A3A0--


------=_NextPart_000_0003_01D03BEB.DC18A3A0
Content-Type: text/plain;
	name="WaveOut.cpp"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="WaveOut.cpp"

#include "StdAfx.h"
#include "WaveOut.h"
#include "general.h"
#include "DelayTone.h"
#include <math.h>

#pragma comment(lib,"winmm.lib")

void CALLBACK waveOutFunc(HWAVEOUT hwo,UINT uMsg,DWORD dwInstance,DWORD =
dwParam1,DWORD dwParam2)
{
	WAVEHDR *pHdr=3DNULL;
	switch(uMsg)
	{
		case WOM_CLOSE:
			break;

		case WOM_DONE:
			{
				CWaveOut *pDlg=3D(CWaveOut*)dwInstance;
				pDlg->ProcessHeader((WAVEHDR *)dwParam1);
			}
			break;

		case WOM_OPEN:
			break;

		default:
			break;
	}
}

CWaveOut::CWaveOut(void)
{
	read_size	=3D 0		;
	wBytesPerSample =3D 0 ;
	m_hWaveOut	=3D NULL	;
	pReaderQ	=3D NULL	;
	st			=3D NULL	;
	echo_state  =3D NULL	;
	echo_buffer	=3D NULL	;
	input_buffer=3D NULL	;

	ZeroMemory(&m_stWFEX,sizeof(WAVEFORMATEX));
	ZeroMemory( m_stWHDR,MAX_OUTPUT_BUFFERS*sizeof(WAVEHDR));
}

CWaveOut::~CWaveOut(void)
{
	StopPlay();
	if(pReaderQ)
		delete pReaderQ;
	pReaderQ =3D NULL;
	if(st)
	{
		 speex_preprocess_state_destroy(st);
		 st =3D NULL;
	}
	if(echo_state)
	{
		speex_echo_state_destroy(echo_state);	=09
		echo_state =3D NULL;
	}
	if(echo_buffer)
	{
		delete echo_buffer;
		echo_buffer =3D NULL;
	}
	if(input_buffer)
	{
		delete input_buffer;
		input_buffer =3D NULL;
	}
}

int CWaveOut::GetDeviceCount(void)
{
	return waveOutGetNumDevs();
}

int CWaveOut::GetDeviceCaps(int deviceNo,PWAVEOUTCAPS pWaveParams)
{
	return waveOutGetDevCaps(deviceNo,pWaveParams,sizeof(WAVEOUTCAPS));
}

int CWaveOut::OpenDevice( WORD	 deviceNo,
						  DWORD	 samplesPerSecond,
						  WORD	 nChannels,
						  WORD   wBitsPerSample
					    )
{

	if(m_hWaveOut)// Device is open now.
		return FAILURE;

	MMRESULT mRes			 =3D	0					;
	m_stWFEX.nSamplesPerSec  =3D	samplesPerSecond	;
	m_stWFEX.nChannels	     =3D	nChannels			;
	m_stWFEX.wBitsPerSample  =3D	wBitsPerSample		;
	m_stWFEX.wFormatTag		 =3D	WAVE_FORMAT_PCM		;
	m_stWFEX.nBlockAlign	 =3D	m_stWFEX.nChannels*m_stWFEX.wBitsPerSample/8;
	m_stWFEX.nAvgBytesPerSec =3D	=
m_stWFEX.nSamplesPerSec*m_stWFEX.nBlockAlign;
	m_stWFEX.cbSize			 =3D	sizeof(WAVEFORMATEX);
	pReaderQ				 =3D  new CReaderQ()		;


	mRes =3D waveOutOpen(
						&m_hWaveOut,
						deviceNo,
						&m_stWFEX,
						(DWORD_PTR)waveOutFunc,
						(DWORD_PTR)this,
						CALLBACK_FUNCTION
					  );
	if(mRes =3D MMSYSERR_NOERROR)
	{
		MessageBoxA(NULL,"success", "Final Speaker List", NULL);
	}

	return mRes;
}

int CWaveOut::ProcessHeader(WAVEHDR * pHdr)
{
	MMRESULT mRes	=3D	0	;
	int vad;

	if(WHDR_DONE=3D=3D(WHDR_DONE &pHdr->dwFlags))
	{
		memset(input_buffer,0,read_size*wBytesPerSample);
		while(pReaderQ->GetFilledSize() >=3D read_size)
		{
			pReaderQ->RemoveFromQueue((uint8*)input_buffer,read_size);
		}
		speex_echo_cancellation(echo_state, input_buffer, echo_buffer, =
(spx_int16_t *)pHdr->lpData);
		vad =3D speex_preprocess_run(st, (spx_int16_t *)pHdr->lpData);

		mRes=3DwaveOutWrite(m_hWaveOut,pHdr,sizeof(WAVEHDR));
		memcpy(echo_buffer,pHdr->lpData,read_size*2);
	}
	return SUCCESS;
}

int CWaveOut::StartPlay(float ratio)
{
	MMRESULT res=3D0;
	PrepareBuffers(ratio);
	for(int i=3D0; i < MAX_OUTPUT_BUFFERS ; i++)
	{
		res=3DwaveOutWrite(m_hWaveOut,&m_stWHDR[i],sizeof(WAVEHDR));
		if ( res !=3D MMSYSERR_NOERROR )
			return FAILURE;
	}
	return SUCCESS;
}

int CWaveOut::StopPlay(void)
{
	MMRESULT mRes=3D0;
	if(m_hWaveOut)
	{
		UnprepareBuffers();
		mRes=3DwaveOutClose(m_hWaveOut);

		m_hWaveOut =3D NULL;
		return SUCCESS;
	}
	return FAILURE;
}

int CWaveOut::PrepareBuffers(float ratio)
{
	int			i		;
	float		f		;
	MMRESULT	mRes=3D0	;
	int			nT1=3D0	;
	double		lg		;
	int			c_size	;

	for(nT1=3D0;nT1<MAX_OUTPUT_BUFFERS;++nT1)
	{
		c_size =3D (SIZE_T)m_stWFEX.nAvgBytesPerSec*ratio;

		lg		=3D log10((double)c_size)/log10((double)2);
		lg		=3D ceil(lg);
		c_size	=3D pow(2,lg);


		m_stWHDR[nT1].lpData=3D(LPSTR)HeapAlloc(GetProcessHeap(),8,c_size);
		m_stWHDR[nT1].dwBufferLength=3Dc_size	;
		m_stWHDR[nT1].dwUser		=3D				nT1						;
		=
mRes=3DwaveOutPrepareHeader(m_hWaveOut,&m_stWHDR[nT1],sizeof(WAVEHDR));
		if(mRes!=3D0)
		{
			return FAILURE;
		}
	}
	echo_state =3D speex_echo_state_init(c_size/2, =
m_stWFEX.nSamplesPerSec/10);
	st =3D speex_preprocess_state_init(c_size/2, m_stWFEX.nSamplesPerSec);
	i=3D1;
    speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DENOISE, &i);
    i=3D0;
    speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC, &i);
    i=3D8000;
    speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_AGC_LEVEL, &i);
    i=3D0;
    speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB, &i);
    f=3D.0;
    speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &f);
    f=3D.0;
    speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &f);
	speex_preprocess_ctl(st, SPEEX_PREPROCESS_SET_ECHO_STATE,echo_state);

	wBytesPerSample =3D m_stWFEX.wBitsPerSample/8;
	read_size =3D (SIZE_T)c_size/wBytesPerSample;

	echo_buffer		=3D new short[read_size]		;
	memset(echo_buffer,0,read_size*sizeof(short));
	input_buffer	=3D new short[read_size]		;
	memset(input_buffer,0,read_size*sizeof(short));


	return SUCCESS;
}

int CWaveOut::UnprepareBuffers(void)
{
	MMRESULT mRes=3D0;
	int nT1=3D0;

	if(m_hWaveOut)
	{
		mRes=3DwaveOutPause(m_hWaveOut);	=09
//		Sleep(300);
		for(nT1=3D0;nT1<MAX_OUTPUT_BUFFERS;++nT1)
		{
			if(m_stWHDR[nT1].lpData)
			{
				=
mRes=3DwaveOutUnprepareHeader(m_hWaveOut,&m_stWHDR[nT1],sizeof(WAVEHDR));=

				HeapFree(GetProcessHeap(),0,m_stWHDR[nT1].lpData);
				ZeroMemory(&m_stWHDR[nT1],sizeof(WAVEHDR));
			}
		}
	}
	return SUCCESS;
}
------=_NextPart_000_0003_01D03BEB.DC18A3A0
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: inline

X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KU3BlZXgtZGV2
IG1haWxpbmcgbGlzdApTcGVleC1kZXZAeGlwaC5vcmcKaHR0cDovL2xpc3RzLnhpcGgub3JnL21h
aWxtYW4vbGlzdGluZm8vc3BlZXgtZGV2Cg==

------=_NextPart_000_0003_01D03BEB.DC18A3A0--