I make my living developing copyrighted content. I pay my Federal and Michigan taxes with the income I derive writing iPhone and iPad apps, and books about programming.
It is absurdly easy to pirate my work. Google for “adamson ios sdk torrent” and you’ll find the latest book I’m co-authoring available by BitTorrent, despite the fact that my co-author and I haven’t even finished the book yet. Jailbreaking of the iPhone also makes it easy to steal the apps I write.
Nevertheless, I am appalled by the proposed “Stop Online Piracy Act” (SOPA), and the manner in which it has been brought before Congress. The December hearings in the House featured effectively no competent techincal testimony from Internet engineers, and looked to me like it was meant for show at best.
The legislation is rife with over-broad language and unintended consequences, and has little prospect of effectively stopping piracy, while causing massive collateral damage to all manner of legitimate and productive business and art.
Its supporters in Hollywood claim they’re protecting jobs, but what they’re protecting, at best, are their own outdated business models of deliberate scarcity. If you want to reform IP law to protect jobs, how about cleaning up the granting of software patents for trivial ideas, something that presents an imminent mortal threat to my industry?
This is terrible, terrible legislation, and it is shameful that the Congress has allowed it to get as far as it has. If it passes, you will be held accountable.
Your constituent,
Chris Adamson
There’s nothing like losing your editor — to Apple, no less — to ratchet up the heat to finish a book that has been too long on the burner. But with Chuck doing exactly that at the end of December, Kevin and I had the motivation to push aside our clients and other commitments long enough to finally finish the Learning Core Audio book (yes, the title is new), and send it off to the production process.
In our final push, we went through the tech review comments and reported errata — Lion broke a lot of our example code — and ended up rewriting every example in the book as Xcode 4 projects, moving the base SDK to Snow Leopard, which allowed us to ditch all the old Component Manager dependencies. For the iOS chapter, we rev’ed up to iOS 4 as a baseline and tested against iOS 5.
One of the advantages of Xcode 4 is that the source directory is cleaner for source control (no more ever-changing build folder that you have to avoid committing), while also offering a pretty simple way to get to the “derived data” folder with the build result, which was important for us because we have a number of command-line examples that create audio files relative to the executable, and Xcode 4 makes them easy to find.
In our final push, we also managed to get in an exercise with the AUSampler, the MIDI instrument that pitch-shifts the audio file of your choice, into the wrap-up chapter. So that should keep things nice and fresh. Thanks to Apple for finally providing public guidance on how to get the .aupreset file to load into the audio unit, and how the unit deals with absolute paths to the sample audio in the app bundle case.
Updated code is available from my Dropbox: learning-core-audio-xcode4-projects-jan-03-2012.zip
From here, Pearson will take a few months to layout the book, run it by us for proofing and fixes, and send it off to the printer. So… paper copies probably sometime in Spring. The whole book — minus this last round of corrections — is already on Safari Books Online, and will be updated as it goes through Pearson’s production process.
It seems like there’s been a big uptake in Core Audio in the last year or two. More importantly, we’ve moved from people struggling through the basics of Audio Queues for simple file playback (back in iPhone OS 2.0 when Core Audio was the only game in town for media) and now we see a lot of questions about pushing into interesting uses of mixing, effects, digital signal processing, etc. Enough people have gotten sufficiently unblocked that there’s neat stuff going on in this area, and we’re fortunate to be part of it.
The Prags started a forum for readers to discuss their thoughts about Steve Jobs, following his death yesterday, and asked some of their writers to prime the pump with some initial posts.
Mine, A Moral Code Cast in Steel, takes its inspiration from a quote from Ayn Rand’s Atlas Shrugged, about the expression of human genius and creativity in the form of physical things, the things we create.
It’s a dicey book to be quoting because there are a lot of people who hate, absolutely hate, Ayn Rand, and to co-opt a dead person and attach them to the selling of a product or belief system is potentially tasteless and offensive (yes, irony, thanks for noticing). And some of the objectivists doing so are being pretty ham-handed about it. The only reason I thought it was OK to proceed with is because we have that interview of Steve Wozniak saying that Jobs was inspired by Atlas Shrugged in his youth. That’s a sterling source, and easily verifiable, and that made the Jobs-Atlas analogy a viable and fair angle to take.
Plus, I think the central points really hold: that the will and ingenuity of the creator can be perceived in his or her works (indeed, it is what separates them from being raw materials), and that Jobs was particularly fascinating in finding inspiration and truth from many different sources: East and West, spiritual and physical, technology and liberal arts.
Of course, one can’t help but bring one’s own beliefs to the table. Here’s the scene immediately to my left while I work (click for full-size):
Anyways, Bill got on board back in the NeXT days, and he’s got a great post too, so be sure to check that out.
Yuna:book cadamson$ svn commit
Sending book/ch11/Ch11.txt
Sending book/ch12/Ch12.txt
Transmitting file data ..
Committed revision 237.
Yuna:book cadamson$
Folks, that’s the svn commit that marks the completion of the first draft of Core Audio.
How long has it taken to get here? Subversion’s got that too:
Yuna:coreaudiobook cadamson$ svn log -r1 .
----------------------------------------------------
r1 | invalidname | 2010-01-06 17:18:06 -0500 (Wed, 06 Jan 2010) | 2 lines
Created the usual trunk, tags, branches.
----------------------------------------------------
Yeah, almost two years from when I took over after original author-fade… probably will actually be two years by the time we handle rewrites and comments from reviewers, Lion fixes (AudioComponentInstance instead of ComponentInstance, etc.), and get through the production process of copy-edit, layout, and printing.
Oh, and will you be getting your money’s worth?
Yuna:book cadamson$ wc ch??/Ch??.txt
208 3972 24817 ch01/ch01.txt
295 5440 32883 ch02/Ch02.txt
371 5344 34641 ch03/Ch03.txt
623 6674 44278 ch04/Ch04.txt
318 4052 26261 ch05/Ch05.txt
515 5161 37540 ch06/Ch06.txt
884 10837 72025 ch07/Ch07.txt
740 9156 60837 ch08/Ch08.txt
738 8070 54086 ch09/Ch09.txt
910 9949 68737 ch10/Ch10.txt
498 6233 40981 ch11/Ch11.txt
77 2080 12570 ch12/Ch12.txt
6177 76968 509656 total
Yuna:book cadamson$
At a standard estimate of 250 words per page, this 80,000-word book should clock in around 320 pages. We have a few figures, so maybe it’ll be more like 350. We’ll see. Enough to cover what we thought was crucial, not so big that it could stop a charging bison.
More to do, but nice to have finally reached this milestone. Thanks to everyone who’s waited so patiently for it.
I hopped in on the MIDI chapter of the nearly-finished Core Audio book because what we’ve got now is a little obscure, and really needs to address the most obvious questions, like “how do I hook up my MIDI hardware and work with it in code?” I haven’t taken MIDI really seriously in the past, so this was a good chance to catch up.
To keep our focus on iOS for this blog, let’s talk about MIDI support in iOS. iOS 4.2 added CoreMIDI, which is responsible for connecting to MIDI devices via physical cables (through the dock connector) or wifi (on OSX… don’t know if it works on iOS).
Actually getting the connection to work can be touchy. Start with the Camera Connection Kit‘s USB connector. While Apple reps are typically quick to tell you that this is not a general-purpose USB adapter, it’s well-known to support USB-to-MIDI adapters, something officially blessed (with slides!) in Session 411 (“Music in iOS and Lion”) at WWDC 2011.
The catch is that the iPad supplies a tiny amount of power out the dock connector, not necessarily enough to power a given adapter. iOS MIDI keeps an updated list of known-good and known-bad adapters. Price is not a good guide here: a $60 cable from Best Buy didn’t work for me, but the $5 HDE cable works like a charm. The key really is power draw: powered USB devices shouldn’t need to draw from the iPad and will tend to work, while stand-alone cables will work if and only if they eschew pretty lights and other fancy power-draws. The other factor to consider is drivers: iOS doesn’t have them, so compatible devices need to be “USB MIDI Class”, meaning they need to follow the USB spec for driver-less MIDI devices. Again, the iOS MIDI Devices List linked above is going to help you out.
For keys, I used the Rock Band 3 keyboard, half off at Best Buy as they clear out their music game inventory (man, I need to get Wii drums cheap before they become collector’s items). This is
Once you’ve got device, cable, and camera connection kit, try playing your keys in GarageBand to make sure everything works.
If things are cool, let’s turn our attention to the Core MIDI API. There’s not a ton of sample code for it, but if you’ve installed Xcode enough times, you likely have Examples/CoreAudio/MIDI/SampleTools/Echo.cpp, which has a simple example of discovering connected MIDI devices. That’s where I started for my example (zip at the bottom of this blog).
You set up a MIDI session with MIDIClientCreate(), and make your app an input device with MIDIInputPortCreate(). Both of these offer callback functions that you set up with a function pointer and a user-info / context that is passed back to your function in the callbacks. You can, of course, provide an Obj-C object for this, though those of you in NDA-land working with iOS 5 and ARC will have extra work to do (the term __bridge void* should not be unfamiliar to you at this point). The first callback will let you know when devices connect, disconnect, or change, while the second delivers the MIDI packets themselves.
You can then discover the number of MIDI sources with MIDIGetNumberOfSources(), get them as MIDIEndpointRef‘s with MIDIGetSource(), and connect to them with MIDIPortConnectSource(). This connects your input port (from the previous graf) to the MIDI endpoint, meaning the callback function specified for the input port will get called with packets from the device.
MIDIPackets are tiny things. The struct only includes a time-stamp, length, and byte array of data. The semantics fall outside of CoreMIDI’s responsibilities; they’re summarized in the MIDI Messages spec. For basic channel voice messages, data is 2 or 3 bytes long. The first byte, “status”, has a high nybble with the command, and a low nybble indicating which MIDI channel (0-16) sent the event. The remaining bytes depend on the status and the length. For my example, I’m interested in the NOTE-ON message (status 0x9n, where n is the channel). For this message, the next two bytes are called “data 1″ and “data 2″ and represent the rest of the message. The bottom 7 bits of data 1 identify the note as a number (the high bit is always 0), while the bottom 7 bits of data 2 represent velocity, i.e., how hard the key was hit.
So, a suitable callback that only cares about NOTE-ON might look like this:
static void MyMIDIReadProc (const MIDIPacketList *pktlist,
void *refCon,
void *connRefCon)
{
MIDIPacket *packet = (MIDIPacket *)pktlist->packet;
Byte midiCommand = packet->data[0] >> 4;
// is it a note-on
if (midiCommand == 0x09) {
Byte note = packet->data[1] & 0x7F;
Byte veolocity = packet->data[2] & 0x7F;
// do stuff now...
So what do we do with the data we parse from MIDI packets? There’s nothing in Core MIDI that actually generates sounds. On OSX, we can use instrument units (kAudioUnitType_MusicDevice), which are audio units that generate synthesized sounds in response to MIDI commands. You put the units in an AUGraph and customize them as you see fit (maybe pairing them with effect units downstream), then send commands to the instrument units via the Music Device API, which provides functions like MusicDeviceMIDICommand, and takes the unit, and the status, data1 and data2 bytes from the MIDI packet, along with a timing parameter. Music Device isn’t actually in Xcode’s documentation, but there are adequate documentation comments in MusicDevice.h. On OSX, the PlaySoftMIDI example shows how to play notes in code, so it’d be straight-forward to combine this with CoreMIDI and play through from MIDI device to MIDI instrument: get the NOTE-ON events and send them to the instrument unit of your choice.
On iOS, we don’t currently have instrument units, so we need to do something else with the incoming MIDI events. What I decided to do for my example was to just call System Sounds with various iLife sound effects (which should be at the same location on everyone’s Macs, so the paths in the project are absolute). The example uses 4 of these, starting at middle C (MIDI note 60) and going up by half-steps.
To run the example, you’ll actually have to run it twice: first to put the app on your iPad, then stop, plug in your keyboard, and run again. It might just be easier to watch this demo:
Anyways, that’s a brief intro to CoreMIDI on iOS. The book will probably skew a little more OSX, simply because there’s more stuff to play with, but we’ll make sure both are covered. I’m also going to be getting into this stuff at CocoaHeads Ann Arbor on Thursday night.
- Sample code:CoreMidiToSystemSoundExample.zip
So, surprise, in the new iDevBlogADay, I seem to have moved up to Tuesday. And instead of deep thoughts, all I’ve got is a grab-bag of updates:
CocoaConf ’11 – I’ve added links to the slides and all the demos to my previous entry, Can We Go To Slides, Please? Second day of the conference was as good as the first… this conference is off to a great start, with Dave Klein and his family helpers organizing everything to a T. Really good, deep, and unique talks too. The conference’s web page says that they’re coming to North Carolina next… another area that I don’t think has been served by the major touring iOS conferences so far.
iOS SDK Development, 2nd Edition – I’m nearly done with the “Programming iOS” chapter, which includes an introduction to Objective-C (and an optional slam-bang into to C) and a high-level tour of the iOS SDK platform stack. Bill, meanwhile, has been working on view controllers and all the fun new iOS 5 stuff that you can do with them.
Speaking of iOS 5, I found myself with some thoughts about the implications of Automatic Reference Counting (ARC), the iOS 5 feature that so many iOS devs are keen to work with. Since LLVM has published a paper on it, it’s public enough to talk about in the abstract without violating NDA, as long as we stay away from the particulars of the iOS 5 SDK implementation.
One thought that occurred to me was when I wrote the fairly typical:
NSString *aString = [NSString stringWithFormat:
@"Date is %@", [NSDate date]];
This creates an autoreleasing NSString, meaning we don’t have to worry about explicitly releasing it. But with ARC, we never have to worry about explicitly releasing anything. So you could just as easily write the non-autoreleasing equivalent:
NSString *aString = [[NSString alloc] initWithFormat:
@"Date is %@", [NSDate date]];
This creates a retained NSString, but so what? ARC will handle the release. If anything, this may be slightly better than the autoreleased version, since this one will be released as soon as possible, while the autorelease will occur only when the autorelease pool is drained, likely at the top of the main thread’s run loop.
I also caught myself referring to the over-release of objects and the dreaded EXC_BAD_ACCESS. This is probably the most common and most destructive problem for beginning developers, as it turns a simple memory-management mistake into a crash. In the first edition, we spent a lot of time introducing the NSZombie technique to find and kill these kinds of crashers, something I frequently find myself doing in my own work.
But if ARC works as advertised, do over-release bugs go away? If I throw all my retain/release work over to ARC, then I actually can’t over-release an object, since I won’t be doing any releasing at all!
Suddenly, I feel the debugging and performance chapters — some of my favorite stuff in the first edition and maybe the one thing I thought we’d be able to copy over from the first edition with only minor rework — now changing in scope drastically. Which means the 90% rewrite we were doing is now a 95% rewrite. Good for the readers, bad for my sanity.
Core Audio – Kevin’s got an interesting example on generating MIDI events and some of the write-up to go with it, I’m just not sure if telling the Core MIDI story is enough. It kind of begs the question of what you could actually do with the MIDI events if you were the one receiving them. But are we really going to get into the Music Player API (part of Audio Toolbox, but still pretty orthogonal to the rest of the book)? It would be great if Lion’s AUSampler unit, demonstrated at WWDC, could receive the MIDI events we’re generating, but I can’t get it working, the WWDC demo code is MIA, and there is effectively zero documentation (the six hits on Google are one-line references in changeset docs and three copies of my own post to coreaudio-api).
Also, there’s great pressure to just say pencils down and ship this damn book after two years. So… I don’t know how it’s all going to turn out. At this point, we now have to go back and make some Lion and iOS 5 fixes. When I first wrote the Audio Units chapters, I used the Component Manager because it was backwards-compatible with Tiger and Leopard. But it’s gone in Lion, so I need to move that stuff over to Audio Component Manager, and re-set expectations around Snow Leopard and Lion instead.
So, that’s Tuesday. Well, that and actual paying client work. And taking care of family up North. And getting some session descriptions written up for the next two conferences. And…






