Blog

Tag Archives: Cocoa

A simple, fast circular buffer implementation for audio processing

Circular buffers are pretty much what they sound like – arrays that wrap around. They’re fantastically useful as scratch space for audio processing, and generally passing audio around efficiently.

They’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 audio into an NSData you allocate, and then pass that NSData off. This means you’re allocating memory each time, and deallocating the memory later once you’re done processing. That allocation incurs a penalty, which can be a show-stopper when part of an audio pipeline – The Core Audio documentation advises against any allocations when within a render callback, for example.

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.

A better solution is to use a circular buffer, where data goes in at the head, and is read from the tail. 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.

Here’s a simple C implementation I recently put together for my app Loopy: TPCircularBuffer Read More »

Also tagged , , , | 32 Comments

Objective-C + Cocoa on the Command Line

Sometimes there’s just one tiny snippet of Cocoa code that you want to test — maybe to find out the output of NSDateFormatter for various cases, testing out some text replacement routine, or testing out some image drawing code.

It’s often too much trouble to create a new XCode project and set up the framework to do one simple test, which is why I put together this little shell script that lets you run Cocoa code from the command line:

$ runcocoa 'NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease]; [formatter setDateFormat:@"d MMM, h:mm a"]; NSLog(@"%@", [formatter stringFromDate:[NSDate date]]);'

2011-02-23 20:02:10.313 runcocoa-output[28025:903] 23 Feb, 8:02 PM

You have full access to all Cocoa libraries, and in iOS mode, access to most iOS stuff too, straight from the command line.

Update: This is now available as a GitHub project Read More »

Also tagged , | 10 Comments

Oh, Cocoa: Why I love my job

XCode as a beatnik (You heard me) There are some with a passion for paint and canvas; others, for playing musical instruments, or writing stories. For me, as I’ve discovered, it’s striving to create beautiful and functional user interfaces, or constructing in code the perfect representation of a workflow. It’s creating a piece of software that works like an extension of yourself, with the charm and elegance that makes you want to pick it up, and not put it down again.

Developing software for me is an expression of my creativity, and an outlet for my compulsion to find order in the world — not to put things in boxes, but to shape the boxes around the things.

And if ever there’s an apt medium: If French is the language of love, Cocoa is the software development environment of it, too.

Also tagged , | 1 Comment

Resuming ADC downloads (‘cos Safari sucks)

So, Safari’s resume facility is just awful — it’ll randomly restart downloads from the beginning, clobbering anything that’s already been downloaded, and the resume button will frequently disappear entirely and mysteriously from the downloads window. And if the session has expired, it’ll cause all kinds of havoc.

Anyone downloading the gazillion-gb iOS/Mac SDK + XCode on a slow and/or expensive connection will know the sheer fisticuffs-inspiring irritation this creates — speaking personally, living on a mobile broadband connection that’s usually changed at £3 per gig and often runs about as fast as I could send the data via carrier pigeon, this usually makes me want to storm Cupertino with a pitchfork.

Okay, so I could probably use Firefox or something else, but instead I figured I’d whip up* a shell script that lets me use my favoured long-haul download tool – curl. And in case there were any other sufferers of insanely-priced broadband and Safari’s antisocial behaviour, I thought I’d share it.

It’ll ask for your Apple ID and password, and store it in the keychain for you, and it’ll resume from the current working directory.

Chuck it somewhere like /usr/local/bin, make sure it’s executable (chmod +x /usr/local/bin/adc_download.sh) and call it from Terminal like:

adc_download.sh https://developer.apple.com/devcenter/download.action?path=/Developer_Tools/xcode_4_gm_seed/xcode_4_gm_seed_.dmg

If you’ve already started the download in Safari, just grab the partially-downloaded file from within the .download package Safari creates.

Here ’tis:

adc_download.sh

Update: Now includes team support, thanks to Christopher Bowns — see the comments at the top of the script for usage instructions.

