Re: Buffer overrun management with TPCircularBuffer.. best way to do so?
Re: Buffer overrun management with TPCircularBuffer.. best way to do so?
- Subject: Re: Buffer overrun management with TPCircularBuffer.. best way to do so?
- From: Douglas Carmichael <email@hidden>
- Date: Mon, 05 May 2014 13:16:38 -0500
Kyle:
I’ve looked at TAAE, but it seems to be iOS-only and have only experimental support for OS X.
Would you suggest any other abstraction libraries?
—Douglas
On May 5, 2014, at 11:50 AM, Kyle Sluder <email@hidden> wrote:
> On May 4, 2014, at 2:59 PM, Douglas Carmichael <email@hidden> wrote:
>>
>> Ross:
>>
>> Thanks again for your help!
>>
>> You mentioned passing ‘StreamData *’ down to the callback.
>>
>> When I try setting ‘struct StreamData *’ for inRefCon, I get ‘conflicting types for renderModuleCallback.’
>>
>> Also, how should I be referring to the ringBuffer element itself within the callback?
>>
>> I tried using ‘&inRefCon->ringBuffer’ for TPCircularBufferTail(), but it says ‘incompatible pointer types passing struct StreamData * to parameter of type TPCircularBuffer *’.
>>
>> But, ‘&ourStream.ringBuffer’ works fine within main().
>>
>> Any idea?
>
> If I may be frank, I'm worried that if you are unfamiliar enough with C to be stymied by syntax errors like this, you may not understand enough to be doing low-level audio programming. Audio unit render callbacks operate under some very specific conditions that require a certain level of expertise with multiprocessing in addition to comfort with Core Audio's very-much-C API.
>
> Perhaps you can operate at a higher level of abstraction. Have you looked into The Amazing Audio Engine? <http://theamazingaudioengine.com> That framework does all of the plumbing for you, so you might only have to write a simple function or block that calls your decoder library.
>
> --Kyle Sluder
>
>
>>
>> Thanks in advance!
>>
>> —Douglas
>>
>>> On May 3, 2014, at 9:36 PM, Ross Bencina <email@hidden> wrote:
>>>
>>>> On 4/05/2014 11:55 AM, Douglas Carmichael wrote:
>>>> Are the semaphore-handling functions available as library functions in OS X?
>>>
>>> Yes, they are a standard Unix synchronisation primitive:
>>>
>>> https://developer.apple.com/library/mac/documentation/Darwin/Reference/Manpages/man2/sem_open.2.html
>>>
>>>
>>>
>>>> How would I get the size of one frame for the device and number of bytes in the TPCircularBuffer?
>>>
>>> No idea. The codec frame size will be related to your decoding routines.
>>>
>>> I think someone already posted how to get the number of free bytes in TPCircularBuffer -- I've never used it.
>>>
>>> I usually use the PortAudio ring buffer, which has a function to query for the available space.
>>>
>>> http://portaudio.com/docs/v19-doxydocs-dev/pa__ringbuffer_8h.html
>>>
>>> Ross.
>>>
>>>
>>>
>>>> --Douglas
>>>>
>>>>> On May 3, 2014, at 7:41 PM, Ross Bencina <email@hidden> wrote:
>>>>>
>>>>> Hi,
>>>>>
>>>>>> On 4/05/2014 6:34 AM, Kyle Sluder wrote:
>>>>>> Perhaps I should have avoided the term semaphore. You don't want to
>>>>>> actually use a real semaphore because you must not block the render
>>>>>> callback thread.
>>>>>
>>>>> I think a semaphore is exactly what is needed.
>>>>>
>>>>> A semaphore will not block when signaled, especially if the signaling thread has higher priority than the waiting thread. This is guaranteed by the documentation.
>>>>>
>>>>> The schema is:
>>>>>
>>>>> The producer thread produces data until the ringbuffer is full. Then it waits on the semaphore until the consumer signals the semaphore. Essentially something like:
>>>>>
>>>>> // producer
>>>>> for(;;){
>>>>> while (!ringbuffer.isFull()) produceData();
>>>>> semaphore->wait();
>>>>> }
>>>>>
>>>>>
>>>>> The consumer (in this case, the render callback) siphons data out of the ring buffer. When the available free space in the ring buffer exceeds some threshold (e.g. the free space becomes greater than one codec frame) the consumer signals the semaphore.
>>>>>
>>>>> // consumer
>>>>> readDataFromRingbuffer();
>>>>> if (ringBuffer.fillLevel() < fillThreshold)
>>>>> semaphore->signal();
>>>>>
>>>>>
>>>>> To avoid redundant signaling you should only signal the semaphore once for every time threshold is crossed.
>>>>>
>>>>> --------
>>>>>
>>>>>> Would I need to pass the semaphore down to the rendering callback
>>>>>> along with the TPCircularBuffer?
>>>>>
>>>>> Yes.
>>>>>
>>>>>> How would I do that?
>>>>>
>>>>> You're passing a pointer to the render callback right? Well pass a pointer to a struct that contains all the data you need:
>>>>>
>>>>> struct StreamData {
>>>>> TPCircularBuffer ringbuffer;
>>>>> sem_t semaphore;
>>>>> int fillThreshold;
>>>>> ... etc ...
>>>>> };
>>>>>
>>>>> Pass a StreamData * to the render callback.
>>>>>
>>>>>
>>>>> Ross.
>>
>
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden