• 12
• 12
• 9
• 10
• 13

# Streaming with DirectSound Buffers

This topic is 3526 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hello, I have been trying for days to figure this out and can't find any solutions online. I have created a class that represents and manages a DirectSound buffer. The member mWritePosition is used to track the write position. Originally I did not have as many checks before calling Lock but, since I could not figure out the problem, I added the extra checks to ensure my values are within (what I believe to be) the valid range. I am trying to stream into the buffer up to 'dataSize'. The function is intended to be called and if the available space to be written is less than the desired dataSize then dataSize is adjusted to the maximum. Filling the buffer seems to work as expected up until mWritePosition>=mBufferSize (which it is then changed to mWritePosition-=mBufferSize), at this point Lock constantly returns DSERR_INVALIDPARAM. My guess is that DSERR_INVALIDPARAM returned when the "dangerous" ( between Play Cursor and Write Cursor) is asked to be locked. However my extensive checks seem to ensure these values are correct. It is almost as though Lock has the condition if(requestedWritePosition < writeCursor) return DSERR_INVALIDPARAM; The Commented out section is a text visual representation of the buffer and the pointers within (numbers ticked by too quickly to properly analyse them). Any help is greatly appreciated :) Cheers Sean

u32 Buffer::Append(void* data, u32 dataSize)
{
void* block1=0;
DWORD block1Bytes=0;
void* block2=0;
DWORD block2Bytes=0;
DWORD bytesWritten=0;
DWORD playPos,writePos,writeLen;

HRESULT hRes = mBuffer->GetCurrentPosition(&playPos,&writePos);
if(playPos > writePos)
if(mWritePosition < writePos || mWritePosition > playPos)
{
std::cout << "mWritePosition < writePos || mWritePosition > playPos" << std::endl;
return 0;
}

if(mWritePosition < writePos && mWritePosition > playPos)
{
std::cout << "mWritePosition < writePos && mWritePosition > playPos" << std::endl;
return 0;
}

if (mWritePosition < playPos)
writeLen = playPos - mWritePosition;
else
writeLen = mBufferSize - mWritePosition + playPos;

if(dataSize>writeLen)
dataSize=writeLen;

if(dataSize==0)
return 0;

//#define PERCENT_BAR_RANGE 65
//	u32 playPosP=((playPos* PERCENT_BAR_RANGE)/mBufferSize);
//	u32 writePosP=((writePos* PERCENT_BAR_RANGE)/mBufferSize);
//	u32 mwritePosP=((mWritePosition* PERCENT_BAR_RANGE)/mBufferSize);
//	std::cout << /*mwritePosP << "|" << mWritePosition <<*/ "[";
//
//	for(int p=0;p<PERCENT_BAR_RANGE; ++p)
//	{
//		u32 d=(((mWritePosition+writeLen)* PERCENT_BAR_RANGE)/mBufferSize);
//		u32 d2=0;
//		if(mWritePosition+writeLen > mBufferSize)
//			d2=playPosP;
//		if(p==writePosP && p==playPosP)
//			std::cout << "X";
//		else
//		if(p==writePosP)
//			std::cout << "<";
//		else
//		if(p==playPosP)
//			std::cout << ">";
//		else
//		if(p==mwritePosP)
//			std::cout << "W";
//		else
//		if((p<d && p>mwritePosP) || p<d2)
//			std::cout << "D";
//		else
//			std::cout << " ";
//	}
//	std::cout << "]\r";

int r=mBuffer->Lock(mWritePosition,dataSize, &block1,&block1Bytes, &block2,  &block2Bytes, 0);//DSBLOCK_FROMWRITECURSOR);//DSBLOCK_ENTIREBUFFER);
if(r==DS_OK)
{
if(dataSize>block1Bytes)
{
memcpy(block1, data, block1Bytes);
dataSize-=block1Bytes;
bytesWritten+=block1Bytes;
if(dataSize>block2Bytes)
dataSize=block2Bytes;
memcpy(block2, &(((u8*)data)[bytesWritten]), dataSize);
bytesWritten+=dataSize;
mBuffer->Unlock(&block1, block1Bytes, &block2,  dataSize);
}else
{
memcpy(block1, data, dataSize);
bytesWritten+=dataSize;
mBuffer->Unlock(&block1, dataSize, &block2,  0);
}
}else
{
switch(r)
{
case DSERR_BUFFERLOST: std::cout << "Buffer::Append() - DSERR_BUFFERLOST" << std::endl; break;
case DSERR_INVALIDCALL: std::cout << "Buffer::Append() - DSERR_INVALIDCALL" << std::endl; break;
case DSERR_INVALIDPARAM: std::cout << "Buffer::Append() - DSERR_INVALIDPARAM" << std::endl;
break;
case DSERR_PRIOLEVELNEEDED: std::cout << "Buffer::Append() - DSERR_BUFFERLOST" << std::endl; break;
};
}
mWritePosition+=bytesWritten;
if(mWritePosition>=mBufferSize)
{
mWritePosition-=mBufferSize;
}
return bytesWritten;
}



##### Share on other sites
It's entirely possible that I'm misunderstanding your code.

However, the "else" part of this looks bad:
if (mWritePosition < playPos)	writeLen = playPos - mWritePosition;else	writeLen = mBufferSize - mWritePosition + playPos;

Why do you add "playPos" to the length of the data? I would think you only want to write <= remaining length in the buffer, i.e., mBufferSize-mWritePosition.

E.g.:
playPos = 85%
writePos = 90%
mWritePosition = 90%
writeLen = 100% - 90% + 85% = 95%
dataLen = 25%
Writing 25% of the buffer length at the 90% position seems inadvisable. :-)

##### Share on other sites
Hi Buckeye,

The docs for Lock say the following

dwBytes
Size, in bytes, of the portion of the buffer to lock. The buffer is conceptually circular, so this number can exceed the number of bytes between dwOffset and the end of the buffer.

http://msdn.microsoft.com/en-us/library/bb206055(VS.85).aspx

which makes that code correct for determining length which includes the portion of the buffer from the start to play position. Sorry I forgot to mention that the buffer is looping with DSBPLAY_LOOPING.

##### Share on other sites
For those interested I resolved this problem.

mBuffer->Unlock(&block1, block1Bytes, &block2, dataSize);

should have been

mBuffer->Unlock(block1, block1Bytes, block2, dataSize);

##### Share on other sites
I don't understand how that didn't give a compile error? A void** isn't the same as a void*, surely?