<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>yPass.net</title>
	
	<link>http://www.ypass.net/blog</link>
	<description>Solaris, PHP, and Random Things</description>
	<lastBuildDate>Wed, 14 Apr 2010 18:06:49 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/ypass" /><feedburner:info uri="ypass" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Solaris Licensing Changes: The Real Story</title>
		<link>http://feedproxy.google.com/~r/ypass/~3/ecj-erd_34g/</link>
		<comments>http://www.ypass.net/blog/2010/04/solaris-licensing-changes-the-real-story/#comments</comments>
		<pubDate>Wed, 14 Apr 2010 17:18:15 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[Solaris]]></category>

		<guid isPermaLink="false">http://www.ypass.net/blog/?p=534</guid>
		<description><![CDATA[As you should already know, Sun was purchased by Oracle.  Not too long ago, someone noticed a licensing change on the Solaris license website.  A slow rumble of rumors has been building up about what those changes mean.  Well, I contacted our Sun account manager to get the definitive answer, and here [...]]]></description>
			<content:encoded><![CDATA[<p>As you should already know, Sun was purchased by Oracle.  Not too long ago, someone noticed a licensing change on the Solaris license website.  A slow rumble of rumors has been building up about what those changes mean.  Well, I contacted our Sun account manager to get the definitive answer, and here it is:</p>
<blockquote><ol>
<li>The old Solaris subscriptions, the way people got software support for 3rd party hardware, are no longer available for purchase.  Existing contracts are honored. </li>
<p></p>
<li>Solaris support now comes through a contract on the hardware (Oracle SUN hardware) </li>
<p></p>
<li>The license and accompanying entitlement from the web, without a contract and without hardware, only entitle the downloader to non-commercial, non-production, or personal use in perpetuity. Production use and evaluation for production are good for 90 days. </li>
<p></p>
<li>When you purchase hardware, you receive an addendum to the entitlement that grants that piece of hardware perpetual, non-transferable license and entitlement to Solaris. </li>
<p></p>
<li>For hardware purchasers, this is the same (in net effect) as always. </li>
<p></p>
<li>For non-hardware purchasers &#8211; 3rd party, gray market, etc. &#8211; there is no legal way to obtain a permanent entitlement or to obtain support.</li>
</ol>
</blockquote>
<h4>Personal Use</h4>
<p>So lets get the easy one out of the way first.  Solaris is still free for personal use.  So that should satisfy the 0.0001% (yes, that number is an anatomical extraction) of the Solaris users that use Solaris for non-commercial activity.</p>
<h4>Non-Sun Servers</h4>
<p>Let&#8217;s move on to people that run Solaris on non-Sun servers:  No Solaris for you, not yours!  Items 1 and 6 make it clear that there is no possible way to legally run Solaris on non-Sun servers.  Period.  End of story.</p>
<h4>Sun Servers without a Support Contract</h4>
<p>Now lets talk about people that run Solaris on Sun servers, but do not purchase a hardware support contract:  Some Solaris for you, but only a little!  Item 4 says (and I clarified it with them), that purchasing new Sun hardware gives you a binary license <i>only</i> for the version of Solaris that&#8217;s available at the time of the hardware purchase.  It does not entitle you to future upgrades or updates.</p>
<h4>Sun Servers with a Support Contract</h4>
<p>For people running Solaris on Sun hardware with a Sun hardware support contract, your support contract grants you rights to run future versions of Solaris.</p>
 <img src="http://www.ypass.net/blog/wp-content/plugins/feed-statistics.php?view=1&post_id=534" width="1" height="1" style="display: none;" /><img src="http://feeds.feedburner.com/~r/ypass/~4/ecj-erd_34g" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ypass.net/blog/2010/04/solaris-licensing-changes-the-real-story/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		<feedburner:origLink>http://www.ypass.net/blog/2010/04/solaris-licensing-changes-the-real-story/</feedburner:origLink></item>
		<item>
		<title>nVidia Overscan Correction fixed in Latest Drivers</title>
		<link>http://feedproxy.google.com/~r/ypass/~3/SV2Cam9t0Rc/</link>
		<comments>http://www.ypass.net/blog/2010/04/nvidia-overscan-correction-fixed-in-latest-drivers/#comments</comments>
		<pubDate>Fri, 02 Apr 2010 00:03:31 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[nvidia]]></category>
		<category><![CDATA[overscan]]></category>
		<category><![CDATA[xwindows]]></category>

		<guid isPermaLink="false">http://www.ypass.net/blog/?p=517</guid>
		<description><![CDATA[My solution for fixing overscan on nvidia cards is obsolete!  I did find out just a few days ago that my solution does actually work.
The person that I was originally helping with this problem decided to give Linux another shot.  He tested it out and reported that it did indeed fix his overscan [...]]]></description>
			<content:encoded><![CDATA[<p>My solution for <a href="http://www.ypass.net/blog/2009/07/dvi-to-hdmi-overscan-screen-edge-cutoff-on-an-hdtv/">fixing overscan on nvidia cards</a> is obsolete!  I did find out just a few days ago that my solution does actually work.</p>
<p>The person that I was originally helping with this problem decided to give Linux another shot.  He tested it out and reported that it did indeed fix his overscan problems.</p>
<p>However&#8230; for no particular reason I decided to check out the nVidia settings control panel again.  When I opened it up in Ubuntu 10.04, I noticed this (and tested it to make sure it works, which it does):</p>
<p><img src="http://www.ypass.net/blog/wp-content/uploads/2010/04/Screenshot-NVIDIA-X-Server-Settings.png" alt="Screenshot-NVIDIA X Server Settings" title="Screenshot-NVIDIA X Server Settings" width="682" height="535" class="alignnone size-full wp-image-518" /></p>
 <img src="http://www.ypass.net/blog/wp-content/plugins/feed-statistics.php?view=1&post_id=517" width="1" height="1" style="display: none;" /><img src="http://feeds.feedburner.com/~r/ypass/~4/SV2Cam9t0Rc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ypass.net/blog/2010/04/nvidia-overscan-correction-fixed-in-latest-drivers/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.ypass.net/blog/2010/04/nvidia-overscan-correction-fixed-in-latest-drivers/</feedburner:origLink></item>
		<item>
		<title>Solaris ZFS vs. Linux with Hardware Raid</title>
		<link>http://feedproxy.google.com/~r/ypass/~3/O6J-bJ-K-Po/</link>
		<comments>http://www.ypass.net/blog/2010/04/solaris-zfs-vs-linux-with-hardware-raid/#comments</comments>
		<pubDate>Thu, 01 Apr 2010 23:11:15 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Solaris]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[zfs]]></category>

		<guid isPermaLink="false">http://www.ypass.net/blog/?p=509</guid>
		<description><![CDATA[I&#8217;ve had to start using Xen virtualization for a current project we&#8217;re working on.  I always hate switching back to Linux servers because all of our fancy tools and scripts for automation are written for Solaris since we only have a handful of Linux servers.
At any rate, I&#8217;ve got Xen all figured out and [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve had to start using Xen virtualization for a current project we&#8217;re working on.  I always hate switching back to Linux servers because all of our fancy tools and scripts for automation are written for Solaris since we only have a handful of Linux servers.</p>
<p>At any rate, I&#8217;ve got Xen all figured out and really started to dig into Linux&#8217;s LVM for the first time.  There&#8217;s some similarities between LVM and ZFS, but most noticeably LVM doesn&#8217;t deal with RAID at all.  You have to set up manual Linux software RAID and put a VolumeGroup on the RAID meta-device.  So I set up a nice software RAID5 device, created a VolumeGroup, and off I went.</p>
<p>The write performance was horrendous.</p>
<p>So I begrudgingly went into the RAID controller BIOS and set up hardware RAID5 and put LVM on top of that.  After the installation, I decided to see how fast this was compared to  ZFS raid1z (which is more or less RAID5).</p>
<p>The machines are identical:</p>
<ul>
<li>Dual 6 Core Opteron</li>
<li>Sun STK RAID Controller (Adaptec) &#8212; 256MB cache, write-back cache mode enabled</li>
<li>16 Gigs of memory</li>
</ul>
<p>Here&#8217;s the results:</p>
<h4>Linux &#8212; 21GB Write</h4>
<p><code>
<pre>
# time dd if=/dev/zero of=/root/test bs=10240 count=2009600
2009600+0 records in
2009600+0 records out
20578304000 bytes (21 GB) copied, 146.226 seconds, 141 MB/s

real    2m26.377s
user    0m4.068s
sys     1m53.823s
</pre>
<p></code></p>
<h4>Linux &#8212; 1GB Write</h4>
<p><code>
<pre>
# time dd if=/dev/zero of=/root/test bs=10240 count=102400
102400+0 records in
102400+0 records out
1048576000 bytes (1.0 GB) copied, 2.69437 seconds, 389 MB/s

real    0m2.702s
user    0m0.108s
sys     0m2.584s
</pre>
<p></code></p>
<h4>Solaris &#8212; 21GB Write</h4>
<p><code>
<pre>
# time dd if=/dev/zero of=/zonepool/test bs=10240 count=2009600
2009600+0 records in
2009600+0 records out
20578304000 bytes (21 GB) copied, 55.3566 s, 372 MB/s

real    0m55.412s
user    0m0.913s
sys     0m27.012s
</pre>
<p></code></p>
<h4>Solaris &#8212; 1GB Write</h4>
<p><code>
<pre>
# time dd if=/dev/zero of=/zonepool/test bs=10240 count=102400
102400+0 records in
102400+0 records out
1048576000 bytes (1.0 GB) copied, 1.25254 s, 837 MB/s

real    0m1.257s
user    0m0.046s
sys     0m1.211s
</pre>
<p></code></p>
<p>837MB/s for burst writes on raidz1!  ZFS is too awesome.</p>
<p>Here&#8217;s the controller configurations:</p>
<p><a href="http://www.ypass.net/blog/wp-content/uploads/2010/04/linux-controller.cfg">Linux Controller Configuration</a><br />
<a href="http://www.ypass.net/blog/wp-content/uploads/2010/04/solaris-controller.cfg">Solaris Controller Configuration</a></p>
 <img src="http://www.ypass.net/blog/wp-content/plugins/feed-statistics.php?view=1&post_id=509" width="1" height="1" style="display: none;" /><img src="http://feeds.feedburner.com/~r/ypass/~4/O6J-bJ-K-Po" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ypass.net/blog/2010/04/solaris-zfs-vs-linux-with-hardware-raid/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://www.ypass.net/blog/2010/04/solaris-zfs-vs-linux-with-hardware-raid/</feedburner:origLink></item>
		<item>
		<title>Patch for the VastHTML Wordpress Forum Server</title>
		<link>http://feedproxy.google.com/~r/ypass/~3/LnqeRpIQeyw/</link>
		<comments>http://www.ypass.net/blog/2010/03/patch-for-the-vasthtml-wordpress-forum-server/#comments</comments>
		<pubDate>Wed, 03 Mar 2010 21:53:42 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[forums]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.ypass.net/blog/?p=500</guid>
		<description><![CDATA[So, I&#8217;ve made a number of fixes to the VastHTML Wordpress forum server plugin. It has some pretty big bugs, and I don&#8217;t know if the project is being maintained anymore or not.  At any rate, the fixes I&#8217;ve made should have been considered critical and should have been fixed long ago by whoever [...]]]></description>
			<content:encoded><![CDATA[<p>So, I&#8217;ve made a number of fixes to the VastHTML Wordpress forum server plugin. It has some pretty big bugs, and I don&#8217;t know if the project is being maintained anymore or not.  At any rate, the fixes I&#8217;ve made should have been considered critical and should have been fixed long ago by whoever is maintaining it, but I digress&#8230;</p>
<p>I&#8217;m not going to support people trying to apply this patch.  If you don&#8217;t know what a diff is and you don&#8217;t know what the patch command does, you&#8217;re probably out of luck.  If you want me to fix all of the problems in this code and release it, pay me a bunch of money&#8230;</p>
<p>Also, the security problems in their code makes babies cry&#8230; but that&#8217;s for another day.</p>
<p>Lastly, to make the search actually work, you need to connect to your wordpress mysql database and issue this SQL statement:</p>
<p><code>
<pre>alter table wp_forum_posts add fulltext key `text` (`text`);</code></pre>
<p>Here's the patch: <a href="http://www.ypass.net/downloads/vasthtml-forum-server/vasthtml-forum-server.diff">vasthtml-forum-server.diff</a></p>
<p>Here's what it fixes (in no particular order):</p>
<ul>
<li>RSS feeds now contain the username of the poster instead of "feeds@r.us"</li>
<li>All &amp;amp; characters in the links have been properly changed to &amp; as they should be</li>
<li>Page 2+ of your forums will work</li>
<li>Page 2+ of posts will work</li>
<li>The number of replies shown in the topic list is properly set to number of posts - 1</li>
<li>The title delimeter is changed from &raquo; to "|" (don't remember why i did this, but there ya go)</li>
<li>The search form/box uses HTTP GET instead of POST so your back button works without complaining about having to resubmit your request</li>
<li>You can press enter in the search box to submit</li>
<li>A $ followed by a number doesn't get filtered out</li>
<li>Apostrophes in posts/titles get their slashes properly stripped</li>
</ul>
<p>I may have fixed other things in this patch and forgot about it.  This works for me... your mileage may vary.</p>
 <img src="http://www.ypass.net/blog/wp-content/plugins/feed-statistics.php?view=1&post_id=500" width="1" height="1" style="display: none;" /><img src="http://feeds.feedburner.com/~r/ypass/~4/LnqeRpIQeyw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ypass.net/blog/2010/03/patch-for-the-vasthtml-wordpress-forum-server/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.ypass.net/blog/2010/03/patch-for-the-vasthtml-wordpress-forum-server/</feedburner:origLink></item>
		<item>
		<title>Threaded/Parallel Web Crawler (or Web Server Killing Software)</title>
		<link>http://feedproxy.google.com/~r/ypass/~3/IAIb_RDp1Jw/</link>
		<comments>http://www.ypass.net/blog/2010/01/threadedparallel-web-crawler-or-web-server-killing-software/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 23:47:38 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.ypass.net/blog/?p=494</guid>
		<description><![CDATA[Short Version

Parallel URL Fetcher &#8211; If you want to put load on a webserver by crawling it, this is what you&#8217;re looking for.  No java, no python, just a nice small, fast C program.
Long Version

It&#8217;s time to re-evaluate our HTTP caching software.  At present we use Apache mod_cache (disk cache) and we&#8217;ve run [...]]]></description>
			<content:encoded><![CDATA[<p><b>Short Version</b></p>
<hr />
<a href="http://puf.sourceforge.net/" target="_blank">Parallel URL Fetcher</a> &#8211; If you want to put load on a webserver by crawling it, this is what you&#8217;re looking for.  No java, no python, just a nice small, fast C program.</p>
<p><b>Long Version</b></p>
<hr />
It&#8217;s time to re-evaluate our HTTP caching software.  At present we use Apache mod_cache (disk cache) and we&#8217;ve run into some problems.</p>
<p>Apache mod_cache + ZFS + millions of URLs and hundreds of gigs of cache files = bad</p>
<p>I&#8217;m not sure which of these guys is the culprit in this one.  But I do know that when the ZFS dataset holding Apache&#8217;s cache gets to a certain size, disk I/O requests go through the roof.  By clearing the cache (and freeing up that I/O), we see a good 5%-10% (extremely significant) jump in traffic.</p>
<p>At any rate, this prompted us to start looking into alternatives to Apache.  The obvious first choice is Squid in accelerator mode.  So I got Squid all set up in our offline datacenter, fixed the little things, and was ready the beat the crap out of it with web requests.</p>
<p>I can easily request <i>all</i> of our 500k+ &#8220;static&#8221; URLs, but those pesky URLs with arguments aren&#8217;t quite that easy.  I needed a crawler.  Something like <b>wget &#8211;mirror</b> but much, much, much faster.</p>
<p>After a <i>lot</i> of searching, I found a few python apps that failed to compile on Solaris, had deprecated/old dependencies, required specific python, etc.  Python is starting to feel more and more like Java.  Either the developers are horrible or the language interpreter is too picky to work properly (think&#8230;. JRE 1.2.5 build 1482????  no no no, you need build 1761!!!).</p>
<p>Speaking of Java, I also found a Java app (<a href="http://jcrawler.sourceforge.net/" target="_blank">JCrawler</a>) that looked perfect for what I needed.  It certainly claimed to be &#8220;perfect.&#8221;  It actually worked better than the Python apps that failed to build/run properly, but it didn&#8217;t actually work.  It just kept spawning threads until it ran out of memory.</p>
<p>I was almost to the point where I thought I would have to write one myself, until I clicked on a link and a bright light from the heavens shone down on my monitor and a choir started singing in the background.</p>
<p>I had found the <a href="http://puf.sourceforge.net/" target="_blank">Parallel URL Fetcher</a>.  It was <i>exactly</i> what I needed.  It was like wget, but ran parallel requests.  It didn&#8217;t compile on Solaris either, but adding timeradd() and timersub() macros fixed that real quick.</p>
<p>I don&#8217;t think it supports Keep-Alive requests either, which would have been nice, but either way it rocked through some URLs.  After letting it run for a few hours, I had my Squid server maxed out at 100Gigs of cache and ready for some I/O testing.</p>
 <img src="http://www.ypass.net/blog/wp-content/plugins/feed-statistics.php?view=1&post_id=494" width="1" height="1" style="display: none;" /><img src="http://feeds.feedburner.com/~r/ypass/~4/IAIb_RDp1Jw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ypass.net/blog/2010/01/threadedparallel-web-crawler-or-web-server-killing-software/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.ypass.net/blog/2010/01/threadedparallel-web-crawler-or-web-server-killing-software/</feedburner:origLink></item>
		<item>
		<title>PCM Audio | Part 3: Basic Audio Effects – Volume Control</title>
		<link>http://feedproxy.google.com/~r/ypass/~3/DHxLfCqM9yQ/</link>
		<comments>http://www.ypass.net/blog/2010/01/pcm-audio-part-3-basic-audio-effects-volume-control/#comments</comments>
		<pubDate>Tue, 12 Jan 2010 04:22:28 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[audio]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.ypass.net/blog/?p=464</guid>
		<description><![CDATA[So now we know what data is stored in a PCM stream, let&#8217;s look at some real waveform examples.  The easiest is a simple sine wave:

Now if we &#8220;amplify&#8221; that wave by 5, we&#8217;d get a much louder sound, represented by a wave that looked like this:

So if you want to increase the volume [...]]]></description>
			<content:encoded><![CDATA[<p>So now we know what data is stored in a PCM stream, let&#8217;s look at some real waveform examples.  The easiest is a simple sine wave:</p>
<p><img src="http://www.ypass.net/blog/wp-content/uploads/2010/01/sinewave1-300x300.png" alt="sine wave" title="sine wave" width="300" height="300" class="alignnone size-medium wp-image-465" /></p>
<p>Now if we &#8220;amplify&#8221; that wave by 5, we&#8217;d get a much louder sound, represented by a wave that looked like this:</p>
<p><img src="http://www.ypass.net/blog/wp-content/uploads/2010/01/sinewave2-300x300.png" alt="sine wave times 10" title="sine wave times 10" width="300" height="300" class="alignnone size-medium wp-image-467" /></p>
<p>So if you want to increase the volume of your PCM stream, just multiply every PCM value by some number.  If we had 2048 <b>bytes</b> of audio (remember&#8230; that&#8217;s 1024 samples since each sample is two bytes), we could amplify the stream with this type of code:</p>
<p><code>
<pre>int16_t pcm[1024] = read in some pcm data;
for (ctr = 0; ctr < 1024; ctr++) {
    pcm[ctr] *= 2;
}</pre>
<p></code></p>
<p>Volume control is <i>almost</i> that simple.  There's two catches.</p>
<h4>Clipping</h4>
<p>Clipping occurs when your resulting value increases above the maximum value for a sample.  So since we're dealing with signed 16 bit integers our maximum positive sample is 32767.  If we have a PCM sample value of 5000 and we multiplied it by 10, the resulting value is -15536, not the expected 50000.  When clipping occurs, you end up with noise in the audio.  You should always check to see if the result of your multiplication would cause clipping, and if so, set the value to 32767 (or -32768) instead.</p>
<p>So our code above becomes:</p>
<p><code>
<pre>int16_t pcm[1024] = read in some pcm data;
int32_t pcmval;
for (ctr = 0; ctr < 1024; ctr++) {
    pcmval = pcm[ctr] * 2;
    if (pcmval < 32767 &#038;&#038; pcmval > -32768) {
        pcm[ctr] = pcmval
    } else if (pcmval > 32767) {
        pcm[ctr] = 32767;
    } else if (pcmval < -32768) {
        pcm[ctr] = -32768;
    }
}</pre>
<p></code></p>
<h4>Volume Is Logarithmic</h4>
<p>The other catch is that volume as perceived by humans (measured in decibels) is logarithmic, not linear.  Your first instinct would be to think "Well if I wanted to double the volume, I should just multiply the samples by 2."  Unfortunately, it's not quite that easy.</p>
<p>Multiplying a value by 1 will obviously give you no amplification.  So to decrease volume, you would multiply by a value less than 1 and greater than 0.  To increase volume, multiply by a number greater than one.  Unfortunately, I didn't pay enough attention to logarithms in school, so I don't have a clever answer as to how to implement a proper volume control, but I've found that this function works pretty well:</p>
<p><code>
<pre>int some_level;
float multiplier = tan(some_level/100.0);
</pre>
<p></code></p>
<p>If some_level is set to a value between 0 and 148 or so, this will give you a rather linear sounding multiplier.    79 is almost a multiplier of 1 (no amplification).   It is far -- really far -- from perfect, but it worked well enough for my needs of implementing a volume slider.  Graphing that function from 0 to 148 gives you this:</p>
<p><img src="http://www.ypass.net/blog/wp-content/uploads/2010/01/logvolume1-300x300.png" alt="volume multiplier" title="volume multiplier" width="300" height="300" class="alignnone size-medium wp-image-476" /></p>
<p>So to set an appropriate level, now we have a volume slider at 39 (roughly half volume):</p>
<p><code>
<pre>int16_t pcm[1024] = read in some pcm data;
int32_t pcmval;
uint8_t level = 39; // half as loud
// uint8_t level = 118 // twice as loud (79 * 1.5)
float multiplier = tan(level/100.0);
for (ctr = 0; ctr < 1024; ctr++) {
    pcmval = pcm[ctr] * multiplier;
    if (pcmval < 32767 &#038;&#038; pcmval > -32768) {
        pcm[ctr] = pcmval
    } else if (pcmval > 32767) {
        pcm[ctr] = 32767;
    } else if (pcmval < -32768) {
        pcm[ctr] = -32768;
    }
}</pre>
<p></code></p>
<p>I wasn't able to find a simple logarithmic slider example, so if you have one, <b>please</b> post in the comments.  I'd love to replace my hack.</p>
<p>Using some simple algorithms and that function above, you could easily implement a fade-in/out effect on PCM data by stepping through all 148 possible values over a period of time.  And don't worry, we'll get to "time" later in the series.</p>
<p>That's pretty much all there is to know about volume, in the next part of the series, we're going to discuss mixing two streams together to create one stream.</p>
 <img src="http://www.ypass.net/blog/wp-content/plugins/feed-statistics.php?view=1&post_id=464" width="1" height="1" style="display: none;" /><img src="http://feeds.feedburner.com/~r/ypass/~4/DHxLfCqM9yQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ypass.net/blog/2010/01/pcm-audio-part-3-basic-audio-effects-volume-control/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.ypass.net/blog/2010/01/pcm-audio-part-3-basic-audio-effects-volume-control/</feedburner:origLink></item>
		<item>
		<title>PCM Audio | Part 2: What does a PCM stream look like?</title>
		<link>http://feedproxy.google.com/~r/ypass/~3/AI40EHJpgjc/</link>
		<comments>http://www.ypass.net/blog/2010/01/pcm-audio-part-2-what-does-a-pcm-stream-look-like/#comments</comments>
		<pubDate>Sat, 09 Jan 2010 20:55:31 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[audio]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.ypass.net/blog/?p=451</guid>
		<description><![CDATA[In Part 1, we looked at how a PCM stream is described.  Once you know all of the parameters for your PCM stream, we can examine the data and put it in memory as useful data.
So, let&#8217;s assume we have a file that contains signed 16-bit little endian mono PCM.  That means that [...]]]></description>
			<content:encoded><![CDATA[<p>In Part 1, we looked at <a href="http://www.ypass.net/blog/2010/01/pcm-audio-part-1-what-is-pcm/">how a PCM stream is described</a>.  Once you know all of the parameters for your PCM stream, we can examine the data and put it in memory as useful data.</p>
<p>So, let&#8217;s assume we have a file that contains signed 16-bit little endian mono PCM.  That means that data in the file is just a collection of 16 bit integers.  Each integer represents one sample.  So the first 9 samples in the file could be:</p>
<pre>
+------+------+------+------+------+------+------+------+------+
|  500 |  300 | -100 | -20  | -300 |  900 | -200 |  -50 |  250 |
+------+------+------+------+------+------+------+------+------+
</pre>
<p>Each of those integers is stored in the file as 2 bytes (16-bit), so the 9 samples above take up 18 bytes of space.  The value of each sample, obviously, can range from -32768 to 32767.  If you take those samples and plot them on a graph, you&#8217;ll end up with a visualization of the waveform for the audio that you see in your music player.</p>
<p>If we wanted to read that into an array in C, we would do something like this (obviously this is pseudo-code):</p>
<p>FILE *pcmfile<br />
int16_t *pcmdata;<br />
pcmfile = fopen(your pcm data file);<br />
pcmdata = malloc(size of the file);<br />
fread(pcmdata, sizeof(int16_t), size of file / sizeof(int16_t), pcmfile);</p>
<p>Of course, if you&#8217;re dealing with large files, you probably shouldn&#8217;t read the whole thing into memory.  You should buffer the data and read it in chunks at a time.</p>
<p>If you take that data and send it to your sound card, you&#8217;ll hear the sample being played.  However, the sound card will require you to know the sample rate.  If you have an 8kHz stream and tell the sound card to play it at 16kHz, it&#8217;s like playing a 33.3 RPM record at 45 RPM.  For the younger crowd out there, that means it will be too fast and it&#8217;ll be high pitched&#8230; think Alvin and the Chipmunks here.</p>
<p>Since this is a description of the waveform, a stream of all zeros would be silence (a flat line if you graphed it).</p>
<p>I haven&#8217;t really explained what those samples actually MEAN though&#8230; just what they are.  It will be incredibly obvious what those samples mean starting in the next post, when we get to the fun stuff: <a href="http://www.ypass.net/blog/2010/01/pcm-audio-part-3-basic-audio-effects-volume-control/">basic audio effects processing</a> (don&#8217;t get scared&#8230; it&#8217;s actually really easy).</p>
 <img src="http://www.ypass.net/blog/wp-content/plugins/feed-statistics.php?view=1&post_id=451" width="1" height="1" style="display: none;" /><img src="http://feeds.feedburner.com/~r/ypass/~4/AI40EHJpgjc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ypass.net/blog/2010/01/pcm-audio-part-2-what-does-a-pcm-stream-look-like/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.ypass.net/blog/2010/01/pcm-audio-part-2-what-does-a-pcm-stream-look-like/</feedburner:origLink></item>
		<item>
		<title>PCM Audio | Part 1: What is PCM?</title>
		<link>http://feedproxy.google.com/~r/ypass/~3/CV1YZ291HoM/</link>
		<comments>http://www.ypass.net/blog/2010/01/pcm-audio-part-1-what-is-pcm/#comments</comments>
		<pubDate>Fri, 08 Jan 2010 23:37:39 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[audio]]></category>
		<category><![CDATA[c]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.ypass.net/blog/?p=444</guid>
		<description><![CDATA[It&#8217;s been a long time since I posted anything.  Most of my free time has been spent working on my ventrilo client for linux project.  Of course, that project adds tons of things to discuss, such as how PCM audio works.  I&#8217;m going to make this a multi-part series, because there is [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been a long time since I posted anything.  Most of my free time has been spent working on my <a href="http://www.mangler.org/">ventrilo client for linux</a> project.  Of course, that project adds tons of things to discuss, such as how PCM audio works.  I&#8217;m going to make this a multi-part series, because there is so much information to discuss.</p>
<p>When I first started working on that project, I knew nothing about how audio worked.  I knew a little bit about encoders and decoders, but not really the inner workings.  What are they encoding/decoding?  It turns out, that the answer is PCM (pulse control modulation) audio.  After messing with PCM for a few months, there are a lot of things that are painfully obvious now that were confusing.  This guide is meant to be an introduction to at least give you the working knowledge you&#8217;ll need to ask proper questions and perform simple tasks.  So let&#8217;s get started&#8230;</p>
<p>If you&#8217;ve ever used a computer MP3 player, you&#8217;ve probably seen those options to display the waveform of the audio or the little bars that pop up and down showing you treble and bass levels.  What those are measuring is the PCM audio as it plays it.  So what does all that crap mean?</p>
<p>Let&#8217;s start with the basics.  There&#8217;s five terms that are important to know for PCM:</p>
<h4>Sample Rate</h4>
<p>Real actual audio (like someone talking to you in person) is transmitted as a wave.  PCM is a digital representation of that audio wave at a specified <b>sample rate</b>.  The sample rate is measured in Hz (cycles per second) and more often in kilohertz.  So when you hear someone talk about about 128kHz vs. 160kHz audio, what they&#8217;re talking about is the <b>sample rate</b>.  If you&#8217;ve ever done integrals in calculus, it&#8217;s a lot like that.  The higher the sample rate, the better your quality (at the cost of size).  There is no guessing here.  You need to know what the sample rate is.</p>
<h4>Sign</h4>
<p>Whether the data is signed or unsigned.  It is almost always signed.  Treating a signed PCM stream as unsigned will hurt your ears&#8230; painfully&#8230; (I speak from experience here).</p>
<h4>Sample Size</h4>
<p>This determines how many bits make up one sample.  16-bit seems to be the most common.</p>
<h4>Byte Ordering</h4>
<p>Byte ordering refers to little-endian vs. big-endian data.  If you don&#8217;t know what endian-ness means, you can probably assume little endian.  If you have the option to choose endian for your data, you should always choose little-endian.</p>
<h4>Number of channels</h4>
<p>I&#8217;m mostly going to cover mono (1 channel), but multichannel PCM is usually handled by interleaving the PCM samples.  Don&#8217;t worry about this for now.  Once you understand mono, stereo is easy.</p>
<p>Add those five things together and you&#8217;ll come up with a description of a PCM stream.  For example: signed 16-bit little-endian mono @ 44.1kHz.  In order to actually <i>play</i> audio, you&#8217;ll need to know those 5 things.</p>
<p>Various sound devices support various types of streams, but there&#8217;s usually a set list of sign, sample size, and endian-ness options.  Different APIs use different constants to specify, but usually you&#8217;ll see them as something like S16LE (signed 16-bit little-endian) or S32BE (signed 32-bit big-endian) and so on.</p>
<p>In my next post, I&#8217;ll go over <a href="http://www.ypass.net/blog/2010/01/pcm-audio-part-2-what-does-a-pcm-stream-look-like/">how those are represented in a PCM stream</a>.</p>
 <img src="http://www.ypass.net/blog/wp-content/plugins/feed-statistics.php?view=1&post_id=444" width="1" height="1" style="display: none;" /><img src="http://feeds.feedburner.com/~r/ypass/~4/CV1YZ291HoM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ypass.net/blog/2010/01/pcm-audio-part-1-what-is-pcm/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.ypass.net/blog/2010/01/pcm-audio-part-1-what-is-pcm/</feedburner:origLink></item>
		<item>
		<title>Netflix on the PS3</title>
		<link>http://feedproxy.google.com/~r/ypass/~3/6nALs6GoB7I/</link>
		<comments>http://www.ypass.net/blog/2009/10/netflix-on-the-ps3/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 05:30:09 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[PlayStation3]]></category>
		<category><![CDATA[movies]]></category>
		<category><![CDATA[ps3]]></category>
		<category><![CDATA[streaming]]></category>
		<category><![CDATA[video]]></category>

		<guid isPermaLink="false">http://www.ypass.net/blog/?p=438</guid>
		<description><![CDATA[I would be remiss to not have a blog post about Netflix on the PS3.  As much as I post about streaming video to the PS3 and as much as I love Netflix, I can&#8217;t resist chiming in on this one.
First of all, I don&#8217;t care what the CEO of Netflix says, but having [...]]]></description>
			<content:encoded><![CDATA[<p>I would be remiss to not have a blog post about Netflix on the PS3.  As much as I post about streaming video to the PS3 and as much as I love Netflix, I can&#8217;t resist chiming in on this one.</p>
<p>First of all, I don&#8217;t care what the CEO of Netflix says, but having to put in a disc to stream movies sucks.  The streaming app should be an installable application that sits on the XMB.</p>
<p>It&#8217;s not a matter of being lazy, it is a matter of convenience.  Back on the PS2, when I started working on streaming video to Sony devices using BroadQ (oh yeah&#8230; btw, i&#8217;ve been working on this for about 6 or 7 years now), it was annoying to have to load in the BroadQ disc to stream the movies.  I can&#8217;t imagine it will be any less annoying 7 years later when the system has a hard drive that is perfectly capable of storing the application.</p>
<p>That said, I&#8217;m excited this is finally happening.  There&#8217;s little doubt that Microsoft opened up the checkbook to prevent interoperability.  Netflix will be available for the PS3 almost exactly one year after XBox.  For games, I can understand these exclusive agreements.  For third party services such as Netflix, I think it&#8217;s a dick move on Microsoft&#8217;s part.  I view it as yet another good reason not to support their console.</p>
<p>As a Netflix subscriber, I think it&#8217;s a bad move by both Netflix and Microsoft.  This should have happened long ago.</p>
 <img src="http://www.ypass.net/blog/wp-content/plugins/feed-statistics.php?view=1&post_id=438" width="1" height="1" style="display: none;" /><img src="http://feeds.feedburner.com/~r/ypass/~4/6nALs6GoB7I" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ypass.net/blog/2009/10/netflix-on-the-ps3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.ypass.net/blog/2009/10/netflix-on-the-ps3/</feedburner:origLink></item>
		<item>
		<title>Safari User Agent Strings Are Dumb</title>
		<link>http://feedproxy.google.com/~r/ypass/~3/n8aztF05ZH4/</link>
		<comments>http://www.ypass.net/blog/2009/10/safari-user-agent-strings-are-dumb/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 16:50:15 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.ypass.net/blog/?p=432</guid>
		<description><![CDATA[Sometimes it&#8217;s hard to decide which company is worse: Apple or Microsoft.  Apple&#8217;s web browser, Safari, has the dumbest User-Agent of any browser out there.  Opera, Firefox, and even MSIE figured out how to do it correctly.  You&#8217;d think Apple would be able to figure it out, too.
Generally, people want to know [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes it&#8217;s hard to decide which company is worse: Apple or Microsoft.  Apple&#8217;s web browser, Safari, has the dumbest User-Agent of any browser out there.  Opera, Firefox, and even MSIE figured out how to do it correctly.  You&#8217;d think Apple would be able to figure it out, too.</p>
<p>Generally, people want to know the major revision of a browser.  The minor revision is <i>usually</i> not important since most of the time these are just used for reporting statistics.  Well, as I&#8217;m here setting up a piece software that does simple string searches in the user-agent to determine browser version, I got hung up on Safari.  Here&#8217;s a basic mapping of User-Agent search terms to corresponding browser versions:</p>
<p><code>
<pre>
opera6 opera/6
opera6 opera 6
opera7 opera/7
opera7 opera 7
galeon1 galeon/1
explorer3 msie 3.
explorer4 msie 4.
explorer5 msie 5.
explorer6 msie 6.
explorer7 msie 7.
explorer8 msie 8.
konqueror2 konqueror/2
konqueror3 konqueror/3
netscape6 netscape6
netscape7 netscape/7
netscape4 mozilla/4
netscape3 mozilla/3
firefox1 firefox/1
firefox2 firefox/2
<b>safari1 safari/1
safari1 safari/85
safari1 safari/3
safari2 safari/4
safari4 safari/5</b>
chrome chrome/0
</pre>
<p></code></p>
<p>So check out those Safari searches.  The reason they look that way is because Safari doesn&#8217;t report it&#8217;s version number as Safari/X.  Where there <i>should</i> be a major version number is a WebKit build number or some other useless value.  Safari does put the actual version into the User-Agent string, but does it in such a fashion that you either need multiple string searches or regex to figure it out.  Check out some Safari User-Agent strings:</p>
<p><code>
<pre>
Safari 3.1.2:
Mozilla/5.0 (...) AppleWebKit/525.18 (KHTML, like Gecko) Version/3.1.2 Safari/525.20.1

Safari 4:
Mozilla/5.0 (...) AppleWebKit/531.9 (KHTML, like Gecko) Version/4.0.3 Safari/531.9
</pre>
<p></code></p>
<p>So by matching Safari/5, you&#8217;re actually going to end up with either Safari 3.x or Safari 4.x.  Or you could search for &#8220;Safari&#8221; and then search for &#8220;Version/X.&#8221;  Or you could regex search for &#8220;/Version\/4.*Safari/&#8221;  Of course, this software I&#8217;m configuring doesn&#8217;t support either of those methods because only a mind-bogglingly stupid browser maker would use this format in their User-Agent string.</p>
<p>Oh, and if you&#8217;re wondering why Safari/85 matches Safari 1.x, here&#8217;s some 1.x User-Agents:</p>
<p><code>
<pre>
Mozilla/5.0 (...) AppleWebKit/85.8.5 (KHTML, like Gecko) Safari/85.8.1
Mozilla/5.0 (...) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12
Mozilla/5.0 (...) AppleWebKit/312.1 (KHTML, like Gecko) Safari/312
</code></pre>
 <img src="http://www.ypass.net/blog/wp-content/plugins/feed-statistics.php?view=1&post_id=432" width="1" height="1" style="display: none;" /><img src="http://feeds.feedburner.com/~r/ypass/~4/n8aztF05ZH4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.ypass.net/blog/2009/10/safari-user-agent-strings-are-dumb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.ypass.net/blog/2009/10/safari-user-agent-strings-are-dumb/</feedburner:origLink></item>
	</channel>
</rss>
