<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>A Tasty Pixel » Blog &#187; Audio</title>
	<atom:link href="http://atastypixel.com/blog/tag/audio/feed/" rel="self" type="application/rss+xml" />
	<link>http://atastypixel.com/blog</link>
	<description></description>
	<lastBuildDate>Wed, 16 May 2012 11:07:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>The Amazing Audio Engine: Funky Remote IO-based Core Audio Engine Coming Soon</title>
		<link>http://atastypixel.com/blog/the-amazing-audio-engine-funky-remote-io-based-core-audio-engine-coming-soon/</link>
		<comments>http://atastypixel.com/blog/the-amazing-audio-engine-funky-remote-io-based-core-audio-engine-coming-soon/#comments</comments>
		<pubDate>Sat, 17 Mar 2012 22:14:38 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Products]]></category>
		<category><![CDATA[Announcement]]></category>
		<category><![CDATA[Audio]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[iOS]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=2486</guid>
		<description><![CDATA[Huzzah! I&#8217;m announcing a new project which will be launching over the next couple of months. It&#8217;s called The Amazing Audio Engine, and it represents the product of years of experience with iOS audio. It&#8217;s a sophisticated iOS audio engine that lets developers skip the Core Audio learning curve, and get on with writing great [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://theamazingaudioengine.com"><img src="http://atastypixel.com/blog/wp-content/uploads/2012/03/amazingaudioengine.jpg" alt="The Amazing Audio Engine" title="amazingaudioengine.jpg" border="0" width="400" height="266" style="float:right; margin-left: 10px; margin-bottom: 10px;" class="alignright" /></a>Huzzah! I&#8217;m announcing a new project which will be launching over the next couple of months.</p>

<p>It&#8217;s called <a href="http://theamazingaudioengine.com">The Amazing Audio Engine</a>, and it represents the product of years of experience with iOS audio. It&#8217;s a sophisticated iOS audio engine that lets developers skip the Core Audio learning curve, and get on with writing great software.</p>

<p>The tech behind this is what drives <a href="http://loopyapp.com">Loopy and Loopy HD</a>, as well as the in-development <a href="http://audiob.us">Audiobus</a> app.</p>

<p><a href="http://theamazingaudioengine.com">Subscribe at theamazingaudioengine.com</a> to be kept in the loop as it approaches launch time.</p>

<p>Some of the features:</p>

<ul>
<li>Automatic mixing of multiple audio signals with per-channel volume and pan controls.</li>
<li>Built-in support for audio filtering and effects, including the ability to form complex filter chains, constructing channel groups, or even whole trees of groups, and filtering them as one composite signal.</li>
<li>Built-in support for audio input, including optional use of the Voice Processing IO unit, for automatic echo removal &#8211; great for VoIP.</li>
<li>Record or monitor the output of the whole audio system, for in-app session recording, or get the output of one channel, or any group of channels in the processing tree.</li>
<li>Support for any audio format (AudioStreamBasicDescription) that the hardware supports: Interleaved, non-interleaved, mono, stereo, 44.1kHz or any other supported sample rate, 16-bit, 8.24 fixed floating-point &#8211; whatever you need for your project.</li>
<li>Very light, efficient engine, designed from the ground up for speed. All Core Audio code is pure C; no Objective-   C or BSD calls, no locks, no memory allocation.</li>
<li>Efficient mixing of input signals, using Apple&#8217;s MultiChannelMixer.</li>
<li>Fast, lock-free synchronisation mechanism, enabling developers to send messages to the main thread from the Core Audio context, and vice versa, without
        locking or memory allocation from the Core Audio thread.  Message sending from the main thread is two-way, and can be asynchronous, with a response
        block, or synchronous.</li>
</ul>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=2486" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/the-amazing-audio-engine-funky-remote-io-based-core-audio-engine-coming-soon/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Some updates to TPCircularBuffer</title>
		<link>http://atastypixel.com/blog/some-updates-to-tpcircularbuffer/</link>
		<comments>http://atastypixel.com/blog/some-updates-to-tpcircularbuffer/#comments</comments>
		<pubDate>Tue, 14 Feb 2012 10:28:09 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Audio]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Optimisation]]></category>
		<category><![CDATA[Update]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=2450</guid>
		<description><![CDATA[I&#8217;ve recently made some updates to TPCircularBuffer (on GitHub), my C circular/ring buffer implementation, which add a memory barrier on read and write, inline the main functions for a potential performance boost, and add support for use within C++ projects. If you&#8217;re using TPCircularBuffer at all, I recommend updating!]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve recently made some updates to <a href="http://atastypixel.com/blog/circular-ring-buffer-plus-neat-virtual-memory-mapping-trick/">TPCircularBuffer</a> (<a href="https://github.com/michaeltyson/TPCircularBuffer">on GitHub</a>), my C circular/ring buffer implementation, which add a memory barrier on read and write, inline the main functions for a potential performance boost, and add support for use within C++ projects.</p>

<p>If you&#8217;re using TPCircularBuffer at all, I recommend updating!</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=2450" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/some-updates-to-tpcircularbuffer/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Circular (ring) buffer plus neat virtual memory mapping trick</title>
		<link>http://atastypixel.com/blog/circular-ring-buffer-plus-neat-virtual-memory-mapping-trick/</link>
		<comments>http://atastypixel.com/blog/circular-ring-buffer-plus-neat-virtual-memory-mapping-trick/#comments</comments>
		<pubDate>Sat, 10 Dec 2011 13:13:20 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Audio]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Optimisation]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=2370</guid>
		<description><![CDATA[I&#8217;ve just updated my C circular buffer implementation, adopting the trick originally proposed by Philip Howard and adapted to Darwin by Kurt Revis: A virtual copy of the buffer is inserted directly after the end of the buffer, so that you can write past the end of the buffer, but have your writes automatically wrapped [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just updated my <a href="http://atastypixel.com/blog/a-simple-fast-circular-buffer-implementation-for-audio-processing/">C circular buffer implementation</a>, adopting the trick originally proposed by <a href="http://vrb.slashusr.org/">Philip Howard</a> and <a href="http://www.snoize.com/Code/PlayBufferedSoundFile.tar.gz">adapted to Darwin</a> by <a href="http://www.snoize.com">Kurt Revis</a>: A virtual copy of the buffer is inserted directly after the end of the buffer, so that you can write past the end of the buffer, but have your writes automatically wrapped around to the start &#8212; no need to manually implement buffer wrapping logic.</p>

<p>This dramatically simplifies the use of a circular buffer &#8212; you can use chunks of the buffer without any need to worry about where the wrap point is.</p>

<p>See the new implementation, which is thread-safe with one consumer and one producer, with no need for locks, making it perfect for use with high-priority Core Audio threads, on <a href="https://github.com/michaeltyson/TPCircularBuffer">GitHub: TPCircularBuffer</a>.</p>

<p>There&#8217;s a basic example of its use over on the <a href="http://atastypixel.com/blog/a-simple-fast-circular-buffer-implementation-for-audio-processing/">original post</a>.</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=2370" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/circular-ring-buffer-plus-neat-virtual-memory-mapping-trick/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Experiments with precise timing in iOS</title>
		<link>http://atastypixel.com/blog/experiments-with-precise-timing-in-ios/</link>
		<comments>http://atastypixel.com/blog/experiments-with-precise-timing-in-ios/#comments</comments>
		<pubDate>Wed, 07 Sep 2011 16:31:18 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Audio]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Timing]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=2265</guid>
		<description><![CDATA[iOS is by no means a realtime operating system, but I&#8217;m aware that NSTimer and NSObject&#8217;s performSelector:withObject:afterDelay: mechanism aren&#8217;t particularly accurate, and I was curious to see whether I could do better. Hands up, backing away Disclaimer: I am not at all an expert in realtime programming, or Mach, or iOS-device optimisation, so this is [...]]]></description>
			<content:encoded><![CDATA[<p>iOS is by no means a realtime operating system, but I&#8217;m aware that NSTimer and NSObject&#8217;s <em>performSelector:withObject:afterDelay:</em> mechanism aren&#8217;t particularly accurate, and I was curious to see whether I could do better.</p>

<h3>Hands up, backing away</h3>

<p>Disclaimer: I am not at all an expert in realtime programming, or Mach, or iOS-device optimisation, so this is pretty much a fumble in the dark.   I won&#8217;t be at all offended if anyone wishes to shoot me down and offer a more sensible solution &#8212; in fact, please do! Until then, watch as I stumble on…</p>

<p>Also note that there are often ways to eliminate the need for precise timing of this nature, by architecting code appropriately &#8212; when it comes to audio, for example, CoreAudio provides a very accurate time base in render callbacks.  For things like metronomes or audio synthesizers, it&#8217;s always better to establish a starting time, and use the difference between the current time and the starting time in order to determine state, rather than using a timer to advance the state.  Still, sometimes, you just need a timer…</p>

<h3>What the blazes?</h3>

<p>So, I&#8217;m working on an update to <a href="http://loopyapp.com">Loopy</a>, which uses a shared clock object to synchronise tracks and a variety of events (like user interface updates or timed track manipulations).  A tester noted that the mute/unmute quantisation feature that I&#8217;ve recently implemented, which will mute or unmute a loop at its starting point (rather than whenever you tap it), tends to overshoot a little, resulting in a small part of the beginning of the loop being audible.</p>

<p>Of course, there are other solutions to this particular problem (like stopping or starting playback from the audio render callback, and using Core Audio&#8217;s timestamps for exact timing), but I use timers in other places outside Core Audio&#8217;s domain, which makes Core Audio&#8217;s timing mechanism unavailable, and I wanted to see how accurate I could get the timing.</p>

<h3>Our friend, <em>mach_wait_until</em></h3>

<p>I read in several places mention of the Mach API utility <em>mach_wait_until</em> (from <em>mach/mach_time.h</em>), which is very low-level and supposedly fairly accurate.  So, based on that lead, I put together an Objective-C singleton class that launches a high-priority thread, and uses said thread to schedule events.</p>

<p>An NSArray of events are maintained, and a <em>scheduleAction:target:inTimeInterval:</em> routine creates and adds events to this array, then pokes the thread.</p>

<p>The thread grabs the next event in sequence, then uses <em>mach_wait_until</em> to sleep until the time of the next event arrives, then performs the specified action on the target.  It&#8217;s kinda a DIY NSRunLoop.</p>

<p>Here&#8217;s a comparison between this technique, and just using <em>performSelector:withObject:afterDelay:</em> (which schedules a timer on the NSRunLoop), observed while performing various scheduled events within Loopy running on my iPhone 4 with the debugger, and derived by comparing the time of event execution with the event&#8217;s scheduled time:</p>

<table>
<tr><th>Mechanism</th><th>Average discrepancy</th><th>Minimum discrepancy</th><th>Maximum discrepancy</th></tr>
<tr><td><strong>NSRunLoop</strong></td><td>16.9ms</td><td>0.25ms</td><td>153.7ms</td></tr>
<tr><td><strong>TPPreciseTimer</strong></td><td>5.5ms</td><td>0.033ms</td><td>72.0ms</td></tr>
</table>

<p>That was attempt number 1: This seems to give us about 11.4ms better accuracy on average (three times more accurate).</p>

<p>Not bad, but it turns out <em>mach_wait_until</em> isn&#8217;t really that accurate, particularly if there&#8217;s a bunch of other stuff going on in other threads.</p>

<h3>Spinning, for fun and profit</h3>

<p>For my second attempt, the thread performs a <em>mach_wait_until</em> until just before the event is due, then performs a spin lock until the time arrives, using <em>mach_absolute_time</em> to compare the current time with the target time.</p>

<p>This gave further improved results &#8212; here&#8217;s that table again, but with the new scheme added, with a few different spin lock times:</p>

<table>
<tr><th>Mechanism</th><th>Average discrepancy</th><th>Minimum discrepancy</th><th>Maximum discrepancy</th></tr>
<tr><td><strong>NSRunLoop</strong></td><td>16.9ms</td><td>0.25ms</td><td>153.7ms</td></tr>
<tr><td><strong>TPPreciseTimer (original)</strong></td><td>5.5ms</td><td>0.033ms</td><td>72.0ms</td></tr>
<tr><td><strong>TPPreciseTimer (10ms spinlock)</strong></td><td>6.0ms</td><td>0.002ms</td><td>76.5ms</td></tr>
<tr><td><strong>TPPreciseTimer (100ms spinlock)</strong></td><td>3.7ms</td><td>0.002ms</td><td>44.8ms</td></tr>
<tr><td><strong>TPPreciseTimer (200ms spinlock)</strong></td><td>2.91ms</td><td>0.002ms</td><td>74.1ms</td></tr>
</table>

<p>It appears that the more stuff there is going on in other threads, the more likely the <em>mach_absolute_time</em> call is to overshoot.  So, the more time spent in the spin lock, the more leeway <em>mach_absolute_time</em> has to wait too long.  Of course, that&#8217;s at the cost of making the CPU twiddle its thumbs for the duration.</p>

<h3>Better than a punch in the knee</h3>

<p>The results weren&#8217;t quite as fantastic as I&#8217;d hoped &#8212; still within the same order of magnitude, that&#8217;s for sure &#8212; but the average case for the 200ms spinlock approach is 14ms, or 5.8 times, more accurate than the traditional approach, and the minimum case is dramatically better.</p>

<p>You know, I think if I was aware of the results in advance, I might not bother, but I&#8217;ll stick with my hard-won 14ms now that I&#8217;m here (that&#8217;s 617 audio samples, I&#8217;ll have you know).</p>

<p>If anyone&#8217;s curious about the implementation (or wants to take a stab at doing better), here it is, along with a wildly simplistic commandline test app: <a href="http://atastypixel.com/blog/wp-content/uploads/2011/09/TPPreciseTimer.zip" title="TPPreciseTimer.zip" alt="TPPreciseTimer">TPPreciseTimer.zip</a></p>

<p>Now to get back to some real work.</p>

<h3>Addendum: GCD follow-up</h3>

<p>Chris in the comments below suggested trying a GCD-based approach, using <em>dispatch_after</em>.  Curious, I rigged it up, and these are the stats, collected the same way as above, added to the prior table:</p>

<table>
<tr><th>Mechanism</th><th>Average discrepancy</th><th>Minimum discrepancy</th><th>Maximum discrepancy</th></tr>
<tr><td><strong>NSRunLoop</strong></td><td>16.9ms</td><td>0.25ms</td><td>153.7ms</td></tr>
<tr><td><strong>TPPreciseTimer (original)</strong></td><td>5.5ms</td><td>0.033ms</td><td>72.0ms</td></tr>
<tr><td><strong>TPPreciseTimer (10ms spinlock)</strong></td><td>6.0ms</td><td>0.002ms</td><td>76.5ms</td></tr>
<tr><td><strong>TPPreciseTimer (100ms spinlock)</strong></td><td>3.7ms</td><td>0.002ms</td><td>44.8ms</td></tr>
<tr><td><strong>TPPreciseTimer (200ms spinlock)</strong></td><td>2.91ms</td><td>0.002ms</td><td>74.1ms</td></tr>
<tr><td><strong>dispatch_after (main queue)</strong></td><td>14.8ms</td><td>0.16ms</td><td>161.2ms</td></tr>
<tr><td><strong>dispatch_after (dedicated queue)</strong></td><td>19.2ms</td><td>0.1ms</td><td>174.9ms</td></tr>
<tr><td><strong>dispatch_after (dedicated queue + 100ms spinlock)</strong></td><td>22.4ms</td><td>0.002ms</td><td>306.8ms</td></tr>
</table>

<p>So, they appear pretty much the same as the NSRunLoop stats.</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=2265" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/experiments-with-precise-timing-in-ios/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
		</item>
		<item>
		<title>Easy AAC compressed audio conversion on iOS</title>
		<link>http://atastypixel.com/blog/easy-aac-compressed-audio-conversion-on-ios/</link>
		<comments>http://atastypixel.com/blog/easy-aac-compressed-audio-conversion-on-ios/#comments</comments>
		<pubDate>Sat, 02 Apr 2011 22:55:33 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Audio]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=2176</guid>
		<description><![CDATA[From the iPhone 3Gs up, it&#8217;s possible to encode compressed AAC audio from PCM audio data. That means great things for apps that deal with audio sharing and transmission, as the audio can be sent in compressed form, rather than sending huge PCM audio files over the network. Apple&#8217;s produced some sample code (iPhoneExtAudioFileConvertTest), which [...]]]></description>
			<content:encoded><![CDATA[<p>From the iPhone 3Gs up, it&#8217;s possible to encode compressed AAC audio from PCM audio data.  That means great things for apps that deal with audio sharing and transmission, as the audio can be sent in compressed form, rather than sending huge PCM audio files over the network.</p>

<p>Apple&#8217;s produced some <a href="http://developer.apple.com/library/ios/samplecode/iPhoneExtAudioFileConvertTest/Introduction/Intro.html">sample code (iPhoneExtAudioFileConvertTest)</a>, which demonstrates how it&#8217;s done, but their implementation isn&#8217;t particularly easy to use in existing projects, as it requires some wrapping to make it play nice.</p>

<p>For my upcoming looper app <a href="http://loopyapp.com">Loopy</a>, I&#8217;ve put together a simple Objective-C class that performs the conversion of any audio file to an AAC-encoded m4a, asynchronously with a delegate, or converts any audio provided by a data source class (which provides for recording straight to AAC) and I thought I&#8217;d share it.<span id="more-2176"></span></p>

<p></p>

<p>Grab the code, and a sample project demonstrating its use at the <a href="https://github.com/michaeltyson/TPAACAudioConverter">GitHub repository for TPAACAudioConverter</a>.</p>

<p>To use it:</p>

<ul>
<li>Include the class in your project, and make sure you&#8217;ve got the <em>AudioToolbox</em> framework added, too.</li>
<li>Audio session setup: </li>
</ul>

<p>If you already have an audio session set up in your app, make sure you disable mixing with other device audio for the duration of the copy operation, as this stops the hardware encoder from working (you&#8217;ll see funny errors like <code>kAudioQueueErr_InvalidCodecAccess</code> (Error 66672)).  I know that <code>AVAudioSessionCategoryPlayAndRecord</code>, <code>AVAudioSessionCategorySoloAmbient</code> and <code>AVAudioSessionCategoryAudioProcessing</code> work for sure.  <code>TPAACAudioConverter</code> will automatically disable <code>kAudioSessionProperty_OverrideCategoryMixWithOthers</code>, if it&#8217;s set.</p>

<p>If you&#8217;re not already setting up an audio session, you could do so just before you start the conversion process.</p>

<p>You&#8217;ll need to provide an interruption handler to be notified of audio session interruptions, which impact the encoding process.  You&#8217;ll also need to create a member variable to store the converter instance, so you can tell it when interruptions begin and end (via <code>interrupt</code> and <code>resume</code>).</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Callback to be notified of audio session interruptions (which have an impact on the conversion process)</span>
<span style="color: #a61390;">static</span> <span style="color: #a61390;">void</span> interruptionListener<span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span> <span style="color: #002200;">*</span>inClientData, UInt32 inInterruption<span style="color: #002200;">&#41;</span>
<span style="color: #002200;">&#123;</span>
	AACConverterViewController <span style="color: #002200;">*</span>THIS <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>AACConverterViewController <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>inClientData;
&nbsp;
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>inInterruption <span style="color: #002200;">==</span> kAudioSessionEndInterruption<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
		<span style="color: #11740a; font-style: italic;">// make sure we are again the active session</span>
		checkResult<span style="color: #002200;">&#40;</span>AudioSessionSetActive<span style="color: #002200;">&#40;</span><span style="color: #a61390;">true</span><span style="color: #002200;">&#41;</span>, <span style="color: #bf1d1a;">&quot;resume audio session&quot;</span><span style="color: #002200;">&#41;</span>;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> THIS<span style="color: #002200;">-</span>&gt;audioConverter <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#91;</span>THIS<span style="color: #002200;">-</span>&gt;audioConverter resume<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#125;</span>
&nbsp;
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>inInterruption <span style="color: #002200;">==</span> kAudioSessionBeginInterruption<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> THIS<span style="color: #002200;">-</span>&gt;audioConverter <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#91;</span>THIS<span style="color: #002200;">-</span>&gt;audioConverter interrupt<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">/*snip*/</span>
&nbsp;
<span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>startConverting <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">/*snip*/</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Initialise audio session, and register an interruption listener, important for AAC conversion</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> <span style="color: #002200;">!</span>checkResult<span style="color: #002200;">&#40;</span>AudioSessionInitialize<span style="color: #002200;">&#40;</span><span style="color: #a61390;">NULL</span>, <span style="color: #a61390;">NULL</span>, interruptionListener, self<span style="color: #002200;">&#41;</span>, <span style="color: #bf1d1a;">&quot;initialise audio session&quot;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIAlertView alloc<span style="color: #002200;">&#93;</span> initWithTitle<span style="color: #002200;">:</span>NSLocalizedString<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Converting audio&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;&quot;</span><span style="color: #002200;">&#41;</span>
                                     message<span style="color: #002200;">:</span>NSLocalizedString<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Couldn't initialise audio session!&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;&quot;</span><span style="color: #002200;">&#41;</span>
                                    delegate<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span>
                           cancelButtonTitle<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span>
                           otherButtonTitles<span style="color: #002200;">:</span>NSLocalizedString<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;OK&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;&quot;</span><span style="color: #002200;">&#41;</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span> show<span style="color: #002200;">&#93;</span>;
        <span style="color: #a61390;">return</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Set up an audio session compatible with AAC conversion.  Note that AAC conversion is incompatible with any session that provides mixing with other device audio.</span>
    UInt32 audioCategory <span style="color: #002200;">=</span> kAudioSessionCategory_MediaPlayback;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> <span style="color: #002200;">!</span>checkResult<span style="color: #002200;">&#40;</span>AudioSessionSetProperty<span style="color: #002200;">&#40;</span>kAudioSessionProperty_AudioCategory, <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>audioCategory<span style="color: #002200;">&#41;</span>, <span style="color: #002200;">&amp;</span>audioCategory<span style="color: #002200;">&#41;</span>, <span style="color: #bf1d1a;">&quot;setup session category&quot;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>UIAlertView alloc<span style="color: #002200;">&#93;</span> initWithTitle<span style="color: #002200;">:</span>NSLocalizedString<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Converting audio&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;&quot;</span><span style="color: #002200;">&#41;</span>
                                     message<span style="color: #002200;">:</span>NSLocalizedString<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Couldn't setup audio category!&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;&quot;</span><span style="color: #002200;">&#41;</span>
                                    delegate<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span>
                           cancelButtonTitle<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span>
                           otherButtonTitles<span style="color: #002200;">:</span>NSLocalizedString<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;OK&quot;</span>, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;&quot;</span><span style="color: #002200;">&#41;</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span> show<span style="color: #002200;">&#93;</span>;
        <span style="color: #a61390;">return</span>;
    <span style="color: #002200;">&#125;</span> 
&nbsp;
&nbsp;
    <span style="color: #11740a; font-style: italic;">/*snip*/</span>
<span style="color: #002200;">&#125;</span></pre></div></div>


<ul>
<li>Make the relevant view controller implement the <code>TPAACAudioConverterDelegate</code> protocol: That means implementing <code>AACAudioConverterDidFinishConversion:</code>, and  <code>AACAudioConverter:didFailWithError:</code>, and optionally <code>AACAudioConverter:didMakeProgress:</code> to receive progress updates.</li>
<li>Create an instance of the converter, pass it the view controller as the delegate, and call <code>start</code>:</li>
</ul>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">audioConverter <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>TPAACAudioConverter alloc<span style="color: #002200;">&#93;</span> initWithDelegate<span style="color: #002200;">:</span>self 
                                                         source<span style="color: #002200;">:</span>mySourcePath
                                                    destination<span style="color: #002200;">:</span>myDestinationPath<span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
&nbsp;
<span style="color: #002200;">&#91;</span>audioConverter start<span style="color: #002200;">&#93;</span>;</pre></div></div>


<p>Alternatively, if you wish to encode live audio, or provide another source of audio data, you can implement the <code>TPAACAudioConverterDataSource</code> protocol, which defines <code>AACAudioConverter:nextBytes:length:</code>, which provides a buffer to copy at most &#8220;length&#8221; bytes of audio into, and then expects you to update &#8220;length&#8221; to the amount of bytes provided.  For that you&#8217;ll need to use the second initialiser, <code>initWithDelegate:dataSource:audioFormat:destination:</code>.</p>

<p>I noted previously that you can&#8217;t encode AAC live, which is what Apple&#8217;s docs say, but Alex in the comments informed me that it wasn&#8217;t so.  So, I added the datasource method, and sure enough, it does work live!</p>

<p>The one caveat is that it&#8217;s a relatively heavy process.  As it turns out, because my app Loopy is busily mixing and displaying visualisations and such, it was too much to also encode straight to AAC, and I was getting glitches.  But it would probably work fine for plain recording.  Thanks, Alex!</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=2176" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/easy-aac-compressed-audio-conversion-on-ios/feed/</wfw:commentRss>
		<slash:comments>43</slash:comments>
		</item>
		<item>
		<title>A simple, fast circular buffer implementation for audio processing</title>
		<link>http://atastypixel.com/blog/a-simple-fast-circular-buffer-implementation-for-audio-processing/</link>
		<comments>http://atastypixel.com/blog/a-simple-fast-circular-buffer-implementation-for-audio-processing/#comments</comments>
		<pubDate>Thu, 24 Mar 2011 16:06:45 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Audio]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Optimisation]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=2166</guid>
		<description><![CDATA[Circular buffers are pretty much what they sound like &#8211; arrays that wrap around. They&#8217;re fantastically useful as scratch space for audio processing, and generally passing audio around efficiently. They&#8217;re designed for FIFO (first-in-first-out) use, like storing audio coming in the microphone for later playback or processing. Consider a naive alternative: You copy the incoming [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://en.wikipedia.org/wiki/Circular_buffer">Circular buffers</a> are pretty much what they sound like &#8211; arrays that wrap around.  They&#8217;re fantastically useful as scratch space for audio processing, and generally passing audio around efficiently.</p>

<p>They&#8217;re designed for FIFO (first-in-first-out) use, like storing audio coming in the microphone for later playback or processing.</p>

<p>Consider a naive alternative: You copy the incoming audio into an NSData you allocate, and then pass that NSData off.  This means you&#8217;re allocating memory each time, and deallocating the memory later once you&#8217;re done processing.  That allocation incurs a penalty, which can be a show-stopper when part of an audio pipeline &#8211; The Core Audio documentation advises against any allocations when within a render callback, for example.</p>

<p>Alternatively, you can allocate space in advance, and write to that, but that has problems too: Either you have a synchronisation nightmare, or you spend lots of time moving bytes around so that the unprocessed audio is always at the beginning of the array.</p>

<p>A better solution is to use a circular buffer, where data goes in at the <em>head</em>, and is read from the <em>tail</em>.  When you produce data at the head, the head moves up the array, and wraps around at the end.  When you consume at the tail, the tail moves up too, so the tail chases the head around the circle.</p>

<p>Here&#8217;s a simple C implementation I recently put together for my app Loopy:  <a href="https://github.com/michaeltyson/TPCircularBuffer">TPCircularBuffer</a><span id="more-2166"></span></p>


<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">typedef</span> <span style="color: #993333;">struct</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">void</span>             <span style="color: #339933;">*</span>buffer<span style="color: #339933;">;</span>
    <span style="color: #993333;">int32_t</span>           length<span style="color: #339933;">;</span>
    <span style="color: #993333;">int32_t</span>           tail<span style="color: #339933;">;</span>
    <span style="color: #993333;">int32_t</span>           head<span style="color: #339933;">;</span>
    <span style="color: #993333;">volatile</span> <span style="color: #993333;">int32_t</span>  fillCount<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> TPCircularBuffer<span style="color: #339933;">;</span>
&nbsp;
bool  TPCircularBufferInit<span style="color: #009900;">&#40;</span>TPCircularBuffer <span style="color: #339933;">*</span>buffer<span style="color: #339933;">,</span> <span style="color: #993333;">int32_t</span> length<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">void</span>  TPCircularBufferCleanup<span style="color: #009900;">&#40;</span>TPCircularBuffer <span style="color: #339933;">*</span>buffer<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">void</span>  TPCircularBufferClear<span style="color: #009900;">&#40;</span>TPCircularBuffer <span style="color: #339933;">*</span>buffer<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Reading (consuming)</span>
<span style="color: #993333;">void</span><span style="color: #339933;">*</span> TPCircularBufferTail<span style="color: #009900;">&#40;</span>TPCircularBuffer <span style="color: #339933;">*</span>buffer<span style="color: #339933;">,</span> <span style="color: #993333;">int32_t</span><span style="color: #339933;">*</span> availableBytes<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">void</span>  TPCircularBufferConsume<span style="color: #009900;">&#40;</span>TPCircularBuffer <span style="color: #339933;">*</span>buffer<span style="color: #339933;">,</span> <span style="color: #993333;">int32_t</span> amount<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Writing (producing)</span>
<span style="color: #993333;">void</span><span style="color: #339933;">*</span> TPCircularBufferHead<span style="color: #009900;">&#40;</span>TPCircularBuffer <span style="color: #339933;">*</span>buffer<span style="color: #339933;">,</span> <span style="color: #993333;">int32_t</span><span style="color: #339933;">*</span> availableBytes<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">void</span>  TPCircularBufferProduce<span style="color: #009900;">&#40;</span>TPCircularBuffer <span style="color: #339933;">*</span>buffer<span style="color: #339933;">,</span> <span style="color: #993333;">int32_t</span> amount<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">int</span>   TPCircularBufferProduceBytes<span style="color: #009900;">&#40;</span>TPCircularBuffer <span style="color: #339933;">*</span>buffer<span style="color: #339933;">,</span> <span style="color: #993333;">const</span> <span style="color: #993333;">void</span><span style="color: #339933;">*</span> src<span style="color: #339933;">,</span> <span style="color: #993333;">int32_t</span> len<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>


<p><strong>Update</strong>: The implementation has been recently amended to make use of a neat virtual memory mapping technique that inserts a virtual copy of the buffer memory directly after the buffer&#8217;s end, negating the need for any buffer wrap-around logic. Clients can simply use the returned memory address as if it were contiguous space.</p>

<p>The virtual memory technique was originally proposed by <a href="http://vrb.slashusr.org/">Philip Howard</a>, and <a href="http://www.snoize.com/Code/PlayBufferedSoundFile.tar.gz">adapted</a> to Darwin by <a href="http://www.snoize.com">Kurt Revis</a>.</p>

<p>Use <code>TPCircularBufferHead</code> to get a pointer to write to the buffer, followed by <code>TPCircularBufferProduce</code> to submit the written data, then <code>TPCircularBufferTail</code> to get a pointer to the next data to read, followed by <code>TPCircularBufferConsume</code> to free up the space once processed.</p>

<p><code>TPCircularBufferProduceBytes</code> is a convenience routine for writing data straight to the buffer.</p>

<p>The implementation is thread-safe (no need for locks) in the case of a single producer and single consumer.</p>

<p>Here&#8217;s an example, using circular buffers to implement a simple playthrough scheme that plays audio coming in the microphone:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@interface</span> MyAudioController <span style="color: #002200;">:</span> <span style="color: #400080;">NSObject</span> <span style="color: #002200;">&#123;</span>
  TPCircularBuffer buffer;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span>
&nbsp;
<span style="color: #6e371a;">#define kBufferLength 1024</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> MyAudioController
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>setup <span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// Initialise buffer</span>
    TPCircularBufferInit<span style="color: #002200;">&#40;</span><span style="color: #002200;">&amp;</span>buffer, kBufferLength<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Setup audio, etc</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>dealloc <span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// Release buffer resources</span>
    TPCircularBufferCleanup<span style="color: #002200;">&#40;</span><span style="color: #002200;">&amp;</span>buffer<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>super dealloc<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">static</span> OSStatus audioInputCallback<span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span> <span style="color: #002200;">*</span>inRefCon, 
                                   AudioUnitRenderActionFlags <span style="color: #002200;">*</span>ioActionFlags, 
                                   <span style="color: #a61390;">const</span> AudioTimeStamp <span style="color: #002200;">*</span>inTimeStamp, 
                                   UInt32 inBusNumber, 
                                   UInt32 inNumberFrames, 
                                   AudioBufferList <span style="color: #002200;">*</span>ioData<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    MyAudioController <span style="color: #002200;">*</span>THIS <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>MyAudioController <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>inRefCon;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Render audio into buffer</span>
    AudioBufferList bufferList;
    bufferList.mNumberBuffers <span style="color: #002200;">=</span> <span style="color: #2400d9;">1</span>;
    bufferList.mBuffers<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>.mNumberChannels <span style="color: #002200;">=</span> <span style="color: #2400d9;">2</span>;
    bufferList.mBuffers<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>.mData <span style="color: #002200;">=</span> <span style="color: #a61390;">NULL</span>;
    bufferList.mBuffers<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>.mDataByteSize <span style="color: #002200;">=</span> inNumberFrames <span style="color: #002200;">*</span> <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>SInt16<span style="color: #002200;">&#41;</span> <span style="color: #002200;">*</span> <span style="color: #2400d9;">2</span>;
    OSStatus err <span style="color: #002200;">=</span> AudioUnitRender<span style="color: #002200;">&#40;</span>THIS<span style="color: #002200;">-</span>&gt;ioAudioUnit, ioActionFlags, inTimeStamp, kInputBus, inNumberFrames, <span style="color: #002200;">&amp;</span>bufferList<span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> <span style="color: #002200;">!</span>checkResultLite<span style="color: #002200;">&#40;</span>err, <span style="color: #bf1d1a;">&quot;AudioUnitRender&quot;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span> <span style="color: #a61390;">return</span> err; <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Put audio into circular buffer</span>
    TPCircularBufferProduceBytes<span style="color: #002200;">&#40;</span><span style="color: #002200;">&amp;</span>THIS<span style="color: #002200;">-</span>&gt;buffer, bufferList.mBuffers<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>.mData, inNumberFrames <span style="color: #002200;">*</span> <span style="color: #2400d9;">2</span> <span style="color: #002200;">*</span> <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>SInt16<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">static</span> OSStatus audioOutputCallback<span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span> <span style="color: #002200;">*</span>inRefCon, 
                                    AudioUnitRenderActionFlags <span style="color: #002200;">*</span>ioActionFlags, 
                                    <span style="color: #a61390;">const</span> AudioTimeStamp <span style="color: #002200;">*</span>inTimeStamp, 
                                    UInt32 inBusNumber, 
                                    UInt32 inNumberFrames, 
                                    AudioBufferList <span style="color: #002200;">*</span>ioData<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    MyAudioController <span style="color: #002200;">*</span>THIS <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>MyAudioController <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>inRefCon;
&nbsp;
    <span style="color: #a61390;">int</span> bytesToCopy <span style="color: #002200;">=</span> ioData<span style="color: #002200;">-</span>&gt;mBuffers<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>.mDataByteSize;
    SInt16 <span style="color: #002200;">*</span>targetBuffer <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>SInt16<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>ioData<span style="color: #002200;">-</span>&gt;mBuffers<span style="color: #002200;">&#91;</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>.mData;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Pull audio from playthrough buffer</span>
    int32_t availableBytes;
    SInt16 <span style="color: #002200;">*</span>buffer <span style="color: #002200;">=</span> TPCircularBufferTail<span style="color: #002200;">&#40;</span><span style="color: #002200;">&amp;</span>THIS<span style="color: #002200;">-</span>&gt;buffer, <span style="color: #002200;">&amp;</span>availableBytes<span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">memcpy</span><span style="color: #002200;">&#40;</span>targetBuffer, buffer, MIN<span style="color: #002200;">&#40;</span>bytesToCopy, availableBytes<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
    TPCircularBufferConsume<span style="color: #002200;">&#40;</span><span style="color: #002200;">&amp;</span>THIS<span style="color: #002200;">-</span>&gt;buffer, sampleCount<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #a61390;">return</span> noErr;
<span style="color: #002200;">&#125;</span>
<span style="color: #a61390;">@end</span></pre></div></div>

 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=2166" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/a-simple-fast-circular-buffer-implementation-for-audio-processing/feed/</wfw:commentRss>
		<slash:comments>32</slash:comments>
		</item>
		<item>
		<title>What I&#8217;ve been up to: Loopy 2 (track importing)</title>
		<link>http://atastypixel.com/blog/what-ive-been-up-to-loopy-2-track-importing/</link>
		<comments>http://atastypixel.com/blog/what-ive-been-up-to-loopy-2-track-importing/#comments</comments>
		<pubDate>Tue, 22 Feb 2011 13:52:41 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Audio]]></category>
		<category><![CDATA[Demo]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Loopy]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/what-ive-been-up-to-loopy-2-track-importing/</guid>
		<description><![CDATA[Here&#8217;s the result of the last few days&#8217; work: Loopy 2 now has track importing. Drag audio files into Loopy&#8217;s documents folder in iTunes, then import into tracks. Loops are automatically time-fitted for perfect synchronisation, using the frankly awesome Dirac audio processing library.]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s the result of the last few days&#8217; work: <a href="http://loopyapp.com">Loopy 2</a> now has track importing.  Drag audio files into Loopy&#8217;s documents folder in iTunes, then import into tracks.  Loops are automatically time-fitted for perfect synchronisation, using the frankly awesome Dirac audio processing library.</p>

<iframe title="YouTube video player" width="480" height="390" class="aligncenter" src="http://www.youtube.com/embed/y-vCNlo_j-c?rel=0" frameborder="0" allowfullscreen></iframe>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=2141" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/what-ive-been-up-to-loopy-2-track-importing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to mix audio samples properly on iOS</title>
		<link>http://atastypixel.com/blog/how-to-mix-audio-samples-properly-on-ios/</link>
		<comments>http://atastypixel.com/blog/how-to-mix-audio-samples-properly-on-ios/#comments</comments>
		<pubDate>Tue, 01 Feb 2011 13:12:42 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Audio]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=2127</guid>
		<description><![CDATA[In the real world, when you hear two sounds at once, what you&#8217;re hearing is the combination (in the &#8220;+&#8221; sense) of the two noises. If you put five hundred drummers in the same room and, avoiding the obvious drummer jokes for now, told them all to play, you&#8217;d get drummer 1 + drummer 2 [...]]]></description>
			<content:encoded><![CDATA[<p>In the real world, when you hear two sounds at once, what you&#8217;re hearing is the combination (in the &#8220;+&#8221; sense) of the two noises.  If you put five hundred drummers in the same room and, avoiding the obvious drummer jokes for now, told them all to play, you&#8217;d get <em>drummer 1 + drummer 2 + &#8230; + drummer 500</em> (also bleeding ears).</p>

<p>With digital audio though, the volume doesn&#8217;t go up to <em>oh-god-please-make-them-stop</em> &#8211; it&#8217;s limited to a small dynamic range.</p>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2011/02/Mixing-Naive.jpg" width="450" height="293" alt="Naïve mixing, with overflow" class="aligncenter" /></p>

<p>So, digital mixing actually requires a little thought in order to avoid overflowing these bounds and clipping.  I recently came across this when writing some mixing routines for my upcoming app Loopy 2, and found a very useful <a href="http://www.vttoth.com/digimix.htm">discussion on mixing digital audio</a> by software developer and author Viktor Toth.</p>

<p>The basic concept is to mix in such a way that we stay within the dynamic range of the target audio format, while representing the dynamics of the mixed signals as faithfully as possible.<span id="more-2127"></span>Note that a simple average of the samples (as in, <em>(sample 1 + sample 2) / 2</em>) won&#8217;t accomplish this &#8211; for example, if <em>sample 1</em> is silent, while <em>sample 2</em> is happily jamming away, <em>sample 2</em> will be halved in volume.</p>

<p>Instead, we want to meet three goals &#8211; assuming signed audio samples, the standard format for Remote IO/audio units on the iPhone/iPad, which can range from negative, through to zero (silence), up to positive values.</p>

<ol>
<li>If both samples are positive, we mix them so that the output value is somewhere between the maximum value of the two samples, and the maximum possible value</li>
<li>If both samples are negative, we mix them so that the output value is somewhere between the <em>minimum</em> value of the two samples, and the minimum possible value</li>
<li>If one sample is positive, and one is negative, we want them to cancel out somewhat</li>
</ol>

<p>If we&#8217;re talking about signed samples, MIN&#8230;0&#8230;MAX, this does the trick:</p>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2011/02/Eqn.png" width="300" height="106" alt="Mixing equation" class="aligncenter" /></p>

<p>This lets the volume level for both samples remain the same, while fitting within the available range.</p>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2011/02/Mixing-Improved.jpg" width="450" height="293" alt="Improved mixing" class="aligncenter" /></p>

<p>Here&#8217;s how it&#8217;s done on iOS:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">SInt16 <span style="color: #002200;">*</span>bufferA, SInt16 <span style="color: #002200;">*</span>bufferB;
NSInteger bufferLength;
SInt16 <span style="color: #002200;">*</span>outputBuffer;
&nbsp;
<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span> NSInteger i<span style="color: #002200;">=</span><span style="color: #2400d9;">0</span>; i&lt;bufferLength; i<span style="color: #002200;">++</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
  <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> bufferA<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span> &lt; <span style="color: #2400d9;">0</span> <span style="color: #002200;">&amp;&amp;</span> bufferB<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span> &lt; <span style="color: #2400d9;">0</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// If both samples are negative, mixed signal must have an amplitude between </span>
    <span style="color: #11740a; font-style: italic;">// the lesser of A and B, and the minimum permissible negative amplitude</span>
    outputBuffer<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span> <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>bufferA<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span> <span style="color: #002200;">+</span> bufferB<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>bufferA<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span> <span style="color: #002200;">*</span> bufferB<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">/</span>INT16_MIN<span style="color: #002200;">&#41;</span>;
  <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> bufferA<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span> &gt; <span style="color: #2400d9;">0</span> <span style="color: #002200;">&amp;&amp;</span> bufferB<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span> &gt; <span style="color: #2400d9;">0</span> <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// If both samples are positive, mixed signal must have an amplitude between the greater of</span>
    <span style="color: #11740a; font-style: italic;">// A and B, and the maximum permissible positive amplitude</span>
    outputBuffer<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span> <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>bufferA<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span> <span style="color: #002200;">+</span> bufferB<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>bufferA<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span> <span style="color: #002200;">*</span> bufferB<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">/</span>INT16_MAX<span style="color: #002200;">&#41;</span>;
  <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// If samples are on opposite sides of the 0-crossing, mixed signal should reflect </span>
    <span style="color: #11740a; font-style: italic;">// that samples cancel each other out somewhat</span>
    outputBuffer<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span> <span style="color: #002200;">=</span> bufferA<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span> <span style="color: #002200;">+</span> bufferB<span style="color: #002200;">&#91;</span>i<span style="color: #002200;">&#93;</span>;
  <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></div></div>


<p><strong>Update</strong>: A reader recently demonstrated that this technique can introduce some unpleasant distortion with certain kinds of input &#8212; as the algorithm is nonlinear, some distortion is inevitable (see the sharp points on the waveform where the condition switches over).  For the kind of audio I&#8217;m mixing, the results seem to be perfectly adequate, but this may not be generally true.</p>

<p><strong>Update 2</strong>: Here&#8217;s an inline function I put together for neatness:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">inline SInt16 TPMixSamples<span style="color: #002200;">&#40;</span>SInt16 a, SInt16 b<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">return</span>  
            <span style="color: #11740a; font-style: italic;">// If both samples are negative, mixed signal must have an amplitude between the lesser of A and B, and the minimum permissible negative amplitude</span>
            a &lt; <span style="color: #2400d9;">0</span> <span style="color: #002200;">&amp;&amp;</span> b &lt; <span style="color: #2400d9;">0</span> ?
                <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span>a <span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span>b<span style="color: #002200;">&#41;</span> <span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span>a <span style="color: #002200;">*</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span>b<span style="color: #002200;">&#41;</span><span style="color: #002200;">/</span>INT16_MIN<span style="color: #002200;">&#41;</span> <span style="color: #002200;">:</span>
&nbsp;
            <span style="color: #11740a; font-style: italic;">// If both samples are positive, mixed signal must have an amplitude between the greater of A and B, and the maximum permissible positive amplitude</span>
            <span style="color: #002200;">&#40;</span> a &gt; <span style="color: #2400d9;">0</span> <span style="color: #002200;">&amp;&amp;</span> b &gt; <span style="color: #2400d9;">0</span> ?
                <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span>a <span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span>b<span style="color: #002200;">&#41;</span> <span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span>a <span style="color: #002200;">*</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span>b<span style="color: #002200;">&#41;</span><span style="color: #002200;">/</span>INT16_MAX<span style="color: #002200;">&#41;</span>
&nbsp;
            <span style="color: #11740a; font-style: italic;">// If samples are on opposite sides of the 0-crossing, mixed signal should reflect that samples cancel each other out somewhat</span>
            <span style="color: #002200;">:</span>
                a <span style="color: #002200;">+</span> b<span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>

 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=2127" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/how-to-mix-audio-samples-properly-on-ios/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Pushing MultiChannelMixer to the limit</title>
		<link>http://atastypixel.com/blog/pushing-multichannelmixer-to-the-limit/</link>
		<comments>http://atastypixel.com/blog/pushing-multichannelmixer-to-the-limit/#comments</comments>
		<pubDate>Sun, 23 Jan 2011 23:40:42 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Audio]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/pushing-multichannelmixer-to-the-limit/</guid>
		<description><![CDATA[A friend made an interesting suggestion to an issue I&#8217;m facing in the upcoming Loopy 2, and I thought I&#8217;d do some investigation: How many tracks can the MultiChannelMixer (kAudioUnitSubType_MultiChannelMixer) manage at once? He was quite optimistic, and as it turns out, he was right: It&#8217;s rather capable. I modified the iPhoneMultichannelMixerTest sample project to [...]]]></description>
			<content:encoded><![CDATA[<p>A friend made an interesting suggestion to an issue I&#8217;m facing in the upcoming Loopy 2, and I thought I&#8217;d do some investigation: How many tracks can the <a href="http://developer.apple.com/library/ios/documentation/MusicAudio/Conceptual/AudioUnitHostingGuide_iOS/UsingSpecificAudioUnits/UsingSpecificAudioUnits.html#//apple_ref/doc/uid/TP40009492-CH17-SW8">MultiChannelMixer (kAudioUnitSubType_MultiChannelMixer)</a> manage at once?</p>

<p>He was quite optimistic, and as it turns out, he was right: It&#8217;s rather capable.</p>

<p>I modified the <a href="http://developer.apple.com/library/ios/#samplecode/iPhoneMultichannelMixerTest/Introduction/Intro.html">iPhoneMultichannelMixerTest</a> sample project to add a bunch of channels, and measured how my iPhone 4 performed.  It looks pretty linear: there&#8217;s pretty much a 1:1 relationship between number of channels, and the CPU usage, actually.</p>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2011/01/201101232332.jpg" width="450" height="319" alt="Number of Inputs to MultiChannelMixer versus CPU usage" class="aligncenter" /></p>

<p>Of course, this is on the newest-most powerful iPhone, but there was no stuttering, and the interface (admittedly simple as it is) was fully responsive, including setting output volume, even with 100 channels.  You&#8217;d probably want to stick with a maximum number of channels around the 75-100 mark, less for targeting lesser devices, but that&#8217;s a pretty generous limit.</p>

<p>Not bad.</p>

<p><em>Update</em>: Not such great news for the iPhone 3G I just tested this on, though &#8212; it freaks at anything more than 20 channels, and isn&#8217;t too responsive with 20.  The 3Gs seems to behave almost as well as the iPhone 4, but the CPU:channels relationship is more like 2:1.</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=2118" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/pushing-multichannelmixer-to-the-limit/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Playing audio in time using Remote IO</title>
		<link>http://atastypixel.com/blog/playing-audio-in-time-using-remote-io/</link>
		<comments>http://atastypixel.com/blog/playing-audio-in-time-using-remote-io/#comments</comments>
		<pubDate>Thu, 19 Aug 2010 20:46:38 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Audio]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Loopy]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/playing-audio-in-time-using-remote-io/</guid>
		<description><![CDATA[I got an email today with a question about how to handle playback of audio in time, synchronised with a clock. My &#8216;musical notepad&#8217; app Loopy does this, and I thought I&#8217;d briefly explain how. Any app that makes use of the Remote IO audio unit framework (which is generally necessary for the kind of [...]]]></description>
			<content:encoded><![CDATA[<p>I got an email today with a question about how to handle playback of audio in time, synchronised with a clock.  My &#8216;musical notepad&#8217; app <a href="http://atastypixel.com/products/loopy">Loopy</a> does this, and I thought I&#8217;d briefly explain how.</p>

<p>Any app that makes use of the <a href="http://atastypixel.com/blog/using-remoteio-audio-unit/">Remote IO</a> audio unit framework (which is generally necessary for the kind of responsiveness required in a realtime musical app) provides audio to the hardware via a callback, which is periodically called when the hardware is ready for more.</p>

<p>The trick here is to provide the right chunk of samples in this callback for the current time position.</p>

<p>Loopy achieves this by:</p>

<h3>1. Keeping track of where in the timeline we are at the time the callback is called</h3>

<p>This is easily accomplished by keeping a record of the time the clock was started, subtracting this from the current time, and possibly performing a modulus with the tempo.  For example:</p>

<ul>
<li><code>(now - startTime) % timePerBar</code> gives the number of time units into the current bar (lets call it <code>timeIntoBar</code>).  </li>
<li><code>timeIntoBar / (timePerBar/beatsPerBar)</code> gives the number of beats into the current bar, and </li>
<li><code>timeIntoBar % (timePerBar/beatsPerBar)</code> gives us the time into the current beat.</li>
</ul>

<h3>2. Determining first if we should be playing audio at this time, and if so, which samples should be playing</h3>

<p>This involves first converting our time units from step 1 into samples.  For instance, you can convert microseconds to samples by dividing your time by <code>1000000/yourSampleRate</code>.  Aside: Of course, you can convert back from samples to time by multiplying instead of dividing.</p>

<p>Next, in the case of Loopy&#8217;s metronome, for example, we test for whether <code>samplesIntoBeat &lt; sound.lengthInSamples</code>.  If so, that means we should be playing audio.  If the sound was a loop, of course, we could be always playing.</p>

<p>The offset into the sound, in samples, is just samplesIntoBeat, in the case of the simple metronome.  In the case of a loop, you probably will be more interested in the number of samples into your loop &#8212; so instead of determining <code>(now - startTime) % timePerBar</code>, you may be interested in <code>(now - startTime) % timePerLoop</code>.</p>

<p>So, we want to return the requested number of samples starting from this offset into the sample array representing our audio.</p>

<h3>3. Returning smooth audio in time</h3>

<p>Note that if you just go returning any old set of samples, willy-nilly, you&#8217;re going to get nasty clicks and pops from discontinuities you get by not matching the start of your next buffer to the last one.</p>

<p>To ensure smoothness, Loopy keeps track of the offset of the last samples we returned, and just return the immediately following bunch of samples &#8212; unless we&#8217;re more than some threshold number of samples out of time, in which case we&#8217;ll suffer the pop in order to stay synchronised.  Actually, you can even generally avoid the pop if you smoothly blend buffers over a short time, removing any discontinuity.</p>

<h3>Final words</h3>

<p>The example above was a relatively trivial one, for a metronome sound.  For longer audio that may span multiple bars, you&#8217;ll probably want to perform a modulus by the length of your audio clip, possibly quantised to your time signature, and possibly using a per-loop time base, so you can start the loop at any point in your timeline and have it begin from the start.  This is something Loopy doesn&#8217;t currently do &#8212; Loopy will keep your loops synchronised so when you start a loop playing, it&#8217;ll play whatever part corresponds to the current timeline, not from the start of the loop. Maybe it&#8217;ll be an option in the future?</p>

<p>I wrote a little about the timing of loops in my <a href="http://atastypixel.com/blog/developing-loopy-part-2-implementation/">second article on Loopy&#8217;s implementation</a>.</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1993" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/playing-audio-in-time-using-remote-io/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Error -12986 and you</title>
		<link>http://atastypixel.com/blog/error-12986-and-you/</link>
		<comments>http://atastypixel.com/blog/error-12986-and-you/#comments</comments>
		<pubDate>Sun, 10 Jan 2010 20:59:39 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Audio]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/2010/01/10/error-12986-and-you/</guid>
		<description><![CDATA[A customer recently got in touch with me with an odd problem &#8212; Talkie for iPhone was going silent on him. After a little diagnosis, it turned out the audio system was throwing up an undocumented error &#8212; -12986 &#8212; while starting up on his iPod Touch. Some googling turned up this thread on Stack [...]]]></description>
			<content:encoded><![CDATA[<p>A customer recently got in touch with me with an odd problem &#8212; Talkie for iPhone was going silent on him.  After a little diagnosis, it turned out the audio system was throwing up an undocumented error &#8212; -12986 &#8212; while starting up on his iPod Touch.</p>

<p>Some googling turned up <a href="http://stackoverflow.com/questions/1540078/iphone-sdk-audio-session-error-12986-after-upgrade-to-3-1">this thread</a> on Stack Overflow, which presented a solution for the <code>AVAudioSession</code> framework: It turns out, on recent SDKs (somewhere equal to or above 3.0), the audio system will refuse to start up if the session is set to a recording mode, with no input device available, spitting out this error.  Alas, the error isn&#8217;t listed anywhere that I could find.</p>

<p>So, the way to fix it is to check whether there&#8217;s an input device available, then choose an audio category accordingly:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">OSStatus status;
&nbsp;
UInt32 inputAvailable<span style="color: #002200;">=</span><span style="color: #2400d9;">0</span>;
UInt32 size <span style="color: #002200;">=</span> <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>inputAvailable<span style="color: #002200;">&#41;</span>;
AudioSessionGetProperty<span style="color: #002200;">&#40;</span>kAudioSessionProperty_AudioInputAvailable, 
                        <span style="color: #002200;">&amp;</span>size, 
                        <span style="color: #002200;">&amp;</span>inputAvailable<span style="color: #002200;">&#41;</span>;
UInt32 sessionCategory;
<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> inputAvailable <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// Set the audio session category for simultaneous play and record</span>
    sessionCategory <span style="color: #002200;">=</span> kAudioSessionCategory_PlayAndRecord;
<span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// Just playback</span>
    sessionCategory <span style="color: #002200;">=</span> kAudioSessionCategory_MediaPlayback;
<span style="color: #002200;">&#125;</span>
&nbsp;
status <span style="color: #002200;">=</span> AudioSessionSetProperty <span style="color: #002200;">&#40;</span>kAudioSessionProperty_AudioCategory,
                                  <span style="color: #a61390;">sizeof</span> <span style="color: #002200;">&#40;</span>sessionCategory<span style="color: #002200;">&#41;</span>,
                                  <span style="color: #002200;">&amp;</span>sessionCategory<span style="color: #002200;">&#41;</span>;    
checkStatus<span style="color: #002200;">&#40;</span>status<span style="color: #002200;">&#41;</span>;</pre></div></div>


<p>It&#8217;s probably a good idea to respond when input becomes available or goes away, so add a property listener too:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">void</span> inputAvailablePropertyListener <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span>                      <span style="color: #002200;">*</span>inClientData,
                                     AudioSessionPropertyID    inID,
                                     UInt32                    inDataSize,
                                     <span style="color: #a61390;">const</span> <span style="color: #a61390;">void</span>                <span style="color: #002200;">*</span>inData<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> inID <span style="color: #002200;">=</span> kAudioSessionProperty_AudioInputAvailable <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        UInt32 <span style="color: #002200;">*</span>inputAvailable <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>UInt32<span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>inData;
        UInt32 sessionCategory;
        <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span> <span style="color: #002200;">*</span>inputAvailable <span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #11740a; font-style: italic;">// Set the audio session category for simultaneous play and record</span>
            sessionCategory <span style="color: #002200;">=</span> kAudioSessionCategory_PlayAndRecord;
        <span style="color: #002200;">&#125;</span> <span style="color: #a61390;">else</span> <span style="color: #002200;">&#123;</span>
            <span style="color: #11740a; font-style: italic;">// Just playback</span>
            sessionCategory <span style="color: #002200;">=</span> kAudioSessionCategory_MediaPlayback;
        <span style="color: #002200;">&#125;</span>
&nbsp;
        OSStatus status <span style="color: #002200;">=</span> AudioSessionSetProperty <span style="color: #002200;">&#40;</span>kAudioSessionProperty_AudioCategory,
                                                   <span style="color: #a61390;">sizeof</span> <span style="color: #002200;">&#40;</span>sessionCategory<span style="color: #002200;">&#41;</span>,
                                                   <span style="color: #002200;">&amp;</span>sessionCategory<span style="color: #002200;">&#41;</span>;    
        checkStatus<span style="color: #002200;">&#40;</span>status<span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>then:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Listen for audio input availability</span>
status <span style="color: #002200;">=</span> AudioSessionAddPropertyListener<span style="color: #002200;">&#40;</span>kAudioSessionProperty_AudioInputAvailable,
                                         inputAvailablePropertyListener, 
                                         <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>;</pre></div></div>

 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1786" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/error-12986-and-you/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using RemoteIO audio unit</title>
		<link>http://atastypixel.com/blog/using-remoteio-audio-unit/</link>
		<comments>http://atastypixel.com/blog/using-remoteio-audio-unit/#comments</comments>
		<pubDate>Tue, 04 Nov 2008 14:36:31 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Audio]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/2008/10/27/using-remoteio-audio-unit/</guid>
		<description><![CDATA[I&#8217;ve had nasty old time trying to get some audio stuff going on the iPhone, no thanks to Apple&#8217;s lack of documentation. If you&#8217;re an iPhone developer interested in getting RemoteIO/IO Remote/whatever it&#8217;s called working on the iPhone&#8230; Do I have good news for you. Read on. Wanna skip the Core Audio learning curve and [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve had nasty old time trying to get some audio stuff going on the iPhone, no thanks to Apple&#8217;s lack of documentation. If you&#8217;re an iPhone developer interested in getting RemoteIO/IO Remote/whatever it&#8217;s called working on the iPhone&#8230; Do I have good news for you.  Read on.</p>

<p><span id="more-1003"></span></p>

<p style="font-style: italic;">Wanna skip the Core Audio learning curve and start writing code straight away? Check out my new project:</p>

<p><a href="http://theamazingaudioengine.com"><img src="http://atastypixel.com/blog/wp-content/uploads/2012/03/the-amazing-audio-engine-banner.jpg" alt="The Amazing Audio Engine: Core Audio, Cordially" title="the-amazing-audio-engine-banner.jpg" border="0" width="582" height="178" style="margin: 0 auto;" class="aligncenter" /></a></p>

<p><strong>Update: Thanks to <a href="http://tinyco.de">Joel Reymont</a>, we now have an <a href="http://tinyco.de/2009/02/12/solution-for-crashifclientprovidedbogusaudiobufferlist-in-iphone-simulator.html">explanation</a> for the &#8220;CrashIfClientProvidedBogusAudioBufferList&#8221; iPhone simulator bug: The simulator doesn&#8217;t like mono audio. Thanks, Joel!</strong></p>

<p><strong>Update: Happily, Apple have now created some <a href="http://developer.apple.com/library/ios/#documentation/MusicAudio/Conceptual/AudioUnitHostingGuide_iOS/Introduction/Introduction.html%23//apple_ref/doc/uid/TP40009492-CH1-SW1">excellent documentation on Remote IO</a>, with some good <a href="http://developer.apple.com/library/ios/#samplecode/aurioTouch/Introduction/Intro.html%23//apple_ref/doc/uid/DTS40007770">sample projects</a>.  I recommend using that as a resource, now that it&#8217;s there, as that will continue to be updated.</strong></p>

<p><strong>Update: Tom Zicarelli has created a very extensive <a href="http://zerokidz.com/audiograph/Home.html">sample app that demonstrates the use of AUGraph</a>, with all sorts of goodies.</strong></p>

<p>So, we need to obtain an instance of the RemoteIO audio unit, configure it, and hook it up to a recording callback, which is used to notify you that there is data ready to be grabbed, and where you pull the data from the audio unit.</p>

<p><br /></p>

<h3>Overview</h3>

<ol>
  <li>Identify the audio component (kAudioUnitType_Output/ kAudioUnitSubType_RemoteIO/ kAudioUnitManufacturerApple)</li>

  <li>Use AudioComponentFindNext(NULL, &amp;descriptionOfAudioComponent) to obtain the AudioComponent, which is like the factory with which you obtain the audio unit<br /></li>

  <li>Use AudioComponentInstanceNew(ourComponent, &amp;audioUnit) to make an instance of the audio unit<br /></li>

  <li>Enable IO for recording and possibly playback with AudioUnitSetProperty<br /></li>

  <li>Describe the audio format in an AudioStreamBasicDescription structure, and apply the format using AudioUnitSetProperty<br /></li>

  <li>Provide a callback for recording, and possibly playback, again using AudioUnitSetProperty<br /></li>

  <li>Allocate some buffers<br /></li>

  <li>Initialise the audio unit<br /></li>

  <li>Start the audio unit<br /></li>

  <li>Rejoice<br /></li>
</ol>

<p>Here&#8217;s my code: I&#8217;m using both recording and playback. Use what applies to you!</p>

<h3>Initialisation</h3>

<p>Initialisation looks like this. We have a member variable of type AudioComponentInstance which will contain our audio unit.</p>

<p>The audio format described below uses SInt16 for samples (i.e. signed, 16 bits per sample)</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#define kOutputBus 0</span>
<span style="color: #6e371a;">#define kInputBus 1</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// ...</span>
&nbsp;
&nbsp;
OSStatus status;
AudioComponentInstance audioUnit;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Describe audio component</span>
AudioComponentDescription desc;
desc.componentType <span style="color: #002200;">=</span> kAudioUnitType_Output;
desc.componentSubType <span style="color: #002200;">=</span> kAudioUnitSubType_RemoteIO;
desc.componentFlags <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
desc.componentFlagsMask <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
desc.componentManufacturer <span style="color: #002200;">=</span> kAudioUnitManufacturer_Apple;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Get component</span>
AudioComponent inputComponent <span style="color: #002200;">=</span> AudioComponentFindNext<span style="color: #002200;">&#40;</span><span style="color: #a61390;">NULL</span>, <span style="color: #002200;">&amp;</span>desc<span style="color: #002200;">&#41;</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Get audio units</span>
status <span style="color: #002200;">=</span> AudioComponentInstanceNew<span style="color: #002200;">&#40;</span>inputComponent, <span style="color: #002200;">&amp;</span>audioUnit<span style="color: #002200;">&#41;</span>;
checkStatus<span style="color: #002200;">&#40;</span>status<span style="color: #002200;">&#41;</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Enable IO for recording</span>
UInt32 flag <span style="color: #002200;">=</span> <span style="color: #2400d9;">1</span>;
status <span style="color: #002200;">=</span> AudioUnitSetProperty<span style="color: #002200;">&#40;</span>audioUnit, 
                              kAudioOutputUnitProperty_EnableIO, 
                              kAudioUnitScope_Input, 
                              kInputBus,
                              <span style="color: #002200;">&amp;</span>flag, 
                              <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>flag<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
checkStatus<span style="color: #002200;">&#40;</span>status<span style="color: #002200;">&#41;</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Enable IO for playback</span>
status <span style="color: #002200;">=</span> AudioUnitSetProperty<span style="color: #002200;">&#40;</span>audioUnit, 
                              kAudioOutputUnitProperty_EnableIO, 
                              kAudioUnitScope_Output, 
                              kOutputBus,
                              <span style="color: #002200;">&amp;</span>flag, 
                              <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>flag<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
checkStatus<span style="color: #002200;">&#40;</span>status<span style="color: #002200;">&#41;</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Describe format</span>
audioFormat.mSampleRate			<span style="color: #002200;">=</span> <span style="color: #2400d9;">44100.00</span>;
audioFormat.mFormatID			<span style="color: #002200;">=</span> kAudioFormatLinearPCM;
audioFormat.mFormatFlags		<span style="color: #002200;">=</span> kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
audioFormat.mFramesPerPacket	<span style="color: #002200;">=</span> <span style="color: #2400d9;">1</span>;
audioFormat.mChannelsPerFrame	<span style="color: #002200;">=</span> <span style="color: #2400d9;">1</span>;
audioFormat.mBitsPerChannel		<span style="color: #002200;">=</span> <span style="color: #2400d9;">16</span>;
audioFormat.mBytesPerPacket		<span style="color: #002200;">=</span> <span style="color: #2400d9;">2</span>;
audioFormat.mBytesPerFrame		<span style="color: #002200;">=</span> <span style="color: #2400d9;">2</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Apply format</span>
status <span style="color: #002200;">=</span> AudioUnitSetProperty<span style="color: #002200;">&#40;</span>audioUnit, 
                              kAudioUnitProperty_StreamFormat, 
                              kAudioUnitScope_Output, 
                              kInputBus, 
                              <span style="color: #002200;">&amp;</span>audioFormat, 
                              <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>audioFormat<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
checkStatus<span style="color: #002200;">&#40;</span>status<span style="color: #002200;">&#41;</span>;
status <span style="color: #002200;">=</span> AudioUnitSetProperty<span style="color: #002200;">&#40;</span>audioUnit, 
                              kAudioUnitProperty_StreamFormat, 
                              kAudioUnitScope_Input, 
                              kOutputBus, 
                              <span style="color: #002200;">&amp;</span>audioFormat, 
                              <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>audioFormat<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
checkStatus<span style="color: #002200;">&#40;</span>status<span style="color: #002200;">&#41;</span>;
&nbsp;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Set input callback</span>
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc <span style="color: #002200;">=</span> recordingCallback;
callbackStruct.inputProcRefCon <span style="color: #002200;">=</span> self;
status <span style="color: #002200;">=</span> AudioUnitSetProperty<span style="color: #002200;">&#40;</span>audioUnit, 
                              kAudioOutputUnitProperty_SetInputCallback, 
                              kAudioUnitScope_Global, 
                              kInputBus, 
                              <span style="color: #002200;">&amp;</span>callbackStruct, 
                              <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>callbackStruct<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
checkStatus<span style="color: #002200;">&#40;</span>status<span style="color: #002200;">&#41;</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Set output callback</span>
callbackStruct.inputProc <span style="color: #002200;">=</span> playbackCallback;
callbackStruct.inputProcRefCon <span style="color: #002200;">=</span> self;
status <span style="color: #002200;">=</span> AudioUnitSetProperty<span style="color: #002200;">&#40;</span>audioUnit, 
                              kAudioUnitProperty_SetRenderCallback, 
                              kAudioUnitScope_Global, 
                              kOutputBus,
                              <span style="color: #002200;">&amp;</span>callbackStruct, 
                              <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>callbackStruct<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
checkStatus<span style="color: #002200;">&#40;</span>status<span style="color: #002200;">&#41;</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">// Disable buffer allocation for the recorder (optional - do this if we want to pass in our own)</span>
flag <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
status <span style="color: #002200;">=</span> AudioUnitSetProperty<span style="color: #002200;">&#40;</span>audioUnit, 
                              kAudioUnitProperty_ShouldAllocateBuffer,
                              kAudioUnitScope_Output, 
                              kInputBus,
                              <span style="color: #002200;">&amp;</span>flag, 
                              <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>flag<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
<span style="color: #11740a; font-style: italic;">// TODO: Allocate our own buffers if we want</span>
&nbsp;
<span style="color: #11740a; font-style: italic;">// Initialise</span>
status <span style="color: #002200;">=</span> AudioUnitInitialize<span style="color: #002200;">&#40;</span>audioUnit<span style="color: #002200;">&#41;</span>;
checkStatus<span style="color: #002200;">&#40;</span>status<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>


<p>Then, when you&#8217;re ready to start:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;">OSStatus status <span style="color: #002200;">=</span> AudioOutputUnitStart<span style="color: #002200;">&#40;</span>audioUnit<span style="color: #002200;">&#41;</span>;
checkStatus<span style="color: #002200;">&#40;</span>status<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>


<p>And to stop:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;">OSStatus status <span style="color: #002200;">=</span> AudioOutputUnitStop<span style="color: #002200;">&#40;</span>audioUnit<span style="color: #002200;">&#41;</span>;
checkStatus<span style="color: #002200;">&#40;</span>status<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>


<p>Then, when we&#8217;re finished:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;">AudioUnitUninitialize<span style="color: #002200;">&#40;</span>audioUnit<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>


<p>And now for our callbacks.</p>

<h4>Recording</h4>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">static</span> OSStatus recordingCallback<span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span> <span style="color: #002200;">*</span>inRefCon, 
                                  AudioUnitRenderActionFlags <span style="color: #002200;">*</span>ioActionFlags, 
                                  <span style="color: #a61390;">const</span> AudioTimeStamp <span style="color: #002200;">*</span>inTimeStamp, 
                                  UInt32 inBusNumber, 
                                  UInt32 inNumberFrames, 
                                  AudioBufferList <span style="color: #002200;">*</span>ioData<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// TODO: Use inRefCon to access our interface object to do stuff</span>
    <span style="color: #11740a; font-style: italic;">// Then, use inNumberFrames to figure out how much data is available, and make</span>
    <span style="color: #11740a; font-style: italic;">// that much space available in buffers in an AudioBufferList.</span>
&nbsp;
    AudioBufferList <span style="color: #002200;">*</span>bufferList; <span style="color: #11740a; font-style: italic;">// &lt;- Fill this up with buffers (you will want to malloc it, as it's a dynamic-length list)</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Then:</span>
    <span style="color: #11740a; font-style: italic;">// Obtain recorded samples</span>
&nbsp;
    OSStatus status;
&nbsp;
    status <span style="color: #002200;">=</span> AudioUnitRender<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>audioInterface audioUnit<span style="color: #002200;">&#93;</span>, 
                             ioActionFlags, 
                             inTimeStamp, 
                             inBusNumber, 
                             inNumberFrames, 
                             bufferList<span style="color: #002200;">&#41;</span>;
    checkStatus<span style="color: #002200;">&#40;</span>status<span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Now, we have the samples we just read sitting in buffers in bufferList</span>
    DoStuffWithTheRecordedAudio<span style="color: #002200;">&#40;</span>bufferList<span style="color: #002200;">&#41;</span>;
    <span style="color: #a61390;">return</span> noErr;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<h4>Playback</h4>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">static</span> OSStatus playbackCallback<span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span> <span style="color: #002200;">*</span>inRefCon, 
                                  AudioUnitRenderActionFlags <span style="color: #002200;">*</span>ioActionFlags, 
                                  <span style="color: #a61390;">const</span> AudioTimeStamp <span style="color: #002200;">*</span>inTimeStamp, 
                                  UInt32 inBusNumber, 
                                  UInt32 inNumberFrames, 
                                  AudioBufferList <span style="color: #002200;">*</span>ioData<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>    
    <span style="color: #11740a; font-style: italic;">// Notes: ioData contains buffers (may be more than one!)</span>
    <span style="color: #11740a; font-style: italic;">// Fill them up as much as you can. Remember to set the size value in each buffer to match how</span>
    <span style="color: #11740a; font-style: italic;">// much data is in the buffer.</span>
    <span style="color: #a61390;">return</span> noErr;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Finally, rejoice with me in this discovery ;)</p>

<p>Resources that helped</p>

<ul>
<li><a href="http://pastie.org/pastes/219616">http://pastie.org/pastes/219616</a></li>
<li><a href="http://developer.apple.com/samplecode/CAPlayThrough/listing8.html">http://developer.apple.com/samplecode/CAPlayThrough/listing8.html</a></li>
<li><a href="http://listas.apesol.org/pipermail/svn-libsdl.org/2008-July/000797.html">http://listas.apesol.org/pipermail/svn-libsdl.org/2008-July/000797.html</a></li>
</ul>

<p>No thanks at all to Apple for their lack of accessible documentation on this topic &#8211; They really have a long way to go here! Also boo to them with their lack of search engine, and refusal to open up their docs to Google. It&#8217;s a jungle out there!</p>

<p><strong>Update</strong>: You can adjust the latency of RemoteIO (and, in fact, any other audio framework) by setting the <code>kAudioSessionProperty_PreferredHardwareIOBufferDuration</code> property:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">float</span> aBufferLength <span style="color: #002200;">=</span> <span style="color: #2400d9;">0.005</span>; <span style="color: #11740a; font-style: italic;">// In seconds</span>
AudioSessionSetProperty<span style="color: #002200;">&#40;</span>kAudioSessionProperty_PreferredHardwareIOBufferDuration, 
                        <span style="color: #a61390;">sizeof</span><span style="color: #002200;">&#40;</span>aBufferLength<span style="color: #002200;">&#41;</span>, <span style="color: #002200;">&amp;</span>aBufferLength<span style="color: #002200;">&#41;</span>;</pre></div></div>


<p>This adjusts the length of buffers that&#8217;re passed to you &#8211; if buffer length was originally, say, 1024 samples, then halving the number of samples halves the amount of time taken to process them.</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1003" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/using-remoteio-audio-unit/feed/</wfw:commentRss>
		<slash:comments>219</slash:comments>
		</item>
		<item>
		<title>Core Audio and freakin&#8217; error -66632</title>
		<link>http://atastypixel.com/blog/core-audio-and-freakin-error-66632/</link>
		<comments>http://atastypixel.com/blog/core-audio-and-freakin-error-66632/#comments</comments>
		<pubDate>Wed, 22 Oct 2008 21:03:52 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Audio]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/2008/10/22/core-audio-and-freakin-error-66632/</guid>
		<description><![CDATA[This will only be of interest to a very small minority, but for those of us who have used Core Audio and come across error -66632 in all its glorious undocumented-ness, this is a helpful note. The error occurs when using AudioQueueEnqueueBuffer. It happens when one tries to enqueue a buffer when the queue in [...]]]></description>
			<content:encoded><![CDATA[<p>This will only be of interest to a very small minority, but for those of us who have used Core Audio and come across error -66632 in all its glorious undocumented-ness, this is a helpful note.</p>

<p>The error occurs when using <a href="http://developer.apple.com/iphone/library/documentation/MusicAudio/Reference/AudioQueueReference/Reference/reference.html#//apple_ref/doc/uid/TP40005117-CH3-SW5">AudioQueueEnqueueBuffer</a>. It happens when one tries to enqueue a buffer when the queue in question is no longer running.<br /></p>

<p>Wrap the AudioQueueEnqueueBuffer in a statement that checks to see if the queue is actually running, as in the SpeakHere/SpeakHear (depending on where you look) example. Something like:</p>

<blockquote><pre><tt><span style="color: #ff7800">if</span> ( [track <span style="color: #3b5bb5">recording</span>] ) {<br />
<span style="color: #8c868f">&nbsp;&nbsp;// Re-enqueue this buffer</span><br/>
&nbsp;&nbsp;status = <span style="color: #3b5bb5">AudioQueueEnqueueBuffer</span> (inAudioQueue,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;inBuffer,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #3b5bb5">0</span>,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #3b5bb5">NULL</span>);<br />
&nbsp;&nbsp;<span style="color: #3b5bb5">checkStatus</span>(status);<br />
}</tt></pre></blockquote>

<p>..Should do the trick.</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=991" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/core-audio-and-freakin-error-66632/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

