<?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>Wouter Hisschemöller &#187; Wouter</title>
	<atom:link href="http://www.hisschemoller.com/author/wouter/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.hisschemoller.com</link>
	<description>Flash actionscript and audio programming</description>
	<lastBuildDate>Fri, 09 Apr 2010 20:32:43 +0000</lastBuildDate>
	
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Audio Editor 1.0</title>
		<link>http://www.hisschemoller.com/2010/audio-editor-1-0/</link>
		<comments>http://www.hisschemoller.com/2010/audio-editor-1-0/#comments</comments>
		<pubDate>Fri, 09 Apr 2010 20:30:05 +0000</pubDate>
		<dc:creator>Wouter</dc:creator>
				<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.hisschemoller.com/?p=527</guid>
		<description><![CDATA[A useful application!
I posted a lot of experimental stuff on this weblog over the past year. Or components that might have their use when built into proper applications. But this is my first web app that&#8217;s useful on it&#8217;s own.
This is a simple Flash audio editor that works in the browser. Everything it does is [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.hisschemoller.com/2010/audio-editor-1-0/audioeditor1/" rel="attachment wp-att-528"><img src="http://www.hisschemoller.com/wp-content/uploads/2010/04/audioeditor1.gif" alt="Audio Editor 1.0" title="AudioEditor10" width="285" height="171" class="alignright size-full wp-image-528" /></a>A useful application!</p>
<p>I posted a lot of experimental stuff on this weblog over the past year. Or components that might have their use when built into proper applications. But this is my first web app that&#8217;s useful on it&#8217;s own.</p>
<p>This is a simple Flash audio editor that works in the browser. Everything it does is done by ActionScript code inside the application. There&#8217;s no backend that does the difficult work. So it would function just as well in the standalone Flash Player or exported as an Air application as it does in the browser.</p>
<p><span id="more-527"></span><br />
This audio editor has only a very basic set of features. Here&#8217;s the things it can do:</p>
<ul>
<li>Open mono and stereo WAV and MP3 files.</li>
<li>Select part of the audio file by graphically adjusting the start and end point.</li>
<li>Change the pitch by adjusting the playback speed.</li>
<li>Reverse the file so it plays backwards.</li>
<li>The result of these adjustments (start and end, pitch, reverse) can be saved as a new stereo WAV file.</li>
</ul>
<h1>The Flash file</h1>
<div style="position:relative; width:540px; height:540px;">

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="fm_app_635623902"
			align="left"
			class="flashmovie"
			width="540"
			height="540">
	<param name="movie" value="http://www.hisschemoller.com/flash/v013_audioeditor/static/swf/app.swf" />
	<param name="menu" value="false" />
	<param name="quality" value="best" />
	<param name="scale" value="noscale" />
	<param name="bgcolor" value="#FFFFFF" />
	<param name="base" value="http://www.hisschemoller.com/flash/v013_audioeditor/static/swf/" />
	<!--[if !IE]>-->
	<object	type="application/x-shockwave-flash"
			data="http://www.hisschemoller.com/flash/v013_audioeditor/static/swf/app.swf"
			name="fm_app_635623902"
			align="left"
			width="540"
			height="540">
		<param name="menu" value="false" />
		<param name="quality" value="best" />
		<param name="scale" value="noscale" />
		<param name="bgcolor" value="#FFFFFF" />
		<param name="base" value="http://www.hisschemoller.com/flash/v013_audioeditor/static/swf/" />
	<!--<![endif]-->
		
<p><a href="http://adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></p>

	<!--[if !IE]>-->
	</object>
	<!--<![endif]-->
</object></div>
<p><a href="http://www.hisschemoller.com/flash/v013_audioeditor/audioeditor_1_0.zip">Download the source files here.</a></p>
<h1>Code</h1>
<p>This project is built on the PureMVC framework again. It&#8217;s what I&#8217;ve been using for all my projects the last half year and I&#8217;m still really happy with it. The code gets more complicated with each project but I still have a clear overview of where everything is and I can even find my way quickly around older projects.</p>
<p>Here&#8217;s a short overview of the main building blocks of the audio engine:</p>
<div id="attachment_548" class="wp-caption alignleft" style="width: 550px"><img src="http://www.hisschemoller.com/wp-content/uploads/2010/04/audioeditor_engineoverview.jpg" alt="Audio engine overview" title="Audio engine overview" width="540" height="420" class="size-full wp-image-548" /><p class="wp-caption-text">Audio engine overview</p></div>
<ul>
<li><strong>AudioDriverProxy</strong> listens to the SampleDataEvent. On each event it sends a request to the audio engine (AudioEngineProxy) to fill the buffer with samples.</li>
<li><strong>AudioEngineProxy</strong> holds all the instruments (of type IAudioInstrument) that produce sound. When it receives the request for samples from the audio driver it passes this request on to all the instruments that are registered with the engine.</li>
<li><strong>IAudioInstrument</strong> is (the interface for) a general instrument. An instrument doesn&#8217;t generate sound itself, but it maintains a list of IAudioProcessor objects that produce the actual audio. Each processor is a note that the instrument currently plays. So if an instrument was to play a three note chord three processors would be added to the list. And when a note is finished the processor is removed from the list. Besides that IAudioInstrument has an API for the instrument to be played. These are MIDI inspired functions like noteOn(), noteOff() and programChange().</li>
<li><strong>IAudioProcessor</strong> is the object that produces sound. When an instrument receives a buffer from the audio engine it passes the buffer on to each of its processors. The processor loops through all the samples in the buffer and adds its own values to it. An IAudioProcessor can generate sound like a synthesizer or play back existing sound like a sampler. It doesn&#8217;t matter as long as it implements the IAudioProcessor interface. </li>
<li><strong>AudioOutputProxy</strong> is the last stage in the audio generation process. Once all instruments have contributed their sounds to the buffer, the audio output is the last one that gets the buffer with sample data from the audio engine. Here final adjustments to the sound can be made. In the case of the audio editor the only adjustment that can be made is to set the overall output volume.</li>
</ul>
<p>The audio editor is a really simple implementation of this audio engine: There is only one instrument &#8211; the editor itself (WaveEditorProxy) &#8211; and it can play only one sound at a time: the audio being edited (PitchedSampleProcessor as IAudioProcessor).</p>
<div style="position:relative; width:540px; height:200px;">
<div id="attachment_537" class="wp-caption alignleft" style="width: 310px"><img src="http://www.hisschemoller.com/wp-content/uploads/2010/04/harrington1200.jpg" alt="The Harrington 1200" title="harrington1200" width="300" height="168" class="size-full wp-image-537" /><p class="wp-caption-text">The Harrington 1200, a state of the art songwriting computer.</p></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.hisschemoller.com/2010/audio-editor-1-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Animation &amp; audio synchronization</title>
		<link>http://www.hisschemoller.com/2010/animation-audio-synchronization/</link>
		<comments>http://www.hisschemoller.com/2010/animation-audio-synchronization/#comments</comments>
		<pubDate>Mon, 08 Mar 2010 22:32:03 +0000</pubDate>
		<dc:creator>Wouter</dc:creator>
				<category><![CDATA[ActionScript]]></category>

		<guid isPermaLink="false">http://www.hisschemoller.com/?p=488</guid>
		<description><![CDATA[It&#8217;s not that easy to synchronize programmed animation and dynamic sound in Flash. To have something happen on screen at exactly the same time a sound starts to play.
I thought about it a bit and came up with two different scenarios where audio and visuals need to be synchronized:

The first is where a sound plays [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.hisschemoller.com/2010/animation-audio-synchronization"><img src="http://www.hisschemoller.com/wp-content/uploads/2010/03/latency_screenshot.gif" alt="" title="Sync test screenshot" width="275" height="241" class="alignright size-full wp-image-489" /></a></a>It&#8217;s not that easy to synchronize programmed animation and dynamic sound in Flash. To have something happen on screen at exactly the same time a sound starts to play.</p>
<p>I thought about it a bit and came up with two different scenarios where audio and visuals need to be synchronized:</p>
<ol>
<li>The first is where a sound plays and something visual on screen happens to accompany that audio event.</li>
<li>The second is the other way around. Something happens on screen that should be accompanied by a sound.</li>
</ol>
<p>In the first case the animation is the initiator, in the second case the sound. For the second case I included a Flash example here with the source code available.</p>
<p><span id="more-488"></span></p>
<h1>1. Animation follows audio</h1>
<p>This is the simpler scenario. For example: There&#8217;s an online drum machine built in Flash that plays a drum sound on every beat. A kick drum in a techno track for example. On the machine&#8217;s interface there&#8217;s a small red LED light (a MovieClip) that should blink each time the drum hits.</p>
<p>The drum machine has a steady rhythm set in BPM (Beats Per Minute). So once the machine has started it&#8217;s always known when the next drum hit will happen. Here&#8217;s a graph of the events:</p>
<p><img class="alignleft size-full wp-image-490" title="Animation follows audio events." src="http://www.hisschemoller.com/wp-content/uploads/2010/03/latency_graph1.jpg" alt="" width="540" height="137" /></p>
<ul>
<li>(a), (b), (c) &#8230; are the moments in time when a SampleDataEvent is received and the buffer is filled with samples.</li>
<li>(p) is where the drum hit should happen. Because the drum BPM and buffer refresh rate are completely independent the drum hit will almost always start somewhere between two buffer refreshes.</li>
<li>(q) is where the drum sound is actually heard through the speakers. There is a delay between when the samples are sent out from Flash to when they are played through the speakers. This is the latency; the time needed for the soundcard to process the samples and send them as analog audio to the soundcard&#8217;s outputs. Latency is the duration from (p) to (q).</li>
</ul>
<p>To synchronize the two it&#8217;s a simple addition. Duration (a)(p) plus duration (p)(q).</p>
<ul>
<li>(a)(p) is the time from the first sample in the buffer to the first sample of the drum hit (and to convert this duration in samples to a duration in milliseconds it must be divided by 44.1 (sample rate / 1000)).</li>
<li>(p)(q) is the latency. That&#8217;s <font face="monospace">((SampleDataEvent.position / 44.1) &#8211; SoundChannelObject.position)</font>. (See the <a href="http://help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/events/SampleDataEvent.html">AS3.0 Language reference on SampleDataEvent</a>.)</li>
<li>The result is the total delay in milliseconds. A Timer could be started when the buffer is filled at (a) so that the LED blinks at the frame nearest (q).</li>
</ul>
<h1>2. Audio follows animation</h1>
<div style="position:relative; width:540px; height:400px;">

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="fm_app_1682259195"
			align="left"
			class="flashmovie"
			width="400"
			height="400">
	<param name="movie" value="http://www.hisschemoller.com/flash/v015_latency/static/swf/app.swf" />
	<param name="menu" value="false" />
	<param name="quality" value="best" />
	<param name="scale" value="noscale" />
	<param name="bgcolor" value="#FFFFFF" />
	<param name="base" value="http://www.hisschemoller.com/flash/v015_latency/static/swf/" />
	<!--[if !IE]>-->
	<object	type="application/x-shockwave-flash"
			data="http://www.hisschemoller.com/flash/v015_latency/static/swf/app.swf"
			name="fm_app_1682259195"
			align="left"
			width="400"
			height="400">
		<param name="menu" value="false" />
		<param name="quality" value="best" />
		<param name="scale" value="noscale" />
		<param name="bgcolor" value="#FFFFFF" />
		<param name="base" value="http://www.hisschemoller.com/flash/v015_latency/static/swf/" />
	<!--<![endif]-->
		
<p><a href="http://adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></p>

	<!--[if !IE]>-->
	</object>
	<!--<![endif]-->
</object></div>
<p><a href="http://www.hisschemoller.com/flash/v015_latency/animation_sound_sync.zip">Download the source code of this example</a>.</p>
<p>This second scenario is a bit more complicated. Hopefully someone else has a simpler solution. But until then this is the solution I use.</p>
<p>Click the &#8216;Start&#8217; button in the example above: Balls bounce on the floor and each time one of them hits the floor a &#8216;boing&#8217; sound plays. A simple implementation of <a href="http://en.wikipedia.org/wiki/Newton%27s_laws_of_motion">Newton&#8217;s laws of motion</a>.</p>
<p>A graph of the events:<br />
<img src="http://www.hisschemoller.com/wp-content/uploads/2010/03/latency_graph2.jpg" alt="" title="Audio follows animation." width="540" height="225" class="alignleft size-full wp-image-497" /></p>
<ul>
<li>(a), (b), (c) &#8230; are the times when a buffer is requested and filled. Same as in the previous example.</li>
<li>(1), (2), (3) &#8230; are frames where Flash updates the screen (Event.ENTER_FRAME).</li>
<li>(p) is where the ball hitting the floor is calculated to happen.</li>
<li>(q) is where the sound is heard.</li>
<li>(r) is where the ball hitting the floor is drawn on screen.</li>
</ul>
<h1>What&#8217;s going on?</h1>
<p>The trick is to delay drawing the animation for a &#8216;latency&#8217; amount of time. </p>
<ol>
<li>First calculate where the ball WOULD be (but NOT draw it).</li>
<li>Fire a sound if the calculation shows the ball would hit the floor.</li>
<li>Draw the animation with a delay determined by the latency.</li>
</ol>
<p>That is the principle of how it works. The actual implementation is a bit more involved:</p>
<ul>
<li>At (a), (b), (c) &#8230; (each SampleDataEvent.SAMPLE_DATA) the position of the ball is calculated. The current time and position of the ball are stored in a Vector called _history.</li>
<li>If the calculation shows the ball will hit the floor during the current buffer (at  (p)):
<ul>
<li>The time from the start of the buffer till the hit is calculated (a)(p).</li>
<li>The sound is started at time offset (a)(p) in the buffer.</li>
</ul>
</li>
<li>Meanwhile at (1), (2), (3) &#8230; (at each Event.ENTER_FRAME) the screen is updated.</li>
<li>To know where to draw the ball the _history of the ball is used.</li>
<li>First get the current time and subtract the latency. This is the moment in the past that should be drawn on screen.</li>
<li>Search in the balls _history for that moment in the past. </li>
<li>It&#8217;s very unlikely however that the position at exactly the required millisecond is stored. More likely somewhere in between two stored moments in time. So get the closest positions before and after the requested time and use linear interpolation to draw the ball at the right position between the &#8216;before&#8217; and &#8216;after&#8217; records.</li>
</ul>
<h1>So what&#8217;s going on?</h1>
<p>I&#8217;m afraid this explanation might be more complex than the actual code. So I&#8217;ll add some of the relevant ActionScript. </p>
<p>To understand it you should know that there is an AudioDriver class that listens to the SampleDataEvent. Each SampleDataEvent it sends an ENTER_BUFFER notification (this is PureMVC) to notify all Ball instances to store their position. To do this the function enterBuffer is called on each Ball instance:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p488code3'); return false;">View Code</a> ACTIONSCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p4883"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
</pre></td><td class="code" id="p488code3"><pre class="actionscript" style="font-family:monospace;"><span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> enterBuffer<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> : <span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">var</span> hit : <span style="color: #0066CC;">Boolean</span>;
&nbsp;
    <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span>_isDragging<span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#123;</span>
        _vy = <span style="color: #cc66cc;">0</span>;
    <span style="color: #66cc66;">&#125;</span>
    <span style="color: #b1b100;">else</span>
    <span style="color: #66cc66;">&#123;</span>
        _vy += _gravity;
        <span style="color: #0066CC;">_y</span> += _vy;
&nbsp;
        <span style="color: #808080; font-style: italic;">/** If the ball hits the floor. */</span>
        <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">_y</span> <span style="color: #66cc66;">&gt;</span> _floorY - _radius<span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">var</span> distance : <span style="color: #0066CC;">Number</span> = _vy;
            <span style="color: #000000; font-weight: bold;">var</span> overlap : <span style="color: #0066CC;">Number</span> = <span style="color: #0066CC;">_y</span> + _radius - _floorY;
            _hitAlpha = <span style="color: #66cc66;">&#40;</span>distance - overlap<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">/</span> distance;
&nbsp;
            <span style="color: #0066CC;">_y</span> = _floorY - _radius - overlap;
            _vy <span style="color: #66cc66;">*</span>= -<span style="color: #cc66cc;">1</span>;
            hit = <span style="color: #000000; font-weight: bold;">true</span>;
&nbsp;
            dispatchEvent<span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> Event<span style="color: #66cc66;">&#40;</span>Ball.<span style="color: #006600;">BOUNCE</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
        <span style="color: #66cc66;">&#125;</span>
    <span style="color: #66cc66;">&#125;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/** Store as data for later use. */</span>
    _history.<span style="color: #0066CC;">splice</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">0</span>, <span style="color: #000000; font-weight: bold;">new</span> BallVO<span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">_x</span>, <span style="color: #0066CC;">_y</span>, _vx, _vy, hit<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #808080; font-style: italic;">/** Keep maximum 100 history items so the maximum latency is buffer * 100. */</span>
    <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span>_history.<span style="color: #0066CC;">length</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #cc66cc;">100</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">var</span> n : <span style="color: #0066CC;">int</span> = _history.<span style="color: #0066CC;">length</span>;
        <span style="color: #b1b100;">while</span><span style="color: #66cc66;">&#40;</span>--n <span style="color: #66cc66;">&gt;</span> <span style="color: #cc66cc;">99</span><span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#123;</span>
            _history.<span style="color: #0066CC;">pop</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
        <span style="color: #66cc66;">&#125;</span>
    <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre></td></tr></table></div>

<p>This function does what was expected: A new position is calculated and stored in a BallVO value object, the BallVO is added to the _history and a bit of maintenance is done: Keep _history&#8217;s length within bounds.</p>
<p>The only other thing is the _isDragging Boolean. Balls can be dragged to a new position.</p>
<p>The AudioDriver also sends an ENTER_FRAME notification. This is just like a regular Event.ENTER_FRAME from a DisplayObject except that it has a AudioStreamInfoVO value object as an argument. The AudioStreamInfoVO has a &#8216;latencyInMS&#8217; property that holds (as you&#8217;ll have guessed) the latency in milliseconds that the animation should be delayed.</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p488code4'); return false;">View Code</a> ACTIONSCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p4884"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
</pre></td><td class="code" id="p488code4"><pre class="actionscript" style="font-family:monospace;"><span style="color: #0066CC;">public</span> <span style="color: #000000; font-weight: bold;">function</span> enterFrame<span style="color: #66cc66;">&#40;</span>infoVO : AudioStreamInfoVO<span style="color: #66cc66;">&#41;</span> : <span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
    graphics.<span style="color: #0066CC;">clear</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
    graphics.<span style="color: #0066CC;">lineStyle</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span>, 0xFFFFFF<span style="color: #66cc66;">&#41;</span>;
    graphics.<span style="color: #0066CC;">beginFill</span><span style="color: #66cc66;">&#40;</span>0xBBBBBB, <span style="color: #cc66cc;">0.1</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
    <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span>_isDragging<span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#123;</span>
        graphics.<span style="color: #006600;">drawCircle</span><span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">_x</span>, <span style="color: #0066CC;">_y</span>, _radius<span style="color: #66cc66;">&#41;</span>;
    <span style="color: #66cc66;">&#125;</span>
    <span style="color: #b1b100;">else</span>
    <span style="color: #66cc66;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">var</span> <span style="color: #0066CC;">time</span> : <span style="color: #0066CC;">Number</span> = <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #0066CC;">Date</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #0066CC;">getTime</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> - infoVO.<span style="color: #006600;">latencyInMS</span>;
&nbsp;
        <span style="color: #000000; font-weight: bold;">var</span> i : <span style="color: #0066CC;">int</span> = -<span style="color: #cc66cc;">1</span>;
        <span style="color: #000000; font-weight: bold;">var</span> n : <span style="color: #0066CC;">int</span> = _history.<span style="color: #0066CC;">length</span>;
        <span style="color: #b1b100;">while</span><span style="color: #66cc66;">&#40;</span>++i <span style="color: #66cc66;">&lt;</span> n<span style="color: #66cc66;">&#41;</span>
        <span style="color: #66cc66;">&#123;</span>
            <span style="color: #808080; font-style: italic;">/** Get the data from immediately before and after 'time'. */</span>
            <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span>_history<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>.<span style="color: #0066CC;">time</span> <span style="color: #66cc66;">&lt;</span> <span style="color: #0066CC;">time</span> <span style="color: #66cc66;">&amp;&amp;</span> i <span style="color: #66cc66;">&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>
            <span style="color: #66cc66;">&#123;</span>
                <span style="color: #000000; font-weight: bold;">var</span> before : BallVO = _history<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>;
                <span style="color: #000000; font-weight: bold;">var</span> after : BallVO = _history<span style="color: #66cc66;">&#91;</span>i - <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#93;</span>;
                <span style="color: #000000; font-weight: bold;">var</span> alpha : <span style="color: #0066CC;">Number</span> = <span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">time</span> - before.<span style="color: #0066CC;">time</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">/</span> <span style="color: #66cc66;">&#40;</span>after.<span style="color: #0066CC;">time</span> - before.<span style="color: #0066CC;">time</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
                <span style="color: #808080; font-style: italic;">/** If a bounce on the floor happened between before and after. */</span>
                <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span>before.<span style="color: #006600;">vy</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #cc66cc;">0</span> <span style="color: #66cc66;">&amp;&amp;</span> after.<span style="color: #006600;">vy</span> <span style="color: #66cc66;">&lt;</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span>
                <span style="color: #66cc66;">&#123;</span>
                    <span style="color: #808080; font-style: italic;">/** Linear interpolation to correct the vertical position. */</span>
                    <span style="color: #000000; font-weight: bold;">var</span> maxY : <span style="color: #0066CC;">Number</span> = _floorY - _radius;
                    <span style="color: #000000; font-weight: bold;">var</span> partBeforeBounce : <span style="color: #0066CC;">Number</span> = maxY - before.<span style="color: #006600;">y</span>;
                    <span style="color: #000000; font-weight: bold;">var</span> partAfterBounce : <span style="color: #0066CC;">Number</span> = maxY - after.<span style="color: #006600;">y</span>;
                    <span style="color: #000000; font-weight: bold;">var</span> bounceAlpha : <span style="color: #0066CC;">Number</span> = partBeforeBounce <span style="color: #66cc66;">/</span> <span style="color: #66cc66;">&#40;</span>partBeforeBounce + partAfterBounce<span style="color: #66cc66;">&#41;</span>;
&nbsp;
                    <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span>alpha <span style="color: #66cc66;">&lt;</span> bounceAlpha<span style="color: #66cc66;">&#41;</span>
                    <span style="color: #66cc66;">&#123;</span>
                        <span style="color: #000000; font-weight: bold;">var</span> y : <span style="color: #0066CC;">Number</span> = before.<span style="color: #006600;">y</span> + <span style="color: #66cc66;">&#40;</span>before.<span style="color: #006600;">vy</span> <span style="color: #66cc66;">*</span> bounceAlpha<span style="color: #66cc66;">&#41;</span>;
                    <span style="color: #66cc66;">&#125;</span>
                    <span style="color: #b1b100;">else</span>
                    <span style="color: #66cc66;">&#123;</span>
                        y = after.<span style="color: #006600;">y</span> + <span style="color: #66cc66;">&#40;</span>before.<span style="color: #006600;">vy</span> <span style="color: #66cc66;">*</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1</span> - bounceAlpha<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
                    <span style="color: #66cc66;">&#125;</span>
                <span style="color: #66cc66;">&#125;</span>
                <span style="color: #b1b100;">else</span>
                <span style="color: #66cc66;">&#123;</span>
                    <span style="color: #808080; font-style: italic;">/** Regular linear interpolation for a ball in mid flight. */</span>
                    y = before.<span style="color: #006600;">y</span> + <span style="color: #66cc66;">&#40;</span>alpha <span style="color: #66cc66;">*</span> <span style="color: #66cc66;">&#40;</span>after.<span style="color: #006600;">y</span> - before.<span style="color: #006600;">y</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
                <span style="color: #66cc66;">&#125;</span>
&nbsp;
                <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span>before.<span style="color: #006600;">hit</span><span style="color: #66cc66;">&#41;</span> graphics.<span style="color: #0066CC;">beginFill</span><span style="color: #66cc66;">&#40;</span>0xFFFFFF<span style="color: #66cc66;">&#41;</span>;
                graphics.<span style="color: #006600;">drawCircle</span><span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">_x</span>, y, _radius<span style="color: #66cc66;">&#41;</span>;
&nbsp;
                <span style="color: #b1b100;">break</span>;
            <span style="color: #66cc66;">&#125;</span>
        <span style="color: #66cc66;">&#125;</span>
    <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span></pre></td></tr></table></div>

<p>So in this function there&#8217;s a variable &#8216;time&#8217; which holds the moment in time in the past that must be drawn, &#8216;before.time&#8217; and &#8216;after.time&#8217; and a resulting &#8216;alpha&#8217; which is the interpolation value between before and after. The resulting ball position calculation is this:</p>
<p><font face="monospace">y = before.y + (alpha * (after.y &#8211; before.y));</font></p>
<p><div id="attachment_510" class="wp-caption alignright" style="width: 160px"><img src="http://www.hisschemoller.com/wp-content/uploads/2010/03/isaac_newton_small.jpg" alt="Isaac Newton" title="Isaac Newton" width="150" height="159" class="size-full wp-image-510" /><p class="wp-caption-text">Isaac Newton</p></div>The new thing here is that if the ball hits the floor somewhere between before and after  (if(before.vy > 0 &#038;&#038; after.vy < 0)), then the regular linear interpolation doesn&#8217;t give the right visual result and some extra code is necessary. But that&#8217;s another story.</p>
<p>All this code is not optimized at all. In this example I wanted to keep it all as clear as possible to read and understand. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.hisschemoller.com/2010/animation-audio-synchronization/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Augmented reality and sound</title>
		<link>http://www.hisschemoller.com/2010/augmented-reality-and-sound/</link>
		<comments>http://www.hisschemoller.com/2010/augmented-reality-and-sound/#comments</comments>
		<pubDate>Fri, 19 Feb 2010 13:01:00 +0000</pubDate>
		<dc:creator>Wouter</dc:creator>
				<category><![CDATA[ActionScript]]></category>

		<guid isPermaLink="false">http://www.hisschemoller.com/?p=343</guid>
		<description><![CDATA[Yes I know, it&#8217;s the hype of 2009 and we&#8217;re in 2010 now, but I haven&#8217;t seen anything yet where augmented reality is combined with sound. If you do know examples of augmented reality and audio, please leave a comment. I&#8217;d love to see what other people do with it.
This is a small experiment I [...]]]></description>
			<content:encoded><![CDATA[<p><a rel="attachment wp-att-344" href="http://www.hisschemoller.com/2010/augmented-reality-and-sound/flartoolkit/"><img class="alignright size-full wp-image-344" title="flartoolkit" src="http://www.hisschemoller.com/wp-content/uploads/2010/02/flartoolkit.jpg" alt="" width="263" height="186" /></a>Yes I know, it&#8217;s the hype of 2009 and we&#8217;re in 2010 now, but I haven&#8217;t seen anything yet where augmented reality is combined with sound. If you do know examples of augmented reality and audio, please leave a comment. I&#8217;d love to see what other people do with it.</p>
<p>This is a small experiment I started half a year ago but never finished. I looked it up again last week because I needed a Flash AR example for a project at work. Here I improved it a bit to make it more presentable.</p>
<p><span id="more-343"></span></p>
<h1>What it is</h1>
<p>It&#8217;s basically a sort of <a href="http://en.wikipedia.org/wiki/Theremin">theremin</a>. Hold the marker in front of your computer&#8217;s webcam and a sound starts to play. Move the marker and the sound changes.</p>
<h1>The Flash file</h1>
<div style="position:relative; width:540px; height:280px;">

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="fm_v010_flartoolkit_1284520187"
			align="left"
			class="flashmovie"
			width="460"
			height="280">
	<param name="movie" value="http://www.hisschemoller.com/flash/v010_flartoolkit/static/swf/v010_flartoolkit.swf" />
	<param name="menu" value="false" />
	<param name="quality" value="best" />
	<param name="scale" value="noscale" />
	<param name="bgcolor" value="#112233" />
	<param name="base" value="http://www.hisschemoller.com/flash/v010_flartoolkit/static/swf/" />
	<!--[if !IE]>-->
	<object	type="application/x-shockwave-flash"
			data="http://www.hisschemoller.com/flash/v010_flartoolkit/static/swf/v010_flartoolkit.swf"
			name="fm_v010_flartoolkit_1284520187"
			align="left"
			width="460"
			height="280">
		<param name="menu" value="false" />
		<param name="quality" value="best" />
		<param name="scale" value="noscale" />
		<param name="bgcolor" value="#112233" />
		<param name="base" value="http://www.hisschemoller.com/flash/v010_flartoolkit/static/swf/" />
	<!--<![endif]-->
		
<p><a href="http://adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></p>

	<!--[if !IE]>-->
	</object>
	<!--<![endif]-->
</object></div>
<p><a href="http://www.hisschemoller.com/flash/v010_flartoolkit/augmented_reality_and_sound.zip">All source files can be downloaded here.</a> They&#8217;re a bit messy however. This was just a quick update to an abandoned older experiment, I didn&#8217;t take care to write clean code.</p>
<p>To try this you&#8217;ll need the marker to move in front of the webcam. <a href="http://www.hisschemoller.com/flash/v010_flartoolkit/static/bin/flarlogo-marker.pdf">Download it here as a PDF file</a>. Print the file and &#8211; for the best results &#8211; glue it on a piece of cardboard.</p>
<h1>The video</h1>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="400" height="238" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://vimeo.com/moogaloop.swf?clip_id=9495963&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" /><embed type="application/x-shockwave-flash" width="400" height="238" src="http://vimeo.com/moogaloop.swf?clip_id=9495963&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=00ADEF&amp;fullscreen=1" allowscriptaccess="always" allowfullscreen="true"></embed></object><br />
Because I know it&#8217;s a lot of hassle to download and print the marker I recorded a short demonstration screencap video to show how it all works.</p>
<h1>How to use it</h1>
<p>Click &#8220;Allow&#8221; on the Flash player settings screen. This allows Flash to switch on the webcam and use the images it films. Then hold the printed marker in front of the webcam to generate some sounds:</p>
<ul>
<li>With the marker at the center of the video a sine wave plays a C note.</li>
<li>Move the marker slowly up and the pitch rises in steps, move down and the pitch goes down. It plays a pentatonic scale in the key of C minor. Two octaves up and two down. With added flattened fifth to make it sound more bluesy.</li>
<li>Move the marker to the right to add vibrato. The more to the right the faster and the more intense the vibrato gets.</li>
<li>Move left from the center and a &#8216;note repeat&#8217; effect starts. At the outer left edge of the webcam the repeat effect doubles in speed. When the marker is moved vertically at the left new notes start and combine with the previous notes that still play and produce a harp-like sound. Very nice.</li>
</ul>
<p>This idea could be taken a lot further. There&#8217;s more information to be had from the marker:</p>
<ul>
<li>The distance from the webcam can be measured. To lower the volume the farther the marker is away from the webcam for instance.</li>
<li>The three rotations in 3D are available: Rotation around the X, Y and Z axis.</li>
</ul>
<p>The only obstacle for direct musical use is the latency. The delay between a movement and hearing the resulting sound is too big to be able to play along with a record for example.</p>
<p>For the augmented reality code I used FLARToolkit. More information can be found at the <a href="http://www.libspark.org/wiki/saqoosha/FLARToolKit/en">English FLARToolKit page</a> and the <a href="http://saqoosha.net/en/flartoolkit/start-up-guide">Start Up Guide</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hisschemoller.com/2010/augmented-reality-and-sound/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>MP3 Wave Display 2</title>
		<link>http://www.hisschemoller.com/2010/mp3-wave-display-2/</link>
		<comments>http://www.hisschemoller.com/2010/mp3-wave-display-2/#comments</comments>
		<pubDate>Sun, 17 Jan 2010 19:18:24 +0000</pubDate>
		<dc:creator>Wouter</dc:creator>
				<category><![CDATA[ActionScript]]></category>

		<guid isPermaLink="false">http://www.hisschemoller.com/?p=290</guid>
		<description><![CDATA[Wave Display 2 is an improved version of the last one (in the previous post). A few things had to be rewritten in the code for waveform rendering, and there were some extra features I wanted to include to make the application a bit more interesting to use.
The new features in this version:

Audio playback. You [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_291" class="wp-caption alignright" style="width: 275px"><a href="http://www.hisschemoller.com/2010/mp3-wave-display-2/"><img src="http://www.hisschemoller.com/wp-content/uploads/2010/01/wavedisplay2.gif" alt="This version is orange." title="wavedisplay2" width="265" height="267" class="size-full wp-image-291" /></a><p class="wp-caption-text">MP3 wave display is orange.</p></div>
<p>Wave Display 2 is an improved version of the last one (in the <a href="http://www.hisschemoller.com/2010/mp3-wave-display/">previous post</a>). A few things had to be rewritten in the code for waveform rendering, and there were some extra features I wanted to include to make the application a bit more interesting to use.</p>
<p>The new features in this version:
<ul>
<li>Audio playback. You can now listen to the loaded MP3 file. Click &#8216;play mp3&#8242; or press the SPACE bar to listen.</li>
<li>Draggable start and end locators to select only part of the sound. Drag the &#8216;S&#8217; and &#8216;E&#8217; locators to set the start and end point.</li>
<li>Reverse playback. Click the &#8216;reverse&#8217; button to toggle reverse playback.</li>
<li>Adjustable playback speed. Drag the &#8216;transpose&#8217; slider to change the playback speed. The speed is adjusted so that the pitch changes from one octave down to one octave up in semitone steps.</li>
<li>Drag to zoom. Press and drag the mouse on the display area for finer control: Drag vertical to zoom and horizontal to move the waveform. I always really liked this behaviour in <a href="http://www.steinberg.net">Steinberg</a> <a href="http://www.steinberg.net/en/products/audioediting_product/audioediting_wavelab6.html">WaveLab</a> where I first saw it, and where I now copied it from.</li>
</ul>
<p><span id="more-290"></span><br />

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="fm_app_84357760"
			class="flashmovie"
			width="450"
			height="450">
	<param name="movie" value="http://www.hisschemoller.com/flash/v012_wavedisplay2/static/swf/app.swf" />
	<param name="menu" value="false" />
	<param name="quality" value="best" />
	<param name="scale" value="noscale" />
	<param name="base" value="http://www.hisschemoller.com/flash/v012_wavedisplay2/static/swf/" />
	<!--[if !IE]>-->
	<object	type="application/x-shockwave-flash"
			data="http://www.hisschemoller.com/flash/v012_wavedisplay2/static/swf/app.swf"
			name="fm_app_84357760"
			width="450"
			height="450">
		<param name="menu" value="false" />
		<param name="quality" value="best" />
		<param name="scale" value="noscale" />
		<param name="base" value="http://www.hisschemoller.com/flash/v012_wavedisplay2/static/swf/" />
	<!--<![endif]-->
		
<p><a href="http://adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></p>

	<!--[if !IE]>-->
	</object>
	<!--<![endif]-->
</object>
<p><a href="http://www.hisschemoller.com/flash/v012_wavedisplay2/mp3_wavedisplay2.zip">Click here to download all source files in a ZIP.</a></p>
<h1>Transpose by playback speed</h1>
<p>Transpose works fairly straightforward. The transpose value is set with the slider. And every time the slider is moved the new transpose value is stored.</p>
<p>Each time playback is started, the transpose value is passed to the class PitchedSamplePlayer that processes the sound. However,  PitchedSamplePlayer uses a multiplier to set the playback speed instead of a semitone value. For example 0.5 is playback at half speed. So the transpose value in semitones must be converted to playback speed. That&#8217;s done with this conversion:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p290code7'); return false;">View Code</a> ACTIONSCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p2907"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code" id="p290code7"><pre class="actionscript" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/**
 * Covert semitone shift to playback speed multiplier.
 * For example: -12 returns 0.5, 12 returns 2, 0 returns 1.
 */</span>
<span style="color: #0066CC;">public</span> <span style="color: #0066CC;">static</span> <span style="color: #000000; font-weight: bold;">function</span> semitoneToRate<span style="color: #66cc66;">&#40;</span>semitone : <span style="color: #0066CC;">Number</span><span style="color: #66cc66;">&#41;</span> : <span style="color: #0066CC;">Number</span>
<span style="color: #66cc66;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0066CC;">Math</span>.<span style="color: #0066CC;">pow</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">2</span>, semitone <span style="color: #66cc66;">/</span> <span style="color: #cc66cc;">12</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span></pre></td></tr></table></div>

<p>Then inside PitchedSamplePlayer linear interpolation is used to change the playback speed and maintain acceptable sound quality. I took the code for pitching a sample from this <a href="http://blog.andre-michelle.com/2009/pitch-mp3/">MP3 Pitch example</a> by <a href="http://www.andre-michelle.com">Andre Michelle</a>, which builds on <a href="http://www.leebrimelow.com/">Lee Brimelow</a>&#8217;s post <a href="http://theflashblog.com/?p=1129">Adjusting audio pitch in Flash Player 10</a>.</p>
<h1>Reverse playback</h1>
<p>The display and the sample player both read samples from a ByteArray. I had the choice of reversing the whole ByteArray or leaving the ByteArray as it is and read from it backwards. From end to start.</p>
<p>It seemed best to reverse the order of the ByteArray because the audio processing and display rendering code can stay the same and as short and fast as possible:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p290code8'); return false;">View Code</a> ACTIONSCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p2908"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code" id="p290code8"><pre class="actionscript" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/** Reverse the order of samples in samplerPresetVO.soundData.byteArray. */</span>
<span style="color: #000000; font-weight: bold;">var</span> bytesPerSample : <span style="color: #0066CC;">int</span> = AudioDriverProxy.<span style="color: #006600;">BYTES_PER_SAMPLE</span>;
<span style="color: #000000; font-weight: bold;">var</span> numBytes : <span style="color: #0066CC;">Number</span> = samplerPresetVO.<span style="color: #006600;">soundData</span>.<span style="color: #006600;">numSamplesTotal</span> <span style="color: #66cc66;">*</span> bytesPerSample;
<span style="color: #000000; font-weight: bold;">var</span> tempByteArray : ByteArray = <span style="color: #000000; font-weight: bold;">new</span> ByteArray<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
samplerPresetVO.<span style="color: #006600;">soundData</span>.<span style="color: #006600;">byteArray</span>.<span style="color: #0066CC;">position</span> = <span style="color: #cc66cc;">0</span>;
tempByteArray.<span style="color: #006600;">writeBytes</span><span style="color: #66cc66;">&#40;</span>samplerPresetVO.<span style="color: #006600;">soundData</span>.<span style="color: #006600;">byteArray</span><span style="color: #66cc66;">&#41;</span>;
samplerPresetVO.<span style="color: #006600;">soundData</span>.<span style="color: #006600;">byteArray</span>.<span style="color: #0066CC;">position</span> = <span style="color: #cc66cc;">0</span>;
&nbsp;
<span style="color: #b1b100;">for</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">var</span> offset : <span style="color: #0066CC;">Number</span> = <span style="color: #66cc66;">&#40;</span>numBytes - bytesPerSample<span style="color: #66cc66;">&#41;</span>; offset <span style="color: #66cc66;">&gt;</span>= <span style="color: #cc66cc;">0</span>; offset -= bytesPerSample<span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
   samplerPresetVO.<span style="color: #006600;">soundData</span>.<span style="color: #006600;">byteArray</span>.<span style="color: #006600;">writeBytes</span><span style="color: #66cc66;">&#40;</span>tempByteArray, offset, bytesPerSample<span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span></pre></td></tr></table></div>

<p>What happens here is:
<ul>
<li>Copy all sample data to a temporary ByteArray.</li>
<li>Read two samples (or one stereo sample) at a time from the temporary ByteArray, reading backwards from end to start.</li>
<li>And write each stereo sample to the original ByteArray, writing normally from start to end.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.hisschemoller.com/2010/mp3-wave-display-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>MP3 Wave Display</title>
		<link>http://www.hisschemoller.com/2010/mp3-wave-display/</link>
		<comments>http://www.hisschemoller.com/2010/mp3-wave-display/#comments</comments>
		<pubDate>Sat, 09 Jan 2010 18:02:09 +0000</pubDate>
		<dc:creator>Wouter</dc:creator>
				<category><![CDATA[ActionScript]]></category>

		<guid isPermaLink="false">http://www.hisschemoller.com/?p=250</guid>
		<description><![CDATA[2010! A new year, a new decennium even! This year I want to be more consistent in publishing articles on this weblog. That&#8217;s my new year&#8217;s resolution.
The first one of the new year is more of a utility than a complete application. It&#8217;s a wave display; It loads an MP3 file and displays the sound [...]]]></description>
			<content:encoded><![CDATA[<div id="attachment_251" class="wp-caption alignright" style="width: 290px"><a href="http://www.hisschemoller.com/2010/mp3-wave-display/"><img class="size-full wp-image-251" title="wavedisplay" src="http://www.hisschemoller.com/wp-content/uploads/2010/01/wavedisplay.gif" alt="The waveform display panel" width="280" height="260" /></a><p class="wp-caption-text">The waveform display</p></div>
<p>2010! A new year, a new decennium even! This year I want to be more consistent in publishing articles on this weblog. That&#8217;s my new year&#8217;s resolution.</p>
<p>The first one of the new year is more of a utility than a complete application. It&#8217;s a wave display; It loads an MP3 file and displays the sound as a graph of the waveform. It makes no sound. A simple waveform display like this might be a useful component in a larger application where audio needs to be edited. Here it&#8217;s on its own because I was figuring out how to best program such a component. So this application is more experimental than useful.</p>
<p><span id="more-250"></span><br />

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="fm_app_2140541984"
			class="flashmovie"
			width="450"
			height="450">
	<param name="movie" value="http://www.hisschemoller.com/flash/v011_wavedisplay/static/swf/app.swf" />
	<param name="menu" value="false" />
	<param name="quality" value="best" />
	<param name="scale" value="noscale" />
	<param name="base" value="http://www.hisschemoller.com/flash/v011_wavedisplay/static/swf/" />
	<!--[if !IE]>-->
	<object	type="application/x-shockwave-flash"
			data="http://www.hisschemoller.com/flash/v011_wavedisplay/static/swf/app.swf"
			name="fm_app_2140541984"
			width="450"
			height="450">
		<param name="menu" value="false" />
		<param name="quality" value="best" />
		<param name="scale" value="noscale" />
		<param name="base" value="http://www.hisschemoller.com/flash/v011_wavedisplay/static/swf/" />
	<!--<![endif]-->
		
<p><a href="http://adobe.com/go/getflashplayer"><img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player" /></a></p>

	<!--[if !IE]>-->
	</object>
	<!--<![endif]-->
</object>
<p><a href="flash/v011_wavedisplay/wavedisplay.zip">Click here to download all source files in a ZIP.</a></p>
<h1>How to use it</h1>
<p>A default MP3 file is loaded and displayed at startup. But you can load your own MP3. Click the &#8216;load mp3&#8242; button and browse to an MP3 file on your computer. Opening a large MP3 file might take a long time however. Best to try with short files. Five minutes or less for example.</p>
<p>Once the MP3 is loaded and displayed there&#8217;s several controls to zoom in closer on details of the waveform:</p>
<ul>
<li>Zoom in to a detail of the waveform with the &#8216;zoom horizontal&#8217; slider.</li>
<li>When zoomed in you can move through the waveform with the scrollbar directly under the waveform.</li>
<li>For more precise movement once zoomed in drag the mouse left or right on the waveform.</li>
<li>Magnify the waveform vertically with the &#8216;zoom vertical&#8217; slider. This is useful to inspect very quiet parts of the sound.</li>
</ul>
<p>Some information is shown above the display</p>
<ul>
<li>In Flash the sample rate is 44100 samples per second. When the waveform is at the highest zoom level, it shows one sample per pixel. (So one second of audio would take up 44100 pixels!)</li>
<li>At lower zoom levels each pixel displays the average amplitude of several pixels. The amount is displayed  at &#8217;samples per pixel&#8217;.</li>
<li>The first and last sample in view are shown at &#8216;first sample&#8217; and &#8216;last sample&#8217;.</li>
</ul>
<h1>Some notes on the ActionScript</h1>
<p>The biggest problem with the display was to get it to respond quick to zoom and position changes. It should use as little calculations as possible to refresh the display. Three things reduce the number of calculations (and so the processor load) here:</p>
<p>Each change in zoom level or position results in a changed portion of the waveform that is actually shown in the display. When the display needs updating, it&#8217;s first determined what the first and last sample are that will be displayed. Then only that portion of the file is processed. That means that especially at high zoom levels only a tiny fraction of the file needs to be calculated.</p>
<p>But at low zoom levels still a lot of samples need to be averaged: To show one minute of waveform 44100 x 60 = 2,646,000 samples must be processed. More than two and a half million! To reduce this number samples are skipped. The more samples there are, the more are skipped.</p>
<p>This bit of ActionScript shows how these two reductions are done:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p250code12'); return false;">View Code</a> ACTIONSCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p25012"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="code" id="p250code12"><pre class="actionscript" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/**
 * Sets the zoom level of the display. Measured in how many samples one horizontal pixel of the display represents.
 * @param inSamplesPerPixel : How many samples one horizontal pixel of the display represents.
 * @param inCenterSamplePosition : The center or focus of the zoom. 0.5 is the horizontal center. 
 */</span>
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> setCurrentSamplesPerPixel<span style="color: #66cc66;">&#40;</span>inSamplesPerPixel : <span style="color: #0066CC;">Number</span>, inCenterSamplePosition : <span style="color: #0066CC;">Number</span> = <span style="color: #cc66cc;">0.5</span><span style="color: #66cc66;">&#41;</span> : <span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span>inSamplesPerPixel == mCurrentSamplesPerPixel<span style="color: #66cc66;">&#41;</span> <span style="color: #b1b100;">return</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">// get the sample that is the center of the zoom</span>
  <span style="color: #000000; font-weight: bold;">var</span> centerSample : <span style="color: #0066CC;">int</span> = mFirstSampleInView + <span style="color: #66cc66;">&#40;</span>mNumSamplesInView <span style="color: #66cc66;">*</span> inCenterSamplePosition<span style="color: #66cc66;">&#41;</span>;
&nbsp;
  mCurrentSamplesPerPixel = <span style="color: #0066CC;">Math</span>.<span style="color: #0066CC;">max</span><span style="color: #66cc66;">&#40;</span>mMinSamplesPerPixel, <span style="color: #0066CC;">Math</span>.<span style="color: #0066CC;">min</span><span style="color: #66cc66;">&#40;</span>inSamplesPerPixel, mMaxSamplesPerPixel<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
  mNumSamplesInView = mCurrentSamplesPerPixel <span style="color: #66cc66;">*</span> mDisplayWidth;
  mFirstSampleInView = centerSample - <span style="color: #66cc66;">&#40;</span>mNumSamplesInView <span style="color: #66cc66;">*</span> inCenterSamplePosition<span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">// polling stuff</span>
  mPollingFrequency = <span style="color: #0066CC;">Math</span>.<span style="color: #0066CC;">ceil</span><span style="color: #66cc66;">&#40;</span>mCurrentSamplesPerPixel <span style="color: #66cc66;">/</span> <span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span>;
  mNumPolls = <span style="color: #0066CC;">int</span><span style="color: #66cc66;">&#40;</span>mCurrentSamplesPerPixel <span style="color: #66cc66;">/</span> mPollingFrequency<span style="color: #66cc66;">&#41;</span>;
  mBytesToSkip = <span style="color: #66cc66;">&#40;</span>mPollingFrequency - <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">*</span> SoundProxy.<span style="color: #006600;">BYTES_PER_SAMPLE</span>;
&nbsp;
  <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span>mFirstSampleInView <span style="color: #66cc66;">&lt;</span> <span style="color: #cc66cc;">0</span><span style="color: #66cc66;">&#41;</span> mFirstSampleInView = <span style="color: #cc66cc;">0</span>;
  <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>mFirstSampleInView + mNumSamplesInView<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&gt;</span> mNumSamplesTotal<span style="color: #66cc66;">&#41;</span> mFirstSampleInView = mNumSamplesTotal - mNumSamplesInView;
&nbsp;
  updateGraphic<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span></pre></td></tr></table></div>

<p>And the third thing to reduce the processor load is a simple timer. There&#8217;s a maximum of how often the display can update. In this case a maximum of once every 50 milliSeconds was fine. The timer script was added at the start of the update function:</p>

<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p250code13'); return false;">View Code</a> ACTIONSCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p25013"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p250code13"><pre class="actionscript" style="font-family:monospace;"><span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">var</span> mUpdateDelayTimer : Timer = <span style="color: #000000; font-weight: bold;">new</span> Timer<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">50</span>, <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>


<div class="wp_codebox_msgheader"><span class="right"><sup><a href="http://www.ericbess.com/ericblog/2008/03/03/wp-codebox/#examples" target="_blank" title="WP-CodeBox HowTo?"><span style="color: #99cc00">?</span></a></sup></span><span class="left"><a href="javascript:;" onclick="javascript:showCodeTxt('p250code14'); return false;">View Code</a> ACTIONSCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p25014"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code" id="p250code14"><pre class="actionscript" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/**
 * Redraws the display.
 */</span>
<span style="color: #0066CC;">private</span> <span style="color: #000000; font-weight: bold;">function</span> updateGraphic<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> : <span style="color: #0066CC;">void</span>
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #808080; font-style: italic;">// delay between updates</span>
  <span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span>mUpdateDelayTimer.<span style="color: #006600;">running</span><span style="color: #66cc66;">&#41;</span> <span style="color: #b1b100;">return</span>;
  mUpdateDelayTimer.<span style="color: #0066CC;">start</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
  <span style="color: #808080; font-style: italic;">// etcetera ...</span></pre></td></tr></table></div>

<p>That&#8217;s it for now. Download the <a href="flash/v011_wavedisplay/wavedisplay.zip">source files</a> to have a closer look at the code or to use it in your own projects.</p>
<p>This project is build with <a href="http://www.puremvc.org">PureMVC</a> as framework again. I like it more and more.<br />
The UI components I used here are very much based on <a href="http://www.bit-101.com">Keith Peters</a>&#8216; <a href="http://code.google.com/p/minimalcomps/">Minimal Comps</a>.<br />
To load an MP3 file and use it in Flash as a Sound object I used <a href="http://www.flexiblefactory.co.uk">FlexibleFactory</a>&#8217;s <a href="http://www.flexiblefactory.co.uk/flexible/?p=46">MP3FileReferenceLoader</a> library.<br />
For debugging I used the <a href="http://code.google.com/p/yalog/">Yalog</a> logging tool by <a href="http://stephan.acidcats.nl/blog/">Stephan Bezoen</a>. Very nice Air application.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hisschemoller.com/2010/mp3-wave-display/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
