<?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>tdistler.com</title>
	<atom:link href="http://tdistler.com/feed" rel="self" type="application/rss+xml" />
	<link>http://tdistler.com</link>
	<description>&#34;To err is human, but to really foul things up you need a computer.”</description>
	<lastBuildDate>Wed, 13 Mar 2013 20:32:56 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.1</generator>
		<item>
		<title>Encoding Using FFMpeg and x264</title>
		<link>http://tdistler.com/2013/03/13/encoding-using-ffmpeg-and-x264</link>
		<comments>http://tdistler.com/2013/03/13/encoding-using-ffmpeg-and-x264#comments</comments>
		<pubDate>Wed, 13 Mar 2013 20:32:56 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[Tech and Security]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=1227</guid>
		<description><![CDATA[Note-to-self: ffmpeg -i input.mp4 -x264opts keyint=15:min-keyint=15 -c:v libx264 -preset slow -crf 22 output.mp4 Links: FFMpeg x264 encoding guide x264 encoder settings]]></description>
			<content:encoded><![CDATA[<p>Note-to-self:</p>
<p><code>ffmpeg -i input.mp4 -x264opts keyint=15:min-keyint=15 -c:v libx264 -preset slow -crf 22 output.mp4</code></p>
<p>Links:</p>
<ul>
<li><a title="ffmpeg x264 encoding guide" href="http://ffmpeg.org/trac/ffmpeg/wiki/x264EncodingGuide" target="_blank">FFMpeg x264 encoding guide</a></li>
<li><a title="x264 encoder settings" href="http://www.afterdawn.com/guides/archive/x264_options_explained.cfm" target="_blank">x264 encoder settings</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2013/03/13/encoding-using-ffmpeg-and-x264/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Homebrew: Thornton Colorado Water Profile</title>
		<link>http://tdistler.com/2012/11/07/homebrew-thornton-colorado-water-profile</link>
		<comments>http://tdistler.com/2012/11/07/homebrew-thornton-colorado-water-profile#comments</comments>
		<pubDate>Wed, 07 Nov 2012 15:12:00 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[homebrew]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=1206</guid>
		<description><![CDATA[Water profile for home brewers for the City of Thornton, Colorado]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2012/11/beer-icon2.gif"><img class="alignright size-full wp-image-1212" title="beer-icon" src="http://tdistler.com/wp-content/uploads/2012/11/beer-icon2.gif" alt="Homebrew" width="100" height="93" /></a>The water report for Thornton, CO doesn&#8217;t contain all the information you need to properly adjust your water for home brewing. Fortunately, the water analysts for the city are very helpful. Here is an excerpt from the response I got when I asked for more details:</p>
<blockquote><p>The City of Thornton does in fact have two separate water sources and we don’t always use both so the character of your water can actually vary a bit throughout the year. Thornton owns a significant share of the water in Standley Lake in Arvada. This water comes from Clear Creek. The Coors Beer commercials are accurate. This water is very clean and low in pollutants as I will summarize below.</p>
<p>Our second water source is the South Platte River. We divert water from the South Platte and store it in our gravel lakes until it is needed. While still better than many water sources, The South Platte is certainly exposed to more contaminants then our Standley Lake water.</p>
<p>In most years, water is drawn from Standley Lake nearly all year &#8211; only ceasing for maintenance to the treatment plant. Meanwhile, water from the South Platte is used to supplement our supply when demand spikes in the summertime.</p>
<p>Typically, we start using South Platte water in March and we might stop using it around October or November. This year we turned off our South Platte supply in late September, so the City is currently receiving only Standley Lake water. It is difficult to guess what ratio of our two water supplies you might receive at your residence when we do utilize both sources.</p>
<p>Now that you know the reasons behind the variability in Thornton’s water quality, I’ll throw several numbers at you which should represent your water quality at different times of year. These values were measured at a residence near your location that we sample year round. This residence is located near [redacted]. All values are in ppm:</p>
<table border=1>
<tr>
<th></th>
<th>Standley Lake (Winter) &#8211; </th>
<th>Both (Summer) &#8211; </th>
<th>South Platte Only</th>
</tr>
<tr>
<td>Calcium</td>
<td>56.3</td>
<td>85*</td>
<td>97.1</td>
</tr>
<tr>
<td>Magnesium</td>
<td>8.4</td>
<td>14*</td>
<td>18.1</td>
</tr>
<tr>
<td>Total Hardness</td>
<td>152</td>
<td>276</td>
<td>280</td>
</tr>
<tr>
<td>Calcium Hardness</td>
<td>100</td>
<td>200</td>
<td>236</td>
</tr>
<tr>
<td>Sulfate</td>
<td>51</td>
<td>92*</td>
<td>137</td>
</tr>
<tr>
<td>Chloride</td>
<td>36</td>
<td>76*</td>
<td>74</td>
</tr>
<tr>
<td>Bicarbonate</td>
<td>52.1</td>
<td>139.2</td>
<td>173.4</td>
</tr>
</table>
<p>* = estimates based on the average of both sources during this time frame</p>
<p>Hopefully that’s enough detail to answer your questions. If you have any more questions or need more specific data certainly let me know and I’d be happy to help.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2012/11/07/homebrew-thornton-colorado-water-profile/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>lighttpd: Configuring Python Support</title>
		<link>http://tdistler.com/2012/05/24/lighttpd_config_python</link>
		<comments>http://tdistler.com/2012/05/24/lighttpd_config_python#comments</comments>
		<pubDate>Thu, 24 May 2012 15:00:25 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=1195</guid>
		<description><![CDATA[I wanted to play with Django recently, so I needed to enable python support in lighttpd. I found a few links about using the default lighttpd.conf file, but I have a custom (minimalist) lighttpd.conf file that I don&#8217;t want to pollute with unnecessary options. It turns out that enabling python support through mod_cgi is quite [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2012/05/python-logo.png"><img class="alignright size-thumbnail wp-image-1200" title="Python" src="http://tdistler.com/wp-content/uploads/2012/05/python-logo-150x150.png" alt="" width="150" height="150" /></a>I wanted to play with <a title="Django" href="https://www.djangoproject.com/" target="_blank">Django</a> recently, so I needed to enable python support in <a title="lighttpd" href="http://www.lighttpd.net/" target="_blank">lighttpd</a>. I found a few links about using the default lighttpd.conf file, but I have a custom (minimalist) lighttpd.conf file that I don&#8217;t want to pollute with unnecessary options. It turns out that enabling python support through mod_cgi is quite trivial:</p>
<p style="padding-left: 30px;">1. Open lighttpd.conf</p>
<p style="padding-left: 30px;">2. Add <code>".py"</code> to the <code>static-file.exclude-extensions</code> variable to prevent people from viewing the raw python code:</p>
<p style="padding-left: 60px;"><code>static-file.exclude-extensions = ( ".py" )</code></p>
<p style="padding-left: 30px;">3. Add <code>"mod_cgi"</code> to the <code>server.modules</code> variable:</p>
<p style="padding-left: 60px;"><code>server.modules = ( "mod_cgi" )</code></p>
<p style="padding-left: 30px;">4. Add the association between *.py files and the python interpreter to the <code>cgi.assign</code> variable:</p>
<p style="padding-left: 60px;"><code>cgi.assign = ( ".py" =&gt; "/usr/bin/python" )</code></p>
<p style="padding-left: 30px;">5. Make sure you have a &#8220;breakage&#8221; log defined&#8230; this helps debugging because python errors will get written here:</p>
<p style="padding-left: 60px;"><code>server.breakagelog = "/var/log/lighttpd/breakage.log"</code></p>
<p style="padding-left: 30px;">6. Restart lighttpd</p>
<p>For more mod_cgi configuration options, <a title="mod cgi documentation" href="http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:ModCGI" target="_blank">read this</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2012/05/24/lighttpd_config_python/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Linux: How to Detect Dropped Network Packets</title>
		<link>http://tdistler.com/2012/05/15/linux-detecting-dropped-network-packets</link>
		<comments>http://tdistler.com/2012/05/15/linux-detecting-dropped-network-packets#comments</comments>
		<pubDate>Wed, 16 May 2012 03:00:31 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=1174</guid>
		<description><![CDATA[There are a few ways on linux to see if the network stack is dropping packets, or just having problems in general: 1. ifconfig ... RX packets:522 errors:0 dropped:0 overruns:0 frame:0 TX packets:406 errors:0 dropped:0 overruns:0 frame:0 ... 2. cat /proc/net/dev Inter-&#124; Receive ... face &#124; bytes packets errs drop fifo frame ... eth0: 87689 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2012/05/netcable.jpg"><img class="alignright size-full wp-image-1188" title="netcable" src="http://tdistler.com/wp-content/uploads/2012/05/netcable.jpg" alt="" width="134" height="76" /></a>There are a few ways on linux to see if the network stack is dropping packets, or just having problems in general:</p>
<p>1. <strong><code>ifconfig</code></strong></p>
<blockquote>
<pre><code> ... 
 RX packets:522 errors:0 dropped:0 overruns:0 frame:0
 TX packets:406 errors:0 dropped:0 overruns:0 frame:0
 ...</code></pre>
</blockquote>
<p>2. <strong><code>cat /proc/net/dev</code></strong></p>
<blockquote>
<pre><code>Inter-| Receive ... 
 face | bytes packets errs drop fifo frame ... 
 eth0:  87689 785 0 0 0 0 ...
 ...</code></pre>
</blockquote>
<p>3. <strong><code>cat /proc/net/udp</code></strong></p>
<blockquote>
<pre><code> so local_address rem_address ... drops
 277: 00000000:0044 00000000:0000 ... 0 
 ...</code></pre>
</blockquote>
<p>4. <strong><code>cat /proc/net/snmp</code></strong></p>
<blockquote>
<pre><code>...
Tcp: ...
Udp: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors
Udp: 453 0 0 452 0 0
...</code></pre>
</blockquote>
<p>You can also see this on a per-process basis using <code>cat /proc/&lt;pid&gt;/net/{udp,dev,snmp}</code></p>
<p>Check out <a title="iftop" href="http://www.ex-parrot.com/pdw/iftop/" target="_blank">iftop</a> also.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2012/05/15/linux-detecting-dropped-network-packets/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ebonicode++: Hackin C++ Gangsta Style</title>
		<link>http://tdistler.com/2011/12/03/eubonicode-hackin-c-gangsta-style</link>
		<comments>http://tdistler.com/2011/12/03/eubonicode-hackin-c-gangsta-style#comments</comments>
		<pubDate>Sat, 03 Dec 2011 16:00:02 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[funny]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=1077</guid>
		<description><![CDATA["Foshizzle" is a modified version of the Clang compiler which supports Eubonicode++ (an alternate C++ syntax). Foshizzle supports all the existing features of Clang, but with extensions to more fully express your gansta style. All the regular C++ syntax still works, but you can now substitute Eubonicode++ keywords and operators.]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2011/12/Bjarne_foshizzle.jpg"><img class="alignright size-thumbnail wp-image-1078" title="A small part of me died doing this to Bjarne, but I couldn't resist." src="http://tdistler.com/wp-content/uploads/2011/12/Bjarne_foshizzle-150x150.jpg" alt="A little part of me died doing this to Bjarne, but I couldn't resist." width="150" height="150" /></a></p>
<p>&#8220;Foshizzle&#8221; is a modified version of the <a title="Clang Compiler" href="http://clang.llvm.org/" target="_blank">Clang</a> compiler which supports Ebonicode++ (an alternate C++ syntax). Foshizzle supports all the existing features of Clang, but with extensions to more fully express your gansta style. All the regular C++ syntax still works, but you can now substitute Ebonicode++ keywords and operators (see below).</p>
<p>Here&#8217;s a sample method that calculates factorials (Note: the semicolons can be replaced with a certain expletive):</p>
<pre>int factorialz(int n)
{
    int rezult be 1;
    slongas (n bepimpin 0)
    {
        rezult be rezult dimes n;
        dissin n;
    }
    putou rezult;
}</pre>
<p>&nbsp;</p>
<p>I can&#8217;t take all the credit. I was inspired by the Iowa State students that first created Ebonicode (webpage no longer available).</p>
<p>Here are my Clang modifications:<a title="Eubonicode++ Clang modifications" href="http://tdistler.com/media/code/eubonicode/ebpp-clang30rc4.patch" target="_blank"> ebpp-clang30rc4.patch</a></p>
<p>Build instructions are near the end of this post.<span id="more-1077"></span></p>
<h2>How It Happened</h2>
<p>I periodically venture off into the h4x0r wilderness and pour myself into some random project. It always starts out innocently enough, but the project soon takes on a life of it’s own. This time was no different&#8230; except it happened over Thanksgiving (much to my wife’s chagrin).</p>
<p>Being the charismatic socialite that I am (sarcasm), I was digging through the C++11 spec on Thanksgiving. What struck me was how much of my language design course I had forgotten, and it really bugged me. It&#8217;s one of those required courses in the CompSci graduate program that I loathed having to take, but turned out to be invaluable (don’t get me started on the database and UI design courses&#8230; blah).</p>
<p>Long story less long, I started refreshing on compilers (<a title="Rich Programmer Food" href="http://steve-yegge.blogspot.com/2007/06/rich-programmer-food.html" target="_blank">read this</a> for inspiration). I’d heard about Clang and <a title="LLVM" href="http://llvm.org/" target="_blank">LLVM</a> awhile ago, and I remembered their focus on modularity, maintainability, and all sorts of other *ability’s. I figured it&#8217;d be a good place to start, so I download the source code and dug through it (watch <a title="Clang Video" href="http://clang.llvm.org/clang_video-05-25-2007.html" target="_blank">this video</a> for background on Clang).</p>
<p>Stepping through Clang in a debugger sounded like a great way to start, but I quickly had mental stack overflow through the recursive parsing code. Okay, time for plan B. Common wisdom says that a good way to learn a piece of code is to try and fix a bug. So I went to the Clang bug list looking for a starter task, but all the “interesting” tasks were way too large in scope for a Clang newb like me.</p>
<p>Time to invent plan C: make a small tweak to the language and see if I can get it working. I remembered a few years ago that some students from Iowa State built an Ebonicode compiler for a language class they had. It got quite a few laughs around the office and was always wishing for a working compiler. So I decided take their idea and replace ‘<code>while</code>’ with ‘<code>slongas</code>’&#8230; and an hour later I had it working (which is testament to the readability of the Clang code&#8230; it’s very well commented).</p>
<p>Not satisfied to stop there, I moved on to other keywords&#8230; simple, once you get comfortable with how the code’s laid out. &#8220;What about operators and punctuators?&#8221;, I wondered. After a few failed attempts, it dawned on me that C++ has aliases for operators (‘<code>and_eq</code>’ can be used in place of ‘<code>&amp;=</code>’, etc). Instead of heavily modifying the parser/lexer, I started looking for how Clang handled these aliases&#8230; maybe I could just add some more. Turns out, it fairly simple to add new aliases, so ‘<code>==</code>’ got overloaded with ‘<code>sameas</code>’, ‘<code>!=</code>’ got overloaded with ‘<code>aint</code>’, etc&#8230; and it worked! Sweet!</p>
<p>After all that, I dug a little into the preprocessor and figured out how to support ‘<code>#mahomie</code>’ in place of ‘<code>#include</code>’. Simple enough. I dug a little into the build stuff and changed the name from ‘clang’ to ‘foshizzle’&#8230; cool. I little bit of frustration later, and I had it recognizing ‘*.opp’ and ‘*.ho’ as source and header files, respectively.</p>
<p>Three days after I started, I had a fully functional Ebonicode++ compiler and a lot deeper understanding of how a production C++ compiler works. I can’t stress enough that this project would never have happened if the Clang code wasn’t written so well. Kudos to the Clang team.</p>
<p>I really enjoyed this project, and I hope you get half the fun out of it I did. Next time you have a coding task, consider adding a litta gansta sizzle <img src='http://tdistler.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<h2>C++ To Ebonicode++ Mapping</h2>
<p>&nbsp;</p>
<table style="text-align: center;" width="400" border="0">
<tbody>
<tr>
<th>C++</th>
<th>Ebonicode++</th>
<th>|</th>
<th>C++</th>
<th>Ebonicode++</th>
</tr>
<tr>
<td><code>#include</code></td>
<td><code>#mahomie</code></td>
<td>|</td>
<td><code>switch</code></td>
<td><code>whatchugondo</code></td>
</tr>
<tr>
<td><code>break</code></td>
<td><code>bustanut</code></td>
<td>|</td>
<td><code>this</code></td>
<td><code>dis</code></td>
</tr>
<tr>
<td><code>case</code></td>
<td><code>ifa</code></td>
<td>|</td>
<td><code>throw</code></td>
<td><code>throz</code></td>
</tr>
<tr>
<td><code>catch</code></td>
<td><code>wrekdit</code></td>
<td>|</td>
<td><code>true</code></td>
<td><code>tru</code></td>
</tr>
<tr>
<td><code>char</code></td>
<td><code>alphabizzle</code></td>
<td>|</td>
<td><code>try</code></td>
<td><code>checkit</code></td>
</tr>
<tr>
<td><code>class</code></td>
<td><code>claz</code></td>
<td>|</td>
<td><code>typedef</code></td>
<td><code>reprezentin</code></td>
</tr>
<tr>
<td><code>const</code></td>
<td><code>foodonchange</code></td>
<td>|</td>
<td><code>using</code></td>
<td><code>uzin</code></td>
</tr>
<tr>
<td><code>continue</code></td>
<td><code>mo</code></td>
<td>|</td>
<td><code>virtual</code></td>
<td><code>frontin</code></td>
</tr>
<tr>
<td><code>delete</code></td>
<td><code>cap</code></td>
<td>|</td>
<td><code>void</code></td>
<td><code>shiznit</code></td>
</tr>
<tr>
<td><code>else</code></td>
<td><code>elz</code></td>
<td>|</td>
<td><code>volatile</code></td>
<td><code>trippin</code></td>
</tr>
<tr>
<td><code>export</code></td>
<td><code>bounce</code></td>
<td>|</td>
<td><code>while</code></td>
<td><code>slongas</code></td>
</tr>
<tr>
<td><code>extern</code></td>
<td><code>othahood</code></td>
<td>|</td>
<td><code>;</code></td>
<td><code>bitch</code> or <code>biatch</code></td>
</tr>
<tr>
<td><code>false</code></td>
<td><code>falz</code></td>
<td>|</td>
<td><code>=</code></td>
<td><code>be</code></td>
</tr>
<tr>
<td><code>float</code></td>
<td><code>flo</code></td>
<td>|</td>
<td><code>==</code></td>
<td><code>sameas</code></td>
</tr>
<tr>
<td><code>for</code></td>
<td><code>fo</code></td>
<td>|</td>
<td><code>!=</code></td>
<td><code>aint</code></td>
</tr>
<tr>
<td><code>friend</code></td>
<td><code>homie</code></td>
<td>|</td>
<td><code>+</code></td>
<td><code>an</code></td>
</tr>
<tr>
<td><code>long</code></td>
<td><code>shlong</code></td>
<td>|</td>
<td><code>-</code></td>
<td><code>widout</code></td>
</tr>
<tr>
<td><code>namespace</code></td>
<td><code>namespaze</code></td>
<td>|</td>
<td><code>*</code></td>
<td><code>dimes</code></td>
</tr>
<tr>
<td><code>new</code></td>
<td><code>makea</code></td>
<td>|</td>
<td><code>/</code></td>
<td><code>videdby</code></td>
</tr>
<tr>
<td><code>private</code></td>
<td><code>nonyobiz</code></td>
<td>|</td>
<td><code>&gt;</code></td>
<td><code>bepimpin</code></td>
</tr>
<tr>
<td><code>protected</code></td>
<td><code>indafamily</code></td>
<td>|</td>
<td><code>&lt;</code></td>
<td><code>fearin</code></td>
</tr>
<tr>
<td><code>public</code></td>
<td><code>tweetdat</code></td>
<td>|</td>
<td><code>++</code></td>
<td><code>propsta</code></td>
</tr>
<tr>
<td><code>return</code></td>
<td><code>putou</code></td>
<td>|</td>
<td><code>--</code></td>
<td><code>dissin</code></td>
</tr>
</tbody>
</table>
<ul>
<li> *.cpp -&gt; *.opp</li>
<li>*.h -&gt; *.ho</li>
</ul>
<p>Many thanks to <a href="https://plus.google.com/s/sean%20tegtmeyer" target="_blank">Sean Tegtmeyer</a> for helping with the syntax definition.</p>
<h2>Building Foshizzle</h2>
<p>I <em>highly</em> suggest building Clang <strong>without</strong> my changes first and verify that you have it working correctly. Then it should be simple to apply my patch and rebuild. I did all my work on Fedora 16, so your mileage may vary on other distros or OSes.</p>
<p><strong>Note</strong>: If you have any problems building LLVM or Clang, please refer to their build page: <a title="Clang: Getting Started" href="http://clang.llvm.org/get_started.html" target="_blank">Getting Started</a></p>
<ol>
<li>Create a new directory (e.g. &#8220;foshizzle&#8221;).</li>
<li>Within the &#8220;foshizzle&#8221; directory, create the following directories: &#8220;build&#8221;, &#8220;src&#8221;, &#8220;install&#8221;</li>
<li>Checkout the LLVM source code into the &#8220;src&#8221; directory:</li>
<ul>
<li><code>svn co http://llvm.org/svn/llvm-project/llvm/tags/RELEASE_30/rc4 ./src</code></li>
</ul>
<li>Create a new directory for the Clang source within the LLVM &#8220;tools&#8221; directory:</li>
<ul>
<li><code>mkdir src/tools/clang</code></li>
</ul>
<li>Checkout the Clang source code into the &#8220;src/tools/clang&#8221; directoy:</li>
<ul>
<li><code>svn co http://llvm.org/svn/llvm-project/cfe/tags/RELEASE_30/rc4 ./src/tools/clang</code></li>
</ul>
<li>Change directories into the &#8220;build&#8221; directory.</li>
<li>Configure the Clang/LLVM build and point it to the &#8220;install&#8221; directory you created earlier:</li>
<ul>
<li><code>../src/configure --prefix=&lt;path&gt;/&lt;to&gt;/&lt;foshizzle&gt;/install</code></li>
</ul>
<li>Build (takes quite a while): <code>make</code></li>
<li>Install: <code>make install</code></li>
<li>Compile some test code to make sure it works: <code>install/bin/clang++ yourtestcode.cpp</code></li>
</ol>
<p><strong>Only</strong> continue on once the unmodified version of Clang is working.</p>
<ol>
<li>Download my patch file: <a href="http://tdistler.com/media/code/eubonicode/ebpp-clang30rc4.patch" target="_blank">ebpp-clang30rc4.patch</a></li>
<li>Change directories to where the Clang source is (src/tools/clang).</li>
<li>Apply the patch: <code>patch -p0 -i ebpp-clang30rc4.patch</code></li>
<li>Change back to the &#8220;build&#8221; directory.</li>
<li>Build: <code>make</code></li>
<li>Install: <code>make install</code></li>
<li>Test: <code>install/bin/foshizzle++ yordopecodez.opp</code></li>
</ol>
<p>You can also build the sample code below.</p>
<h2>Sample Code</h2>
<p><a href="http://tdistler.com/media/code/eubonicode/baseclaz.ho" target="_blank">baseclaz.ho</a>, <a href="http://tdistler.com/media/code/eubonicode/friendclaz.ho" target="_blank">friendclaz.ho</a>, <a href="http://tdistler.com/media/code/eubonicode/main.opp" target="_blank">main.opp</a></p>
<p><strong>Building</strong></p>
<pre>install/bin/foshizzle++ main.opp</pre>
<p>&nbsp;</p>
<p><strong>Program Output</strong></p>
<pre>baseclaz: protected = 1, private = 1
derivedclaz: protected = 0, private = 1
friendclaz: friend private = 0

Factorial(7) = 5040</pre>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/12/03/eubonicode-hackin-c-gangsta-style/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Adding stdint.h to Visual Studio</title>
		<link>http://tdistler.com/2011/11/13/adding-stdint-h-to-visual-studio</link>
		<comments>http://tdistler.com/2011/11/13/adding-stdint-h-to-visual-studio#comments</comments>
		<pubDate>Sun, 13 Nov 2011 13:00:51 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=1066</guid>
		<description><![CDATA[Yes, stdint.h and inttypes.h are missing from Microsoft Visual Studio. As a result, anyone who&#8217;s written cross-platform C\C++ code for Windows has probably seen this error: error C2146: syntax error : missing ';' before identifier 'foo' error C4430: missing type specifier - int assumed. Note: C++ does not support default-int The fact is that Visual [...]]]></description>
			<content:encoded><![CDATA[<p>Yes, <code>stdint.h</code> and <code>inttypes.h</code> are missing from Microsoft Visual Studio. As a result, anyone who&#8217;s written cross-platform C\C++ code for Windows has probably seen this error:</p>
<p><code>error C2146: syntax error : missing ';' before identifier 'foo'<br />
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int</code></p>
<p>The fact is that Visual Studio doesn&#8217;t implement C99&#8230; it implements C89 (for compatibility reasons). So, you don&#8217;t have access to familiar types like:</p>
<ul>
<li><code>int8_t, int16_t, int32_t, int64_t</code></li>
<li><code>uint8_t, uint16_t, uint32_t, uint64_t</code></li>
<li><code>INT8_MIN</code>, <code>INT8_MAX</code>, etc</li>
<li>The <code>fprintf</code> macros <code>PRId32</code>, <code>PRIu32</code>, etc</li>
<li><code>strtoimax()</code>, etc</li>
</ul>
<p>Fortunately, <a href="http://www.chemeris.ru/" target="_blank">Alexander Chemeris</a> has written <a title="Google Code" href="http://code.google.com/p/msinttypes/" target="_blank">msinttypes</a>: an implementation of <code>stdint.h</code> and <code>inttypes.h</code> for Microsoft Visual Studio. It is licensed under the BSD license, so the headers are actually usable commercially (no viral GPL). This following quote probably goes without saying (emphasis mine):</p>
<blockquote><p>Note though, that just adding these headers does <strong>not</strong> make Visual Studio compiler fully C99 compliant.</p></blockquote>
<p>This project has saved me a bunch of unwanted coding. Thanks Alex!</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/11/13/adding-stdint-h-to-visual-studio/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>First Digitally Rendered Film by Ed Catmull (1972)</title>
		<link>http://tdistler.com/2011/10/21/first-digitally-rendered-film-by-ed-catmull-1972</link>
		<comments>http://tdistler.com/2011/10/21/first-digitally-rendered-film-by-ed-catmull-1972#comments</comments>
		<pubDate>Fri, 21 Oct 2011 15:00:55 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Tech and Security]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=1057</guid>
		<description><![CDATA[Here&#8217;s a video done by Ed Catmull (founder of Pixar) in 1972 while at the University of Utah. It&#8217;s purported to be the first digitally rendered film. It&#8217;s just amazing how far we&#8217;ve come since these early pioneering days. The math that we take for granted for rendering 3D was being invented, real time, to create this [...]]]></description>
			<content:encoded><![CDATA[<p><a title="First Digital 3D Rendered Film (from 1972) and My Visit to Pixar" href="http://nerdplusart.com/first-3d-rendered-film-from-1972-and-my-visit-to-pixar" target="_blank">Here&#8217;s a video</a> done by Ed Catmull (founder of <a title="Pixar" href="http://www.pixar.com/" target="_blank">Pixar</a>) in 1972 while at the University of Utah. It&#8217;s purported to be the first digitally rendered film. It&#8217;s just amazing how far we&#8217;ve come since these early pioneering days.</p>
<blockquote><p>The math that we take for granted for rendering 3D was being invented, real time, to create this video. (Ed’s credited for having working out that math to handle things like texture mapping, 3D anti-aliasing and z-buffering.)</p></blockquote>
<p>The story behind the video and how it was found recently is pretty cool too. Props to <a title="Robby Ingebretsen" href="http://nerdplusart.com/about" target="_blank">Robby Ingebretsen</a> for sharing this!<br />
<br/><br />
<iframe src="http://player.vimeo.com/video/16292363?title=0&amp;byline=0&amp;portrait=0" frameborder="0" width="400" height="225"></iframe></p>
<p><a href="http://vimeo.com/16292363">40 Year Old 3D Computer Graphics (Pixar, 1972)</a> from <a href="http://vimeo.com/nerdplusart">Robby Ingebretsen</a> on <a href="http://vimeo.com">Vimeo</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/10/21/first-digitally-rendered-film-by-ed-catmull-1972/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Inside the .NET CLR Garbage Collector</title>
		<link>http://tdistler.com/2011/09/09/inside-the-net-clr-garbage-collector</link>
		<comments>http://tdistler.com/2011/09/09/inside-the-net-clr-garbage-collector#comments</comments>
		<pubDate>Fri, 09 Sep 2011 15:00:29 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[Tech and Security]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=1049</guid>
		<description><![CDATA[Here&#8217;s a great interview with Microsoft Technical Fellow and author of the CLR garbage collector, Patrick Dussud. How does GC, work, generally? Why is it important? The GC inside of the CLR is of a specfic type &#8211; ephemeral, concurrent (the server version has always been concuurent and now with Background GC on the client [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a great interview with Microsoft Technical Fellow and author of the CLR garbage collector, <a title="Profile: Patrick Dussud" href="http://www.microsoft.com/presspass/exec/techfellow/dussud/default.mspx" target="_blank">Patrick Dussud</a>.</p>
<blockquote><p>How does GC, work, generally? Why is it important? The GC inside of the CLR is of a specfic type &#8211; ephemeral, concurrent (the server version has always been concuurent and now with Background GC on the client in CLR 4, GC is concurrent on the client as well, but there are differences&#8230;)</p></blockquote>
<p><iframe style="height: 288px; width: 512px;" src="http://channel9.msdn.com/Shows/Going+Deep/E2E-Erik-Meijer-and-Patrick-Dussud-Inside-Garbage-Collection/player?w=512&amp;h=288" frameborder="0" scrolling="no" width="320" height="240"></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/09/09/inside-the-net-clr-garbage-collector/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C++11: Move Semantics and Rvalue References</title>
		<link>http://tdistler.com/2011/08/18/c11-move-semantics-and-rvalue-references</link>
		<comments>http://tdistler.com/2011/08/18/c11-move-semantics-and-rvalue-references#comments</comments>
		<pubDate>Thu, 18 Aug 2011 15:00:36 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=1017</guid>
		<description><![CDATA[Thomas Becker has a great article explaining C++11&#8242;s rvalue references and how they allow move semantics and perfect forwarding. I particularly liked his summary of the 3 things you need to remember about rvalue references: By overloading a function like this: void foo(X&#38; x); // lvalue reference overload void foo(X&#38;&#38; x); // rvalue reference overload [...]]]></description>
			<content:encoded><![CDATA[<p><a title="Thomas Becker: C++ Rvalue References Explained" href="http://thbecker.net/articles/rvalue_references/section_01.html" target="_blank">Thomas Becker has a great article</a> explaining C++11&#8242;s rvalue references and how they allow move semantics and perfect forwarding.</p>
<p>I particularly liked his summary of the 3 things you need to remember about rvalue references:</p>
<ol>
<li>By overloading a function like this:<br />
<code>
<pre>

void foo(X&amp; x); // lvalue reference overload
void foo(X&amp;&amp; x); // rvalue reference overload
</pre>
<p></code><br />
you can branch at compile time on the condition &#8220;is foo being called on an lvalue or an rvalue?&#8221; The primary (and for all practical purposes, the only) application of that is to overload the copy constructor and copy assignment operator of a class for the sake of implementing move semantics. If and when you do that, make sure to pay attention to exception handling, and use the new noexcept keyword as much as you can.</li>
<li><code>std::move</code> turns its argument into an rvalue.</li>
<li><code>std::forward</code> allows you to achieve perfect forwarding if you use it exactly as shown:<br />
<code>
<pre>

template&lt;typename T, typename Arg&gt;
shared_ptr&lt;T&gt; factory(Arg&amp;&amp; arg)
{
    return shared_ptr&lt;T&gt;(new T(std::forward&lt;Arg&gt;(arg));
}</pre>
<p></code>
</li>
</ol>
<p>I also like his definition of lvalues and rvalues in the <a title="Thomas Becker: Introduction" href="http://thbecker.net/articles/rvalue_references/section_01.html" target="_blank">introduction</a>:</p>
<blockquote><p>The original definition of lvalues and rvalues from the earliest days of C is as follows: An <em>lvalue</em> is an expression <code>e</code> that may appear on the left or on the right hand side of an assignment, whereas an<em>rvalue</em> is an expression that can only appear on the right hand side of an assignment.</p>
<p>In C++, this is still useful as a first, intuitive approach to lvalues and rvalues. <strong>However</strong>, C++ with its user-defined types has introduced some subtleties regarding modifiability and assignability that cause this definition to be incorrect. There is no need for us to go further into this. Here is an alternate definition which, although it can still be argued with, will put you in a position to tackle rvalue references: <em><strong>An lvalue is an expression that refers to a memory location and allows us to take the address of that memory location via the <code>&amp;</code> operator. An rvalue is an expression that is not an lvalue. </strong></em></p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/08/18/c11-move-semantics-and-rvalue-references/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to connect Linux to a Cisco VPN using a PCF file</title>
		<link>http://tdistler.com/2011/07/07/how-to-connect-linux-to-a-cisco-vpn-using-a-pcf-file</link>
		<comments>http://tdistler.com/2011/07/07/how-to-connect-linux-to-a-cisco-vpn-using-a-pcf-file#comments</comments>
		<pubDate>Thu, 07 Jul 2011 15:10:19 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[Tech and Security]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=1007</guid>
		<description><![CDATA[Connecting Linux to a Cisco VPN server using a PCF file is easy (even from within a VirtualBox virtual machine). First, I wouldn&#8217;t bother with Cisco&#8217;s Linux client&#8230; especially if you are running 64bit. You have to patch a source file and mod the Makefile. Using VPNC is so much easier. NOTE: I only had [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2011/11/tux_cisco.jpg"><img class="alignright size-thumbnail wp-image-1011" title="tux_cisco" src="http://tdistler.com/wp-content/uploads/2011/11/tux_cisco-150x150.jpg" alt="" width="150" height="150" /></a>Connecting Linux to a Cisco VPN server using a PCF file is easy (even from within a <a title="VirtualBox" href="https://www.virtualbox.org/" target="_blank">VirtualBox</a> virtual machine). First, I wouldn&#8217;t bother with Cisco&#8217;s Linux client&#8230; especially if you are running 64bit. You have to patch a source file and mod the Makefile. Using <a title="VPNC" href="http://www.unix-ag.uni-kl.de/~massar/vpnc/" target="_blank">VPNC</a> is so much easier.</p>
<p><em>NOTE: I only had the PCF file provided by work, and the group password was encrypted. If you know your group password, then you can just run VPNC directly or write a conf file yourself.</em></p>
<p>My setup:</p>
<ul>
<li>Fedora 12 x86_64</li>
<li>Running in VirtualBox 4.1.6 with <em><strong>bridged networking</strong></em> (I didn&#8217;t try it with NAT)</li>
<li>Connecting to a Cisco VPN server at work</li>
</ul>
<p>Connecting:</p>
<ol>
<li>Install VPNC (`<code>sudo yum install vpnc</code>` in Fedora)</li>
<li>Download the <a title="pcf2vpnc" href="http://svn.unix-ag.uni-kl.de/vpnc/trunk/pcf2vpnc" target="_blank">pcf2vpnc</a> Perl script (<a title="cached pcf2vpnc" href="http://www.tdistler.com/media/code/pcf2vpnc" target="_blank">cached</a>)</li>
<li>Convert your Cisco PCF file to VPNC conf format: `<code>perl pcf2vpnc company.pcf vpnc.conf</code>`</li>
<li>Connect to the VPN server: `<code>sudo vpnc ./vpnc.conf</code>` (you will be prompted for you username and password)</li>
<li>(optional) Run <code>`ifconfig</code>` to see the tunnel interface that was created</li>
</ol>
<blockquote>
<pre><code>eth0     Link encap:Ethernet  HWaddr 08:00:DE:AD:BE:EF
         inet addr:192.168.1.10  Bcast:192.168.1.255  Mask:255.255.255.0
         ...

lo       Link encap:Local Loopback
         inet addr:127.0.0.1  Mask:255.0.0.0
         ...

<strong>tun0     Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
         inet addr:10.200.100.1  P-t-P:10.220.116.219  Mask:255.255.255.255</strong>
         ...</code></pre>
</blockquote>
<p>Disconnecting:</p>
<ol>
<li>Run `<code>sudo vpnc-disconnect</code>` (don&#8217;t forget the `<code>sudo</code>`)</li>
</ol>
<p>That&#8217;s it. Cheers!</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/07/07/how-to-connect-linux-to-a-cisco-vpn-using-a-pcf-file/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>CRC32: A Simple C++ Class</title>
		<link>http://tdistler.com/2011/06/22/crc32-a-simple-c-class</link>
		<comments>http://tdistler.com/2011/06/22/crc32-a-simple-c-class#comments</comments>
		<pubDate>Wed, 22 Jun 2011 17:32:51 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=993</guid>
		<description><![CDATA[A simple C++ class for calculating CRC32.]]></description>
			<content:encoded><![CDATA[<p><a title="Wikipedia: Cyclic Redundancy Check" href="http://en.wikipedia.org/wiki/Cyclic_redundancy_check" target="_blank">Cyclic Redundancy Checks</a> are a quick and convenient way to verify if a data set has changed. They are not meant to be &#8220;secure&#8221; like a MD5 or SHA-1, but they offer a very practical solution to most problems. CRC&#8217;s are also useful for verifying if 2 data sets are equal. Here&#8217;s a simple class I use that&#8217;s efficient. Honestly, I don&#8217;t remember what flavor of CRC32 it implements (sorry), but it has always worked for what I&#8217;ve needed. Cheers!</p>
<pre><code>static const uint32_t kCrc32Table[256] = {
    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
    0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
    0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
    0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
    0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
    0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
    0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
    0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
    0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
    0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
    0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
    0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
    0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,<span id="more-993"></span>
    0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
    0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
    0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
    0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
    0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
    0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
    0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
    0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
    0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
    0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
    0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
    0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
    0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
    0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
    0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
    0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
    0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
    0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
    0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
    0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
    0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
    0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
    0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
    0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
    0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
    0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
    0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
    0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
    0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
    0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
    0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
    0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
    0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
    0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
    0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
}; // kCrc32Table

class Crc32
{
public:
    Crc32() { Reset(); }
    ~Crc32() throw() {}
    void Reset() { _crc = (uint32_t)~0; }
    void AddData(const uint8_t* pData, const uint32_t length)
    {
        uint8_t* pCur = (uint8_t*)pData;
        uint32_t remaining = length;
        for (; remaining--; ++pCur)
            _crc = ( _crc &gt;&gt; 8 ) ^ kCrc32Table[(_crc ^ *pCur) &amp; 0xff];
    }
    const uint32_t GetCrc32() { return ~_crc; }

private:
    uint32_t _crc;
};

</code></pre>
<p><strong>Note</strong>: I always have <code>uint32_t</code> defined in Windows, so you may have to define it yourself or use the Microsoft intrinsic <code>unsigned __int32</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/06/22/crc32-a-simple-c-class/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Netem WAN Emulation: How to Setup a Netem Box</title>
		<link>http://tdistler.com/2011/06/10/netem-wan-emulation-how-to-setup-a-netem-box</link>
		<comments>http://tdistler.com/2011/06/10/netem-wan-emulation-how-to-setup-a-netem-box#comments</comments>
		<pubDate>Sat, 11 Jun 2011 00:33:43 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Tech and Security]]></category>
		<category><![CDATA[network]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=973</guid>
		<description><![CDATA[Instructions for building and configuring a Netem box to simulate a WAN connection using Fedora 14.]]></description>
			<content:encoded><![CDATA[<p><a title="Netem" href="http://www.linuxfoundation.org/collaborate/workgroups/networking/netem" target="_blank">Netem</a> is a great tool for simulating a WAN connection, with all the expected latency, jitter, packet loss, duplication, and bandwidth limitations. These instructions walk you through setting up a machine that sits between your server and client that emulates the behavior of a WAN connection. I use <a title="Fedora Linux Project" href="http://fedoraproject.org/" target="_blank">Fedora 14</a>, so your distro may be a little different, but hopefully this post gets you pointed in the right direction.</p>
<p>The picture below shows the 2 most common configurations for a Netem box:</p>
<p><a href="http://tdistler.com/wp-content/uploads/2011/06/netem_setup.jpg"><img class="aligncenter size-full wp-image-975" title="netem_setup" src="http://tdistler.com/wp-content/uploads/2011/06/netem_setup.jpg" alt="Netem Box Setup" width="449" height="295" /></a></p>
<p>I&#8217;ve always used the first configuration, but it doesn&#8217;t really matter.</p>
<h2>1. Find a Suitable System</h2>
<ul>
<li>Any &#8220;reasonable&#8221; machine that can run Fedora 14 (I use an old Pentium 4 box since I don&#8217;t need to simulate a high-speed link)</li>
<li>It must have 2 network interfaces</li>
<li>It&#8217;s nice to use a smaller box if you want it to be portable</li>
</ul>
<h2>2. Install <code>bridge-utils</code></h2>
<p>Make sure you are <code>root</code>, and run:</p>
<p><code>brctl</code></p>
<p>to see if <code>bridge-utils</code> is installed. If it isn&#8217;t, run:</p>
<p><code>yum install bridge-utils</code>.<span id="more-973"></span></p>
<h2>3. Bridge the 2 Network Interfaces</h2>
<p>First make sure to clear the network configuration for your interfaces:</p>
<p><code>ifconfig eth0 0.0.0.0<br />
ifconfig eth1 0.0.0.0</code></p>
<p>Then create the bridge and bring it up:</p>
<p><code>brctl addbr br0<br />
brctl setfd br0 0<br />
brctl addif br0 eth0<br />
brctl addif br0 eth1<br />
ifconfig br0 up</code></p>
<p>Note that we disable the forwarding delay (&#8216;setfd&#8217;). This makes the bridge pass traffic through it immediately instead of the configured delay time.</p>
<p>One final set I had to perform is disabling kernel-level filtering on the bridge. This is done by writing <code>0</code> to the bridge nodes under proc:</p>
<p><code>for f in /proc/sys/net/bridge-*; do echo 0 &gt; $f; done</code></p>
<p>Note: If for some reason none of this works for you, check out <a title="Linux Foundation: Network Bridging" href="http://www.linuxfoundation.org/collaborate/workgroups/networking/bridge" target="_blank">the Linux Foundation page on network bridging</a>.</p>
<h2>4. Configure Netem</h2>
<p>Netem is actually used in conjunction with the Traffic Control application, <code>tc</code>. I&#8217;m not going to go into detail here, but suffice it to say that <code>tc</code> allows you to do packet shaping and adjust packet scheduling. <a title="Traffic Control man page" href="http://linux.die.net/man/8/tc" target="_blank">Check out the <code>tc</code> man page for more information</a>.</p>
<p><code>tc</code> allows you to specify the &#8220;queueing discipline&#8221; (or &#8220;qdisc&#8221; for short) used for sending <strong>outbound</strong> packets on an interface (the fact that it operates on outbound packets only is important to remember). Basically, a qdisc defines how outbound packets are ordered and sent. To view the current qdisc setup on your box, type:</p>
<p><code>tc qdisc</code></p>
<p>The default qdisc is pfifo_fast. We&#8217;re going to change this to use a combination of Netem and <a title="Token Bucket Filter" href="http://linux.die.net/man/8/tc-tbf" target="_blank">Token Bucket Filter</a>.</p>
<p><strong>Note:</strong> For the following examples, I assume <code>eth0</code> is connected to the network (client-side), and <code>eth1</code> is <em>directly</em> connected to the server.</p>
<h3>Limiting Bandwidth</h3>
<p>The <a title="Token Bucket Filter" href="http://linux.die.net/man/8/tc-tbf" target="_blank">Token Bucket Filter</a> (tbf) is used to limit how much data can exit the network interface per second&#8230; perfect for simulating WAN bandwidth limitations. Let&#8217;s assume we want to emulate a client-side WAN connection of 768kbps down and 128kbps up. Assuming the server is connected to <code>eth1</code>, the <code>eth1</code> interface receives inbound traffic from the server and <code>eth0</code> sends that traffic outbound to the client. Since we know the a qdisc works on outbound traffic only, we need to limit <code>eth0</code> for our download speed of 768kbps. Conversely, we configure <code>eth1</code> for our upload speed of 128kbps.</p>
<p><code>tc qdisc replace dev eth0 root handle 1:0 tbf rate 768kbit burst 2048 latency 100ms</code></p>
<p><code>tc qdisc replace dev eth1 root handle 2:0 tbf rate 128kbit burst 2048 latency 100ms</code></p>
<p>We use the &#8216;replace&#8217; command to overwrite any qdisc setting that&#8217;s there (you can use the &#8216;del&#8217; command to simple remove qdiscs). We set the qdisc as the &#8216;<code>root</code>&#8216; of the tree, and configure the tbf &#8216;<code>rate</code>&#8216; accordingly. The &#8216;<code>burst</code>&#8216; and &#8216;<code>latency</code>&#8216; parameters control the initial number of tokens in the bucket and how long queued packet can hang around before being dropped, respectively.</p>
<h3>Adding Latency</h3>
<p>We can append qdiscs that will allows us to use different tools to control how our simulated WAN behaves. In this example, I&#8217;ll use Netem to artifically add 57ms of latency to the download connection with a random variantion of +/- 13ms:</p>
<p><code>tc qdisc add dev eth0 parent 1:1 handle 10: netem delay 57ms 13ms</code></p>
<h3>And So Much More&#8230;</h3>
<p>The <a title="Netem Examples" href="http://www.linuxfoundation.org/collaborate/workgroups/networking/netem" target="_blank">Netem page on the Linux Foundation website</a> has many other great examples, so there&#8217;s no point in me copying them here. If you&#8217;ve made it this far and are still interested, I highly encourage you to check out their page.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/06/10/netem-wan-emulation-how-to-setup-a-netem-box/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Live555: Compiling with VS2008</title>
		<link>http://tdistler.com/2011/05/14/live555-compiling-with-vs2008</link>
		<comments>http://tdistler.com/2011/05/14/live555-compiling-with-vs2008#comments</comments>
		<pubDate>Sat, 14 May 2011 18:30:49 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[live555]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=959</guid>
		<description><![CDATA[4 easy steps to compile Live555 using VS2008. Fixes link error: LNK1181: cannot open input file 'msvcirt.lib'.]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2011/02/network.jpg"><img class="alignright size-thumbnail wp-image-795" title="network" src="http://tdistler.com/wp-content/uploads/2011/02/network-150x150.jpg" alt="" width="100" height="100" /></a>Compiling <a title="Live555 Streaming Media" href="http://www.live555.com/liveMedia/" target="_blank">Live555 Streaming Media</a> with Visual Studio 2008 isn&#8217;t obvious. Using Cygwin or MinGW is just a pain and frankly unnecessary. There is no built-in support for VS solution files, because Windows support is a low priority for the Live555 community. This is evidenced by <a title="Live555 Forum" href="http://lists.live555.com/pipermail/live-devel/2008-January/008022.html" target="_blank">this forum response</a> from Ross Finlayson:</p>
<blockquote><p><em>&gt;4.  Is it possible to include a Visual Studio solution in the</em><br />
<em> &gt;distrubution to make it more convenient for Windows developers to</em><br />
<em> &gt;use live555?</em><br />
<em> &gt;5.  Is it possible for live555 to generate adequate makefiles for</em><br />
<em> &gt;Windows systems with development environments newer than Visual</em><br />
<em> &gt;Studio 2003?</em></p>
<p><strong>I have no current plans to change this.  (These days, fewer and fewer</strong> <strong>people seem to be using Windows for development of system software.)</strong></p></blockquote>
<p>Regardless, Live555 works fine on Windows and is actually quite easy to build. Simply do the following:</p>
<ol>
<li>Open the &#8216;win32config&#8217; file and change the <code>TOOLS32=... </code>variable to your VS2008 install directory. For me, it&#8217;s <code>TOOLS32=C:\Program Files\Microsoft Visual Studio 9.0\VC</code></li>
<li>In &#8216;win32config&#8217;, modify the <code>LINK_OPTS_0=...</code> line from <code>msvcirt.lib</code> to <code>msvcrt.lib</code>. This fixes the link error:<br />
<code>LINK : fatal error LNK1181: cannot open input file 'msvcirt.lib'</code></li>
<li>Open the Visual Studio command prompt.</li>
<li>From the &#8216;live&#8217; source directory, run <code>genWindowsMakefiles</code></li>
<li>Now you&#8217;re ready to build. Simply run the following commands:
<pre><code>cd liveMedia
nmake /B -f liveMedia.mak
cd ..\groupsock
nmake /B -f groupsock.mak
cd ..\UsageEnvironment
nmake /B -f UsageEnvironment.mak
cd ..\BasicUsageEnvironment
nmake /B -f BasicUsageEnvironment.mak
cd ..\testProgs
nmake /B -f testProgs.mak
cd ..\mediaServer
nmake /B -f mediaServer.mak</code></pre>
</li>
</ol>
<p>That&#8217;s it. You should be good to go.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/05/14/live555-compiling-with-vs2008/feed</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Lua: Get CPU Load on Linux</title>
		<link>http://tdistler.com/2011/05/02/lua-get-cpu-load-on-linux</link>
		<comments>http://tdistler.com/2011/05/02/lua-get-cpu-load-on-linux#comments</comments>
		<pubDate>Tue, 03 May 2011 00:07:01 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[Lua]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=951</guid>
		<description><![CDATA[Here's a Lua function that returns the percentage of CPU used on Linux. The load includes time in user space and system space. ]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a Lua function that returns the percentage of CPU used on Linux. The load includes time in user space and system space. In case you&#8217;re curious, I used `<code>top</code>` to get the load for a couple reasons:</p>
<ol>
<li>It&#8217;s installed by default on most distros (as opposed to the <code>sysstat</code> tools).</li>
<li>It gives the idle time in percentage normalized to 100% (as opposed to <code>/proc/stat</code> which requires knowledge of the jiffy&#8217;s interval, which can vary).</li>
</ol>
<pre><code>function cpu_load(interval)
   interval = interval or 1
   local f = io.popen('top -bp$$ -d ' .. interval .. ' -n 2')
   local s = f:read('*all')

   -- Find the idle times in the stdout output
   local tokens = s:gmatch(',%s*([%d%.]+)%%%s*id')

   -- We're interested in the 2nd 'top' idle time
   local ii = 1
   for idle in tokens do
      if ii == 2 then
         return 100.0 - tonumber(idle)
      end
      ii = ii + 1
   end
end

</code></pre>
<p>You can call it from the Lua shell as:</p>
<pre><code>&gt; load = cpu_load()
&gt; print(load)
43.7

</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/05/02/lua-get-cpu-load-on-linux/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rendering Video with GDI (Example)</title>
		<link>http://tdistler.com/2011/04/20/rendering-video-with-gdi-example</link>
		<comments>http://tdistler.com/2011/04/20/rendering-video-with-gdi-example#comments</comments>
		<pubDate>Wed, 20 Apr 2011 18:04:25 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=932</guid>
		<description><![CDATA[Example C++ GDI video window class with text overlay.]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2011/04/video-icon.jpg"><img class="alignright size-thumbnail wp-image-948" title="video-icon" src="http://tdistler.com/wp-content/uploads/2011/04/video-icon-150x150.jpg" alt="" width="150" height="150" /></a>In this post, I outline a basic GDI video window class. GDI is inefficient for rendering video, but it&#8217;s also very convinient when writing simple tools on Windows. I find myself doing it often enough that it makes sense to do a brain-dump here. This is only an outline, but it should get you over the biggest hurdles.</p>
<h4>Outline</h4>
<ol>
<li>Video Window Class Definition</li>
<li>Creating and Destroying the Window</li>
<li>The Window Thread</li>
<li>The Message Pump</li>
<li>Rendering a Video Frame</li>
</ol>
<p>Things to note:</p>
<ul>
<li>You will need a thread in your window class to &#8220;pump&#8221; window events.</li>
<li>GDI does NOT do any color conversion, so you will need to convert each frame into the same format as the display (always RGB, usually 24 or 32 bits).</li>
</ul>
<h4>Video Window Class Definition</h4>
<pre><code>class VideoWindow
{
public:
    ...
private:
    static DWORD _ThreadMain(void*);
    static LRESULT WINAPI _MsgProc(HWND, UINT, WPARAM, LPARAM);

    CRITICAL_SECTION _lok;
    HANDLE _thread;
    HWND _hWnd;
    HDC _hDC;
    HDC _hFrameDC;
    HFONT _hFont;
    int _bpp;   // bit depth
    volatile bool _exit;
    int _x, _y, _w, _h; // Window dimensions
    int _imgWidth, _imgHeight, _imgLength; // Frame dimensions
    unsigned char *_imgBits;
};

</code></pre>
<h4>Creating and Destroying the Window</h4>
<pre><code>void VideoWindow::Create(int x, int y, int w, int h)
{
    EnterCriticalSection(&amp;_lok);
    _x = x;
    _y = y;
    _w = w;
    _h = h;
    _hWnd = 0;
    _exit = false;
    _thread = CreateThread( NULL, NULL, (LPTHREAD_START_ROUTINE)_ThreadMain,
        this, NULL, 0 );
    LeaveCriticalSection(&amp;_lok);

    // Wait for window to be created. Cheap, but it works.
    while (!_hWnd) {
        ::Sleep(100);
    }
}
<span id="more-932"></span>
void VideoWindow::Destroy()
{
    // Safe to call from the destructor.

    EnterCriticalSection(&amp;_lok);
    if(_hWnd)
    {
        _exit = true;
        LeaveCriticalSection(&amp;_lok);
        WaitForSingleObject( _thread, INFINITE );
        CloseHandle(_thread);
        EnterCriticalSection(&amp;_lok);
        DestroyWindow(_hWnd);
        _hWnd = 0;
    }
    if (_hFont) ::DeleteObject(_hFont);
    if (_hFrameDC) ::DeleteDC(_hFrameDC);
    if (_hDC) ::DeleteDC(_hDC);
    LeaveCriticalSection(&amp;_lok);
}

</code></pre>
<h4>The Window Thread</h4>
<pre><code>DWORD VideoWindow::_ThreadMain(void* ctx)
{
    VideoWindow *p = (VideoWindow*)ctx;
    EnterCriticalSection(&amp;p-&gt;_lok);

    LPCSTR className = "VideoWndClass";
    LPCSTR windowName = "MyWindowText";
    WNDCLASSEX wcex = { 
        sizeof(WNDCLASSEX), 
        CS_OWNDC | CS_HREDRAW | CS_VREDRAW, 
        _MsgProc, 
        0L, 
        0L,
        NULL, 
        NULL, 
        NULL, 
        (HBRUSH)GetStockObject(BLACK_BRUSH),
        NULL, 
        className, 
        NULL 
    };

    RegisterClassEx(&amp;wcex);   

    p-&gt;_hWnd = CreateWindow(className, windowName, WS_OVERLAPPEDWINDOW, 
        p-&gt;_x, p-&gt;_y, p-&gt;_w, p-&gt;_h, ::GetDesktopWindow(), NULL, NULL, NULL);

    p-&gt;_hDC = ::GetDC(p-&gt;_hWnd);
    p-&gt;_bpp = ::GetDeviceCaps(p-&gt;_hDC, BITSPIXEL);
    p-&gt;_hFrameDC = ::CreateCompatibleDC(p-&gt;_hDC);

    p-&gt;_hFont = ::CreateFont(18, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
        ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
        ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Arial");

    ShowWindow(p-&gt;_hWnd,SW_SHOW);
    UpdateWindow(p-&gt;_hWnd);

    while( !p-&gt;_exit )
    {
        MSG msg;
        if(PeekMessage(&amp;msg,p-&gt;_hWnd,0,0,PM_REMOVE))
        {
            TranslateMessage(&amp;msg);
            DispatchMessage(&amp;msg);
        }

        LeaveCriticalSection(&amp;p-&gt;_lok);
        Sleep(50); // A better way to do this is to use a message
        EnterCriticalSection(&amp;p-&gt;_lok);
    }
    LeaveCriticalSection(&amp;p-&gt;_lok);
    return 0;
}

</code></pre>
<h4>The Message Pump</h4>
<pre><code>LRESULT WINAPI VideoWindow::_MsgProc(HWND hWnd, UINT msg, WPARAM w, LPARAM l)
{
    if (msg == WM_PAINT &amp;&amp; l)
    {
        VideoWindow *p = (VideoWindow*)l;
        EnterCriticalSection(&amp;p-&gt;_lok);

        
        HGDIOBJ  oldFont  = ::SelectObject(p-&gt;_hDC, p-&gt;_hFont);
        COLORREF oldFtColor = ::SetTextColor(p-&gt;_hDC, RGB(255,255,255));
        COLORREF oldBkColor = ::SetBkColor(p-&gt;_hDC, RGB(64,64,64));

        // Render image
        //
        // NOTE: This assumes you've already coverted the image to the proper
        // RGB bit-depth (_bpp) and copied the data into _imageBits.
        //
        HBITMAP hBMP = ::CreateCompatibleBitmap(p-&gt;_hDC, p-&gt;_imgWidth,
            p-&gt;_imgHeight);
        ::SetBitmapBits(hBMP, p-&gt;_imgLength, p-&gt;_imgBits);
        HGDIOBJ oldBMP = ::SelectObject(p-&gt;_hFrameDC, hBMP);
        ::BitBlt(p-&gt;_hDC, 0, 0, p-&gt;_imgWidth, p-&gt;_imgHeight, p-&gt;_hFrameDC,
            0, 0, SRCCOPY);
        ::SelectObject(p-&gt;_hFrameDC, oldBMP);

        // Draw some text over the image
        RECT rect;
        ::SetRectEmpty(&amp;rect);
        ::DrawText(p-&gt;_hDC, p-&gt;_imageText, -1, &amp;rect, DT_CALCRECT);
        ::DrawText(p-&gt;_hDC, p-&gt;_imageText, -1, &amp;rect, DT_CENTER | DT_VCENTER);

        if (hBMP) ::DeleteObject(hBMP);

        LeaveCriticalSection(&amp;p-&gt;_lok);
    }
    return DefWindowProc(hWnd, msg, w, l);
}

</code></pre>
<p><strong>Rendering a Video Frame</strong></p>
<pre><code>
void VideoWindow::Render(const unsigned char* frame, int w, int h, int stride)
{
    // Convert frame to the proper RGB bit depth to match _bpp and copy it
    // into _imgBits buffer. Update _imgWidth, _imgHeight, and _imgLength as
    // necessary.

    ::PostMessage(_hWnd, WM_PAINT, 0, (LPARAM)this);
}

</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/04/20/rendering-video-with-gdi-example/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to Define NaN (Not-a-Number) on Windows</title>
		<link>http://tdistler.com/2011/03/24/how-to-define-nan-not-a-number-on-windows</link>
		<comments>http://tdistler.com/2011/03/24/how-to-define-nan-not-a-number-on-windows#comments</comments>
		<pubDate>Thu, 24 Mar 2011 20:41:48 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=874</guid>
		<description><![CDATA[The C99 spec requires that math.h should define the constant float value NAN. However, NAN isn&#8217;t defined in the Visual Studio version of math.h, so you have to define it yourself (VS only implements C89). It&#8217;s pretty straight-forward for 32-bit machines&#8230; here&#8217;s my implementation with cross-platform protection: #ifdef WIN32 #ifndef NAN static const unsigned long [...]]]></description>
			<content:encoded><![CDATA[<p>The C99 spec requires that <a title="The Open Group: math.h" href="http://pubs.opengroup.org/onlinepubs/009695399/basedefs/math.h.html" target="_blank">math.h should define the constant float value NAN</a>. However, NAN isn&#8217;t defined in the Visual Studio version of math.h, so you have to define it yourself (VS only implements C89). It&#8217;s pretty straight-forward for 32-bit machines&#8230; here&#8217;s my implementation with cross-platform protection:</p>
<pre><code>#ifdef WIN32
    #ifndef NAN
        static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
        #define NAN (*(const float *) __nan)
    #endif
#endif

</code></pre>
<p>This code is adapted from an MSDN <a title="MSDN: Not A Number (NAN) Items" href="http://msdn.microsoft.com/en-us/library/w22adx1s(v=vs.80).aspx" target="_blank">example</a>.<del datetime="2011-04-20T17:26:37+00:00"></del></p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/03/24/how-to-define-nan-not-a-number-on-windows/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>xkcd: IPv6</title>
		<link>http://tdistler.com/2011/03/04/xkcd-ipv6</link>
		<comments>http://tdistler.com/2011/03/04/xkcd-ipv6#comments</comments>
		<pubDate>Fri, 04 Mar 2011 18:52:53 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Oh So Random]]></category>
		<category><![CDATA[Tech and Security]]></category>
		<category><![CDATA[funny]]></category>
		<category><![CDATA[IPv6]]></category>
		<category><![CDATA[network]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=819</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p style="text-align: center;"><a href="http://xkcd.com/865/"><img class="aligncenter" src="http://imgs.xkcd.com/comics/nanobots.png" alt="xkcd: Nanobots" width="592" height="201" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/03/04/xkcd-ipv6/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cross-Platform IPv6 Socket Programming</title>
		<link>http://tdistler.com/2011/02/28/cross-platform-ipv6-socket-programming</link>
		<comments>http://tdistler.com/2011/02/28/cross-platform-ipv6-socket-programming#comments</comments>
		<pubDate>Tue, 01 Mar 2011 04:00:39 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[IPv6]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=793</guid>
		<description><![CDATA[Writing code that works on Windows, Linux, and Mac is frequently challenging. Socket programming is no exception. Modern versions of Linux and Mac have full implementations of the latest IPv6 socket API extensions defined in RFC 3493. Windows, however, has only a partial implementation of the original (deprecated) version, RFC 2553. This sounds worse than [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2011/02/network.jpg"><img class="alignright size-thumbnail wp-image-795" title="network" src="http://tdistler.com/wp-content/uploads/2011/02/network-150x150.jpg" alt="IPv6 Networking" width="150" height="150" /></a>Writing code that works on Windows, Linux, and Mac is frequently challenging. Socket programming is no exception. Modern versions of Linux and Mac have full implementations of the latest IPv6 socket API extensions defined in <a title="IETF RFC 3493" href="http://tools.ietf.org/html/rfc3493" target="_blank">RFC 3493</a>. Windows, however, has only a partial implementation of the original (deprecated) version, <a title="IETF RFC 2553" href="http://tools.ietf.org/html/rfc2553" target="_blank">RFC 2553</a>. This sounds worse than it is, but it&#8217;s something you have to consider.</p>
<p><em><strong>Note</strong></em>: This post assumes you are already familiar with the socket extensions for IPv6 (<a title="IETF RFC 3493" href="http://tools.ietf.org/html/rfc3493" target="_blank">RFC 3493</a>).</p>
<p><strong>Linux and Mac</strong><br />
Good news&#8230; they both fully support <a title="IETF RFC 3493" href="http://tools.ietf.org/html/rfc3493" target="_blank">RFC 3493</a>.</p>
<p><strong>Windows</strong><br />
Windows IPv6 support varies based on which version you&#8217;re targeting. Microsoft started adding IPv6 in Windows 2000, and they&#8217;ve continued adding more of the socket extensions as time went on. Most of the core functionality is present in XP, and what&#8217;s missing is easily replaced by using Winsock calls directly (more on this later).</p>
<p>Windows gained IPv6 support while <a title="IETF RFC 2553" href="http://tools.ietf.org/html/rfc2553" target="_blank">RFC 2553</a> was still the supported standard. Since then, it has been deprecated by <a title="IETF RFC 3493" href="http://tools.ietf.org/html/rfc3493" target="_blank">RFC 3493</a>. However, Microsoft doesn&#8217;t want to break existing code written against it&#8217;s API, so the older API lives on. The main impact of this is that <code>sockaddr_in6</code> and <code>sockaddr_storage</code> are slightly different on Windows than Mac and Linux. The size of the structures across platforms is the same (the <code>sa_family_t</code> member was shortened), it&#8217;s just that the Windows structures don&#8217;t begin with the length member. For example:</p>
<pre><code>// Linux and Mac
struct sockaddr_in6 {
    uint8_t      sin6_len;    /* Added in RFC 3493 */
    sa_family_t  sin6_family;
    ...
};
struct sockaddr_storage {
    uint8_t      ss_len;      /* Added in RFC 3493 */
    sa_family_t  ss_family;
    ...
};

// Windows
struct sockaddr_in6 {
    sa_family_t  sin6_family;
    ...
};
struct sockaddr_storage {
    sa_family_t  ss_family;
    ...
};</code></pre>
<p>I&#8217;ve never had a problem with this, because the size of <code>sockaddr_in6</code> is easily determined (<code>sizeof(sockaddr_in6)</code>) and I always end up casting <code>sockaddr_storage</code> to the specific type (<code>sockaddr_in</code> or <code>sockaddr_in6</code>) based on <code>ss_family</code>.</p>
<p>Besides the data structure differences, it&#8217;s important to remember that Microsoft added IPv6 support over multiple versions. Support first appeared in Windows 2000, but more of the extensions have been added over time. Most of the core functionality was present in XP (including multicast), but not everything is implemented as of Windows 7. It&#8217;s annoying, but I will say that what&#8217;s missing is easily replaced by using Winsock calls directly.</p>
<p>Here&#8217;s the breakdown of IPv6 socket extensions by Windows version:</p>
<table border="1" width="570">
<tbody><!-- Results table headers --></p>
<tr>
<th>Socket Extension</th>
<th>2K</th>
<th>XP</th>
<th>Vista</th>
<th>7</th>
<th>Comments</th>
</tr>
<tr>
<td>if_indextoname()</td>
<td></td>
<td></td>
<td>x</td>
<td>x</td>
<td>GetAdaptersAddresses() for XP</td>
</tr>
<tr>
<td>if_nametoindex()</td>
<td></td>
<td></td>
<td>x</td>
<td>x</td>
<td>GetAdaptersAddresses() for XP</td>
</tr>
<tr>
<td>if_nameindex()</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td>GetAdaptersAddresses() (XP, later)</td>
</tr>
<tr>
<td>if_freenameindex()</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>getaddrinfo()</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
</tr>
<tr>
<td>getnameinfo()</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
</tr>
<tr>
<td>freeaddrinfo()</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
</tr>
<tr>
<td>gai_strerror()</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
</tr>
<tr>
<td>inet_pton()</td>
<td></td>
<td></td>
<td>x</td>
<td>x</td>
<td>WSAStringToAddress() (2000, XP)</td>
</tr>
<tr>
<td>inet_ntop()</td>
<td></td>
<td></td>
<td>x</td>
<td>x</td>
<td>WSAAddressToString() (2000, XP)</td>
</tr>
<tr>
<td>All IN6_IS_ADDR_* macros</td>
<td></td>
<td>x</td>
<td>x</td>
<td>x</td>
<td>Ex: IN6_IS_ADDR_LOOPBACK()</td>
</tr>
<tr>
<td>struct sockaddr_storage</td>
<td></td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
</tr>
<tr>
<td>Multicast support</td>
<td></td>
<td>x</td>
<td>x</td>
<td>x</td>
<td></td>
</tr>
</tbody>
</table>
<p>As you can see, you may still have to call Winsock directly depending on what version of Windows you are targeting. In my opinion, programming IPv6 on Windows is a lot easier if you only support XP and later, but I know that&#8217;s not always possible.</p>
<p><strong>Summary</strong></p>
<p>Modern operating systems all support IPv6. However, for business reasons, Windows has a slightly older version of the socket API which requires special consideration. My goal was to enumerate those differences to help make the transition to IPv6 smoother. Writing cross-platform code can be a fun challenge at times, but it&#8217;s also a little tedious. Hopefully, this post helps ease the pain.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/02/28/cross-platform-ipv6-socket-programming/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to Test if an Address is IPv4 or IPv6</title>
		<link>http://tdistler.com/2011/02/25/how-to-test-if-an-address-is-ipv4-or-ipv6</link>
		<comments>http://tdistler.com/2011/02/25/how-to-test-if-an-address-is-ipv4-or-ipv6#comments</comments>
		<pubDate>Fri, 25 Feb 2011 19:16:33 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[IPv6]]></category>
		<category><![CDATA[network]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=785</guid>
		<description><![CDATA[Here&#8217;s a simple function using getaddrinfo() that will take an IP address and return the address family (AF_INET for IPv4, AF_INET6 for IPv6, etc). I works on both Linux and Windows. This function will also accept hostnames and return the address family of the first address returned. You can disable this feature (and the corresponding [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a simple function using <a title="getaddrinfo man page" href="http://linux.die.net/man/3/getaddrinfo" target="_blank">getaddrinfo()</a> that will take an IP address and return the address family (<code>AF_INET</code> for IPv4, <code>AF_INET6</code> for IPv6, etc). I works on both Linux and Windows. This function will also accept hostnames and return the address family of the first address returned. You can disable this feature (and the corresponding DNS lookup) by passing the AI_NUMERICHOST flag.<br />
<code>
<pre>
// Returns the address family of an address or hostname.
// AF_INET, AF_INET6, or -1 on error.
int getaddrfamily(const char *addr)
{
    struct addrinfo hint, *info =0;
    memset(&amp;hint, 0, sizeof(hint));
    hint.ai_family = AF_UNSPEC;
    // Uncomment this to disable DNS lookup
    //hint.ai_flags = AI_NUMERICHOST;
    int ret = getaddrinfo(addr, 0, &amp;hint, &amp;info);
    if (ret)
        return -1;
    int result = info-&gt;ai_family;
    freeaddrinfo(info);
    return result;
}</pre>
<p></code></p>
<p>See <a title="IETF RFC 3493" href="http://tools.ietf.org/html/rfc3493" target="_blank">RFC 3493</a> for more information on the latest socket API for dealing with IPv6.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/02/25/how-to-test-if-an-address-is-ipv4-or-ipv6/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How To Test An Audio Codec: A Practical Approach</title>
		<link>http://tdistler.com/2011/01/25/how-to-test-an-audio-codec-a-practical-approach</link>
		<comments>http://tdistler.com/2011/01/25/how-to-test-an-audio-codec-a-practical-approach#comments</comments>
		<pubDate>Wed, 26 Jan 2011 01:16:28 +0000</pubDate>
		<dc:creator>Tom</dc:creator>
				<category><![CDATA[Code Monkey]]></category>
		<category><![CDATA[Did you know?]]></category>
		<category><![CDATA[audio]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://tdistler.com/?p=727</guid>
		<description><![CDATA[Recently, I was tasked with picking an AAC audio codec library for one of our products. There were several libraries I had to evaluate, and I needed some quantitative metrics for doing the comparison. I&#8217;m not what professionals call an &#8220;expert listener&#8221;, so I had to do the best with what I had. While creating [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://tdistler.com/wp-content/uploads/2011/01/audio_waveform.jpg"><img class="alignright size-thumbnail wp-image-732" title="audio_waveform" src="http://tdistler.com/wp-content/uploads/2011/01/audio_waveform-150x150.jpg" alt="" width="150" height="150" /></a>Recently, I was tasked with picking an AAC audio codec library for one of our products. There were several libraries I had to evaluate, and I needed some quantitative metrics for doing the comparison. I&#8217;m not what professionals call an &#8220;expert listener&#8221;, so I had to do the best with what I had. While creating my test plan, I noticed that more people seemed interested in <em>how</em> I was doing testing rather than the actual results. So I decided to share my approach to audio codec testing.</p>
<p><strong>Note</strong>: <em>This is intended to be a pragmatic guide for engineers evaluating codecs. It is not a comprehensive treatment of the subject. The goal is to give readers a solid overview and some practical ideas</em>.</p>
<p><strong>Get Familiar with Psychoacoustics</strong></p>
<p><a title="Wikipedia: Psychoacoustics" href="http://en.wikipedia.org/wiki/Psychoacoustics" target="_blank">Psychoacoustics</a> is the study of how humans <em>perceive</em> sound. As you might expect, we humans don&#8217;t process sound in a perfect, linear fashion. The physical shape of the ear, the transfer function of the Basilar membrane, and the psychological interpretation of the data all affect how we perceive sound (and by extension, how &#8220;good&#8221; an audio codec sounds to us).</p>
<p>I highly recommend you start by reading this excerpt from <a title="EETimes: Psychoacoustics Part 1" href="http://www.eetimes.com/design/audio-design/4015872/Surround-Sound-Psychoacoustics--Part-1" target="_blank">Surround Sound: Psychoacoustics Part 1, by Tomlinson Holman</a> (he created <a title="Wikipedia: THX" href="http://en.wikipedia.org/wiki/THX" target="_blank">THX</a> for Lucasfilm).</p>
<p><strong>Understand the Codec</strong></p>
<p>Make sure you understand the codec you are testing; not necessarily the implementation, but what tools (i.e. methods) the codec uses for compression. Many codecs have different &#8220;profiles&#8221;, which describe what subset of available tools are used (e.g. <a title="MPEG-4 Part 3 Audio Preview" href="http://webstore.iec.ch/preview/info_isoiec14496-3%7Bed4.0%7Den.pdf" target="_blank">AAC</a>). You should also have some idea how each compression tool works and any short-comings it has. This will help guide you in selecting reference audio samples and knowing what artifacts to listen for.</p>
<p>For an introduction to modern audio compression, read <a title="EETimes: Audio Coding: An Introduction to Data Compression Part 1" href="http://www.eetimes.com/design/audio-design/4015827/Audio-Coding-An-Introduction-to-Data-Compression--Part-1" target="_blank">Audio Coding: An Introduction to Data Compression Part 1</a>, and <a title="EETimes: Audio Coding: An Introduction to Data Compression Part 2" href="http://www.eetimes.com/design/audio-design/4015828/Audio-Coding-An-Introduction-to-Data-Compression--Part-2" target="_blank">Part 2</a> (discusses MP3 and AAC). I actually suggest buying the book <a title="Amazon" href="http://www.amazon.com/Introduction-Compression-Kaufmann-Multimedia-Information/dp/012620862X/" target="_blank">&#8220;Introduction to Data Compression&#8221;</a>, by Khalid Sayood.</p>
<p><strong>Understand the API</strong></p>
<p>Make sure you actually read the codec documentation and look at any available code samples. This step has more to do with due-diligence than anything, as I haven&#8217;t seen a codec API we couldn&#8217;t work with, but you need to do this. This will also help you scope the work required to get a working encoder/decoder for future steps (if your lucky, the sample code can be used).</p>
<p><strong>Choose the Reference Audio Samples</strong></p>
<p>An effective test requires multiple audio samples with different characteristics. There are many types of artifacts a codec can introduce, and your choice of audio samples will dictate how easy they are to detect. It&#8217;s also important to pick samples that reflect the actual types of sound the codec to have to deal with. For example, if the final system will primarily be encoding speech, then you should choose more speech-oriented references as opposed to music samples.</p>
<p>Some characteristics you might consider:</p>
<ul>
<li><strong>Transients</strong> (snare drum): Sensitive to pre-echo and noise &#8220;smearing&#8221;.</li>
<li><strong>Tonal structure</strong> (clarinet, saxophone): Sensitive to noise and &#8220;roughness&#8221;.</li>
<li><strong>Natural speech</strong> (male and female voices of various languages): Sensitive to distortion and smearing of &#8220;attacks&#8221;.</li>
<li><strong>Complex sound</strong> (bag pipes): Stresses the codec.</li>
<li><strong>High bandwidth</strong> (bag pipes): Loss of high frequencies and program-modulated high frequency noise.</li>
</ul>
<p>It is also possible to use synthetic sounds and sweeps, but this is only recommended for the automated objective tests below.</p>
<p>As a basic guideline, you need 10-25 second &#8220;raw&#8221; samples recorded at the highest sample rate your system needs to work with. It is vital that the samples you choose have never been compressed with a lossy codec (mp3, AAC, etc)&#8230; that would severally limit the quality of your test. For sample rate and size, I suggest 48kHz 16-bit PCM, but a lower rate/size makes sense if the final system is limited in this area. It also makes sense to use a sample rate of 44.1kHz, since many quality audio samples can be ripped losslessly from CD. Just keep in mind that the objective PEAQ test mentioned below requires 48kHz 16-bit PCM, so up-sampling may be required.</p>
<p>The audio samples can be stored in whatever container format you want (raw, WAV, etc) as long as your codec test application can unpack it. This is important to keep in mind&#8230; <em>you don&#8217;t want to accidentally run the WAV header through the codec</em> (yes, I&#8217;ve done this). The container format is more of a practical issue, but it was worth mentioning.</p>
<p><strong>Generate Various Test Samples and Observe CPU Load</strong></p>
<p>This step is pretty straight-forward: wrap the codec in an application and encode the reference audio samples at different bit rates. You should choose bit rates that represent the full spectrum of bit rates that will be used in the final system. While you&#8217;re encoding, track the CPU usage on the codec and how many cores it&#8217;s using. You may even want to do a separate test running many encodes in parallel (this works nicely if the CPU usage is too low to measure accurately). Make sure to consider application overhead and disk I/O when making measurements.</p>
<p>After encoding, you need to decode back to raw PCM. Clearly label your files so you know what bit rate each one was encoded with. These decoded test samples are what we will be comparing to the original reference samples.</p>
<p><strong>Do a Subjective Test</strong></p>
<p>How you conduct your subjective testing will depend on several factors, such as time constraints, cost, and the required test precision. At the low end, you could simply listen to the test samples in a pair of headphones and judge the quality yourself. For a high precision test, you could do a full <a title="ITU BS.1116" href="http://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.1116-1-199710-I!!PDF-E.pdf" target="_blank">ITU BS.1116</a> test using &#8220;expert listeners&#8221; in a controlled environment. While these examples represent the extremes, there are many permutations that can give you the desired quality of results.</p>
<p>The most common subjective test is called a &#8220;double-blind triple-stimulus with hidden reference&#8221; test. The listener hears three samples (commonly labeled A, B, and C) for a period of 10 to 25 seconds. A is always the original reference sample. The next two samples, B and C, are randomly assigned either the test sample from the codec or the original reference sample played again (called the &#8220;hidden reference&#8221;). The listener must then rate the difference between B and A, and C and A, not knowing which one is the test sample. The grading scale is:</p>
<ul>
<li>5.0 Imperceptible</li>
<li>4.0 Perceptible, but not annoying</li>
<li>3.0 Slightly annoying</li>
<li>2.0 Annoying</li>
<li>1.0 Very annoying</li>
</ul>
<p>Ideally, you would conduct several tests and average the results together. If you do the listening test yourself, your results will be limited to your listening skills and understanding of audio codec artifacts. Here&#8217;s a summary of factors that affect the quality of your results:</p>
<ul>
<li>The quality of the listener.</li>
<li>The choice of audio samples.</li>
<li>The number and duration of the testing.</li>
<li>The testing environment, including speaker/headphone quality, room design, and listener placement.</li>
<li>The quality of randomization of sample order to remove any correlation between samples.</li>
<li>Proper statistical analysis of the combined test results.</li>
</ul>
<p>A proper subjective test is both expensive and time consuming. It&#8217;s important to find the right balance for your particular needs.</p>
<p><strong>Do an Objective Test</strong></p>
<p>Evaluating a codec objectively requires testing methods that correlate well to actual human perception. You can&#8217;t simply measure the distortion introduced by the codec using traditional measurements like Signal-to-Noise ratio (S/N) and  Total-Harmonic-Distortion (THD), because they don&#8217;t correlate well to perceived audio  quality. Some distortion is imperceptible to the human ear, and codecs take advantage of this to increase the compression ratio.</p>
<p>Fortunately, the <a title="Wikipedia: International Telecommunications Union" href="http://en.wikipedia.org/wiki/International_Telecommunication_Union" target="_blank">ITU</a> has standardized an objective audio test called <a title="Wikipedia: PEAQ" href="http://en.wikipedia.org/wiki/PEAQ" target="_blank">PEAQ</a> (<a title="ITU: Perceptual Evaluation of Audio Quality" href="http://www.itu.int/dms_pubrec/itu-r/rec/bs/R-REC-BS.1387-1-200111-I!!PDF-E.pdf" target="_blank">BS.1387</a>). The acronym stands for Perceptual Evaluation of Audio Quality. PEAQ uses software to model the entire human auditory system (including blood flow noise in the inner ear) to generate a set of metrics that are used to give a final &#8220;quality&#8221; score. The original reference signal is compared to a signal run through the codec, and the result is a real number between 0.0 and -4.0. The result is interpreted on the following scale:</p>
<ul>
<li> 0.0 = Imperceptible</li>
<li>-1.0 = Perceptible but not annoying</li>
<li>-2.0 = Slightly annoying</li>
<li>-3 .0= Annoying</li>
<li>-4.0 = Very annoying</li>
</ul>
<p>Obviously, values closer to zero are better.</p>
<p>The test was developed by a similar group of audio experts that developed BS.1116 (mentioned above) and the results have been validated against a long list of subjective tests done using expert listeners.</p>
<p>There are several free and commercial software packages available for doing PEAQ tests. The best free package I&#8217;ve found is <a title="McGill: AFsp PEAQ Software" href="http://www-mmsp.ece.mcgill.ca/Documents/Software/index.html" target="_blank">AFsp</a> from the McGill Telecommunications and Signal Processing Lab. There&#8217;s also <a title="Sourceforge: peaqb" href="http://sourceforge.net/projects/peaqb/" target="_blank">peaqb</a>, but there&#8217;s a comment that it gives incorrect results. AFsp worked great in my tests and included some helpful tools like <a title="AFsp: CompAudio" href="http://www-mmsp.ece.mcgill.ca/Documents/Software/Packages/AFsp/CompAudio.html" target="_blank">CompAudio</a> and <a title="AFsp: InfoAudio" href="http://www-mmsp.ece.mcgill.ca/Documents/Software/Packages/AFsp/InfoAudio.html" target="_blank">InfoAudio</a>.</p>
<p><strong>Summary</strong></p>
<p>Hopefully this post has given you a good starting point and some practical ideas for testing audio codecs. My goal was to provide a pragmatic approach with different options depending on what your actual evaluation needs are. This is in no way a comprehensive treatment of the subject; only an overview. I highly suggest reading some of the books I referenced if you&#8217;d like a deeper treatment of the subject. Either way, I hope you found this post helpful.</p>
]]></content:encoded>
			<wfw:commentRss>http://tdistler.com/2011/01/25/how-to-test-an-audio-codec-a-practical-approach/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 0.530 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2013-05-19 09:13:12 -->
