Stephen Fry on Blog Comments, Twitter, etc.

Aug 13 2010

Really timely quote with some of the stuff I was talking about with others today.

You know there is nothing easier than writing an article against something, which is so simple. It writes itself. You just got to be angry about something and just got to puff and wheeze with indignation and fury and resentment and bile and malice and the thing writes itself and if you write anything that’s for something it looks sentimental and cutesy and you know so much… and so much harder to write, so much harder to write well. So all the successful columnists are… certainly in the British press are vicious and they’re good at being vicious and admirable and if you share their politics mostly their viciousness is something you can applaud. If you don’t then you just call them beasts and animals and revolting. It just gets so annoying. It’s such a pity and that’s one of the reasons I love the online world is that although that exists in abundance you can choose absolutely which part of the online world you want to live in. You can make your own kingdom in that sense, so things like Twitter or whatever I’m sure there are all kinds of Twitter you know clusters of people who have politics that I would find horrific and really just views that I would preposterous and impertinent, but I just don’t have to follow them and I can block them and I will never know they exist and that’s glorious.

And similarly as long as you don’t lower your eyes when reading a blog, as long as you don’t go down to the comment section where the trolls lurk, where the viciousness is because that’s… I mean there really is just suppurating, boiling seas of acid where if you just so much as dip a toe you’ve lost your limbs you know, just vileness abounding. Again, there is this resentment, “I will be heard and not only will I be heard I will offend.” “I will tear.” “I will lacerate.” “I will wound.” “I want the sensibilities of anyone who disagrees with me to be bruised beyond mending.” That kind of attitude is very strong on the net and for all that we can be advocates for the glory and the democracy that exists online we must be aware too that that dark side of humanity that just needs to be heard and can’t bear people like me for example who have access to greater numbers of followers on Twitter or whose website gets more hits and the more they see that, the more the web becomes a reflection of their view of the meanness and wrongness of society where somebody will get it all and others get none and then the more bitterness there is and I think it’s difficult because I don’t certainly want there to be aristocracy on the net. I don’t want there to be that. I think that whole beauty of it at its best is that there is genuine equality and genuine reciprocity between you know a Twitterer and his or her followers or between a blogger and their readers and that it’s not… You know it’s not an audience going to one site that is permanent and stable and is like the equivalent of the old models of the broadcaster, but that it’s much more fluid and the broadcaster becomes the broadcasted too, you know the TV station becomes the audience and as long as people believe that and behave as if that is true then there is real hope in the way information is going.

- Stephen Fry

Or better yet, watch and listen. Quote starts about 12 minutes in.

13 responses so far

Kindle and iPad Displays: Up close and personal.

Aug 12 2010

This really isn’t meant to be a contentious post. It really only came about because I got a new toy, something I’ve been wanting to get for a while – a USB microsope! Here’s the model I got:

Veho VMS004 DELUXE USB Powered Microscope

The family had great fun playing with it tonight – looking at everyone’s skin and hair and dirty fingernails and bug bites, and paper and money and cloth and salt and sugar, etc. I could barely pry my daughter away from it. The software allows you to capture images and videos and even notate them with actual measurements, etc. based on the level of magnification.

While playing a bit more with it, I held it up to my computer screen and my Nexus One screen and could clearly see the pixels. Neat. Then I wondered what the Kindle’s screen looks like close up. Quite different! I then compared the Kindle’s screen at roughly 26x and 400x with the iPad’s screen at approximately the same resolution. Wow! No wonder the Kindle is so much easier to read!

First at about 26x.

Kindle:

iPad:

And now at about 400x for the Kindle and 375x for the iPad.

Kindle:

iPad:

The Kindle’s screen looks almost organic at high magnification. I need to learn more about eInk now. I will hopefully be getting my Kindle 3 in a couple of weeks (should ship August 27). I’m interested to see how that shows up – supposedly the contrast is much better. And now I need to get my hands on a iPhone 4 with that retina display. I’d love to see what that looks like close up. Not buying one though. Maybe someone at FiTC San Francisco will have one they can lend me for a photo.

[Update 8/13/10]

As requested, here are some additional photos at 26x and 400x, of print media.

First, newsprint, then a magazine, then a paperback book at 26x.

Newsprint:

Magazine:

Book:

And now the same three, in the same order, at 400x:

Newsprint:

Magazine:

Book:

Again, I leave it to you to make your conclusions.

