6
\$\begingroup\$

I am writing a networked audio application that sends the audio in 320 byte chunks, later I need to provide the player a bigger amount of bytes to play so I try to merge 2 or more chunks into one buffer and return it, well the code works but I hear some small audio artifacts, any ideas if the code is correct?

-(NSData*) getRawBufferWithSize:(int) requestedBufferSize
{
 if(audio.isBuffering && audio.bufferTimer>[[NSDate date] timeIntervalSince1970] && !AUDIO_BYPASS_NET)
 {
 return nil;
 }
 audio.isBuffering = NO;
 int readyBufferSize = 0;
 int bytesPending = requestedBufferSize;
 if(returnBufferSize<requestedBufferSize)
 {
 returnBuffer = (char*)realloc(returnBuffer, requestedBufferSize);
 returnBufferSize = requestedBufferSize;
 }
 while (readyBufferSize<requestedBufferSize)
 {
 NSData* newBuffer;
 @synchronized(playbackRawBuffer)
 {
 if([playbackRawBuffer count] != 0)
 {
 newBuffer = [[playbackRawBuffer objectAtIndex:0] retain];
 [playbackRawBuffer removeObjectAtIndex:0];
 }
 else
 {
 break;
 }
 } 
 char* bytes = (char*)[newBuffer bytes];
 int readableBytes = newBuffer.length;
 int amountOfBytesToRead = bytesPending;
 int amountOfBytesToSaveForLater = 0;
 if(readableBytes<amountOfBytesToRead)//if we can read less than we want
 {
 amountOfBytesToRead = readableBytes;
 }
 else if(readableBytes>amountOfBytesToRead)//if we can read more bytes than we want (we save the remaining bytes)
 {
 amountOfBytesToSaveForLater = readableBytes - amountOfBytesToRead;
 }
 bytesPending -= amountOfBytesToRead;
 memcpy((char*)returnBuffer+readyBufferSize, bytes, amountOfBytesToRead);
 [newBuffer release];
 readyBufferSize+=amountOfBytesToRead;
 if(amountOfBytesToSaveForLater>0)
 {//save these bytes back in the buffers array
 if(tBufSize<amountOfBytesToSaveForLater)
 {
 tBuf = (char*)realloc(tBuf, amountOfBytesToSaveForLater);
 tBufSize = amountOfBytesToSaveForLater;
 }
 memcpy(tBuf, &(bytes[amountOfBytesToRead]), amountOfBytesToSaveForLater);
 @synchronized(playbackRawBuffer)
 {
 [playbackRawBuffer insertObject:[NSData dataWithBytes:tBuf length:amountOfBytesToSaveForLater] atIndex:0];
 }
 break;
 }
 }
 if(readyBufferSize>0)
 {
 return [NSData dataWithBytes:returnBuffer length:readyBufferSize];
 }
 else
 {
 audio.isBuffering = YES;
 audio.bufferTimer = [[NSDate date] timeIntervalSince1970]+0.1;
 return nil;
 }
}
ruds
3,37117 silver badges23 bronze badges
asked Sep 27, 2012 at 8:04
\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

This is the wrong way to sue realloc:

returnBuffer = (char*)realloc(returnBuffer, requestedBufferSize);

If it fails you have just leaked the old returnBuffer.
The way realloc should be used is:

char* tmp = (char*)realloc(returnBuffer, requestedBufferSize);
if (tmp != NULL)
{
 returnBuffer = tmp;
}
else { /* Deal with realloc() failure */ }

But why are you dealing with this. I would use a std::vector<char> it deals with all the memory management issues for you (and your post id tagged C++).

TO be honest I have trouble following the rest of your code.

answered Sep 27, 2012 at 17:25
\$\endgroup\$
3
  • \$\begingroup\$ Well in this case the requested buffer size is from 600 to 700 bytes of data, if realloc cannot manage to extend it to this size then I think I have more serious problems than a memory leak :) \$\endgroup\$ Commented Sep 28, 2012 at 7:12
  • \$\begingroup\$ @AntonBanchev: That's not really the point. You are writing code that is known bad pattern. I reject people from an interview for making such obvious mistakes. \$\endgroup\$ Commented Sep 28, 2012 at 19:04
  • \$\begingroup\$ +1 for "use std::vector", although maybe for this particular problem, std::deque would work even better. \$\endgroup\$ Commented Jul 24, 2013 at 23:00
0
\$\begingroup\$

I'm not sure what your sample rate is, but two 320-byte blocks put together is likely to be such a short time interval that merging them into 640 entirely wrong bytes would just sound like a quick "artifact."

What evidence do you have that this merge works correctly at all? It's hard to interpret on it's own, and if all you've got to go on currently is an audible artifact, there's a possibility that it is just 640 bytes of junknoise.

Suggestion: run the method on it's own with known input, expected output, and validate that it does merge at all.

answered Feb 24, 2013 at 20:36
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.