<?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>jonls devblog</title>
	<atom:link href="http://jonls.dk/feed/" rel="self" type="application/rss+xml" />
	<link>http://jonls.dk</link>
	<description>Jon Lund Steffensen</description>
	<lastBuildDate>Thu, 26 Aug 2010 23:38:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Redshift 1.5 released</title>
		<link>http://jonls.dk/2010/08/redshift-1-5-released/</link>
		<comments>http://jonls.dk/2010/08/redshift-1-5-released/#comments</comments>
		<pubDate>Wed, 18 Aug 2010 20:11:31 +0000</pubDate>
		<dc:creator>Jon Lund Steffensen</dc:creator>
				<category><![CDATA[Redshift]]></category>

		<guid isPermaLink="false">http://jonls.dk/?p=152</guid>
		<description><![CDATA[I had wanted to release redshift 1.5 last month but for various reasons I never got around to it. Today I received a very generous donation which reminded me that I really needed to get this release out.  The source is available &#8230; <a href="http://jonls.dk/2010/08/redshift-1-5-released/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I had wanted to release <a href="http://jonls.dk/redshift/">redshift</a> 1.5 last month but for various reasons I never got around to it. Today I received a very generous donation which reminded me that I really needed to get this release out.  The <a href="https://launchpad.net/redshift/+download">source</a> is available from the <a href="https://launchpad.net/redshift">launchpad project page</a> as usual. Packages for Ubuntu Lucid are <a href="https://launchpad.net/~jonls/+archive/redshift-ppa">available in the PPA</a>. The contributors for this release are: Francesco Marella, Gabriel de Perthuis, aleth and the translators.</p>
<ul>
<li>Application launcher and autostart feature contributed by Francesco Marella (fixes #590550, #612710).</li>
<li>Improve GNOME location provider (patch by Gabriel de Perthuis) (fixes #598277).</li>
<li>New ubuntu-mono-dark icons that fit the color guidelines better. Contributed by aleth (semi-fixes #596536).</li>
<li>Improve error message when first adjustment method fails (fixes #596537).</li>
<li>Translation updates: Basque (Ibai Oihanguren); Chinese (Jonathan Lumb);
<div id="_mcePaste">French (Hangman, XioNoX); German (Jan-Christoph Borchardt); Hebrew</div>
<div id="_mcePaste">(dotancohen); Spanish (Fernando Ossandon)</div>
</li>
</ul>
<p>Thank you contributors and donators! (btw, the donation will be spent on hosting for this website).</p>
]]></content:encoded>
			<wfw:commentRss>http://jonls.dk/2010/08/redshift-1-5-released/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Redshift 1.4 released</title>
		<link>http://jonls.dk/2010/06/redshift-1-4-released/</link>
		<comments>http://jonls.dk/2010/06/redshift-1-4-released/#comments</comments>
		<pubDate>Sun, 13 Jun 2010 22:50:24 +0000</pubDate>
		<dc:creator>Jon Lund Steffensen</dc:creator>
				<category><![CDATA[Redshift]]></category>
		<category><![CDATA[changelog]]></category>
		<category><![CDATA[gpl]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[ppa]]></category>
		<category><![CDATA[redshift]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[update]]></category>

		<guid isPermaLink="false">http://jonls.dk/?p=113</guid>
		<description><![CDATA[I&#8217;ve released redshift 1.4 today. The source is available from the launchpad project page as usual. Packages for Ubuntu Lucid are available in the PPA. There&#8217;s lots of exiting new stuff in this release thanks to several contributors: Francesco Marella, &#8230; <a href="http://jonls.dk/2010/06/redshift-1-4-released/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve released <a href="http://jonls.dk/redshift/">redshift</a> 1.4 today. The <a href="https://launchpad.net/redshift/+download">source</a> is available from the <a href="https://launchpad.net/redshift">launchpad project page</a> as usual. Packages for Ubuntu Lucid are <a href="https://launchpad.net/~jonls/+archive/redshift-ppa">available in the PPA</a>. There&#8217;s lots of exiting new stuff in this release thanks to several contributors: Francesco Marella, Dan Helfman and all the translators.</p>
<ul>
<li>Command line options for color adjustment methods changed. Procedure for setting specific screen (-s) or CRTC (-c) changed. See <code>redshift -h</code> for more information.</li>
<li>Automatically obtain the location from the GNOME Clock applet if possible.</li>
<li>Add application indicator GUI (by Francesco Marella) (fixes #588086).</li>
<li>Add reset option (-x) that removes any color adjustment applied. Based on patch by Dan Helfman (fixes #590777).</li>
<li><code>configure</code> options for GUI changed; see <code>configure --help</code> for more information.</li>
<li>New translations: German (Jan-Christoph Borchardt), Italian (Andrea Amoroso), Czech (clever_fox), Spanish (Fernando Ossandon), Finnish (Ilari Oras).</li>
</ul>
<p>UPDATE: 1.4.1 released. It includes mono icons for Ubuntu (by Joern Konopka); the status icon toggles to show whether Redshift is on or off; and it has updated translations: Spanish (Fernando Ossandon), Russian (Чистый).</p>
]]></content:encoded>
			<wfw:commentRss>http://jonls.dk/2010/06/redshift-1-4-released/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Settlers 1 remake</title>
		<link>http://jonls.dk/2010/06/settlers-1-remake/</link>
		<comments>http://jonls.dk/2010/06/settlers-1-remake/#comments</comments>
		<pubDate>Sat, 05 Jun 2010 16:42:54 +0000</pubDate>
		<dc:creator>Jon Lund Steffensen</dc:creator>
				<category><![CDATA[Free Software]]></category>
		<category><![CDATA[game]]></category>
		<category><![CDATA[remake]]></category>
		<category><![CDATA[reverse engineering]]></category>
		<category><![CDATA[serf city]]></category>
		<category><![CDATA[settlers]]></category>

		<guid isPermaLink="false">http://jonls.dk/?p=97</guid>
		<description><![CDATA[Here&#8217;s a quick preview of something I&#8217;ve been working on. As you can see, it uses the graphics from the original game. It is beginning to approach a state where it&#8217;s actually playable. Here&#8217;s some more screens for your viewing &#8230; <a href="http://jonls.dk/2010/06/settlers-1-remake/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a quick preview of something I&#8217;ve been working on.</p>
<p><a href="http://jonls.dk/wp-content/uploads/sett-pre_20100605-1.jpg"><img class="aligncenter size-full wp-image-102" title="Settlers 1 remake (preview 2010-06-05, 1)" src="http://jonls.dk/wp-content/uploads/sett-pre_20100605-1.jpg" alt="" width="400" height="170" /></a></p>
<p>As you can see, it uses the graphics from the original game. It is beginning to approach a state where it&#8217;s actually playable. Here&#8217;s some more screens for your viewing pleasure:</p>

<a href='http://jonls.dk/2010/06/settlers-1-remake/sett-pre_20100605-2/' title='Settlers 1 remake (preview 2010-06-05, 2)'><img width="150" height="150" src="http://jonls.dk/wp-content/uploads/sett-pre_20100605-2-150x150.jpg" class="attachment-thumbnail" alt="Settlers 1 remake (preview 2010-06-05, 2)" title="Settlers 1 remake (preview 2010-06-05, 2)" /></a>
<a href='http://jonls.dk/2010/06/settlers-1-remake/sett-pre_20100605-3/' title='Settlers 1 remake (preview 2010-06-05, 3)'><img width="150" height="150" src="http://jonls.dk/wp-content/uploads/sett-pre_20100605-3-150x150.jpg" class="attachment-thumbnail" alt="Settlers 1 remake (preview 2010-06-05, 3)" title="Settlers 1 remake (preview 2010-06-05, 3)" /></a>

]]></content:encoded>
			<wfw:commentRss>http://jonls.dk/2010/06/settlers-1-remake/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Showing huge images with Google Maps</title>
		<link>http://jonls.dk/2010/04/showing-huge-images-with-google-maps/</link>
		<comments>http://jonls.dk/2010/04/showing-huge-images-with-google-maps/#comments</comments>
		<pubDate>Tue, 27 Apr 2010 09:40:26 +0000</pubDate>
		<dc:creator>Jon Lund Steffensen</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[cairo]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[google maps]]></category>
		<category><![CDATA[image]]></category>
		<category><![CDATA[png]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://jonls.dk/?p=80</guid>
		<description><![CDATA[The Google Maps API can be used for other things than maps. The tiles were created with this python script: pngmaptiler-20100427. It will convert a PNG image to PNG tiles. The script depends on pycairo to do the cutting and &#8230; <a href="http://jonls.dk/2010/04/showing-huge-images-with-google-maps/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The Google Maps API can be used for <a title="Google Maps image example" href="http://jonls.dk/gmaps-image/">other things than maps</a>.</p>
<p style="text-align: center;"><a href="http://jonls.dk/gmaps-image/"><img class="aligncenter size-full wp-image-83" title="Google Maps image example" src="http://jonls.dk/wp-content/uploads/gmaps-image.png" alt="" width="408" height="258" /></a></p>
<p>The tiles were created with this python script: <a href="http://jonls.dk/wp-content/uploads/pngmaptiler-20100427.zip">pngmaptiler-20100427</a>. It will convert a PNG image to PNG tiles. The script depends on <a href="http://cairographics.org/pycairo/">pycairo</a> to do the cutting and scaling of the images. This example converts master.png to tiles of size 256&#215;256 with 1 being the minimum zoom level and 4 being the maximum zoom:</p>
<pre>$ pngmaptiler.py master.png 256 256 1 4
</pre>
]]></content:encoded>
			<wfw:commentRss>http://jonls.dk/2010/04/showing-huge-images-with-google-maps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple flex flip book for WordPress</title>
		<link>http://jonls.dk/2010/03/simple-flex-flip-book-for-wordpress/</link>
		<comments>http://jonls.dk/2010/03/simple-flex-flip-book-for-wordpress/#comments</comments>
		<pubDate>Mon, 08 Mar 2010 22:50:00 +0000</pubDate>
		<dc:creator>Jon Lund Steffensen</dc:creator>
				<category><![CDATA[Free Software]]></category>
		<category><![CDATA[flex]]></category>
		<category><![CDATA[flip book]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[pdf]]></category>
		<category><![CDATA[pdftopng]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[poppler]]></category>
		<category><![CDATA[shortcode]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://jonls.dk/?p=67</guid>
		<description><![CDATA[I wanted to show one of those flash flip books on a web site I maintain. There is a wealth of commercial solutions but they seem to be expensive and, at the same time, not very flexible. I needed flexibility because I wanted a particular effect where the flip book would be an overlay on the web page (think a cross between a flip book and lightbox) and I wanted to integrate it into a wordpress plugin. Fortunately I found an excellent open source flip book solution by Ruben Swieringa. <a href="http://jonls.dk/2010/03/simple-flex-flip-book-for-wordpress/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I wanted to show one of those flash flip books on a web site I maintain. There is a wealth of commercial solutions but they seem to be expensive and, at the same time, not very flexible. I needed flexibility because I wanted a particular effect where the flip book is displayed as an overlay on the web page (think a cross between a flip book and lightbox) and I wanted to integrate it into a wordpress plugin. Fortunately I found an <a title="Flex book component" href="http://www.rubenswieringa.com/blog/flex-book-component-beta">excellent open source flip book solution</a> by <a title="Ruben's blog" href="http://www.rubenswieringa.com/blog/">Ruben Swieringa</a>.</p>
<h3>Flex flip book</h3>
<p>The flip book is written in Adobe Flex and released under the <a href="http://creativecommons.org/licenses/by/3.0/deed.en">CC BY license</a>. It supports embedded images and flash movies, text labels, transparent pages and much more. I just needed a way to show a preview of some static PDF files so I adapted the code code for this purpose:</p>
<div id="attachment_78" class="wp-caption aligncenter" style="width: 310px"><img class="size-medium  wp-image-78 " title="Flip book overlay on a web page" src="http://jonls.dk/wp-content/uploads/flipbook-example-300x141.png" alt="" width="300" height="141" /><p class="wp-caption-text">Flip book overlay on a web page</p></div>
<ul>
<li>Load book pages from XML description file (one image per page; only image files supported).</li>
<li>Allow web page javascript to flip the pages.</li>
<li>Random bug fixes&#8230;</li>
</ul>
<p>The modified source code is available here: <a href="http://jonls.dk/wp-content/uploads/flipbook-20100308.zip">flipbook-20100308</a></p>
<h3>WordPress integration</h3>
<p>The wordpress plugin is still lacking a lot of features and probably has a load of bugs; but it is usable. The plugin uses the shortcode API to allow easy insertion of books into wordpress posts and pages. It is available here: <a href="http://jonls.dk/wp-content/uploads/book-20100308.zip">book-20100308</a>.</p>
<div class="book-box pdf-box"><div><h3><a class="book-link" href="http://jonls.dk/wp-content/plugins/book/book.swf?book=%2Fwp-content%2Fplugins%2Fbook%2Fdesc.php%3Fid%3D1">Example: Discover Ubuntu</a></h3><p><strong><a class="book-link" href="http://jonls.dk/wp-content/plugins/book/book.swf?book=%2Fwp-content%2Fplugins%2Fbook%2Fdesc.php%3Fid%3D1">Show book</a></strong> (<a class="pdf-link" href="http://spreadubuntu.neomenlo.org/en/material/brochure/discover-ubuntu">download PDF</a>)</p></div></div>
<p>When you install and activate the plugin, it will create the necessary database tables to handle the books you upload. You need to manually create the folder on your web server where the uploaded pages will reside. The folder must be in the <em>uploads</em> folder and must be called <em>book</em> (usually <em>wp-content/uploads/book/</em>). It should have the same permissions as the <em>uploads</em> folder. There is currently a bug that will mess things up if you haven&#8217;t set the uploads folder in settings &gt; miscellaneous, so you have to set that even if you use the default folder.</p>
<p>There is no admin interface for managing books but there is an HTTP API for creating books that is really easy to use. The database will have to be manipulated manually if you need to edit an existing book. A new book is created with the HTTP interface in <em>wp-content/plugins/book/manage.php</em>. You can for example use the utility <a href="http://curl.haxx.se/">cURL</a> that is available on many linux systems (line breaks inserted for readability):</p>
<pre>$ curl -F log=USERNAME -F pwd=PASSWORD -F name="Name of the book"
 -F "page[]=@page-1.jpg" -F "page[]=@page-2.jpg"
 example.com/wp-content/plugins/book/manage.php</pre>
<p>This will create a new book in the database with the specified name and pages. You can upload as many page images (as either png or jpg) as you want. The example above won&#8217;t really be a book because it will only have two pages. USERNAME and PASSWORD should be the ones that you use to log in to your wordpress site. When the pages have been uploaded and the book created, the script will return the text &#8220;Success&#8221; followed by the id of the book that you will have to enter in the shortcode.</p>
<p>The shortcode is called <em>book</em> and has the following required parameters:</p>
<ul>
<li><em>book</em>: the id of the book as returned by the manage.php script (it can also be found in the database manually).</li>
<li><em>pdf</em>: link to PDF version of the book.</li>
<li>The content text will be the name of the book.</li>
</ul>
<p>Next you should customize the CSS for the book display. Here&#8217;s <a href="http://tk-ungdomsgaard.dk/sport-friluftsliv/">an example of how it might look</a> (text is in danish).</p>
<h3>Creating image files from PDF documents</h3>
<p>You need your book pages as image files for the above to work. Often times I find myself with PDF documents that I want to convert to images. I decided to use the <a href="http://poppler.freedesktop.org/">poppler library</a> for this conversion as it has the best rendering of fonts of the solutions I tested. I created a python script that does the conversion automatically: <a href="http://jonls.dk/wp-content/uploads/pdftopng-20100308.zip">pdftopng-20100308</a>. It is a command line utility that depends on the python-poppler bindings. Example:</p>
<pre>$ pdftopng.py document.pdf output 420 595</pre>
<p>This will create <em>output-1.png</em>, <em>output-2.png</em> etc. for each page in the PDF document. The images will be 420&#215;595 in the example above. You can easily convert these to JPEG with imagemagick in linux if you want to save some bandwidth:</p>
<pre>$ for f in output-*.png; do convert -quality 90 "$f" "${f%%.png}.jpg"; done</pre>
<p>When you have a satisfactory JPEG file for each page you can upload them as a book with the cURL method above.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonls.dk/2010/03/simple-flex-flip-book-for-wordpress/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>f.lux for Linux</title>
		<link>http://jonls.dk/2009/12/flux-for-linux/</link>
		<comments>http://jonls.dk/2009/12/flux-for-linux/#comments</comments>
		<pubDate>Tue, 22 Dec 2009 18:04:27 +0000</pubDate>
		<dc:creator>Jon Lund Steffensen</dc:creator>
				<category><![CDATA[Redshift]]></category>
		<category><![CDATA[f.lux]]></category>
		<category><![CDATA[gpl]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[redshift]]></category>

		<guid isPermaLink="false">https://sourceforge.net/userapps/wordpress/jonls/?p=31</guid>
		<description><![CDATA[I have been using f.lux for some time now and it is a really nice tool. It adjusts the color temperature of the screen at night to a more reddish tone which greatly reduces the strain on the eyes. It takes a while to get used to the red tint but now there is no going back. There is a version of this tool for linux (xflux) but my experience with it was pure disappointment. I ultimately decided to write my own tool. <a href="http://jonls.dk/2009/12/flux-for-linux/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I have been using <a title="f.lux" href="http://www.stereopsis.com/flux/">f.lux</a> for some time now and it is a really nice tool. It adjusts the color temperature of the screen at night to a more reddish tone which greatly reduces the strain on the eyes. It takes a while to get used to the red tint but now there is no going back.</p>
<p>When I learned that there is a version for linux (xflux) I had to get that for my Ubuntu laptop. I was quite disappointed, however, when I discovered that not only does it not feature a sleek GUI like the windows version, it also simply does not work at all on my laptop. f.lux throws this message at me: “Sorry, we only support 24/32-bit displays right now” which must be a bug because I am running in 24-bit mode with the open source radeon driver.</p>
<p><a href="http://jonls.dk/wp-content/uploads/redshift.png"><img class="aligncenter size-medium wp-image-43" title="Redshift running in one-shot mode" src="http://jonls.dk/wp-content/uploads/redshift-300x176.png" alt="" width="300" height="176" /></a></p>
<p>Other features that are present in the windows version seem to be missing as well in xflux, like setting the daytime temperature. Ultimately I decided to code my own tool to adjust the color temperature. The result is an open source program called <a title="Redshift" href="http://jonls.dk/redshift/">Redshift</a>.</p>
<p>Please post comments <a href="http://jonls.dk/redshift/">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonls.dk/2009/12/flux-for-linux/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Calculating AccurateRip Checksums</title>
		<link>http://jonls.dk/2009/10/calculating-accuraterip-checksums/</link>
		<comments>http://jonls.dk/2009/10/calculating-accuraterip-checksums/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 17:09:22 +0000</pubDate>
		<dc:creator>Jon Lund Steffensen</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[accuraterip]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[checksum]]></category>

		<guid isPermaLink="false">https://sourceforge.net/userapps/wordpress/jonls/?p=24</guid>
		<description><![CDATA[There doesn&#8217;t seem to be a lot of documentation on the AccurateRip checksum algorithm. Actually there seems to be nothing at all. I&#8217;ve wanted to use the AccurateRip checksum to do a batch scan of a bunch of audio CD &#8230; <a href="http://jonls.dk/2009/10/calculating-accuraterip-checksums/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>There doesn&#8217;t seem to be a lot of documentation on the <a title="AccurateRip" href="http://accuraterip.com/">AccurateRip</a> checksum algorithm. Actually there seems to be nothing at all. I&#8217;ve wanted to use the AccurateRip checksum to do a batch scan of a bunch of audio CD rips and that has made me curious as to how the AccurateRip system really works. The result of my investigation into AccurateRip is an efficient version of the (offset) checksum algorithm.</p>
<h3>The Basics</h3>
<p>The AccurateRip algorithm in itself is very simple. Since it operates on audio data extracted from CDs the basic unit is one audio CD <a href="http://en.wikipedia.org/wiki/Sampling_%28signal_processing%29">sample</a>, i.e. one 16-bit, little-endian, signed integer. As it is stereo, samples always appear in pairs, one sample for the left channel one for the right. The algorithm loops through these sample pairs while it keeps track of the 1-based index of the current pair, i.e. 1 is the index of the first pair in the data stream, 2 is the index of the next pair and so forth. For each pair the algorithm produces a 32-bit value by adding the first sample of the pair, to the second sample shifted left 16 places. This value is then multiplied by the index and added to the accumulated checksum. At the end of the data stream the result is simply the accumulated value:</p>
<ol>
<li>Set the checksum value to zero, <code>c = 0</code></li>
<li>Set the index value, <code>i</code>, to the start of the track</li>
<li>Loop while there is more samples in the track
<ol>
<li>Read two samples (left and right), <code>x_l</code>, <code>x_r</code></li>
<li>Combine the samples, <code>v = (x_r &lt;&lt; 16) | x_l</code></li>
<li>Update the checksum value, <code>c += i⋅v</code></li>
<li>Increment <code>i</code></li>
</ol>
</li>
<li>Return the value in <code>c</code></li>
</ol>
<p>This is not exactly a great checksum algorithm. <a href="http://www.hydrogenaudio.org/forums/index.php?showtopic=61468&amp;view=findpost&amp;p=548711">It has been argued</a>, that only about 97% of the bits in the data stream participate in the final checksum.  This disadvantage is of course offset by the large number of entries in the AccurateRip database. Fixing the checksum would require creating a new database from scratch.</p>
<h3>AccurateRip Quirks</h3>
<p>The checksum is not calculated the same way for all tracks on a disc; the first and last tracks are calculated differently. On the audio CD, samples are grouped into larger blocks called frames (<a href="http://en.wikipedia.org/wiki/CD-ROM#CD_sector_contents">sometimes known as sectors</a>). Each frame contains 588 sample pairs (which is exactly 1/75  second worth of audio). In the first track, <em>almost</em> five frames are skipped at the start of the track. It is not <em>exactly</em> five frames because the last sample pair of frame five is actually used. Also note that the index value is incremented even for the samples that are not used in calculating the checksum (only step three in the loop of the algorithm is skipped). In the last track, <em>exactly</em> five frames are skipped at the end.</p>
<p>The effect of these cuts is that the checksum is calculated for a window on the data stream that is slightly shorter than the whole data stream. By sliding this window back and forth it is possible to obtain different checksums for different window offsets. This is important because several pressings of the same audio CDs often exist, the only difference between them being that the audio data on each pressing is slightly offset compared to the others. It would therefore be advantageous to use this sliding window to be able to determine whether a disc is in the AccurateRip database even if the disc registered in the database is of a different pressing.</p>
<p>Obviously, we could use the above algorithm, modified slightly, to calculate a checksum for each offset. That would require going through the loop 5880 to get all the possible checksums. It can be done much more efficiently!</p>
<h3>The Math</h3>
<p>Consider a sequence of values <em>D = v<sub>1</sub>, v<sub>2</sub>, &#8230;, v<sub>n</sub></em> calculated from sample pairs in a data stream as in step two in the loop of the above algorithm. Now, suppose that this is the data from the whole audio CD, and that each track is a subsequence of <em>D</em>. Let&#8217;s further assume that the sequence can be read only sequentially as, in practice, we would be working with some kind of data stream; either data from a CD or from audio files. To calculate the checksum of a track starting at index <em>i</em> of length <em>k</em> one would calculate the sum <em>1⋅v<sub>i</sub> + 2⋅v<sub>i+1</sub> + &#8230; + k⋅v<sub>i+k-1</sub></em>. This is the checksum at index <em>i</em> so lets call it <em>c<sub>i</sub></em>.</p>
<p>The goal here is the find checksums that are offset so lets look at that same track but this time offset by one. The checksum of this track is the sum <em>1⋅v<sub>i+1</sub> + 2⋅v<sub>i+2</sub> + &#8230; + k⋅v<sub>i+k</sub></em> which we will call <em>c<sub>i+1</sub></em>. To see if there is an easy way of obtaining the offset checksum from the base checksum let&#8217;s subtract the last one from the first: <em>c<sub>i+1</sub> &#8211; c<sub>i</sub> = (1⋅v<sub>i+1</sub> + 2⋅v<sub>i+2</sub> + &#8230; + k⋅v<sub>i+k</sub>) &#8211; (1⋅v<sub>i</sub> + 2⋅v<sub>i+1</sub> + &#8230; + k⋅v<sub>i+k-1</sub>) = k⋅v<sub>i+k</sub> &#8211; (v<sub>i</sub> + v<sub>i+1</sub> + &#8230; + v<sub>i+k-1</sub>)</em>.</p>
<p>It can now be seen that <em>c<sub>i+1</sub> = c<sub>i</sub> + k⋅v<sub>i+k</sub> &#8211; (v<sub>i</sub> + v<sub>i+1</sub> + &#8230; + v<sub>i+k-1</sub>)</em>, i.e. the checksum at offset one can be derived from the base checksum by adding a term and subtracting a different term. Now, let&#8217;s consider which parts of this formula we already know. Let&#8217;s also assume that we have just calculated the base checksum of the track, i.e. the next value in the sequence will be <em>v<sub>i+k</sub></em> since we have just read <em>k</em> values starting at index <em>i</em>. But <em>v<sub>i+k</sub></em> is exactly the value we need as part of the term that we&#8217;re going to add to the base checksum. We just need to read it and multiply it with <em>k</em> which is also a known value (the track length).</p>
<p>The term that we&#8217;re going to subtract is obviously just the sum of the values of the track. It would be trivial to compute this as we&#8217;re going through the values to compute the checksum anyway, so with a small modification of the algorithm this is no problem as well. It should be clear now that we don&#8217;t need to go through <em>k</em> values to obtain the checksum offset by one, we can just derive it from the base checksum by doing one simple addition and one subtraction.  Let&#8217;s see if we can extend this to obtain more than just the first derived checksum. Let&#8217;s see if we can obtain <em>c<sub>i+2</sub></em>.</p>
<p>Reusing the formula obtained earlier, we see that <em>c<sub>i+2</sub> = c<sub>i+1</sub> + k⋅v<sub>(i+1)+k</sub> &#8211; (v<sub>i+1</sub> + v<sub>i+2</sub> + &#8230; + v<sub>i+k</sub>)</em>. The right hand side has three terms. The first term is the first derived checksum which we have just calculated. The next term depends on the value <em>v<sub>(i+1)+k</sub></em> but this is the next value in the data stream since we&#8217;ve just read <em>v<sub>i+k</sub></em>. The last term is the tricky part. We need the sum, not of the base track this time, but of the track offset by one. We don&#8217;t have this since we didn&#8217;t loop through the track offset by one to calculate the checksum, we just derived it from the base checksum. We can, however, adjust the sum when we calculate a derived checksum. When we calculate the first derived checksum we need to adjust the sum so it is no longer  the sum of the base track but is the sum of the track offset by one. We can do this by subtracting the first value in the track, then adding the last value in the track offset by one. This will in effect move the track window, to which the sum pertains, one step, and with just two operations we can get the correct sum. The only problem is that we need the first value of the track to do this. Either we need to seek back through the stream and retrieve this value again, or we could have saved it somewhere when we were calculating the checksum at the first index in the track.</p>
<p>The latter solution may seem like a waste of memory space, but if we use a clever trick, it actually isn&#8217;t. We will need to allocate some memory to save all the derived checksums anyway, so why not use this space temporarily to save a value from the beginning of the track? Each calculation of a derived checksum will need just one value to adjust the sum, so clearly, there&#8217;s exactly enough space. Furthermore, each value that is saved from the start of the track will need to be used once, after which it can be immediately overwritten by the derived checksum.</p>
<p>One last thing we need to consider is that the improved method sketched above can&#8217;t work directly on the first track in practice, because the first five frames (almost) are skipped but the index is still incremented. This makes it impossible to use the above formula to derive checksums from the base checksum of the first track because it was assumed that the track index would start at one. Now assume the more general case of a track whose index counter starts at, not one, but <em>p</em>. If we can derive a formula similar to the above from this more general case we can use it  to handle all tracks. The checksum of a track starting at index <em>i</em> but whose index counter starts at <em>p+1</em>, <em>c<sub>i,p</sub> = (p+1)⋅v<sub>i</sub> + (p+2)⋅v<sub>i+1</sub> + &#8230; + (p+k)⋅v<sub>k+i-1</sub></em>. Now let&#8217;s subtract <em>c<sub>i,p</sub></em> from <em>c<sub>i+1,p</sub></em> like above. Continuing this gets us <em>c<sub>i+1,p</sub> = c<sub>i,p</sub> + (p+k)⋅v<sub>k+i</sub> &#8211; (v<sub>i</sub> + v<sub>i+1</sub> + &#8230; + v<sub>k+i-1</sub>) &#8211; p⋅v<sub>i</sub></em>. The first three terms on the right hand side are clearly equivalent to the formula above. The last term depends on the first value of the track, which we, conveniently, have already made available because we needed it to adjust the sum. Also notice that if <em>p = 0</em> the last term disappears. This is what makes the formula work exactly as the simpler one derived above in the case where the index counter of the track starts at one.</p>
<h3>Improved algorithm</h3>
<p>First of all, it must be noted that the above math will be used to construct an algorithm that has to work on real computers, specifically computers that work with 32-bit fixed-width integers. Fortunately, the above formula can be used directly because it only make use of addition and multiplication operators which are compatible with <a href="http://en.wikipedia.org/wiki/Modular_arithmetic">modular arithmetic</a>:</p>
<ol>
<li>Allocate memory space for 5880 values</li>
<li>Set first memory field to zero; <code>m[1] = 0</code></li>
<li>Set sum to zero; <code>s = 0</code></li>
<li>Set the index value, <code>i</code>, to the start of the track minus (5880/2)+1</li>
<li>Loop <code>k</code> times, where <code>k</code> is the length of the track
<ol>
<li>Read two samples (left and right); <code>x_l</code>, <code>x_r</code></li>
<li>Combine the samples; <code>v = (x_r &lt;&lt; 16) | x_l</code></li>
<li>If <code>i</code> is less than 5880, save <code>v</code> in memory field <code>i+1</code></li>
<li>Update the sum; <code>s += v</code></li>
<li>Update the checksum value in the first memory field; <code>m[1] += i⋅v</code></li>
<li>Increment <code>i</code></li>
</ol>
</li>
<li>Loop 5880 minus one times, let <code>i</code> denote the number of the current loop
<ol>
<li>Read two samples (left and right); <code>x_l</code>, <code>x_r</code></li>
<li>Combine the samples; <code>v = (x_r &lt;&lt; 16) | x_l</code></li>
<li>Put aside the value in memory field <code>i+1</code>; <code>f = m[i+1]</code></li>
<li>Calculate the derived checksum by the above formula and store it in memory field <code>i-1</code>; <code>m[i+1] = m[i] + (p+k)⋅v - s - p⋅f</code>, where <code>p</code> is the offset added to the index counter, and <code>k</code> is the length of the track</li>
<li>Adjust the sum; <code>s = s + v - f</code></li>
</ol>
</li>
<li>Return the values in memory space; the checksum at offset <code>o</code> will be in memory field <code>(5880/2)+o</code></li>
</ol>
<p>Notice how there&#8217;s only one loop that depends on the track length, followed by a loop of constant length that in practice will be very short compared to the first loop. There are no inner loops. Also notice, that seeking in the data stream is completely unecessary; the samples are always read sequentially.</p>
<p>A common use case of this algorithm would probably be to calculate checksums for entire discs. Interleaving the two loops for adjacent tracks can be done by calculating derived checksums of one track  while calculating the base checksum for the next track. This way, the algorithm can calculate all checksums for all tracks with only one sequential read through the entire data stream.</p>
]]></content:encoded>
			<wfw:commentRss>http://jonls.dk/2009/10/calculating-accuraterip-checksums/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