[Edit #2]
I changed the post title to remove the “vs.”, replacing it with “and”. This is not a battle, people. Just some interesting photos. Relax. It’s all going to be OK.

354 responses so far

New Kindle, Interview with Jeff Bezos

Jul 28 2010

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’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 its own site.

More importantly though, I just watched the Jeff Bezos interview on Charlie Rose tonight. From the few times I’ve seen Jeff speak, he’s really impressed me. Three things he said today that, to me, got at the crux of why the Kindle is so good.

First, talking about iPad vs. Kindle and the design of the Kindle, saying people, “want a purpose built device where no trade offs have been made, where every single design decision as you’re walking down the process has been made to optimize for reading.” 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’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.

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 “long-form reading” and “short-form reading”, saying, “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’re great for blog posts. They’re not great for 300 page books.”

Finally, the kicker, what it’s really all about: “We’re not trying to create an experience. We want the author to create the experience.” Bingo.

The link to the Bezos interview isn’t up yet, but should be on this page when available: http://www.charlierose.com/guest/view/2618

13 responses so far

AS3 Sound Synthesis IV – Tone Class

Jul 23 2010

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’s the class:

package
{
	import flash.media.Sound;
	import flash.events.SampleDataEvent;
	import flash.events.Event;

	public class Tone
	{
		protected const RATE:Number = 44100;
		protected var _position:int = 0;
		protected var _sound:Sound;
		protected var _numSamples:int = 2048;
		protected var _samples:Vector.<number>;
		protected var _isPlaying:Boolean = false;

		protected var _frequency:Number;

		public function Tone(frequency:Number)
		{
			_frequency = frequency;
			_sound = new Sound();
			_sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);
			_samples = new Vector.<number>();
			createSamples();
		}

		protected function createSamples():void
		{
			var amp:Number = 1.0;
			var i:int = 0;
			var mult:Number = frequency / RATE * Math.PI * 2;
			while(amp > 0.01)
			{
				_samples[i] = Math.sin(i * mult) * amp;
				amp *= 0.9998;
				i++;
			}
			_samples.length = i;
		}

		public function play():void
		{
			if(!_isPlaying)
			{
				_position = 0;
				_sound.play();
				_isPlaying = true;
			}
		}

		protected function onSampleData(event:SampleDataEvent):void
		{
			for (var i:int = 0; i < _numSamples; i++)
			{
				if(_position >= _samples.length)
				{
					_isPlaying = false;
					return;
				}
				event.data.writeFloat(_samples[_position]);
				event.data.writeFloat(_samples[_position]);
				_position++;
			}
		}

		public function set frequency(value:Number):void
		{
			_frequency = value;
			createSamples();
		}
		public function get frequency():Number
		{
			return _frequency;
		}
	}
}

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.

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’m not sure how noticeable it is.

Here’s a brief bit of code that shows it in action:

import flash.events.MouseEvent;

var tone:Tone = new Tone(800);
stage.addEventListener(MouseEvent.CLICK, onClick);
function onClick(event:MouseEvent):void
{
	tone.frequency = 300 + mouseY;
	tone.play();
}

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.

I don’t consider this class anywhere near “complete”. Just a beginning evolution in something. I’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.

15 responses so far

AS3 Sound Synthesis III – Visualization and Envelopes

Jul 21 2010

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 the SAMPLE_DATA event handler, you are already generating 2048 samples to create a wave form. While you’re creating these, it’s a piece of cake to go ahead and draw some lines based on their values. Look here:

import flash.media.Sound;
import flash.events.SampleDataEvent;
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;

var position:int = 0;
var n:Number = 0;
var sound:Sound = new Sound();
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);
sound.play();

function onSampleData(event:SampleDataEvent):void
{
	graphics.clear();
	graphics.lineStyle(0, 0x999999);
	graphics.moveTo(0, stage.stageHeight / 2);
	for(var i:int = 0; i < 2048; i++)
	{
		var phase:Number = position / 44100 * Math.PI * 2;
		position ++;
		var sample:Number = Math.sin(phase * 440 * Math.pow(2, n / 12));
		event.data.writeFloat(sample); // left
		event.data.writeFloat(sample); // right
		graphics.lineTo(i / 2048 * stage.stageWidth, stage.stageHeight / 2 - sample * stage.stageHeight / 8);
	}
}

var timer:Timer = new Timer(500);
timer.addEventListener(TimerEvent.TIMER, onTimer);
timer.start();
function onTimer(event:TimerEvent):void
{
	n = Math.floor(Math.random() * 20 - 5);
	timer.delay = 125 * (1 + Math.floor(Math.random() * 7));
}

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:

