Need help playing audio obtained from RTP stream

Need help playing audio obtained from RTP stream

Post by zjw211 » Fri, 01 Apr 2005 03:38:04


Hello. I am using DirectSound 8 (DirectX v8.0) and I want to be able
to receive RTP packets and play them out through the sound card. I
currently have code that receives RTP packets and stores the data into
a buffer. I am only storing the RTP packet payload in the buffer, not
the whole RTP packet (is this correct). I am expecting the data in the
packet to be PCM16 (1 channel, 16 bits per sample, 8000 samples per
second). After receiving a certain amount of data, I copy the data
into the IDirectSoundBuffer and play the buffer, but all I hear is
noise (static), rather than the nice audible sound I am expecting. Do
I need to convert the data into WAV format (or is PCM16 already WAV
format? I thought it was). Here is some code snippets of what I am
doing. Please let me know if more detail is needed, though I think you
will get the picture. Thanks in advance:

m_WFE.wFormatTag = WAVE_FORMAT_PCM;
m_WFE.nChannels = 1;
m_WFE.wBitsPerSample = 16;
m_WFE.nBlockAlign = (m_WFE.nChannels * m_WFE.wBitsPerSample) / 8;
m_WFE.nSamplesPerSec = 8000;
m_WFE.nAvgBytesPerSec = m_WFE.nSamplesPerSec * m_WFE.nBlockAlign;
m_WFE.cbSize = 0;

//Create DirectSound
DirectSoundCreate(NULL, &m_lpDS, NULL);

//Set Cooperative Level
HWND hWnd = GetForegroundWindow();
if (hWnd == NULL)
{
hWnd = GetDesktopWindow();
}

m_lpDS->SetCooperativeLevel(hWnd, DSSCL_PRIORITY);

DSBUFFERDESC dsbd;
ZeroMemory(&dsbd, sizeof(dsbd));
dsbd.dwSize = sizeof(DSBUFFERDESC);
dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER;
dsbd.dwBufferBytes = 0;
dsbd.lpwfxFormat = NULL;

// Is creating and setting-up the PRIMARY BUFFER needed?
LPDIRECTSOUNDBUFFER lpDSB = NULL;
m_lpDS->CreateSoundBuffer(&dsbd, &lpDSB, NULL);

//Set Primary Buffer Format
lpDSB->SetFormat(&m_WFE);

//Create Secondary Buffer - should be big enough to store 10 secs of
data
dsbd.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GLOBALFOCUS |
DSBCAPS_CTRLVOLUME;
dsbd.dwBufferBytes = 10*m_WFE.nAvgBytesPerSec;
dsbd.lpwfxFormat = &m_WFE;

m_lpDS->CreateSoundBuffer(&dsbd, &m_lpDSB, NULL);

//Write the audio data to DirectSoundBuffer
LPVOID lpvAudio1 = NULL, lpvAudio2 = NULL;
DWORD dwBytesAudio1 = 0, dwBytesAudio2 = 0;

//Lock DirectSoundBuffer - rtpBufferIdx is equal to the number of RTP
bytes, which will actually be less than 10 seconds of data
// that I stored
HRESULT hr = m_lpDSB->Lock(0, rtpBufferIdx, &lpvAudio1,
&dwBytesAudio1, &lpvAudio2, &dwBytesAudio2, 0);

//Copy Audio Buffer to DirectSoundBuffer
if (NULL == lpvAudio2) {
memcpy(lpvAudio1, m_lpRtpBuf, rtpBufferIdx);
}
else {
memcpy(lpvAudio1, m_lpRtpBuf, dwBytesAudio1);
memcpy(lpvAudio2, m_lpRtpBuf + dwBytesAudio1, dwBytesAudio2);
}

m_lpDSB->Unlock(lpvAudio1, dwBytesAudio1, lpvAudio2, dwBytesAudio2);

m_lpDSB->Play(0, 0, DSBPLAY_LOOPING);
 
 
 

Need help playing audio obtained from RTP stream

Post by Chris P. [ » Fri, 01 Apr 2005 07:52:42


That is correct.


Are you 100% sure of the format you are being sent?


Wave format is a generic term. In it's simplest form it is most commonly
PCM yes. I would double check what you are being sent, it's possible it
might be 8-bit PCM or 8-bit mulaw. Mu-law needs to be converted before
playing.


Sometimes it can be useful to dump your payload data to a file, then you
can prepend a wave header with a hex editor and play with the format until
you work out what it is supposed to be.

 
 
 

Need help playing audio obtained from RTP stream

Post by zjw211 » Sat, 02 Apr 2005 02:25:34

I found out what the problem (actually, a co-worker made the
suggestion). RTP packets are sent big-endian, but it appears the data
needs to be stored little-endian in the sound buffer. I made the
conversion and I am now hearing the sound correctly. This was an
excellent "lessons-learned".



able
into
not
commonly
it
before
you
you
until
 
 
 

Need help playing audio obtained from RTP stream

Post by Chris P. [ » Sat, 02 Apr 2005 03:14:38


Yep, I should have thought of that one too - been there done that :)
Actually my next suggestion would have been to post a copy of the first
packet and then it should have been obvious looking at the binary data.