We are developing a Audio streaming application. Audio is captured
using Windows mutimedia APIs, waveInOpen(), waveInPreapreHeader(), ...
Audio is streamed using RTP and on the receiving side received packet
is played using the DirectX DirectSound APIs. Snap shot of the code is
given below.
I am facing a strange problem. With every received opacket I hear
click sound and trying to overcome this problem. Can any one help
me...?
Further to this I also want to incorporate Noise suppression, Silence
detection algorithm. I need guidence preferably with sample code &
useful links on how to implemet these on WindowsXP professional
systems.
/*********************/
#include "RPCAudBase.h"
typedef CList<CRPCAudBuffer*, CRPCAudBuffer*> CRPCDxSndBufferList;
class CRPCDxSndPlay : public CWinThread, public CRPCAudBase
{
DECLARE_DYNCREATE(CRPCDxSndPlay)
public:
CRPCDxSndPlay();
virtual ~CRPCDxSndPlay();
public:
void* m_pOwner;
HWND m_hWnd;
public:
// pointer to callback function
RPCERR (*GetDataToDxSndPaly)(CRPCAudBuffer** buffer, void* Owner);
virtual void Stop();
virtual BOOL Start();
static void OnDxSoundRead(PVOID pData);
void OnDxSoundReceive();
afx_msg void OnDxSoundStart(WPARAM wParam, LPARAM lParam);
DECLARE_MESSAGE_MAP()
protected:
BOOL InitInstance();
protected:
BOOL m_bPlaying;
DWORD m_ThreadID;
LPDIRECTSOUNDBUFFER m_DxBuffer;
LPDIRECTSOUND m_pDxSound;
HANDLE m_hDxSndRead;
DWORD m_hDxSndReadID;
CRPCDxSndBufferList m_SndBufList;
CCriticalSection m_Lock;
DWORD m_dwBufferSize;
DWORD m_dwNextOffset;
DWORD m_dwNotifySize;
};
/******************/
BOOL CRPCDxSndPlay::Start()
{
HRESULT hResult = DirectSoundCreate(NULL, &m_pDxSound, NULL);
if(SUCCEEDED(hResult))
{
// Creation succeeded.
if(FAILED(hResult = m_pDxSound->SetCooperativeLevel(m_hWnd,
DSSCL_PRIORITY)))
{
::MessageBox(NULL, "Failed at m_pDxSound->SetCooperativeLevel()",
"NRBS Communicator", MB_OK | MB_ICONEXCLAMATION);
}
else
{
// Set the buffer sizes
m_dwNotifySize = RPCAUDBASE_PDU_SIZE * (m_Format.wBitsPerSample/8);
m_dwBufferSize = m_dwNotifySize * RPCAUDBASE_NOOF_PDU;
m_dwNextOffset = 0;
PCMWAVEFORMAT pcmwf;
DSBUFFERDESC dsbdesc;
// Set up wave format structure.
// memcpy(&pcmwf.wf, &m_Format, sizeof(WAVEFORMATEX));
memset( &pcmwf, 0, sizeof(PCMWAVEFORMAT) );
pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM;
pcmwf.wf.nChannels = (WORD)m_Format.nChannels;
pcmwf.wf.nSamplesPerSec = m_Format.nSamplesPerSec;
pcmwf.wf.nBlockAlign = (WORD)m_Format.nBlockAlign;
pcmwf.wf.nAvgBytesPerSec = pcmwf.wf.nSamplesPerSec *
pcmwf.wf.nBlockAlign;
pcmwf.wBitsPerSample = (WORD)m_Format.wBitsPerSample;
// Set up DSBUFFERDESC structure.
memset( &dsbdesc, 0, sizeof(DSBUFFERDESC) );
dsbdesc.dwSize = sizeof(DSBUFFERDESC);
dsbdesc.dwFlags = DSBCAPS_CTRLPAN | DSBCAPS_CTRLVOLUME
| DSBCAPS_CTRLFREQUENCY | DSBCAPS_GLOBALFOCUS;
dsbdesc.dwBufferBytes = m_dwBufferSize;
dsbdesc.lpwfxFormat = (LPWAVEFORMATEX)&pcmwf;
hResult = m_pDxSound->CreateSoundBuffer(&dsbdesc, &m_DxBuffer,
NULL);
if(SUCCEEDED(hResult))
{
m_bPlaying = TRUE;
PostThreadMessage(DX_SOUND_START, 0, 0);
}
}
}
return SUCCEEDED(hResult);
}
void CRPCDxSndPlay::Stop()
{
if(m_bPlaying)
{
m_bPlaying = FALSE;
m_DxBuffer->Stop();
Sleep(500);
m_DxBuffer->Release();
m_pDxSound->Release();
}
}
void CRPCDxSndPlay::OnDxSoundStart(WPARAM wParam, LPARAM lParam)
{
m_hDxSndRead = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
OnDxSoundRead, (PVOID) this, 0, &m_hDxSndReadID);
LPVOID pvAudioPtr1;
DWORD dwAudioBytes1;
LPVOID pvAudioPtr2;
DWORD dwAudioBytes2;
// Lock data in buffer for writing
HRESULT m_hResult = m_DxBuffer->Lock(0, m_dwBufferSize, &pvAudioPtr1,
&dwAudioBytes1, &pvAudioPtr2, &dwAudioBytes2,
DSBLOCK_FROMWRITECURSOR);
// Set silence buffer
memset(pvAudioPtr1, 0, dwAudioBytes1);
memset(pvAudioPtr2, 0, dwAudioBytes2);
// Unlock data in buffer
m_hResult = m_DxBuffer->Unlock(pvAudioPtr1, dwAudioBytes1,
pvAudioPtr2, dwAudioBytes2);
m_hResult = m_DxBuffer->Play(0, 0, DSBPLAY_LOOPING);
// Delay return till audio is played
DWORD dwDelay = (DWORD) ((double) (m_dwNotifySize * 8 * 1000) /
(double) (m_Format.nSamplesPerSec * m_Format.wBitsPerSample *
m_Format.nChannels));
BOOL bLoop = TRUE;
while(m_bPlaying)
{
Sleep(dwDelay);
// Lock data in buffer for writing
HRESULT m_hResult = m_DxBuffer->Lock(m_dwNextOffset, m_dwNotifySize,
&pvAudioPtr1, &dwAudioBytes1, &pvAudioPtr2, &dwAudioBytes2,
DSBLOCK_FROMWRITECURSOR);
m_Lock.Lock();
if(m_SndBufList.GetCount()>0)
{
CRPCAudBuffer* buffer = m_SndBufList.RemoveHead();
// Copy data to the sound buffer
memcpy(pvAudioPtr1, buffer->m_ptr.c, dwAudioBytes1);
if(dwAudioBytes2)
memcpy(pvAudioPtr2, buffer->m_ptr.c+dwAudioBytes1, dwAudioBytes2);
delete buffer;
}
else
{
// Set silence buffer
memset(pvAudioPtr1, 0, dwAudioBytes1);
memset(pvAudioPtr2, 0, dwAudioBytes2);
}
m_Lock.Unlock();
// Unlock data in buffer
m_hResult = m_DxBuffer->Unlock(pvAudioPtr1, dwAudioBytes1,
pvAudioPtr2, dwAudioBytes2);
m_dwNextOffset += m_dwNotifySize;
m_dwNextOffset %= m_dwBufferSize;
}
CloseHandle(m_hDxSndRead);
}
void CRPCDxSndPlay::OnDxSoundRead(PVOID pData)
{
CRPCDxSndPlay* pRPCDxSndPlay = (CRPCDxSndPlay*) pData;
pRPCDxSndPlay->OnDxSoundReceive();
}
void CRPCDxSndPlay::OnDxSoundReceive()
{
while(m_bPlaying)
{
CRPCAudBuffer* buffer;
if(RPCSUCCESS(GetDataToDxSndPaly(&buffer, m_pOwner))) // ==> Data
Received using callback functions
{
m_Lock.Lock();
if(m_SndBufList.GetCount()>RPCAUDBASE_NOOF_PDU)
{
CRPCAudBuffer* buf = m_SndBufList.RemoveHead();
delete buf;
}
m_SndBufList.AddTail(buffer);
m_Lock.Unlock();
}
}
}
/**************************/ |