You can see the wave change its frequency with each new note.

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's because the amplitude, or height, of the wave is always constant: -1.0 to 1.0. That's just not natural for real world things that make sounds. If you strike a piano keyboard, you'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 Wikipedia:

Attack time is the time taken for initial run-up of level from nil to peak.
Decay time is the time taken for the subsequent run down from the attack level to the designated sustain level.
Sustain level is the amplitude of the sound during the main sequence of its duration.
Release time is the time taken for the sound to decay from the sustain level to zero after the key is released.

Many of Andre Michelle'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, "OH! Of course!" 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.

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.

import flash.media.Sound;
import flash.events.SampleDataEvent;
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;

var position:int = 0;
var n:Number = 0;
var amp:Number = 1.0;
var sound:Sound = new Sound();
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);
sound.play();

function onSampleData(event:SampleDataEvent):void
{
	graphics.clear();
	graphics.lineStyle(0, 0x999999);
	graphics.moveTo(0, stage.stageHeight / 2);
	for(var i:int = 0; i < 2048; i++)
	{
		var phase:Number = position / 44100 * Math.PI * 2;
		position ++;
		var sample:Number = Math.sin(phase * 440 * Math.pow(2, n / 12)) * amp;
		event.data.writeFloat(sample); // left
		event.data.writeFloat(sample); // right
		graphics.lineTo(i / 2048 * stage.stageWidth, stage.stageHeight / 2 - sample * stage.stageHeight / 8);
	}
	amp *= 0.7;
}

var timer:Timer = new Timer(500);
timer.addEventListener(TimerEvent.TIMER, onTimer);
timer.start();
function onTimer(event:TimerEvent):void
{
	amp = 1.0;
	n = Math.floor(Math.random() * 20 - 5);
	timer.delay = 125 * (1 + Math.floor(Math.random() * 7));
}

Here, I'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:

amp = 0.5 + Math.cos(position * 0.001) * 0.5;

OK, that's all for this time.

11 responses so far

AS3 Sound Synthesis II – Waves

Jul 21 2010

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. 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.

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”.

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.

Synthesizing Sound

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.

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.

Digital Sound

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.

Taking one of the simplest sound forms, a sine wave, here is a smooth analog version:

sine_smooth

And here is the same wave, represented as 50 samples:

sine_sample

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.

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.

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:

import flash.media.Sound;
import flash.events.SampleDataEvent;
import flash.events.MouseEvent;

var position:int = 0;
var sound:Sound = new Sound();
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);
sound.play();

function onSampleData(event:SampleDataEvent):void
{
	for(var i:int = 0; i < 2048; i++)
	{
		var phase:Number = position / 44100 * Math.PI * 2;
		position ++;
		var sample:Number = Math.sin(phase);
		event.data.writeFloat(sample); // left
		event.data.writeFloat(sample); // right
	}
}

If you run that file, you'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's try that. Change the line that calculates the sample to:

var sample:Number = Math.sin(phase * 440);

That gives you A. You can find charts like this all over the net:

A 440
B flat 466
B 494
C 523
C sharp 554
D 587
D sharp 622
E 659
F 698
F sharp 740
G 784
A flat 831
A 880

Or, if you want to get more mathematical about it, the formula for each note, n, above or below 440 is:

440 * 2^(n / 12)

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:

import flash.media.Sound;
import flash.events.SampleDataEvent;
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;

var position:int = 0;
var n:Number = 0;
var sound:Sound = new Sound();
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);
sound.play();

function onSampleData(event:SampleDataEvent):void
{
	for(var i:int = 0; i < 2048; i++)
	{
		var phase:Number = position / 44100 * Math.PI * 2;
		position ++;
		var sample:Number = Math.sin(phase * 440 * Math.pow(2, n / 12));
		event.data.writeFloat(sample); // left
		event.data.writeFloat(sample); // right
	}
}

var timer:Timer = new Timer(500);
timer.addEventListener(TimerEvent.TIMER, onTimer);
timer.start();
function onTimer(event:TimerEvent):void
{
	n++;
}

Alternately, we can make a poor man's generative music composer with a little help from Math.random:

function onTimer(event:TimerEvent):void
{
	n = Math.floor(Math.random() * 20 - 5);
	timer.delay = 125 * (1 + Math.floor(Math.random() * 8));
}

This generates a different note, and a different duration (from 1/8th of a second up to one full second) for each note.

Armed with this alone, you are on your way to making your own sequencer or mini piano or other type instrument. Later, I'll try to post some stuff on other wave forms, combining waves, envelopes, and other topics.

