Rss

Someone care to explain pointer arithmetic to me again?

So, one of the weird things I’m getting used to in the C-based frameworks (Core Audio, CFNetwork) is a pattern for holding “state data” together across a number of calls to related functions. Coming from 10+ years of OO, it seems unwieldy, but it does afford a certain freedom.

What these functions often have as their first parameter is a pointer to a user-defined structure that can have more or less whatever you want to put in it. The idea is that it needs to contain everything you’re going to need to go into or come out of any of a series of related function calls. For example, if you’re going to read bytes from a file and play them in an audio stream, your structure will have pointers to the AudioQueueRef, the AudioFileID, some ints for the buffer size and number of packets you read on your last call, etc. Each call may use only one or two of these, but you bundle them in one big typedef, and that block of data is passed to and from all the related calls.

So, my current challenge is converting the example in the Audio Queue Services Programming Guide from one that plays bytes from a file to one that gets them from a network stream. What’s hanging me up — and will probably become an ADC support request in the next few days — is that the callback-oriented nature of these APIs requires me to buffer some packets extracted from the stream, and hang on to them until I get a callback from the queue telling me it’s ready for me to fill one of its audio buffers with packets. Typically, I get multiple “you have packets” callbacks for each “fill AQ buffers” callback, which is a complexity that the example doesn’t need to deal with, as it can read exactly the amount of data it needs from the file on demand.

Thus, my attempt to hold onto the packets from the callbacks is where the pointer math comes in. Start with my state structure:

typedef struct  { 
	AudioStreamBasicDescription mDataFormat; 
	AudioQueueRef mQueue;
// ...
	void* myAudioData;	// from last handle packets callback
	UInt32 myAudioDataByteSize; // from last handle packets callback
} AQPlayerState; 

Notice the last two here: I have a big-ass buffer of data that I malloc at some point, and a size counter. The counter is effectively an offset: if I get another callback with more data, I need to copy the new data into the buffer at an offset of myAudioDataByteSize, and then update the offset, of course.

Now, since Dr. Gosling has kept me away from pointers for a good 12 years now, I’m not sure how I cajole the C syntax to express the concept of “the address pointed to by taking the address of myAudioData and adding myAudioDataByteSize bytes”. Currently I’m trying to do something like:

memcpy (&pAqData->myAudioData + pAqData->myAudioDataByteSize,
          (void*) inInputData,
          inNumberBytes);

And given that I’m segfaulting somewhere… probably here… I assume that the first argument is pointing to nonsense.

So, C-friendly people, assuming for a second that this approach is even valid (it may well not be), what’s the syntax for saying “take address A, add B, and treat the result as an address”?

Previous Post

Next Post

Comments (2)

  1. Phil Barrett

    Just lose the &. myAudioData is a pointer to the start address, so add the offst to that.

    With the & you’re copying into memory at the end of and following your AQPlayerState struct.


    memcpy (pAqData->myAudioData + pAqData->myAudioDataByteSize,
    (void*) inInputData,
    inNumberBytes);

  2. Ross

    Quick question – what is the value of myAudioDataByteSize just before you call memcpy ? If you haven’t initialised it, it could some random large value that blows your buffer.

    Once you have created your struct, then do the following assuming it is created on the stack somewhere.

    memset( &myStruct, 0, sizeof( AQPlayerState ) );

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.