P.S. I’d be interested to see how incremental updates fare when transferred from an intermediate server with rsync. It’s rather bizarre that Apple reissue the whole 3.x gb SDK with each update, rather than offering a ‘patch’ (I guess Apple lives blithely in the world of cheap bandwidth!), and it makes me wonder whether there’d be sufficient correlation between versions to save some bandwidth by avoiding transferring the similarities…

* read: spend hours on, as is my way.

Also tagged , | 20 Comments

How to mix audio samples properly on iOS

In the real world, when you hear two sounds at once, what you’re hearing is the combination (in the “+” 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’d get drummer 1 + drummer 2 + … + drummer 500 (also bleeding ears).

With digital audio though, the volume doesn’t go up to oh-god-please-make-them-stop – it’s limited to a small dynamic range.

Naïve mixing, with overflow

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 discussion on mixing digital audio by software developer and author Viktor Toth.

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. Read More »

Also tagged , | 11 Comments

Pushing MultiChannelMixer to the limit

A friend made an interesting suggestion to an issue I’m facing in the upcoming Loopy 2, and I thought I’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’s rather capable.

I modified the iPhoneMultichannelMixerTest sample project to add a bunch of channels, and measured how my iPhone 4 performed. It looks pretty linear: there’s pretty much a 1:1 relationship between number of channels, and the CPU usage, actually.

Number of Inputs to MultiChannelMixer versus CPU usage

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’d probably want to stick with a maximum number of channels around the 75-100 mark, less for targeting lesser devices, but that’s a pretty generous limit.

Not bad.

Update: Not such great news for the iPhone 3G I just tested this on, though — it freaks at anything more than 20 channels, and isn’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.

Also tagged , | 6 Comments

Easy inclusion of OpenSSL into iOS projects

Oddly, iOS doesn’t provide any OpenSSL implementation at all — If you want to do anything with crypto (like checking signatures, checksumming, etc.), you have to build in the library yourself.

I came across a great XCode project wrapper for OpenSSL yesterday, by Stephen Lombardo. This is an XCode project file that contains a target to build OpenSSL from source, and works with both Mac and iOS projects. I made some modifications to it, in order to make it work by just dropping in the OpenSSL source tarball, without having to dirty up your source tree with the extracted OpenSSL distribution.

Here’s how to use it:

  1. Download the OpenSSL source.
  2. Put the downloaded OpenSSL source tar.gz into the same folder as openssl.xcodeproj (I put it in Library/openssl within my project tree).
  3. Drag the openssl.xcodeproj file into your main project tree in XCode.
  4. Right-click on your project target, and add openssl.xcodeproj under “Direct Dependencies” on the General tab.
  5. On the Build tab for your project’s target, find the “Header Search Paths” option, and add the path:

    $(SRCROOT)/Library/openssl/build/openssl.build/openssl/include

    (Assuming you’ve put openssl.xcodeproj at the path Library/openssl — adjust as necessary).

  6. Expand your target’s “Link Binary With Libraries” build stage, and drag libcrypto.a from the openssl.xcodeproj group.

Then, you can just import and use as normal (#import <openssl/dsa.h>, etc).

Download it here

Also tagged , , , , | 3 Comments

Avoid the clobber: Nest your network activity indicator updates

On the iPhone, when you are doing anything that uses the network, you’re supposed to let the user know something’s going on, via -[UIApplication setNetworkActivityIndicatorVisible:]. This takes a boolean.

That’s all well and good, but if you have more than one object in your app that may do things with the network simultaneously, you’re going to clobber yourself.

A nice and easy solution: Maintain an activity counter and create a category on UIApplication to maintain it, and show or hide the indicator as appropriate. Then, whenever you start doing something with the network:

[[UIApplication sharedApplication] showNetworkActivityIndicator];

…And when you’re done:

[[UIApplication sharedApplication] hideNetworkActivityIndicator];

Here’s a category that’ll do it: Read More »

Also tagged , , | Leave a comment