<?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>BIT-101</title>
	<atom:link href="http://www.bit-101.com/blog/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.bit-101.com/blog</link>
	<description>Bill Gates Touched My Mac Book Pro</description>
	<lastBuildDate>Thu, 29 Jul 2010 16:46:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>New Kindle, Interview with Jeff Bezos</title>
		<link>http://www.bit-101.com/blog/?p=2707</link>
		<comments>http://www.bit-101.com/blog/?p=2707#comments</comments>
		<pubDate>Thu, 29 Jul 2010 04:14:59 +0000</pubDate>
		<dc:creator>keith</dc:creator>
				<category><![CDATA[Kindle]]></category>

		<guid isPermaLink="false">http://www.bit-101.com/blog/?p=2707</guid>
		<description><![CDATA[So the rumors were true. A new Kindle was announced today. I ordered mine within minutes of it being possible to do so. While more evolutionary than revolutionary, it&#8217;s got some nice features: smaller size (with same screen size), one month battery, double storage size, improved contrast, etc. You can read all about it on [...]]]></description>
			<content:encoded><![CDATA[<p>So the rumors were true. A new Kindle was announced today.</p>
<p><a href="http://www.bit-101.com/blog/wp-content/uploads/2010/07/big-viewer-3G-01-lrg._V188696038_.jpg"><img src="http://www.bit-101.com/blog/wp-content/uploads/2010/07/big-viewer-3G-01-lrg._V188696038_.jpg" alt="" title="big-viewer-3G-01-lrg._V188696038_" width="450" height="630" class="alignnone size-full wp-image-2708" /></a></p>
<p>I ordered mine within minutes of it being possible to do so. While more evolutionary than revolutionary, it&#8217;s got some nice features: smaller size (with same screen size), one month battery, double storage size, improved contrast, etc. <a href="http://www.amazon.com/Kindle-Wireless-Reading-Display-Graphite/dp/B002Y27P3M/ref=amb_link_353611822_2?pf_rd_m=ATVPDKIKX0DER&#038;pf_rd_s=gateway-center-column&#038;pf_rd_r=1GGEVZ7JSNHTGSAXYPA2&#038;pf_rd_t=101&#038;pf_rd_p=1271001842&#038;pf_rd_i=507846">You can read all about it on its own site</a>. </p>
<p>More importantly though, I just watched the Jeff Bezos interview on Charlie Rose tonight. From the few times I&#8217;ve seen Jeff speak, he&#8217;s really impressed me. Three things he said today that, to me, got at the crux of why the Kindle is so good.</p>
<p>First, talking about iPad vs. Kindle and the design of the Kindle, saying people, <em>&#8220;want a purpose built device where no trade offs have been made, where every single design decision as you&#8217;re walking down the process has been made to optimize for reading.&#8221;</em> Very true. This idea not only differentiates the Kindle from the iPad, but also from the Nook. From reviews and testing one in the store, the Nook&#8217;s interface is just plain more complicated than the Kindle. The Nook chose gimmicks like the (relatively useless) color touch screen, where the Kindle tried to make its UI disappear.</p>
<p>This moved right into the whole e-ink display and the ease of reading, as well as the specific size and form factor of the Kindle, he talked about the idea of &#8220;long-form reading&#8221; and &#8220;short-form reading&#8221;, saying, <em>&#8220;Most of the devices that have been developed by we humans over the last couple of decades have tilted the world towards short-form reading. So, Internet connected computers and smart phones and so on are great for short email messages, they&#8217;re great for blog posts. They&#8217;re not great for 300 page books.&#8221;</em></p>
<p>Finally, the kicker, what it&#8217;s really all about: <strong><em>&#8220;We&#8217;re not trying to create an experience. We want the author to create the experience.&#8221;</em></strong> Bingo.</p>
<p>The link to the Bezos interview is<del datetime="2010-07-29T16:45:21+00:00">n&#8217;t up yet, but should be on this page when available</del>: <a href="http://www.charlierose.com/guest/view/2618">http://www.charlierose.com/guest/view/2618</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bit-101.com/blog/?feed=rss2&amp;p=2707</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AS3 Sound Synthesis IV &#8211; Tone Class</title>
		<link>http://www.bit-101.com/blog/?p=2681</link>
		<comments>http://www.bit-101.com/blog/?p=2681#comments</comments>
		<pubDate>Fri, 23 Jul 2010 09:30:38 +0000</pubDate>
		<dc:creator>keith</dc:creator>
				<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[Flash]]></category>

		<guid isPermaLink="false">http://www.bit-101.com/blog/?p=2681</guid>
		<description><![CDATA[In order to make the code so far a little more reusable, I moved it over into its own class, called Tone. I also implemented some optimizations and other little tricks. The most important is that instead of calculating the next batch of samples along with the envelope on every SAMPLE_DATA event, I precalculate all [...]]]></description>
			<content:encoded><![CDATA[<p>In order to make the code so far a little more reusable, I moved it over into its own class, called Tone. I also implemented some optimizations and other little tricks. The most important is that instead of calculating the next batch of samples along with the envelope on every SAMPLE_DATA event, I precalculate all the samples within the envelope right up front, storing it in a Vector of Numbers. Here&#8217;s the class:</p>
<p>[as3]package<br />
{<br />
	import flash.media.Sound;<br />
	import flash.events.SampleDataEvent;<br />
	import flash.events.Event;</p>
<p>	public class Tone<br />
	{<br />
		protected const RATE:Number = 44100;<br />
		protected var _position:int = 0;<br />
		protected var _sound:Sound;<br />
		protected var _numSamples:int = 2048;<br />
		protected var _samples:Vector.<number>;<br />
		protected var _isPlaying:Boolean = false;</p>
<p>		protected var _frequency:Number;</p>
<p>		public function Tone(frequency:Number)<br />
		{<br />
			_frequency = frequency;<br />
			_sound = new Sound();<br />
			_sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);<br />
			_samples = new Vector.<number>();<br />
			createSamples();<br />
		}</p>
<p>		protected function createSamples():void<br />
		{<br />
			var amp:Number = 1.0;<br />
			var i:int = 0;<br />
			var mult:Number = frequency / RATE * Math.PI * 2;<br />
			while(amp > 0.01)<br />
			{<br />
				_samples[i] = Math.sin(i * mult) * amp;<br />
				amp *= 0.9998;<br />
				i++;<br />
			}<br />
			_samples.length = i;<br />
		}</p>
<p>		public function play():void<br />
		{<br />
			if(!_isPlaying)<br />
			{<br />
				_position = 0;<br />
				_sound.play();<br />
				_isPlaying = true;<br />
			}<br />
		}</p>
<p>		protected function onSampleData(event:SampleDataEvent):void<br />
		{<br />
			for (var i:int = 0; i < _numSamples; i++)<br />
			{<br />
				if(_position >= _samples.length)<br />
				{<br />
					_isPlaying = false;<br />
					return;<br />
				}<br />
				event.data.writeFloat(_samples[_position]);<br />
				event.data.writeFloat(_samples[_position]);<br />
				_position++;<br />
			}<br />
		}</p>
<p>		public function set frequency(value:Number):void<br />
		{<br />
			_frequency = value;<br />
			createSamples();<br />
		}<br />
		public function get frequency():Number<br />
		{<br />
			return _frequency;<br />
		}<br />
	}<br />
}[/as3]</p>
<p>Note that in the constructor I call createSamples(). This creates the Vector with all samples needed for the duration of the note, including the amplitude of the pseudo-envelope. In the frequency setter, the samples are re-created. The result is that in the onSampleData handler method, I just fill up the byte array with the next so many values out of the _samples vector, stopping when I reach the end of that Vector.</p>
<p>Note also that the amplitude is decreased per sample, rather than per SAMPLE_DATA event, thus it needs to be reduced by a much smaller amount each time. This should also give a smoother envelope, though I&#8217;m not sure how noticeable it is.</p>
<p>Here&#8217;s a brief bit of code that shows it in action:</p>
<p>[as3]import flash.events.MouseEvent;</p>
<p>var tone:Tone = new Tone(800);<br />
stage.addEventListener(MouseEvent.CLICK, onClick);<br />
function onClick(event:MouseEvent):void<br />
{<br />
	tone.frequency = 300 + mouseY;<br />
	tone.play();<br />
}[/as3]</p>
<p>It creates a tone. Whenever you click on the stage, it calculates a new frequency for the tone based on the y position of the mouse and plays the tone. Simple enough.</p>
<p>I don&#8217;t consider this class anywhere near &#8220;complete&#8221;. Just a beginning evolution in something. I&#8217;d like to add support for more flexible and/or complex envelopes, a stop method, and some other parameters to change the sound. But even so, this is relatively useful as is, IMHO.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bit-101.com/blog/?feed=rss2&amp;p=2681</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>AS3 Sound Synthesis III &#8211; Visualization and Envelopes</title>
		<link>http://www.bit-101.com/blog/?p=2675</link>
		<comments>http://www.bit-101.com/blog/?p=2675#comments</comments>
		<pubDate>Thu, 22 Jul 2010 02:00:52 +0000</pubDate>
		<dc:creator>keith</dc:creator>
				<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[Flash]]></category>

		<guid isPermaLink="false">http://www.bit-101.com/blog/?p=2675</guid>
		<description><![CDATA[In Part I and Part II of this series, we learned how to utilize the Sound object to synthesize sound, and how to create sounds of various frequencies. This post will just be a quick detour onto a couple of tricks you can implement. The first one is visualizing the wave you are playing. In [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://www.bit-101.com/blog/?p=2660">Part I</a> and <a href="http://www.bit-101.com/blog/?p=2669">Part II</a> of this series, we learned how to utilize the Sound object to synthesize sound, and how to create sounds of various frequencies. This post will just be a quick detour onto a couple of tricks you can implement.</p>
<p>The first one is visualizing the wave you are playing. In the SAMPLE_DATA event handler, you are already generating 2048 samples to create a wave form. While you&#8217;re creating these, it&#8217;s a piece of cake to go ahead and draw some lines based on their values. Look here:</p>
<p>[as3]import flash.media.Sound;<br />
import flash.events.SampleDataEvent;<br />
import flash.events.MouseEvent;<br />
import flash.utils.Timer;<br />
import flash.events.TimerEvent;</p>
<p>var position:int = 0;<br />
var n:Number = 0;<br />
var sound:Sound = new Sound();<br />
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);<br />
sound.play();</p>
<p>function onSampleData(event:SampleDataEvent):void<br />
{<br />
	graphics.clear();<br />
	graphics.lineStyle(0, 0&#215;999999);<br />
	graphics.moveTo(0, stage.stageHeight / 2);<br />
	for(var i:int = 0; i < 2048; i++)<br />
	{<br />
		var phase:Number = position / 44100 * Math.PI * 2;<br />
		position ++;<br />
		var sample:Number = Math.sin(phase * 440 * Math.pow(2, n / 12));<br />
		event.data.writeFloat(sample); // left<br />
		event.data.writeFloat(sample); // right<br />
		graphics.lineTo(i / 2048 * stage.stageWidth, stage.stageHeight / 2 - sample * stage.stageHeight / 8);<br />
	}<br />
}</p>
<p>var timer:Timer = new Timer(500);<br />
timer.addEventListener(TimerEvent.TIMER, onTimer);<br />
timer.start();<br />
function onTimer(event:TimerEvent):void<br />
{<br />
	n = Math.floor(Math.random() * 20 - 5);<br />
	timer.delay = 125 * (1 + Math.floor(Math.random() * 7));<br />
}[/as3]</p>
<p>All I've done here is clear the graphics, set a line style, and move to the center left of the screen. Then with each sample, move across the screen a bit and up or down depending on the value of the sample. This gives you something looking like this:</p>
<p><img src="http://www.bit-101.com/blog/wp-content/uploads/2010/07/wave_vis.png" alt="" title="wave_vis" width="550" height="400" class="alignnone size-full wp-image-2678" /></p>
<p>You can see the wave change its frequency with each new note.</p>
<p>The next trick is something I learned from Andre Michelle a very short while ago. You notice that the sine wave as is feels very flat and bland. Quite obviously computer generated. That&#8217;s because the amplitude, or height, of the wave is always constant: -1.0 to 1.0. That&#8217;s just not natural for real world things that make sounds. If you strike a piano keyboard, you&#8217;ll notice that it goes very loud at first, then settles down to a steady value as you hold the key, then when you release it, it fades out. These changes in volume are known as the envelope of a sound. It generally has an four phases, known as ADSR. From <a href="http://en.wikipedia.org/wiki/Synthesizer#ADSR_envelope">Wikipedia</a>:</p>
<blockquote><p>Attack time is the time taken for initial run-up of level from nil to peak.<br />
Decay time is the time taken for the subsequent run down from the attack level to the designated sustain level.<br />
Sustain level is the amplitude of the sound during the main sequence of its duration.<br />
Release time is the time taken for the sound to decay from the sustain level to zero after the key is released.</p></blockquote>
<p>Many of Andre Michelle&#8217;s sound experiments and toys have a very nice, pleasing bell sound to them, so I knew he was using some kind of envelope, but I know that envelopes can be pretty complex to code. So I asked him about it. He gave me a one or two sentence answer which just made me say, &#8220;OH! Of course!&#8221; Basically, all you need to do is start the sound at full amplitude and reduce it over time. So simple. Essentially, you are throwing away the attack, decay, and sustain and just programming in a release.</p>
<p>In this version of the project, we just set up an amp variable and set it to 1.0. On each SAMPLE_DATA event, reduce the amplitude by a fraction. And multiply the sample value by that amplitude. When a new note begins, reset amp to 1.0.</p>
<p>[as3]import flash.media.Sound;<br />
import flash.events.SampleDataEvent;<br />
import flash.events.MouseEvent;<br />
import flash.utils.Timer;<br />
import flash.events.TimerEvent;</p>
<p>var position:int = 0;<br />
var n:Number = 0;<br />
var amp:Number = 1.0;<br />
var sound:Sound = new Sound();<br />
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);<br />
sound.play();</p>
<p>function onSampleData(event:SampleDataEvent):void<br />
{<br />
	graphics.clear();<br />
	graphics.lineStyle(0, 0&#215;999999);<br />
	graphics.moveTo(0, stage.stageHeight / 2);<br />
	for(var i:int = 0; i < 2048; i++)<br />
	{<br />
		var phase:Number = position / 44100 * Math.PI * 2;<br />
		position ++;<br />
		var sample:Number = Math.sin(phase * 440 * Math.pow(2, n / 12)) * amp;<br />
		event.data.writeFloat(sample); // left<br />
		event.data.writeFloat(sample); // right<br />
		graphics.lineTo(i / 2048 * stage.stageWidth, stage.stageHeight / 2 &#8211; sample * stage.stageHeight / 8);<br />
	}<br />
	amp *= 0.7;<br />
}</p>
<p>var timer:Timer = new Timer(500);<br />
timer.addEventListener(TimerEvent.TIMER, onTimer);<br />
timer.start();<br />
function onTimer(event:TimerEvent):void<br />
{<br />
	amp = 1.0;<br />
	n = Math.floor(Math.random() * 20 &#8211; 5);<br />
	timer.delay = 125 * (1 + Math.floor(Math.random() * 7));<br />
}[/as3]</p>
<p>Here, I&#8217;m multiplying amp by 0.7 on each event. This gives a pretty pleasing bell sound. Change that value around to get different characters. Or you could even do some kind of funky vibrato thing like this:</p>
<p>[as3]amp = 0.5 + Math.cos(position * 0.001) * 0.5;[/as3]</p>
<p>OK, that&#8217;s all for this time.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bit-101.com/blog/?feed=rss2&amp;p=2675</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>AS3 Sound Synthesis II &#8211; Waves</title>
		<link>http://www.bit-101.com/blog/?p=2669</link>
		<comments>http://www.bit-101.com/blog/?p=2669#comments</comments>
		<pubDate>Thu, 22 Jul 2010 01:00:00 +0000</pubDate>
		<dc:creator>keith</dc:creator>
				<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[Flash]]></category>

		<guid isPermaLink="false">http://www.bit-101.com/blog/?p=2669</guid>
		<description><![CDATA[This post will show you how to generate sine waves for specific frequencies using the AS3 Sound object. It assumes you have read, or are familiar with the data in Part I of this series. Basics of Sound Sound itself is essentially a change in the pressure of the air. Extremely simple layman’s terms here. [...]]]></description>
			<content:encoded><![CDATA[<p>This post will show you how to generate sine waves for specific frequencies using the AS3 Sound object. It assumes you have read, or are familiar with the data in <a href="http://www.bit-101.com/blog/?p=2660">Part I of this series</a>.</p>
<h2>Basics of Sound</h2>
<p>Sound itself is essentially a change in the pressure of the air. Extremely simple layman’s terms here. Air is composed of various molecules. They are not uniformly smoothly distributed. There can be areas where they are under more pressure and packed more tightly together, and other areas where they are more spaced out. When something like a guitar string vibrates, it moves quickly back and forth at a specific speed. When it moves in one direction, it pushes the molecules of air closer to some other molecules in the same direction. The creates a dense pocket of air. Then the string moves back in the opposite direction, creating a bit of a vacuum. Not a real vacuum, but an area where there are less molecules. It then moves back again, creating another dense pocket.</p>
<p>These areas of dense and undense air move out across the room and eventually hit your ears. The dense air pushes your eardrum in, and the less dense pocket causes it to move out. The result is your eardrum starts vibrating at roughly the same frequency as the guitar string. This causes some bones to vibrate, which stimulate nerves at the same frequency, which send signals to your brain, saying “C Sharp”.</p>
<p>When you record sound, you use a microphone as a sort of electronic ear. It has some kind of diaphragm or other moving part that vibrates and creates and electrical signal which is recorded one way or the other. For playback, this electrical signal is regenerated and causes a speaker to vibrate at the same frequency. This pushes the air the same way the original guitar string did and you hear the same sound.</p>
<h2>Synthesizing Sound</h2>
<p>However, when we talk about synthesizing sound, we are doing it all from scratch. Flash, your computer’s sound card, and your headphones or speakers will handle generating the correct electrical signal and vibrating the air. But you need to do the math to figure out much and how fast to make things vibrate.</p>
<p>In Part I of this tutorial, we created random values which caused the speaker or headphones to vibrate at a completely chaotic pace, resulting in a radio-static-like fuzz. Creating an actual tone requires a bit more work, and hopefully some understanding of what you are doing.</p>
<h2>Digital Sound</h2>
<p>In analog sound, such as vinyl records or 8-track tapes (showing my age here), the sound is encoded smoothly as bumps in the groove of the record, or changes in a magnetic field on the tape. Digital sound takes discrete samples of the sound pressure at specific intervals.</p>
<p>Taking one of the simplest sound forms, a sine wave, here is a smooth analog version:</p>
<p><a href="http://www.bit-101.com/blog/wp-content/uploads/2010/07/sine_smooth.png"><img class="wlDisabledImage" style="margin: 3px 25px 1px 20px; display: inline; border-width: 0px;" title="sine_smooth" src="http://www.bit-101.com/blog/wp-content/uploads/2010/07/sine_smooth_thumb.png" border="0" alt="sine_smooth" width="644" height="469" /></a></p>
<p>And here is the same wave, represented as 50 samples:</p>
<p><a href="http://www.bit-101.com/blog/wp-content/uploads/2010/07/sine_sample.png"><img class="wlDisabledImage" style="margin: 3px 25px 1px 20px; display: inline; border-width: 0px;" title="sine_sample" src="http://www.bit-101.com/blog/wp-content/uploads/2010/07/sine_sample_thumb.png" border="0" alt="sine_sample" width="644" height="469" /></a></p>
<p>As you can see, the sampled version is not quite as accurate as the smooth wave. However, in high quality digital sound, these intervals are numerous enough that it is virtually impossible for most of the population to notice any difference. When you are synthesizing sound in Flash, you will be dealing with 44,100 samples per second. Remember that number, we’ll be doing some calculations with it.</p>
<p>Now, what we need to do is generate our samples with a series of values that wind up forming a sine wave like you see above. The top peak of the sine wave will be 1.0, the bottom will be –1.0 and the middle 0.0. To start simply, we’ll generate a single sine wave over the course of a full second. To keep track of where we’re at, we’ll use a variable called position. We’ll initialize it to 0 and increment it each time we create a new sample. Thus position will range from 0 to 44100 over the course of the first second of audio.</p>
<p>If we then divide position by 44100, we’ll get values that range from 0.0 up to 1.0 over the course of one second. And if we multiply that by 2PI, We’ll get values from 0 to 2PI, just what we need to generate a sine wave with the Math.sin function. Here’s the code so far:</p>
<p>[as3]import flash.media.Sound;<br />
import flash.events.SampleDataEvent;<br />
import flash.events.MouseEvent;</p>
<p>var position:int = 0;<br />
var sound:Sound = new Sound();<br />
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);<br />
sound.play();</p>
<p>function onSampleData(event:SampleDataEvent):void<br />
{<br />
	for(var i:int = 0; i < 2048; i++)<br />
	{<br />
		var phase:Number = position / 44100 * Math.PI * 2;<br />
		position ++;<br />
		var sample:Number = Math.sin(phase);<br />
		event.data.writeFloat(sample); // left<br />
		event.data.writeFloat(sample); // right<br />
	}<br />
}[/as3]</p>
<p>If you run that file, you&#8217;ll be generating a sine wave that does one full cycle each second. Of course, this, being a 1 Hz sound wave, is far too low for the human ear to hear. To get a specific frequency sound, simply multiply phase by the frequency you want to hear. Humans can hear frequencies generally in the range of 25 to 25,000 Hz. Middle A on the standard musical scale is 440 Hz. So let&#8217;s try that. Change the line that calculates the sample to:</p>
<p>[as3]var sample:Number = Math.sin(phase * 440);[/as3]</p>
<p>That gives you A. You can find charts like this all over the net:</p>
<p>A	440<br />
B flat	466<br />
B	494<br />
C	523<br />
C sharp	554<br />
D	587<br />
D sharp	622<br />
E	659<br />
F	698<br />
F sharp	740<br />
G	784<br />
A flat	831<br />
A	880</p>
<p>Or, if you want to get more mathematical about it, the formula for each note, n, above or below 440 is:</p>
<p>440 * 2^(n / 12)</p>
<p>We can implement scales then by setting up an n variable, incrementing it on a timer, and using the above formula to calculate our frequency:</p>
<p>[as3]import flash.media.Sound;<br />
import flash.events.SampleDataEvent;<br />
import flash.events.MouseEvent;<br />
import flash.utils.Timer;<br />
import flash.events.TimerEvent;</p>
<p>var position:int = 0;<br />
var n:Number = 0;<br />
var sound:Sound = new Sound();<br />
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);<br />
sound.play();</p>
<p>function onSampleData(event:SampleDataEvent):void<br />
{<br />
	for(var i:int = 0; i < 2048; i++)<br />
	{<br />
		var phase:Number = position / 44100 * Math.PI * 2;<br />
		position ++;<br />
		var sample:Number = Math.sin(phase * 440 * Math.pow(2, n / 12));<br />
		event.data.writeFloat(sample); // left<br />
		event.data.writeFloat(sample); // right<br />
	}<br />
}</p>
<p>var timer:Timer = new Timer(500);<br />
timer.addEventListener(TimerEvent.TIMER, onTimer);<br />
timer.start();<br />
function onTimer(event:TimerEvent):void<br />
{<br />
	n++;<br />
}[/as3]</p>
<p>Alternately, we can make a poor man&#8217;s generative music composer with a little help from Math.random:</p>
<p>[as3]function onTimer(event:TimerEvent):void<br />
{<br />
	n = Math.floor(Math.random() * 20 &#8211; 5);<br />
	timer.delay = 125 * (1 + Math.floor(Math.random() * 8));<br />
}[/as3]</p>
<p>This generates a different note, and a different duration (from 1/8th of a second up to one full second) for each note.</p>
<p>Armed with this alone, you are on your way to making your own sequencer or mini piano or other type instrument. Later, I&#8217;ll try to post some stuff on other wave forms, combining waves, envelopes, and other topics.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bit-101.com/blog/?feed=rss2&amp;p=2669</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Sound Synthesis in AS3 Part I &#8211; The Basics, Noise</title>
		<link>http://www.bit-101.com/blog/?p=2660</link>
		<comments>http://www.bit-101.com/blog/?p=2660#comments</comments>
		<pubDate>Wed, 21 Jul 2010 23:00:00 +0000</pubDate>
		<dc:creator>keith</dc:creator>
				<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[Flash]]></category>

		<guid isPermaLink="false">http://www.bit-101.com/blog/?p=2660</guid>
		<description><![CDATA[I’ve been meaning to write something up on this for quite a while. It recently struck me that there still wasn’t a whole lot of good material on this out there already. So I figured I’d throw something together. We’ll start by looking at the basic mechanics of the Sound object, how to code it [...]]]></description>
			<content:encoded><![CDATA[<p>I’ve been meaning to write something up on this for quite a while. It recently struck me that there still wasn’t a whole lot of good material on this out there already. So I figured I’d throw something together.</p>
<p>We’ll start by looking at the basic mechanics of the Sound object, how to code it up, and create some random noise. Later, we’ll start generating some real wave forms and start mixing them together, etc.</p>
<h2>Diving right in</h2>
<p>Flash 10 has the ability to synthesize sounds. Actually, there was a hack that could be used in Flash 9 to do the same thing, but it became standardized in 10.</p>
<p>Here’s how it works. You create a new Sound object and add an event listener for the SAMPLE_DATA event (SampleDataEvent.SAMPLE_DATA). This event will fire when there is no more sound data for the Sound to play. Then you start the sound playing.</p>
<p>[as3]var sound:Sound = new Sound();<br />
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);<br />
sound.play();[/as3]</p>
<p>At this point, because you have not loaded any actual sound, such as an MP3, WAV, etc. or attached it to any streaming sound data, there is nothing to play and the SAMPLE_DATA event will fire right away. So we’ll need that handler function:</p>
<p>[as3]function onSampleData(event:SampleDataEvent):void<br />
{<br />
}[/as3]</p>
<p>Our goal here is to give the Sound object some more sound data to play. So how do we do that? Well, the SampleDataEvent that gets passed to this function has a data property, which is a ByteArray. We need to fill that ByteArray with some values that represent some sound to play. We do that using the ByteArray.writeFloat method. Generally you want to write values from –1.0 to 1.0 in there. Each float value you write in there is known as a sample. Hence the “SampleDataEvent”. How many samples should you write? Generally between 2048 and 8192.</p>
<p>OK, that’s a big range of values. What’s best? Well, if you stick to a low number like 2048, the Sound will rip through those values very quickly and another SAMPLE_DATA event will fire very quickly, requiring you to fill it up again. If you use a larger number like 8192, the Sound will take 4 times as long to work through those values and thus you’ll be running your event handler function 4 times less often.</p>
<p>So more samples can mean better performance. However, if you have dynamically generated sounds, more samples means more latency. Latency is the time between some change in the UI or program and when that results in a change in the actual sound heard. For example, say you want to change from a 400 hz tone to a 800 hz tone when a user presses a button. The user presses the button, but the Sound has 8000 samples of this 400 hz tone in the buffer, and will continue to play them until they are gone. Only then will it call the SAMPLE_DATA event handler and ask for more data. This is the only point where you can change the tone to 800 hz. Thus, the user may notice a slight lag between when he pressed the button and when the tone changed. If you use smaller numbers of samples – 2048 – the latency or lag will be shorter and less noticeable.</p>
<p>For now, let’s just generate some noise. We’ll write 2048 samples of random values from –1.0 to 1.0. One thing you need to know first is that you’ll actually be writing twice as many floats. For each sample you need to write a value for the left channel and a value for the right channel. Here’s the whole program:</p>
<p>[as3]import flash.media.Sound;<br />
import flash.events.SampleDataEvent;</p>
<p>var sound:Sound = new Sound();<br />
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);<br />
sound.play();</p>
<p>function onSampleData(event:SampleDataEvent):void<br />
{<br />
    for(var i:int = 0; i < 2048; i++)<br />
    {<br />
        var sample:Number = Math.random() * 2.0 - 1.0; // -1 to 1<br />
        event.data.writeFloat(sample); // left<br />
        event.data.writeFloat(sample); // right<br />
    }<br />
}[/as3]</p>
<p>If you run that, you should hear some fuzzy static like a radio tuned between stations. Note that we are generating a single sample and using that same value for left and right. Because both channels have exactly the same value for each sample, we’ve generated monophonic sound. If we want stereo noise, we could do something like this:</p>
<p>[as3]function onSampleData(event:SampleDataEvent):void<br />
{<br />
    for(var i:int = 0; i < 2048; i++)<br />
    {<br />
        var sampleA:Number = Math.random() * 2.0 - 1.0; // -1 to 1<br />
        var sampleB:Number = Math.random() * 2.0 - 1.0; // -1 to 1<br />
        event.data.writeFloat(sampleA); // left<br />
        event.data.writeFloat(sampleB); // right<br />
    }<br />
}[/as3]</p>
<p>Here we are writing a different random value for each channel, each sample. Running this, especially using headphones, you should notice a bit more “space” in the noise. It’s subtle and may be hard to discern between runs of the program, so let’s alter it so we can switch quickly.</p>
<p>[as3]import flash.media.Sound;<br />
import flash.events.SampleDataEvent;<br />
import flash.events.MouseEvent;</p>
<p>var sound:Sound = new Sound();<br />
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);<br />
sound.play();</p>
<p>var mono:Boolean = true;<br />
stage.addEventListener(MouseEvent.CLICK, onClick);<br />
function onClick(event:MouseEvent):void<br />
{<br />
    mono = !mono;<br />
}</p>
<p>function onSampleData(event:SampleDataEvent):void<br />
{<br />
    for(var i:int = 0; i < 2048; i++)<br />
    {<br />
        var sampleA:Number = Math.random() * 2.0 - 1.0; // -1 to 1<br />
        var sampleB:Number = Math.random() * 2.0 - 1.0; // -1 to 1<br />
        event.data.writeFloat(sampleA); // left<br />
        if(mono)<br />
        {<br />
            event.data.writeFloat(sampleA); // left again<br />
        }<br />
        else<br />
        {<br />
            event.data.writeFloat(sampleB); // right<br />
        }<br />
    }<br />
}[/as3]</p>
<p>Here we have a Boolean variable, mono, that toggles true/false on a mouse click. If true, we write sampleA to the left and right channels. If mono is not true, then we write sampleA to the left channel and sampleB to the right channel. Run this and click the mouse. Again, the change is subtle but you should be able to notice it.</p>
<p>To see, or rather, to hear, the results of latency, change the 2048 in the for loop to 8192. Now when you click, you’ll notice a significant delay in the time between the click and the change from mono to stereo or vice versa.</p>
<p>One other note about the number of samples. I said, “generally” to use between 2048 and 8192. The fact is if you try to use more than 8192, you’ll get a run time error saying one of the parameters is invalid. so 8192 is a pretty hard limit. You can use less than 2048, but if you do, what happens is that the Sound object will work through those samples and then consider the sound is complete. It will not generate another SAMPLE_DATA event when it is done. Instead, it will generate a COMPLETE event. So if you want the sound to keep playing, you need to keep it supplied with at least 2048 samples at all times.</p>
<p>In the next installment, we’ll start creating some simple waves.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bit-101.com/blog/?feed=rss2&amp;p=2660</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Magical!</title>
		<link>http://www.bit-101.com/blog/?p=2654</link>
		<comments>http://www.bit-101.com/blog/?p=2654#comments</comments>
		<pubDate>Fri, 02 Jul 2010 18:18:00 +0000</pubDate>
		<dc:creator>keith</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[iPhone]]></category>

		<guid isPermaLink="false">http://www.bit-101.com/blog/?p=2654</guid>
		<description><![CDATA[I made a funneh: I&#8217;m not trying to be an Apple hater, but this letter just cracked me up. http://www.apple.com/pr/library/2010/07/02appleletter.html]]></description>
			<content:encoded><![CDATA[<p>I made a funneh:</p>
<p><a href="http://www.bit-101.com/blog/wp-content/uploads/2010/07/bars.jpg"><img src="http://www.bit-101.com/blog/wp-content/uploads/2010/07/bars.jpg" alt="" title="bars" width="600" height="1148" class="alignnone size-full wp-image-2655" /></a></p>
<p>I&#8217;m not trying to be an Apple hater, but this letter just cracked me up.</p>
<p><a href="http://www.apple.com/pr/library/2010/07/02appleletter.html">http://www.apple.com/pr/library/2010/07/02appleletter.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bit-101.com/blog/?feed=rss2&amp;p=2654</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>FiTC San Francisco</title>
		<link>http://www.bit-101.com/blog/?p=2651</link>
		<comments>http://www.bit-101.com/blog/?p=2651#comments</comments>
		<pubDate>Sat, 26 Jun 2010 16:31:02 +0000</pubDate>
		<dc:creator>keith</dc:creator>
				<category><![CDATA[Conferences]]></category>

		<guid isPermaLink="false">http://www.bit-101.com/blog/?p=2651</guid>
		<description><![CDATA[A couple more travel items on my agenda this year. First, I&#8217;ll be going on my annual (nearly annual anyway) family trip to Japan in the beginning of July. I&#8217;ll be there for a couple of weeks. We stay with my wife&#8217;s family in Kuwanashi, near Nagoya, on the edge of a mountain range, rice [...]]]></description>
			<content:encoded><![CDATA[<p>A couple more travel items on my agenda this year. First, I&#8217;ll be going on my annual (nearly annual anyway) family trip to Japan in the beginning of July. I&#8217;ll be there for a couple of weeks. We stay with my wife&#8217;s family in Kuwanashi, near Nagoya, on the edge of a mountain range, rice fields and farms on every side. You probably won&#8217;t see much (if any) of me on IM or twitter, though I&#8217;ll probably make a few blog posts, more likely at <a href="http://www.keithpeters.org">keithpeters.org</a> than here. I look forward to some very scenic runs out there though. We have plenty of day trips planned, and we&#8217;ll be driving to Kyoto to spend a couple of days there as well.</p>
<p>After that, in August, I&#8217;m off to <a href="http://www.fitc.ca/events/about/?event=110">FiTC&#8217;s San Francisco debut</a>! I&#8217;ve always loved SF. When I was younger, it was my goal to eventually live there. That&#8217;s probably not in the cards now, and to be honest, my coffee-table-book-concept of the city has been tempered by being there in person, but it&#8217;s still a great place that I love to visit. I&#8217;ve been there for two Flash Forwards, and a number of times for other things. I&#8217;m really glad that FiTC has taken ownership of the city, giving me an excuse to get out there again.</p>
<p>One of the highlights this year is that Shawn has gotten Yugo Nakamura out from Tokyo to speak. Yugo is one of the &#8211; if not THE &#8211; grandfathers of all Flash rock stars. Although I was able to visit his studio the last time I was in Tokyo, sadly, he was out sick that particular day. I did happen to notice one of my books on his shelf though, which I took down and signed for him. Cheeky, I know, but I have no regrets. <img src='http://www.bit-101.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>There are the usual assortment of other great speakers as well. I&#8217;ll be doing my &#8220;Programming Art&#8221; presentation. This being my last conference speaking engagement of the year, it&#8217;s most likely the last chance you&#8217;ll have to see this particular talk.</p>
<p>Another first is that I&#8217;ve finally convinced my wife and daughter to come out this time! I&#8217;m excited to get to introduce them to some of my world wide friends. I&#8217;m hoping that if you all tell them how awesome and godlike I am, they&#8217;ll give me a little more respect at home. <img src='http://www.bit-101.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  (Just kidding!) Anyway, this also means I&#8217;ll probably be out doing a bit more site seeing during the day, and probably taking it pretty easy at night.</p>
<p>Hope to see you in SF. Oh, and by the way, if you sign up and use the code &#8220;bit101&#8243;, you should score a 10% discount off your tickets.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bit-101.com/blog/?feed=rss2&amp;p=2651</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>FlashBelt Monday Run!</title>
		<link>http://www.bit-101.com/blog/?p=2648</link>
		<comments>http://www.bit-101.com/blog/?p=2648#comments</comments>
		<pubDate>Wed, 09 Jun 2010 13:25:05 +0000</pubDate>
		<dc:creator>keith</dc:creator>
				<category><![CDATA[Conferences]]></category>
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.bit-101.com/blog/?p=2648</guid>
		<description><![CDATA[The FlashBelt Run is on! Monday morning, June 14, nice and early. I&#8217;m thinking of around 7 a.m. That will give us time to get in a few miles, then shower up and get to the keynote by 9:15. Thus far, looks like we have the following showing interest: Me Jeni H. Vic C. Veronique [...]]]></description>
			<content:encoded><![CDATA[<p>The FlashBelt Run is on! Monday morning, June 14, nice and early. I&#8217;m thinking of around 7 a.m. That will give us time to get in a few miles, then shower up and get to the keynote by 9:15.</p>
<p>Thus far, looks like we have the following showing interest:</p>
<p>Me<br />
Jeni H.<br />
Vic C.<br />
Veronique B.<br />
Brandon M.<br />
Terry P.</p>
<p>But no need to RSVP. I think we&#8217;ll just leave from the front of the hotel (Holiday Inn Metrodome) right around 7:00. Just show up there with running gear. I&#8217;ll post any changes in this post, so check back right here.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bit-101.com/blog/?feed=rss2&amp;p=2648</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>FlashBelt Geek Run?</title>
		<link>http://www.bit-101.com/blog/?p=2644</link>
		<comments>http://www.bit-101.com/blog/?p=2644#comments</comments>
		<pubDate>Mon, 07 Jun 2010 15:57:24 +0000</pubDate>
		<dc:creator>keith</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.bit-101.com/blog/?p=2644</guid>
		<description><![CDATA[I&#8217;ll be at FlashBelt in MN, arriving this coming Sunday morning, and staying through until Thursday morning. I&#8217;d like to get at least 2-3 runs in while I&#8217;m there and I know that there are several of you in the Flash community. So want to see if anyone wants to get together for a run. [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ll be at FlashBelt in MN, arriving this coming Sunday morning, and staying through until Thursday morning. I&#8217;d like to get at least 2-3 runs in while I&#8217;m there and I know that there are several of you in the Flash community. So want to see if anyone wants to get together for a run.</p>
<p>At this point it looks like I&#8217;ll at least be going for a run on Monday and Tuesday morning before the conference. Probably 3-4 miles each day. Anyone up for it, contact me at kp &#8211; at &#8211; bit-101.com</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bit-101.com/blog/?feed=rss2&amp;p=2644</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Digsby: Warning</title>
		<link>http://www.bit-101.com/blog/?p=2637</link>
		<comments>http://www.bit-101.com/blog/?p=2637#comments</comments>
		<pubDate>Tue, 01 Jun 2010 23:35:43 +0000</pubDate>
		<dc:creator>keith</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.bit-101.com/blog/?p=2637</guid>
		<description><![CDATA[Someone recommended the program Digsby to me today. I watched the video on their site. It seems to be a multi-service IM client with Twitter, Facebook, email, and other social network services built in. A lot of stuff in the video actually turned me off, like &#8220;what if you could update your status on all [...]]]></description>
			<content:encoded><![CDATA[<p>Someone recommended the program Digsby to me today. I watched the video on their site. It seems to be a multi-service IM client with Twitter, Facebook, email, and other social network services built in. A lot of stuff in the video actually turned me off, like &#8220;what if you could update your status on all your networks at once?&#8221; Well, I hate that idea. I always hated going to someone&#8217;s facebook page and seeing that it was just all their tweets, or vice versa. Besides, having just quit facbook, the only social network I use is twitter and I like TweetDeck for that.</p>
<p>But what the hell, it&#8217;s a free download, so if it was a decent IM client, I would be happy and ignore the rest. So I download and start the install process. Here&#8217;s what you get first:</p>
<p><img src="http://www.bit-101.com/blog/wp-content/uploads/2010/06/digsby_01.png" alt="" title="digsby_01" width="503" height="389" class="alignnone size-full wp-image-2638" /></p>
<p>In addition to installing itself, it wants to install a browser plugin that is going to give them money every time you buy something from certain merchants. Um&#8230; wtf? No thanks. Uncheck that and move on, cautiously at this point.</p>
<p>Next up we get this screen.</p>
<p><a href="http://www.bit-101.com/blog/wp-content/uploads/2010/06/digsby_02.png"><img src="http://www.bit-101.com/blog/wp-content/uploads/2010/06/digsby_02.png" alt="" title="digsby_02" width="503" height="389" class="alignnone size-full wp-image-2639" /></a></p>
<p>I admit, I actually fell for this one. I didn&#8217;t read carefully. Didn&#8217;t see an opt-out checkbox like on the other screen, clicked the &#8220;Accept&#8221; button, thinking it was a &#8220;Next&#8221; button. Moving on innocently, we get to this point:</p>
<p><img src="http://www.bit-101.com/blog/wp-content/uploads/2010/06/digsby_03.png" alt="" title="digsby_03" width="503" height="389" class="alignnone size-full wp-image-2640" /></p>
<p>OK, this is getting frigging ridiculous. They want to change my home page to &#8220;Google Powered Digsby&#8221; as well as my default search engine. Bug off! Worse even, is they want to use my CPU for grid computing. I didn&#8217;t even check what the hell they&#8217;d be computing on it, I just did a quick triple opt out and continued on, a bit pissed off at this point.</p>
<p>Then this window pops up.</p>
<p><img src="http://www.bit-101.com/blog/wp-content/uploads/2010/06/digsby_04.png" alt="" title="digsby_04" width="675" height="421" class="alignnone size-full wp-image-2641" /></p>
<p>No, I don&#8217;t want a damn Digsby account. I just want to see what the program does. I close that and get to the main interface, and see this:</p>
<p><img src="http://www.bit-101.com/blog/wp-content/uploads/2010/06/digsby_05.png" alt="" title="digsby_05" width="210" height="408" class="alignnone size-full wp-image-2642" /></p>
<p>Apparently, I HAVE to have a Digsby account to use the software at all. Well screw that. Just wasted 10 minutes of life. I close that, intending to uninstall the damn thing, but decide to check my email first. Whoa! There&#8217;s a giant &#8220;Welcome to Xobni&#8221; panel in my Outlook. Baffled, I uninstalled both Xobni and Digsby, and then walked through the Digsby install process again to see how I got duped into Xobni. That&#8217;s where I got the screenshots.</p>
<p>In the past, I&#8217;ve made critical remarks about software I&#8217;ve installed, only to have the developer contact me personally and say something like, &#8220;sorry you didn&#8217;t like it.&#8221; In a few cases, I felt bad &#8211; maybe I had been a bit overcritical, off the cuff puts downs, etc. But in this case, I&#8217;d say that Digsby leaves the impression of severe sleaze, bordering on malware. By my count, it tried to install 3 other pieces of software and make two browser configuration changes, all opt out. Two different UIs, for opt out, which caught me off-guard and tricked me into installing something I didn&#8217;t want. My fail, but that was their intention. So I have no problem slamming this piece of&#8230; software.</p>
<p>You have been warned.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bit-101.com/blog/?feed=rss2&amp;p=2637</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
	</channel>
</rss>
