The main issue as far as I can tell is that you must be careful to not block in the Audio render callback (note that I didn't mention a separate audio thread, because the API appears to be agnostic to this implementation detail). This means that if you have more processing to do, you've got to do it right then (afaik it's not a no-no to do some processing in the render callback). So what you've got here is a producer-consumer problem with the caveat that you may have to switch the execution context over if your consumer is starved.
I would say that if you think about this, and perhaps write a custom runloop source for the producer, that you may well be able to get this all working without any locks whatsoever.
In fact, now that I've thought about this some more, you should just be able to have two global queues and no RunLoop Sources (if you don't mind polling and wasting cpu). Your producer would pull a buffer out of the "empty" queue, fill it and once it's absolutely done, toss it into the "complete" queue. Your consumer would pull from the complete queue, or send a buffer filled with one single value (memset would come in handy). You can put the buffer back into the empty queue at the very beginning of the next audio interrupt. If two buffers isn't enough, consider using more. Also, consider sending as much data to the converter as requested.
_Mark On May 7, 2007, at 2:52 PM, B. Mitchell Loebel wrote: Thank you Mark and the several other members of this list ... superb! I still have a few questions: - your function 'AudioConverterFillComplexBuffer ()' is the function I will use to fill a buffer to which the AU will refer to obtain data. My app has two buffers and I want to assign a pointer (ioData) to a filled buffer each time the callback function is called. Important ... how do I synchronize my app's setting (writing) the buffer pointer and the AU's using (reading) that pointer? Mutexes, semaphores ... ????
- Here's a cute question ... my buffers are 80 samples long with each sample being 2 bytes wide. If my processing is not yet ready to hand off a full buffer to the AU, I want the AU to use the last single sample from the current buffer until I'm ready. And I want the AU to continue checking to see if I'm ready, i.e. poll. Of course, a better way would be for the AU to continue using the last sample until my thread pulls an interrupt to hand off the OK buffer pointer. How do you suggest I do these things please?
- What is meant by 'inBusNumber' and 'inNumberFrames' in the renderCallback() function?
Thank you again. At 11:59 AM 5/7/2007 -0700, Mark Pauley wrote: Posting this back to the list, as the example I'm posting should go to the archives.
I applaud your stubbornness, and would like to say that your post was intriguing enough for me to wonder if I could do this easily.
So... over the weekend, I wrote more or less what you're talking about: a command-line C tool that can render to a signed-16bit buffer at 16khz. The code posted at the bottom is essentially the simplest code I could think up for doing what you ask, it took me about 2.5 hours from start to finish to get it up and running, then I went outside because the weather was nice :). Let me know if it works for you, and if you have any questions. I agree that such an example may be useful to those who wish to keep to the lowest common denominator. If you'd like the program to end a bit more gracefully than ctrl-c then you'll have to install a signal handler or some such that stops the main runloop.
_Mark
~~~~~~~~~~~ (snipped ... see previous email from Mark for the code he suggested. I am attaching his code to this email, but I'm not sure if the list supports attachments.) --- B. Mitchell Loebel, Executive Director 408 425-9920
The Tech Startup Connection (formerly The PARALLEL Processing Connection) <MacOutputSound.doc>
|