5 responses so far

Sound Synthesis in AS3 Part I – The Basics, Noise

Jul 21 2010

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 up, and create some random noise. Later, we’ll start generating some real wave forms and start mixing them together, etc.

Diving right in

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.

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.

var sound:Sound = new Sound();
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);
sound.play();

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:

function onSampleData(event:SampleDataEvent):void
{
}

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.

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.

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.

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:

import flash.media.Sound;
import flash.events.SampleDataEvent;

var sound:Sound = new Sound();
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);
sound.play();

function onSampleData(event:SampleDataEvent):void
{
    for(var i:int = 0; i < 2048; i++)
    {
        var sample:Number = Math.random() * 2.0 - 1.0; // -1 to 1
        event.data.writeFloat(sample); // left
        event.data.writeFloat(sample); // right
    }
}

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:

function onSampleData(event:SampleDataEvent):void
{
    for(var i:int = 0; i < 2048; i++)
    {
        var sampleA:Number = Math.random() * 2.0 - 1.0; // -1 to 1
        var sampleB:Number = Math.random() * 2.0 - 1.0; // -1 to 1
        event.data.writeFloat(sampleA); // left
        event.data.writeFloat(sampleB); // right
    }
}

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.

import flash.media.Sound;
import flash.events.SampleDataEvent;
import flash.events.MouseEvent;

var sound:Sound = new Sound();
sound.addEventListener(SampleDataEvent.SAMPLE_DATA, onSampleData);
sound.play();

var mono:Boolean = true;
stage.addEventListener(MouseEvent.CLICK, onClick);
function onClick(event:MouseEvent):void
{
    mono = !mono;
}

function onSampleData(event:SampleDataEvent):void
{
    for(var i:int = 0; i < 2048; i++)
    {
        var sampleA:Number = Math.random() * 2.0 - 1.0; // -1 to 1
        var sampleB:Number = Math.random() * 2.0 - 1.0; // -1 to 1
        event.data.writeFloat(sampleA); // left
        if(mono)
        {
            event.data.writeFloat(sampleA); // left again
        }
        else
        {
            event.data.writeFloat(sampleB); // right
        }
    }
}

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.

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.

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.

In the next installment, we’ll start creating some simple waves.

10 responses so far

Magical!

Jul 02 2010

I made a funneh:

I’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

12 responses so far

FiTC San Francisco

Jun 26 2010

A couple more travel items on my agenda this year. First, I’ll be going on my annual (nearly annual anyway) family trip to Japan in the beginning of July. I’ll be there for a couple of weeks. We stay with my wife’s family in Kuwanashi, near Nagoya, on the edge of a mountain range, rice fields and farms on every side. You probably won’t see much (if any) of me on IM or twitter, though I’ll probably make a few blog posts, more likely at keithpeters.org than here. I look forward to some very scenic runs out there though. We have plenty of day trips planned, and we’ll be driving to Kyoto to spend a couple of days there as well.

After that, in August, I’m off to FiTC’s San Francisco debut! I’ve always loved SF. When I was younger, it was my goal to eventually live there. That’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’s still a great place that I love to visit. I’ve been there for two Flash Forwards, and a number of times for other things. I’m really glad that FiTC has taken ownership of the city, giving me an excuse to get out there again.

One of the highlights this year is that Shawn has gotten Yugo Nakamura out from Tokyo to speak. Yugo is one of the – if not THE – 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. :)

There are the usual assortment of other great speakers as well. I’ll be doing my “Programming Art” presentation. This being my last conference speaking engagement of the year, it’s most likely the last chance you’ll have to see this particular talk.

Another first is that I’ve finally convinced my wife and daughter to come out this time! I’m excited to get to introduce them to some of my world wide friends. I’m hoping that if you all tell them how awesome and godlike I am, they’ll give me a little more respect at home. :) (Just kidding!) Anyway, this also means I’ll probably be out doing a bit more site seeing during the day, and probably taking it pretty easy at night.

Hope to see you in SF. Oh, and by the way, if you sign up and use the code “bit101″, you should score a 10% discount off your tickets.

One response so far

FlashBelt Monday Run!

Jun 09 2010

The FlashBelt Run is on! Monday morning, June 14, nice and early. I’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 B.
Brandon M.
Terry P.

But no need to RSVP. I think we’ll just leave from the front of the hotel (Holiday Inn Metrodome) right around 7:00. Just show up there with running gear. I’ll post any changes in this post, so check back right here.

12 responses so far

Older posts »