<?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; Design</title>
	<atom:link href="http://atastypixel.com/blog/tag/design/feed/" rel="self" type="application/rss+xml" />
	<link>http://atastypixel.com/blog</link>
	<description></description>
	<lastBuildDate>Tue, 24 Jan 2012 10:40:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Links for May 30th through August 8th</title>
		<link>http://atastypixel.com/blog/links-may-30th-august-8th/</link>
		<comments>http://atastypixel.com/blog/links-may-30th-august-8th/#comments</comments>
		<pubDate>Sun, 08 Aug 2010 22:00:37 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Fonts]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=1921</guid>
		<description><![CDATA[Links for May 30th through August 8th: cuf&#243;n &#8211; fonts for the people A very impressive framework that embeds any font into a website, via javascript and the canvas element. Great cross-browser support. mikeash.com: Method Replacement for Fun and Profit Method replacement and method swizzling in Objective-C. Core Data Tutorial: How To Use NSFetchedResultsController &#124; [...]]]></description>
			<content:encoded><![CDATA[<p>Links for May 30th through August 8th:</p>

<ul class="delicious-bookmarks">
<li><a href="http://cufon.shoqolate.com/generate/">cuf&oacute;n &#8211; fonts for the people</a> A very impressive framework that embeds any font into a website, via javascript and the canvas element. Great cross-browser support.</li>
<li><a href="http://www.mikeash.com/pyblog/friday-qa-2010-01-29-method-replacement-for-fun-and-profit.html">mikeash.com: Method Replacement for Fun and Profit</a> Method replacement and method swizzling in Objective-C.</li>
<li><a href="http://www.raywenderlich.com/999/core-data-tutorial-how-to-use-nsfetchedresultscontroller">Core Data Tutorial: How To Use NSFetchedResultsController | Ray Wenderlich</a> </li>
<li><a href="http://github.com/akosma/TwitThis">TwitThis &ndash; Use Multiple Twitter Clients on your iPhone Application</a> The class TwitterClientManager loads a list list of supported Twitter clients is loaded from a plist file, which can be extended to support more clients in the future;<br />
Each Twitter client is represented by an instance of the TwitterClient class;<br />
The user can choose his preferred Twitter client at any time, and launch the application by a simple touch; the TwitterClientManager class stores the selected value in the user settings.</li>

</ul>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1921" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/links-may-30th-august-8th/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Links for June 3rd through June 18th</title>
		<link>http://atastypixel.com/blog/links-june-3rd-june-18th/</link>
		<comments>http://atastypixel.com/blog/links-june-3rd-june-18th/#comments</comments>
		<pubDate>Thu, 18 Jun 2009 00:00:26 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=1631</guid>
		<description><![CDATA[Links for June 3rd through June 18th: Ten logo design tips from the field &#124; Logo Design Love 10 astonishing CSS hacks and techniques Adaptive CSS-Layouts: New Era In Fluid Layouts? effective techniques to create 100%-functional adaptive CSS-layouts WordPress Theme Development Frameworks If you build and develop WordPress themes often, you will probably be fed [...]]]></description>
			<content:encoded><![CDATA[<p>Links for June 3rd through June 18th:</p>

<ul class="delicious-bookmarks">
<li><a href="http://www.logodesignlove.com/logo-design-tips">Ten logo design tips from the field | Logo Design Love</a> </li>
<li><a href="http://www.catswhocode.com/blog/10-astonishing-css-hacks-and-techniques">10 astonishing CSS hacks and techniques</a> </li>
<li><a href="http://www.smashingmagazine.com/2009/06/09/smart-fixes-for-fluid-layouts/">Adaptive CSS-Layouts: New Era In Fluid Layouts?</a> effective techniques to create 100%-functional adaptive CSS-layouts</li>
<li><a href="http://www.smashingmagazine.com/2009/05/27/wordpress-theme-development-frameworks/">WordPress Theme Development Frameworks</a> If you build and develop WordPress themes often, you will probably be fed up of all the repetitive code writing, the constantly checking of your mark-up and all you really want to do is focus on the design and the project-specific features. The answer is a WordPress development framework</li>
<li><a href="http://steveweller.com/articles/toolbar-icons/">How to Draw Pixel-Perfect iPhone Toolbar Icons</a> Using OmniGraffle</li>

</ul>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1631" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/links-june-3rd-june-18th/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Links for May 21st through June 2nd</title>
		<link>http://atastypixel.com/blog/links-may-21st-june-2nd/</link>
		<comments>http://atastypixel.com/blog/links-may-21st-june-2nd/#comments</comments>
		<pubDate>Tue, 02 Jun 2009 07:01:25 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Lifestyle]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=1613</guid>
		<description><![CDATA[Links for May 21st through June 2nd: 49 Decent Virtual Assistant &#38; Personal Outsourcing Resources PHP: Display Adobe PSD files on a web page &#34;Any webdesigner know the PSD filetype, which is the Adobe Photoshop format. PSDs have a lot of great features, as such as layers, but they can&#8217;t being read by a browser. [...]]]></description>
			<content:encoded><![CDATA[<p>Links for May 21st through June 2nd:</p>

<ul class="delicious-bookmarks">
<li><a href="http://thegrowinglife.com/2008/04/49-decent-virtual-assistant-personal-outsourcing-resources/">49 Decent Virtual Assistant &amp; Personal Outsourcing Resources</a> </li>
<li><a href="http://www.catswhocode.com/blog/php-display-adobe-psd-files-on-a-web-page">PHP: Display Adobe PSD files on a web page</a> &quot;Any webdesigner know the PSD filetype, which is the Adobe Photoshop format. PSDs have a lot of great features, as such as layers, but they can&rsquo;t being read by a browser. Unless you use this great PHP class!&quot;</li>
<li><a href="http://www.iconfinder.net/">Iconfinder &#8211; Icon Search Made Easy</a> </li>
<li><a href="http://www.typetester.org/">Typetester &ndash; Compare fonts for the screen</a> </li>
<li><a href="http://www.kennettnet.co.uk/code/knappguide/">KNAppGuide</a> KNAppGuide is a Cocoa framework for embedding &ldquo;guides&rdquo; into your application, visually inspired by Apple Guide from the System 7 and 8 era</li>

</ul>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1613" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/links-may-21st-june-2nd/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Links for March 17th through April 24th</title>
		<link>http://atastypixel.com/blog/links-march-17th-april-24th/</link>
		<comments>http://atastypixel.com/blog/links-march-17th-april-24th/#comments</comments>
		<pubDate>Fri, 24 Apr 2009 00:00:41 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[XML]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=1514</guid>
		<description><![CDATA[Links for March 17th through April 24th: XSD Schema XML Validator A XSD Schema validator in Java, provides lots of useful information; use it with a schema and an xml instance Three20 Three20 is a collection of iPhone UI classes, like a photo viewer, and general utilities, like an HTTP disk cache. Three20 is derived [...]]]></description>
			<content:encoded><![CDATA[<p>Links for March 17th through April 24th:</p>

<ul class="delicious-bookmarks">
<li><a href="http://www.herongyang.com/XML-Schema/JAXP-XSD-Schema-XML-Validator-Final-Version.html">XSD Schema XML Validator</a> A XSD Schema validator in Java, provides lots of useful information; use it with a schema and an xml instance</li>
<li><a href="http://github.com/joehewitt/three20/tree/master">Three20</a> Three20 is a collection of iPhone UI classes, like a photo viewer, and general utilities, like an HTTP disk cache. Three20 is derived from the Facebook iPhone app, which is one of the most downloaded iPhone apps ever.</li>
<li><a href="http://www.webdesignerwall.com/tutorials/css-decorative-gallery/">CSS Decorative Gallery</a> &#8230;How to decorate your images and photo galleries without editing the source images. The trick is very simple. All you need is an extra &lt;span&gt; tag and apply a background image to create the overlaying effect.</li>
<li><a href="http://en.wikipedia.org/wiki/Comet_(programming)">Comet (programming) &#8211; Wikipedia, the free encyclopedia</a> Comet is a neologism to describe a web application model in which a long-held HTTP request allows a web server to push data to a browser, without the browser explicitly requesting it</li>
<li><a href="http://www.cimgf.com/2008/03/26/cocoa-tutorial-awakefromnib-vs-applicationdidfinishlaunching/">Cocoa Is My Girlfriend &raquo; Cocoa Tutorial: awakeFromNib vs applicationDidFinishLaunching</a> A very good overview of the &#39;startup&#39; procedure for objects stored in IB nib/xibs.</li>

</ul>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1514" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/links-march-17th-april-24th/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sneak preview of my new web framework Michaelangelo</title>
		<link>http://atastypixel.com/blog/sneak-preview-of-my-new-web-framework-michaelangelo/</link>
		<comments>http://atastypixel.com/blog/sneak-preview-of-my-new-web-framework-michaelangelo/#comments</comments>
		<pubDate>Sat, 28 Mar 2009 14:39:22 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/2009/03/28/sneak-preview-of-my-new-web-framework-michaelangelo/</guid>
		<description><![CDATA[I&#8217;ve been working on a new web framework which provides image theming &#8211; a little like what Elegant Grunge does with its image frames, but much more sophisticated. For example: This is a PHP framework that uses the common GD library to manipulate images. It&#8217;s main interface is a content filter &#8211; give it HTML, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on a new web framework which provides image theming &#8211; a little like what <a href="http://atastypixel.com/blog/wordpress/themes/elegant-grunge">Elegant Grunge</a> does with its image frames, but much more sophisticated.</p>

<p>For example:
<img src="http://atastypixel.com/blog/wp-content/uploads/2009/03/boathouse.jpg" width="400" height="206" alt="boathouse.jpg" title="boathouse.jpg" class="aligncenter sticky-tape tape-corners noframe" /></p>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2009/03/city.jpg" width="400" alt="A dynamic caption" title="A dynamic caption" class="aligncenter polaroid rotation frame-title noframe" /></p>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2009/03/thailand.jpg" width="171" height="300" alt="thailand.jpg" title="thailand.jpg" class="alignright wood-frame noframe" /></p>

<p>This is a PHP framework that uses the common GD library to manipulate images.</p>

<p>It&#8217;s main interface is a content filter &#8211; give it HTML, containing images, and it will return the same HTML modified so that the images are now the converted versions, according to their &#8216;class&#8217; attributes, with appropriate width/height attributes, etc.  This makes it super easy to work with.</p>

<p>It stands alone, but it is also going to be a WordPress plugin (as you can see on this site, it&#8217;s already operational), a Joomla plugin, and I&#8217;m considering establishing a web service too, so those who don&#8217;t have adequate software on their server can still use it.</p>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2009/03/img-1773.jpg" width="300" height="200" alt="IMG_1773.jpg" title="IMG_1773.jpg" class="aligncenter wood-frame noframe" /></p>

<p>It has a plugin-based architecture so anyone can add new &#8216;themes&#8217; (<em>props to my partner Katherine for that beautiful wooden frame, by the way</em>).  I&#8217;m going to also implement a simple XML-based plugin schema, and possibly an interface to it, so that it&#8217;s easy to do so.  I&#8217;m planning a &#8216;community&#8217; style directory site to host contributed styles.</p>

<p>The base frame rendering code is such that it is trivially easy to add a new &#8216;theme&#8217;.  It extracts segments from a single frame image, and handles seamless tiling to make the frame the right dimensions, so you don&#8217;t even have to worry about overlapping regions.</p>

<p>I will release it soon, after adding a little more content &#8211; keep your eyes peeled.</p>

<p>For now, check out the <a href="http://atastypixel.com/blog/wp-content/plugins/michaelangelo/Michaelangelo/Sample">Michaelangelo showcase</a>, which gives an idea of the different styles, and contains an interactive sampler to play with styles (<em>IE users should stop being IE users to view this</em>).</p>

<p>Doing my bit to beautify the web.</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1566" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/sneak-preview-of-my-new-web-framework-michaelangelo/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Links for February 28th through March 3rd</title>
		<link>http://atastypixel.com/blog/links-february-28th-march-3rd/</link>
		<comments>http://atastypixel.com/blog/links-february-28th-march-3rd/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 03:00:23 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=1455</guid>
		<description><![CDATA[Links for February 28th through March 3rd: Lifehacker readers: Most Popular Reliable and Affordable Web Hosts Top seven hosts as voted by readers (DreamHost, Blue Host, NearlyFreeSpeech.NET, 1&#38;1, GoDaddy, HostGator and A Small Orange) Domainr, the domain name search engine Given a name, suggests a variety of different domain name possibilities, and reports on availability [...]]]></description>
			<content:encoded><![CDATA[<p>Links for February 28th through March 3rd:</p>

<ul class="delicious-bookmarks">
<li><a href="http://lifehacker.com/5124856/most-popular-reliable-and-affordable-web-hosts">Lifehacker readers: Most Popular Reliable and Affordable Web Hosts</a> Top seven hosts as voted by readers (DreamHost, Blue Host, NearlyFreeSpeech.NET, 1&amp;1, GoDaddy, HostGator and A Small Orange)</li>
<li><a href="http://domai.nr/">Domainr, the domain name search engine</a> Given a name, suggests a variety of different domain name possibilities, and reports on availability</li>
<li><a href="http://www.schillmania.com/content/projects/even-more-rounded-corners/">Even More Rounded Corners With CSS &#8211; Schillmania.com</a> Single-image, PNG-based, fluid rounded corner dialogs with support for borders, alpha transparency throughout, gradients, patterns and whatever else you (or your designer) could want</li>
<li><a href="http://www.smashingmagazine.com/2009/02/04/50-beautiful-and-user-friendly-navigation-menus/">50 Beautiful And User-Friendly Navigation Menus</a> Navigation inspiration</li>
<li><a href="http://ocrterminal.com/">OCR Terminal</a> OCR Terminal is a free online Optical Character Recognition service that allows you to convert scanned images and PDF&#39;s into editable and text searchable documents. It accurately preserves formatting and layout of documents.</li>

</ul>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1455" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/links-february-28th-march-3rd/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Podcast interview with Dan Grigsby of Mobile Orchard on Loopy&#8217;s development</title>
		<link>http://atastypixel.com/blog/podcast-interview-with-dan-grigsby-of-mobile-orchard-on-loopys-development/</link>
		<comments>http://atastypixel.com/blog/podcast-interview-with-dan-grigsby-of-mobile-orchard-on-loopys-development/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 08:49:26 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Loopy]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/2009/03/03/podcast-interview-with-dan-grigsby-of-mobile-orchard-on-loopys-development/</guid>
		<description><![CDATA[Last Thursday I did an interview with Dan Grigsby from Mobile Orchard; the interview is now online. Highlights from this interview include: From UIView to OpenGL: the seven different implementations it took to finalize its unique — and Best App Ever award-nominated — UI. From audio-queues to Remote IO: the four different architectural approaches he [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://atastypixel.com/blog/wp-content/uploads/2009/03/iphone-loopy-mobileorchard.png" width="106" height="200" alt="iphone-loopy-mobileorchard.png" title="iphone-loopy-mobileorchard.png" class="alignright noframe" />Last Thursday I did an interview with Dan Grigsby from <a href="http://www.mobileorchard.com">Mobile Orchard</a>; the <a href="http://www.mobileorchard.com/interview-with-michael-tyson-creator-of-the-audio-mixing-app-loopy/">interview</a> is now online.</p>

<blockquote>
<em>Highlights from this interview include:

From UIView to OpenGL: the seven different implementations it took to finalize its unique — and Best App Ever award-nominated — UI.

From audio-queues to Remote IO: the four different architectural approaches he tried before finalizing audio subsystems.

The travails of trying to implement echo cancelation.

The business of making a living off of a $10 app</em>
</blockquote>

<p>Listen to it <a href="http://www.mobileorchard.com/interview-with-michael-tyson-creator-of-the-audio-mixing-app-loopy/">here</a>, or <a href="http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=294369513">subscribe in iTunes</a> (30 min.)</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1462" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/podcast-interview-with-dan-grigsby-of-mobile-orchard-on-loopys-development/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Developing Loopy, Part 2: Implementation</title>
		<link>http://atastypixel.com/blog/developing-loopy-part-2-implementation/</link>
		<comments>http://atastypixel.com/blog/developing-loopy-part-2-implementation/#comments</comments>
		<pubDate>Sun, 15 Feb 2009 14:12:34 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Loopy]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/2009/02/15/developing-loopy-part-2-implementation/</guid>
		<description><![CDATA[This is part 2 of a series following the development of Loopy, my iPhone app. Part 2 describes a number of implementation challenges encountered.]]></description>
			<content:encoded><![CDATA[<p><img src="http://atastypixel.com/blog/wp-content/uploads/2009/02/loopy.png" width="93" height="111" alt="Loopy" title="Loopy" class="noframe alignright" />This is part 2 of a series following the development of Loopy, my iPhone app.</p>

<p>In <a href="http://atastypixel.com/blog/2009/02/09/developing-loopy-part-1-interface/">part 1</a>, I wrote about Loopy&#8217;s interface.  Part 2 will be more technical, and will cover some challenges encountered during the evolution of Loopy from concept and mockup to working software.  Or, more specifically, the stupid things I did along the way.<span id="more-1426"></span></p>

<h3>The Long Path to Audio</h3>

<p>Loopy&#8217;s audio implementation went through many revisions, as I both gained insight into the workings of the iPhone&#8217;s audio subsystem, and chased down performance.</p>

<h4>Take One</h4>

<div class="wp-caption alignright">
<a href="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902141924.jpg" rel="lightbox[1426]"><img src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902141924-tm.jpg" width="200" height="111" alt="Audio implementation #1" title="Audio implementation #1" /></a><p class="wp-caption-text">Audio implementation #1</p></div>

<p>The audio implementation that Loopy&#8217;s first prototype had was based on the common &#8216;Audio Queue&#8217; services: Each track had an audio queue for playback, and an audio queue for recording.  Each queue was just started and stopped as needed.</p>

<p>The problem here was the long delays: Whenever one started a recording queue, for example, there was a half-second-or-so delay before audio started coming in. Obviously, for a music app, this was crazy &#8211; you&#8217;d lose the first beat!</p>

<h4>Take Two</h4>

<div class="wp-caption alignright">
<a href="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902141928.jpg" rel="lightbox[1426]"><img src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902141928-tm.jpg" width="200" height="100" alt="Audio implementation #2" title="Audio implementation #2" /></a><p class="wp-caption-text">Audio implementation #2</p></div>

<p>The second attempt involved a single recording audio queue that was always running &#8211; when we weren&#8217;t recording, we&#8217;d just throw away the sound.  When a track started recording, the recorded sound from the queue would be pushed into the recording track.</p>

<p>This did away with any startup delays &#8211; but the new problem was the time taken to start and stop tracks playing. Again, there was a half-second delay when tracks were started.</p>

<h4>Take Three</h4>

<div class="wp-caption alignright">
<a href="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902141932.jpg" rel="lightbox[1426]"><img src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902141932-tm.jpg" width="200" height="103" alt="Audio implementation #3" title="Audio implementation #3" /></a><p class="wp-caption-text">Audio implementation #3</p></div>

<p>The third attempt used a single playback queue, to avoid the play/stop delays.  When no track was playing, silence would be output; when one or more tracks were playing, their audio would be manually mixed and given to the queue.</p>

<p>This nearly had it, but latency was just too long &#8211; if one tapped out a beat, the sound coming out of the speakers would be often half a beat behind, which really messed with one&#8217;s head.</p>

<h4>Take Four</h4>

<div class="wp-caption alignright">
<a href="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902141935.jpg" rel="lightbox[1426]"><img src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902141935-tm.jpg" width="200" height="103" alt="Audio implementation #4" title="Audio implementation #4" /></a><p class="wp-caption-text">Audio implementation #4</p></div>

<p>The final implementation, which turned out fairly well, uses a system that is shrouded in mystery: <a href="http://atastypixel.com/blog/2008/11/04/using-remoteio-audio-unit/">Remote IO</a> (or IO Remote, or <em>The Great Audio Interface Of Doom</em> depending on where you look)</p>

<p>The Remote IO system gives you near-direct access to the audio equipment, which means you can essentially pick the audio latency you want, at the cost of convenience and sanity.</p>

<p>Learning enough about this system to use it was a long process, and it ended up being a <em>pastie.org</em> snippet, random bits and pieces from a <a href="http://libsdl.org">libSDL</a> source code commit notification, and some obscure sample code from Apple that led me in the right direction.  The lack of proper documentation here was quite absurd, and not at all helped by the stranglehold that Apple had placed on all development chatter at the time.  Thankfully, things are moving in the right direction now. (<em>I even got asked recently to write some documentation for Apple on the Remote IO framework, which was very cool, if mystifying</em>)</p>

<p>Anyway, the new audio engine was fast and responsive, and I breathed a sigh of relief.</p>

<h4>Echo Folly</h4>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902141957.jpg" width="99" height="79" alt="200902141957.jpg" title="200902141957.jpg" class="alignright" />The other aspect of Loopy&#8217;s audio worth mentioning was my foray into echo cancellation &#8211; the original intention for Loopy was as a &#8216;performance&#8217; device, able to be used without any necessary bits and pieces &#8211; like headphones &#8211; plugged in.  This, of course, was complicated by the fact that the iPhone&#8217;s mic is right next to the speaker.</p>

<p>Consequently I decided to have a go at removing the echo signal from incoming audio.</p>

<p>Echo removal is actually a fairly interesting technology &#8211; at least, it is if you&#8217;re a geek like me.  The general idea is that you have some audio playing, which you remember, and you have some audio recording.  The recorded audio, because the speaker is nearby, consists of both the desired signal (singing, etc), <em>plus</em> a version of the audio coming out of the speaker.</p>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902142005.jpg" width="400" height="113" alt="200902142005.jpg" title="200902142005.jpg" class="aligncenter" /></p>

<p>Because we remembered what we last put out the speaker, <em>in theory</em> we can then subtract the known audio from the recorded sound, to single out the original desired sound.</p>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902142011.jpg" width="400" height="104" alt="200902142011.jpg" title="200902142011.jpg" class="aligncenter" /></p>

<p>As with many such things, it&#8217;s a lot more complicated: We have to find the speaker&#8217;s sound in the recorded audio before we can subtract it.  Even more tricky, it won&#8217;t be exactly the same, because it&#8217;s distorted by the speaker &#8211; the audio will be a different volume, and in the case of the iPhone&#8217;s speaker, the bass parts of the audio will be gone, for example. It will also be sampled differently to the original signal.</p>

<div class="wp-caption alignright">
<a href="http://atastypixel.com/blog/wp-content/uploads/2009/02/twitpic-photos-large-979737.png" rel="lightbox[1426]"><img src="http://atastypixel.com/blog/wp-content/uploads/2009/02/twitpic-photos-large-979737-tm.jpg" width="232" height="163" alt="Testing correlation" title="Testing correlation" /></a><p class="wp-caption-text">Testing correlation</p></div>

<p>Anyway, I gave it a go.  Enthusiastic for the challenge, I started an implementation myself, which included a <a href="http://en.wikipedia.org/wiki/Cross-correlation">cross-correlation</a> procedure to find the speaker&#8217;s audio in the recorded sound, and a routine to perform a subtraction, with a mechanism to &#8216;tune&#8217; the procedure by determining how much audio was removed, and tuning parameters accordingly.</p>

<p>And, you know, I got close&#8230;but not close enough &#8211; not enough sound was removed to make it usable.  The main issue was the lack of sophistication of my actual signal removal routine.  There are algorithms that do a better job out there, but I didn&#8217;t have the time to spend researching them all.  Maybe another day!</p>

<p>I tried a pre-built solution, built into the great <a href="http://speex.org">Speex</a> engine, but the requirements of the Speex echo cancellation library were much too great for the poor iPhone, and sound lag was huge.</p>

<p>So, in liu of having echo removal, Loopy now drops the speaker volume whenever it is recording (<em>The U.S. spent $11 million developing a pen that works in space&#8230;The Russians used a pencil</em>).</p>

<h3>Seven Different Interfaces</h3>

<p>The second major challenge was Loopy&#8217;s interface &#8211; the six rotating platters.  The problem was update rate: The display had to appear smooth with all six tracks playing, which means a framerate of at least 20 frames per second, for all six tracks &#8211; at least 120 renders per second.</p>

<p>It sounds easy enough, but Loopy&#8217;s interface was re-implemented no less than seven times before I got it right. Some notable stages along this journey:</p>

<ul>
<li><p>
<a href="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902142057.jpg" rel="lightbox[1426]"><img src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902142057-tm.jpg" width="200" height="26" alt="200902142057.jpg" title="200902142057.jpg" class="alignright" /></a>The first implementation used a sequence of images to draw the rotating ring. The drawing routine (<tt>drawInRect</tt> for each of the six <tt>UIView</tt>s) would simply draw each image in turn.</p><p>This turned out to be too slow, and would completely block the interface with more than four tracks playing.</p></li>
<li><p>Next, I tried putting the drawing routines into a thread, and then drawing to an off-screen buffer (actually, drawing into a <tt>UIImage</tt>).  Then the <tt>UIView</tt>&#8216;s drawing routine would only have to draw a single image, instead of compositing the background with the ring and other elements</p><p>My plan failed, however &#8211; at the time, I couldn&#8217;t for the life of me figure out how to draw into an image in a thread (<em>from what I remember after I found out, I think one has to use a CGImage, or something, as the entire UIKit framework isn&#8217;t thread-safe</em>), and even drawing a single image appeared to be too much to keep the framerate up, anyway.</p></li>
<li><p><img src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902142048.jpg" width="150" height="170" alt="200902142048.jpg" title="200902142048.jpg" class="alignright" />I discarded the pre-rendered images, and decided to go with an approach which didn&#8217;t require sending images to the iPhone&#8217;s video card each frame.  Instead, I draw a mask and used that to mask out the ring image, with the mask rotated for each frame.</p><p>Surprisingly, even this technique was too slow, even after trying an implementation that consolidated the drawing for all six tracks into a single thread.</p></li>
</ul>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902142101.jpg" width="150" height="130" alt="200902142101.jpg" title="200902142101.jpg" class="alignright" />After some consultation with other developers, I realised that even Core Animation just wasn&#8217;t cut out to do this kind of rendering (<em>I get the impression that Core Animation, too, creates and uploads image data to the video card for every frame</em>), and threw it all out the window.</p>

<p>I re-implemented the whole thing in OpenGL, with the same &#8216;masking&#8217; concept (but drawing rotating triangles with texture co-ordinates bound to screen co-ordinates), and got what I needed.</p>

<p>This new implementation was much simpler and easier to maintain &#8211; always a good sign that it&#8217;s the right one!</p>

<h3>Start, Stop, Pad, Truncate</h3>

<p>Timing of loop recording was quite tricky to get right &#8211; deceptively so.</p>

<p>Right from the start, Loopy&#8217;s timing mechanism has been based upon a &#8216;clock&#8217;, which defined a length of time representing a base loop length &#8211; in musical terms, a bar.</p>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902151243.jpg" width="331" height="83" alt="200902151243.jpg" title="200902151243.jpg" class="aligncenter" /></p>

<p>Tracks could then be multiples of the bar length, or a half, a quarter or an eighth of the bar.  They could also be offset by a certain amount of time, meaning that recordings could start any time and would be kept in sync.</p>

<p>The original implementation forced the recording to extend to multiples of the &#8216;clock&#8217; length:</p>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902151239.jpg" width="331" height="122" alt="200902151239.jpg" title="200902151239.jpg" class="aligncenter" /></p>

<p>This meant that if you tapped to stop recording, the track would continue recording anyway, until the next clock tick (or half-tick, etc.), plus offset, was reached.  This was the &#8220;<em>don&#8217;t trust the user</em>&#8221; approach, assuming that users wouldn&#8217;t keep time properly and would need to be guided.</p>

<p>I tried several variations on this theme, testing different logic, such as <em>if the recording length is more than X time than the clock length, keep recording until the next tick, otherwise stop and delete the last X of the track</em>.</p>

<p>That whole concept was generally a bad idea, though, and resulted in people (including myself, once or twice) thinking the interface wasn&#8217;t working properly.</p>

<p>The final implementation stops as soon as directed, which feels much better.  It will either pad the rest of the track, so that it is up to multiples of the clock length (or a full quarter/half/etc.):</p>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902151309.jpg" width="331" height="121" alt="200902151309.jpg" title="200902151309.jpg" class="aligncenter" /></p>

<p>&#8230;or it will truncate if it&#8217;s within some threshold of a beat:</p>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2009/02/2009021513091.jpg" width="331" height="142" alt="200902151309.jpg" title="200902151309.jpg" class="aligncenter" /></p>

<p>Something I realised as I was using it was that it was impossible to record things like anacruses (<em>AKA upbeats</em>), where a riff starts just before a beat.  With some experimentation, I decided to replace the straight truncation with a mix-then-truncate approach:</p>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902151305.jpg" width="339" height="159" alt="200902151305.jpg" title="200902151305.jpg" class="aligncenter" /></p>

<p>This is how Loopy operates now, and I think it works fairly well.</p>

<h3>A Sense of Rhythm</h3>

<p>The other timing issue was related to synchronisation and recorder latency &#8211; that is, if you record one track, then record another one, you want both recordings to be in time with each other.  This was, and still is, tricky.</p>

<p>One has to track the latency for both the &#8216;play&#8217; path &#8211; the time taken for audio in the memory buffer to get pushed out the speaker and heard &#8211; and the &#8216;record&#8217; path &#8211; the time taken for sound to be digitised and stored in a buffer.</p>

<p><img src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902151328.jpg" width="377" height="102" alt="200902151328.jpg" title="200902151328.jpg" class="aligncenter" /></p>

<p>In Loopy&#8217;s current implementation, this latency estimation is a hard-coded number worked out during testing: This number is used to offset the time associated with a recording, so that it stays in sync.  And on my iPhone, it works great.  However, I hear reports that the timing is off for other users, and so this is still an outstanding issue.</p>

<p>Does this mean that latency varies between devices &#8211; manufacturing variations?  Or, is it software-based &#8211; perhaps if the device is busy doing some other things, like checking email, latency will increase?</p>

<p>Time will tell, I suppose.</p>

<h3>The Way Forward</h3>

<p>Good software is a constantly-evolving thing, which grows and is guided by its users, and this is certainly the plan for Loopy. I recently wrote a <a href="http://atastypixel.com/blog/2009/01/17/loopy-status-update/">status update</a> on Loopy, which outlines a little of the planned path.</p>

<p>While the original idea for Loopy was very constrained, many users are already seeing a much greater potential, which is exciting and gratifying, and I&#8217;m looking forward to taking it in new directions.</p>

<p><small><em>At some stage, I would like to write a third article for this series, covering promotion.  This will be a while in coming, though, as this is a learning curve I have yet to climb!  I will say this: My next experiment will be the creation of a free, &#8220;Lite&#8221; version of Loopy, which advertises the full version. This seems to have worked <a href="http://blog.wired.com/gadgets/2009/02/shoot-is-iphone.html">ridiculously well</a> for some, so it&#8217;s well worth a shot!<br/>For those who made it this far, thanks for reading &#8211; I&#8217;d love to hear your comments on these articles, and on Loopy itself.</em></small></p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1426" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/developing-loopy-part-2-implementation/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Links for January 31st through February 9th</title>
		<link>http://atastypixel.com/blog/links-january-31st-february-9th/</link>
		<comments>http://atastypixel.com/blog/links-january-31st-february-9th/#comments</comments>
		<pubDate>Mon, 09 Feb 2009 07:00:19 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[Textures]]></category>
		<category><![CDATA[Typography]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=1329</guid>
		<description><![CDATA[These are my links for January 31st through February 6th:

<ul>
<li><a href="http://kickingbear.com/blog/archives/9">NSCollection Extensions</a> Weird and wonderful extensions to key/value coding ([myRecordCollection valueForKeyPath:
@&#34;[collect].{artist like &#39;Tom Waits&#39;}.&#60;NSUnarchiveFromDataTransformerName&#62;.albumCoverImageData&#34;])</li>
<li><a href="http://www.yourfonts.com/">Free Fonts Generator</a> Make Your Own Handwriting Font</li>
<li><a href="http://github.com/Grayson/pluginmanager/tree/master">Grayson's pluginmanager</a> A series of classes that provides support for a vast number of scripting languages as well as standard Cocoa bundles</li>
<li><a href="http://www.deezer.com/">Deezer</a> Listen to full songs online: Good for getting a preview of albums, much better than iTunes&#39; silly 30 second snippets</li>

</ul>]]></description>
			<content:encoded><![CDATA[<p>Links for January 31st through February 9th:</p>

<ul class="delicious-bookmarks">
<li><a href="http://www.lostandtaken.com/">Lost and Taken</a> Free stock textures for your graphic design and photography projects</li>
<li><a href="http://kickingbear.com/blog/archives/9">NSCollection Extensions</a> Weird and wonderful extensions to key/value coding ([myRecordCollection valueForKeyPath:
@&quot;[collect].{artist like &#39;Tom Waits&#39;}.&lt;NSUnarchiveFromDataTransformerName&gt;.albumCoverImageData&quot;])</li>
<li><a href="http://www.yourfonts.com/">Free Fonts Generator</a> Make Your Own Handwriting Font</li>
<li><a href="http://github.com/Grayson/pluginmanager/tree/master">Grayson&#8217;s pluginmanager</a> A series of classes that provides support for a vast number of scripting languages as well as standard Cocoa bundles</li>
<li><a href="http://www.deezer.com/">Deezer</a> Listen to full songs online: Good for getting a preview of albums, much better than iTunes&#39; silly 30 second snippets</li>

</ul>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1329" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/links-january-31st-february-9th/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Developing Loopy, Part 1: Interface</title>
		<link>http://atastypixel.com/blog/developing-loopy-part-1-interface/</link>
		<comments>http://atastypixel.com/blog/developing-loopy-part-1-interface/#comments</comments>
		<pubDate>Mon, 09 Feb 2009 09:26:59 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Loopy]]></category>
		<category><![CDATA[Software]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=1364</guid>
		<description><![CDATA[Part 1 of a series that covers development of Loopy, my loop-based performance/musical scratchpad iPhone App. Part 1 follows the development of Loopy's interface.]]></description>
			<content:encoded><![CDATA[<p><img class="noframe alignright" title="Loopy" src="http://atastypixel.com/blog/wp-content/uploads/2009/02/loopy.png" alt="Loopy" width="93" height="111" />Loopy is my first iPhone app, a loop-based performance/musical scratchpad app based on looping audio equipment and inspired by, equally, the fantastic and free &#8220;<a href="http://freewheeling.sourceforge.net/">Freewheeling</a>&#8221; application, and an <a href="http://www.youtube.com/watch?v=25VGdNU3nrU">a capella performance by Imogen Heap</a>.</p>

<p>It&#8217;s development was a whirlwind of obsessive coding, near-vertical learning curves, impatience, excitement and occasional burnout and writers block.</p>

<p>I thought I&#8217;d share some facts and lessons learned from the process, in a several-part article.  For part 1, read on.<span id="more-1364"></span></p>

<h3>Beginnings</h3>

<p>After using Freewheeling while I was a Linux user, I missed it quite badly.  I made several attempts to get it going under Mac OS X, but failed each time.  I could never find anything quite like it, and so I made do without it.</p>

<p>Then, after deciding to jump on the iPhone app development bandwagon, I thought that pursuing this passion would be a good place to start.</p>

<p>This, of course, was entirely wrong &#8211; as Daniel Jalkut and Manton Reece said a while ago on their podcast <a href="http://coreint.org/">Core Intuition</a>, it&#8217;s a very good idea to start small for your first project, and work out the kinks before trying something more adventurous.  Loopy was huge and ambitious, and thus risky &#8211; the emotional investment alone was significant, and if it was a flop, it would&#8217;ve been heartbreaking, aside from a waste of quite a lot of time.</p>

<p>While that&#8217;s lesson number one right there, I&#8217;m still not entirely sure I could&#8217;ve done it differently &#8211; I&#8217;m the type to get very swept up in an idea.</p>

<p>So, there that is.</p>

<h3>Sketching Interfaces</h3>

<div class="wp-caption alignright"><a href="http://atastypixel.com/blog/wp-content/uploads/2009/02/loopy-original.jpg" rel="lightbox[1364]"><img title="Loopy's first incarnation" src="http://atastypixel.com/blog/wp-content/uploads/2009/02/loopy-original-tm.jpg" alt="Loopy's first incarnation" width="200" height="300" /></a>
<p class="wp-caption-text">Loopy&#8217;s first incarnation</p>

</div>

<p>The first version of the interface mockup emerged fairly quickly.  The primary goal was a physical-feeling interface, and so naturally it was made up of LEDs and push buttons, inspired by studio equipment.  As is the case with all such things, it had to be fairly simple to understand at a glance.  What better path to simplicity by following in Apple&#8217;s footsteps: One button to do absolutely everything.  Thus, loops consisted of just a button &#8211; press to start, press to stop.</p>

<p>The interface needed to quickly get across the concept of the loop, which is where the circle of LEDs came from (my laziness made it a circle that filled up, instead of a &#8216;chase&#8217; sequence. I got over that fairly quickly).  We all like audio meters, so they went in, too &#8211; mostly as a mechanism to identify which track was making which sounds.</p>

<p>Unfortunately it looked fairly amateurish and busy, so I needed an alternative.  I&#8217;d recently bought a <a href="http://www.logitech.com/index.cfm/keyboards/keyboard/devices/3848&amp;cl=US,EN">Logitech diNovo Mini</a> keyboard for our Mac Mini-based entertainment system, and one day it caught my eye.</p>

<div class="wp-caption alignright"><img title="The diNovo Mini Touchpad" src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902081924.jpg" alt="The diNovo Mini Touchpad" width="116" height="128" />
<p class="wp-caption-text">diNovo Mini Touchpad</p>

</div>

<p>The diNovo Mini has a round touch pad, which functions as both a mouse, and a five-way control (arrows and enter). Depending on the mode, it would either light up around the outside in orange, or five symbols on the pad would light up green.  It was very stylish, so as all &#8216;great&#8217; artists do (<em>not that I&#8217;m anything resembling an artist</em>), I shamelessly nicked it. Don&#8217;t tell anyone.</p>

<p>The ring around the outside became a rotating platter, which conveniently carried many useful connotations for the audio &#8211; rotating LPs, in particular.  The audio meter was replaced by varying the brightness of the ring, which kept the interface clean &#8211; although admittedly at the cost of some of its utility.</p>

<p>And thus, Loopy had its interface:</p>

<p><a href="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902081927.jpg" rel="lightbox[1364]"><img class="aligncenter" title="Loopy's Interface" src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902081927-tm.jpg" alt="Loopy's Interface" width="200" height="287" /></a></p>

<h3>Control Freak</h3>

<p>The tricky thing about this app was all the functionality it needed to offer, while still appearing simple.  It wasn&#8217;t enough to just offer tracks that one could record, then start and stop, and that&#8217;s it.  After pouring over Imogen Heap&#8217;s performance mentioned at the start of this article, I realised that there was quite a lot going on.</p>

<p><img class="alignright" title="200902090855.jpg" src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902090855.jpg" alt="200902090855.jpg" width="47" height="37" />Firstly, she was mixing the looped sound with new audio, as she went.  She would sing one part, then immediately sing a harmony, then sing another harmony, adding complexity to the looped sound as she went.  That would be just too cumbersome to perform with only a basic recording functionality, so <em>Mix Recording</em> was born.</p>

<p><img class="alignright" title="200902090855.jpg" src="http://atastypixel.com/blog/wp-content/uploads/2009/02/2009020908551.jpg" alt="200902090855.jpg" width="47" height="37" />Towards the end of the performance, something else was happening &#8211; she would perform one loop, then immediately sing a harmony to it, before going back to the original tune.  At the same time, only the last loop was playing &#8211; thus, she was alternating the main phrase with a harmony.  Voila, <em>Loop Recording</em>.</p>

<p><img class="alignright" title="200902090857.jpg" src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902090857.jpg" alt="200902090857.jpg" width="47" height="37" />The final track function, <em>Merge</em>, came much later.  It emerged as a way to free up tracks, while not losing any audio, and was an alternative to adding more track buttons.</p>

<p>Combined with the need to reset a track, suddenly there were four functions a track had to perform: Record, Clear, Mix Record and Loop Record.  Combine that with adjustments to the track (mainly volume), and suddenly the necessary control scheme had some serious complexity.</p>

<h4>Track Functions</h4>

<p>The original prototype implementation involved &#8216;swipe&#8217; gestures to access the three features other than &#8216;Record&#8217; (Clear, Mix Record, Loop Record) &#8211; one would swipe either left, up, or right to access each feature.  This was cumbersome and unreliable: Half the time, one would end up accessing the wrong feature.</p>

<p>A variety of options were thrown around, during a discussion with a close friend and sometime partner in crime, <a href="http://formyownamusement.com">Tim</a>.  Most possibilities were based on a radial menu, where one opened the menu, probably by holding down the button, then selected an item that popped up.  This appeared to be far more sensible than haphazard swipe gestures.</p>

<p>Rather than radial menus, which involved breaking the physical metaphor of the buttons, and involved some complexity with fitting onscreen, radial &#8216;selectors&#8217; were chosen instead &#8211; lights around the periphery of each button that one selected after holding the button for a moment.  This kept the interface uncluttered.</p>

<p><img class="alignright" title="200902090858.jpg" src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902090858.jpg" alt="200902090858.jpg" width="120" height="109" />Deciding to stay with the single-button interface was a slightly risky proposition, as it had the potential to alienate users who desired more easily accessible features.  In the end, though, this was what I went with.  The alternative was to break up tracks into multiple-button interfaces, which immediately cluttered the application, and either reduced the number of tracks that could be simultaneously manipulated, or reduced the size of the controls, making it harder to hit the right button.  As I was after something that could be used while performing, for example, this just wasn&#8217;t going to work &#8211; it would&#8217;ve been too cumbersome.</p>

<h4>Track Manipulation</h4>

<p>The next issue was how to manipulate track volume.  This came up after the initial interface plan was devised, once it become obvious that users would want control over track volume, at the least.</p>

<p>One of the options on the table was a landscape-view screen, that included slider controls for each track.  One would hold the button down, rotate the device, and the track&#8217;s sliders would appear.  This option was passed over for now, but is very likely to be revisited to support future track features.</p>

<p>Another option was to hold down the button while rotating the device like a giant volume knob, using the device&#8217;s accelerometer to detect the position of the &#8216;dial&#8217;.  The sheer awkwardness of this approach made it a bit impractical, although it would&#8217;ve been cool.</p>

<p><img class="alignright" title="200902090900.jpg" src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902090900.jpg" alt="200902090900.jpg" width="81" height="85" />It was a return to thinking about the original physical metaphor that yielded the final idea &#8211; kinda like a DJ pushes a record to speed or slow playback, a &#8216;swirl&#8217; gesture seemed a reasonable and intuitive way to adjust track parameters like volume.</p>

<h4>Tick, Tock</h4>

<p><img class="alignright" title="200902090901.jpg" src="http://atastypixel.com/blog/wp-content/uploads/2009/02/200902090901.jpg" alt="200902090901.jpg" width="38" height="40" />The final interface element, the clock, was almost an afterthought, and remains more-or-less at a prototype stage in the current version of Loopy.  The tap-timing feature was one that spontaneously occurred to me during development, and got added in: Being able to pre-define a tempo seemed a useful feature, but not one that was expected to be widely used.  As is often the case without performing large-scale user testing, it turns out to be a fairly popular feature.  Consequently, future versions of Loopy are going to have a much more sophisticated clock, metronome and tempo management facility.</p>

<h3>Interface Lessons</h3>

<p>The main lessons which arose from Loopy&#8217;s interface design were actually testing and user interaction lessons.  Impatience to get the product on the market stopped me from spending a great deal of time on talking to potential users about workflow and interface, but this would have been very useful.  This is something I should still do: Find a bunch of musicians, and ask them what they would like to see, and how they work.</p>

<p>One limitation that I encountered along the way was finding an adequately diverse testing community.</p>

<p>Here&#8217;s where the iPhone App Store&#8217;s limitations were a pain.  An increasingly popular trend amongst Mac software developers is to make available a free but time-limited public beta during the final stages of development. Cultured Code did this recently with their app, <a href="http://culturedcode.com/things/">Things</a>, for example.</p>

<p>Doing this has several big advantages: Firstly, you get free testing and feedback from many users, many more than one could typically get the app in front of during a private beta.  Users are engaged with the software, because they are <em>(a)</em> being directly involved in the process, and <em>(b)</em> typically going to end up using the software, so it&#8217;s in their best interests to play an active role.  Any user interface or workflow choices that users don&#8217;t like, you find out about almost immediately, without having to wait and then deal with once customers are paying and have higher expectations (and are leaving ratings!).  Secondly, you are immediately building an image, a brand and a community, something that just won&#8217;t happen while you&#8217;re invisibly developing.</p>

<p>If the iPhone App Store had a facility to provide beta software for free, but with a time limit, and possibly with ratings disabled, this would be a fantastic tool for developers to collaborate with the community to make great software.</p>

<p>Something I needed to do more was to more actively engage beta testers &#8211; not everyone can be expected to come up with and communicate insights about software: It&#8217;s the developer&#8217;s job to start this communication.  Short questionnaires and polls would have provided some useful information about the strengths and weaknesses of the interface, and this is the kind of thing I&#8217;ll be focusing on more for next time.</p>

<h3>Coming up</h3>

<p>Seven re-implementations of the user interface, two or three re-implementations of the audio infrastructure, a ridiculous lack of documentation, and timing, timing, timing&#8230;</p>

<p>Read on, in <a href="http://atastypixel.com/blog/2009/02/15/developing-loopy-part-2-implementation/">Part 2: Implementation</a>.</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1364" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/developing-loopy-part-1-interface/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Links for November 24th through December 9th</title>
		<link>http://atastypixel.com/blog/links-%datestart-december-9th/</link>
		<comments>http://atastypixel.com/blog/links-%datestart-december-9th/#comments</comments>
		<pubDate>Tue, 09 Dec 2008 01:00:02 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[Data]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Geocoding]]></category>
		<category><![CDATA[Graphics]]></category>
		<category><![CDATA[Links]]></category>
		<category><![CDATA[Location]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/?p=1173</guid>
		<description><![CDATA[Links for November 24th through December 9th: Creating libraries for the iPhone Discussion on creating static libraries for the iPhone Photoshop Tutorials &#8211; Layered HDR Tone Mapping Learn how to tone map with Photoshop CS3 to create beautiful high dynamic range (HDR) photos. The final result is exceedingly better than Photoshop&#39;s local adaptation and similar [...]]]></description>
			<content:encoded><![CDATA[<p>Links for November 24th through December 9th:</p>

<ul class="delicious-bookmarks">
<li><a href="https://devforums.apple.com/message/5389">Creating libraries for the iPhone</a> Discussion on creating static libraries for the iPhone</li>
<li><a href="http://photoshoptutorials.ws/photoshop-tutorials/photo-manipulation/layered-hdr-tone-mapping.html">Photoshop Tutorials &#8211; Layered HDR Tone Mapping</a> Learn how to tone map with Photoshop CS3 to create beautiful high dynamic range (HDR) photos. The final result is exceedingly better than Photoshop&#39;s local adaptation and similar to Photomatix&#39;s tone mapping.</li>
<li><a href="http://www.ajaxload.info/">Ajaxload &#8211; Ajax loading gif generator</a> Generate loading animation images, given type, background and foreground.</li>
<li><a href="http://www.bittbox.com/freebies/free-texture-tuesday-inaugural/">Free Texture Tuesday  |  BittBox</a> &quot;Jay over at Bittbox has just announced that he will be giving away five high resolution textures (3,000 x 2,000 pixels) every Tuesday of the year, absolutely free!&quot;</li>
<li><a href="http://www.geonames.org/">GeoNames</a> Free service (including webservice) to search for place names, yielding co-ordinates and a feature class.</li>

</ul>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=1173" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/links-%datestart-december-9th/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Advanced web templating with PHP and regular expressions</title>
		<link>http://atastypixel.com/blog/advanced-web-templating-with-php-and-regular-expressions/</link>
		<comments>http://atastypixel.com/blog/advanced-web-templating-with-php-and-regular-expressions/#comments</comments>
		<pubDate>Sun, 12 Oct 2008 02:53:03 +0000</pubDate>
		<dc:creator>Michael Tyson</dc:creator>
				<category><![CDATA[Geekspeak]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Regex]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://atastypixel.com/blog/2008/10/12/advanced-web-templating-with-php-and-regular-expressions/</guid>
		<description><![CDATA[A method to gain more control over the styling of images for web templates/blog themes, using a bit of Regular Expression magic. This is the technique used for my recent theme, Elegant Grunge.]]></description>
			<content:encoded><![CDATA[<p><em>This post describes a method to gain more control over the styling of images for web templates/blog themes, using a bit of Regular Expression magic. This is the technique used for my recent theme, <a href="http://atastypixel.com/blog/2008/10/10/elegant-grunge-wordpress-theme/">Elegant Grunge</a>.</em></p>

<p>You&#8217;ve just designed the most beautiful template ever &#8211; pleasing composition, clean lines, smooth colours and gradients and an awesome typeface. You apply it as the theme for your blog, or release it to the community, and there is much rejoicing.<a href="http://atastypixel.com/blog/wp-content/uploads/2008/10/200810121259.jpg" rel="lightbox[921]"><img src="http://atastypixel.com/blog/wp-content/uploads/2008/10/200810121259-tm.jpg" width="100" height="67" alt="Example of the 'SH Trocadero' WordPress theme with image" title="Example of the 'SH Trocadero' WordPress theme with image" style="float:right;" /></a></p>

<p>Then you or someone else inconsiderately puts a photograph into a post &#8211; disaster! That nasty square of graphic just destroyed your composition, and the page is unbalanced and suddenly looks terrible.</p>

<p>Images are particularly tricky to make work with a theme, mostly because they&#8217;re so unpredictable. With text, it&#8217;s easy to control the way it looks. With images, they can be any colour or shape, many of which will break the composition of a theme, especially if the design elements of the theme contains irregular lines.</p>

<p>A big impediment to making images work is the limitations introduced by the current versions of CSS: All you can really do is provide a square border, possibly with some padding. That&#8217;s it, unless you&#8217;re willing to manually add tons of markup around images every time – and willing to make your users do it, if you&#8217;ve released a theme.<a href="http://atastypixel.com/blog/wp-content/uploads/2008/10/200810121308.jpg" rel="lightbox[921]"><img src="http://atastypixel.com/blog/wp-content/uploads/2008/10/200810121308-tm.jpg" width="100" height="71" alt="Example of images in the &quot;Green Light&quot; WordPress theme" title="Example of images in the &quot;Green Light&quot; WordPress theme" style="float:right;" /></a></p>

<p>Some people will carefully Photoshop-up their images to make them fit &#8211; <a href="http://webdemar.com/">Webdemar</a> (who made the theme I first used on my blog) does this, for example, and it looks great. That&#8217;s a lot of work, though, especially if you make frequent posts with images!</p>

<p>If you&#8217;re a theme designer, there&#8217;s an easier way to make images work.</p>

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

<h3>CSS Borders</h3>

<p>There are a <a href="http://www.google.com/search?q=css+rounded+borders+OR+corners">thousand and one</a> different ways to create styled borders in CSS. The basic principle is that one adds a certain amount of HTML markup around the content to be framed, and CSS rules apply background images in a variety of ways. The best of these techniques are very flexible, and allow designers to apply any kind of frame they can imagine.</p>

<p>The Joomla documentation describes <a href="http://docs.joomla.org/Creating_rounded_corners">one of these techniques</a> quite well, and it’s worth a read.</p>

<p>So, providing a frame around images allows designers to break up those straight lines, among other things. Thus, this:</p>

<div style="text-align: center;">
  <a href="http://atastypixel.com/blog/wp-content/uploads/2008/10/200810121311.jpg" rel="lightbox[921]"><img src="http://atastypixel.com/blog/wp-content/uploads/2008/10/200810121311-tm.jpg" width="300" height="216" alt="Example of &quot;Elegant Grunge&quot; WordPress theme without framed images" title="Example of &quot;Elegant Grunge&quot; WordPress theme without framed images" /></a><br />
</div>

<div style="text-align: center;">
  <small><em>Note how the straight image border breaks the ‘broken-up’ edge theme</em></small><br />
</div>

<p>Becomes this:</p>

<div style="text-align: center;">
  <a href="http://atastypixel.com/blog/wp-content/uploads/2008/10/200810121312.jpg" rel="lightbox[921]"><img src="http://atastypixel.com/blog/wp-content/uploads/2008/10/200810121312-tm.jpg" width="300" height="205" alt="200810121312.jpg" title="200810121312.jpg" class="Example of "Elegant Grunge" WordPress theme with framed images" /></a><br />
</div>

<div style="text-align: center;">
  <small><em>Frame with drop shadow provides illusion of depth, distancing image from theme</em></small><br />
</div>

<p>This is, of course, just one example, but there are many possibilities.</p>

<p>So, the question becomes: How do we provide the necessary HTML markup in the content, without doing it ourselves or making our users do it? Enter regular expressions…</p>

<h3>Regex magic</h3>

<p>The concept is very simple – whenever we encounter an image in the content, we surround it by the markup necessary to render a frame around it. There are, however, a few extra things that’d be nice:</p>

<ul>
  <li>Provide the ability to frame any content, not just images, by supplying a class</li>

  <li>Provide the ability to avoid framing some images, to provide some control, by supplying a class</li>

  <li>Manage image sizing, in case a too-large image is provided</li>

  <li>Avoid showing frames if the surrounded image is too small (and would thus look wrong)</li>

  <li>Some styles/classes applied to the inner content should be also applied to the frame (such as float settings)</li>
</ul>

<p>This PHP script gives an example of how it can be done as part of a WordPress theme: <a href="http://atastypixel.com/blog/wp-content/uploads/2008/10/framing-samplephp.zip">framing-sample.php.zip</a></p>

<p>The script provides a filter function, used by WordPress during the render pipeline to modify content. The function looks for blocks with a class of ‘frame’, or images. It avoids any block with a class of ‘noframe’ (and also ‘wp-smiley’, which is the class used for those small emoticons in WordPress). It then uses a ‘callback’ helper function to perform the actual replacement, capturing styles/classes for the inner object, and managing image sizes in the process.</p>

<p>A caveat here: The regular expression that supports wrapping any kind of content block (as opposed to just images) uses a relatively modern feature of regular expressions called recursive sub-patterns, which will not work with PHP installations with an older PCRE regular expression library. Hence, the ‘@’ sign preceding the preg_replace_callback, which will cause it to fail silently, without throwing error messages everywhere.</p>

<p>So, this code wraps the content in four ‘span’ objects, which can then be styled using CSS. For small images, it also applies the ‘small’ class, which can be used to provide a smaller frame to avoid visual glitching.</p>

<h3>CSS time</h3>

<p>So, we now have markup in place, and it’s time to provide some styles. Here’s some sample CSS:</p>

<blockquote>
  <br /><span style="color: #8C868F; font-size: 11px;"><span style="color: #8c868f">/* Frame */</span><span style="color: #000000"><br />  <br /></span>.frame-outer <span style="color: #000000">{<br /></span> background<span style="color: #000000">:</span> url<span style="color: #000000">(images/frame-top-left.jpg)</span> no-repeat left top<span style="color: #000000">;<br /></span> padding<span style="color: #000000">:</span> 0<span style="color: #000000">;<br /></span> margin<span style="color: #000000">:</span> 0<span style="color: #000000">;<br /></span> display<span style="color: #000000">:</span> inline-block<span style="color: #000000">;<br />}<br />  <br /></span>.frame-outer span <span style="color: #000000">{<br /></span> background<span style="color: #000000">:</span> url<span style="color: #000000">(images/frame-bottom-left.jpg)</span> no-repeat left bottom<span style="color: #000000">;<br /></span> margin<span style="color: #000000">:</span> 0<span style="color: #000000">;<br /></span> padding<span style="color: #000000">:</span> 0<span style="color: #000000">;<br /></span> display<span style="color: #000000">:</span> block<span style="color: #000000">;<br />}<br />  <br /></span>.frame-outer span span <span style="color: #000000">{<br /></span> background<span style="color: #000000">:</span> url<span style="color: #000000">(images/frame-top-right.jpg)</span> no-repeat right top<span style="color: #000000">;<br /></span> display<span style="color: #000000">:</span> block<span style="color: #000000">;<br />}<br />  <br /></span>.frame-outer span span span <span style="color: #000000">{<br /></span> background<span style="color: #000000">:</span> url<span style="color: #000000">(images/frame-bottom-right.jpg)</span> no-repeat right bottom<span style="color: #000000">;<br /></span> padding<span style="color: #000000">:</span> 32<span style="color: #ff7800">px</span><span style="color: #000000">;<br /></span> min-width<span style="color: #000000">:</span> 150<span style="color: #ff7800">px</span><span style="color: #000000">;<br /></span> min-height<span style="color: #000000">:</span> 150<span style="color: #ff7800">px</span><span style="color: #000000">;<br /></span> text-align<span style="color: #000000">:</span> center<span style="color: #000000">;<br /></span> overflow<span style="color: #000000">:</span> hidden<span style="color: #000000">;<br /></span> display<span style="color: #000000">:</span> block<span style="color: #000000">;<br />}<br />  <br /></span>.frame-outer span span span * <span style="color: #000000">{<br /></span> max-width<span style="color: #000000">:</span> 425<span style="color: #ff7800">px</span><span style="color: #000000">;<br />}<br />  <br /></span>.frame-outer.small <span style="color: #000000">{<br /></span> background<span style="color: #000000">:</span> url<span style="color: #000000">(images/frame-top-left-small.jpg)</span> no-repeat left top<span style="color: #000000">;<br />}<br />  <br /></span>.frame-outer.small span <span style="color: #000000">{<br /></span> background<span style="color: #000000">:</span> url<span style="color: #000000">(images/frame-bottom-left-small.jpg)</span> no-repeat left bottom<span style="color: #000000">;<br />}<br />  <br /></span>.frame-outer.small span span <span style="color: #000000">{<br /></span> background<span style="color: #000000">:</span> url<span style="color: #000000">(images/frame-top-right-small.jpg)</span> no-repeat right top<span style="color: #000000">;<br />}<br />  <br /></span>.frame-outer.small span span span <span style="color: #000000">{<br /></span> background<span style="color: #000000">:</span> url<span style="color: #000000">(images/frame-bottom-right-small.jpg)</span> no-repeat right bottom<span style="color: #000000">;<br /></span> padding<span style="color: #000000">:</span> 10<span style="color: #ff7800">px</span><span style="color: #000000">;<br /></span> min-height<span style="color: #000000">:</span> 38<span style="color: #ff7800">px</span><span style="color: #000000">;<br /></span> min-width<span style="color: #000000">:</span> 38<span style="color: #ff7800">px</span><span style="color: #000000">;<br />}<br />  <br /></span>.frame-outer span span span span <span style="color: #000000">{<br /></span> background<span style="color: #000000">:</span> none<span style="color: #000000">;<br />}</span></span>
</blockquote>

<p>Here’s a sample of the images that are used here:</p>

<div style="text-align: center;">
  <img src="http://atastypixel.com/blog/wp-content/uploads/2008/10/framing-images.jpg" width="400" height="400" alt="framing-images.jpg" title="framing-images.jpg" class="noframe" /><br />
</div>

<h3>Further possibilities</h3>

<p>Providing frames around image is all very well, but what if that’s not enough? Perhaps you have a particular style set up that requires, say, rounded corners, or Aqua-style bubbles, or sepia tones? Maybe something more complicated, as with Webdemar’s page: Rounded corners, a dark border with a light inner-border, a gradient background, then the image itself rotated a bit then cropped.</p>

<p>It just so happens, there’s a whole lot one can do with the PHP ‘GD’ image processing library, if you’re willing to get your hands dirty. Imagemagick’s ‘convert’ utility is fairly capable too. This is outside the scope of this article, but I may return to the topic another time.</p>

<p>So, one possibility is to add an additional function that is called, which extracts the URL of any image, opens and processes the image, saves it to a local cache, and replaces the URL with a URL to the newly created, cached image. This function could do all kinds of nifty operations on the image, with zero work required on the part of the user.</p>
 <img src="http://atastypixel.com/blog/wp-content/plugins/wordpress-feed-statistics/feed-statistics.php?view=1&post_id=921" width="1" height="1" style="display: none;" />]]></content:encoded>
			<wfw:commentRss>http://atastypixel.com/blog/advanced-web-templating-with-php-and-regular-expressions/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

