<?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; ActionScript</title>
	<atom:link href="http://www.hisschemoller.com/category/actionscript/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>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_976049483"
			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_976049483"
			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_1299913603"
			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_1299913603"
			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_1016593445"
			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_1016593445"
			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_1529736492"
			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_1529736492"
			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>
		<item>
		<title>Sine synthesizer with PureMVC</title>
		<link>http://www.hisschemoller.com/2009/sine-synthesizer-in-puremvc/</link>
		<comments>http://www.hisschemoller.com/2009/sine-synthesizer-in-puremvc/#comments</comments>
		<pubDate>Mon, 20 Jul 2009 21:04:16 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[ActionScript]]></category>

		<guid isPermaLink="false">http://www.hisschemoller.com/?p=136</guid>
		<description><![CDATA[The past weeks I&#8217;ve been learning PureMVC. It had been on my mind for some time, and now that a project (a pianoroll type MIDI editor) became too complicated and the lack of structure took the fun out of programming I figured it was time for a nice new clean framework.

I read the &#8216;Framework Overview [...]]]></description>
			<content:encoded><![CDATA[<div class="wp-caption alignright" style="width: 260px"><img class=" " title="Part of the sequencer" src="http://www.hisschemoller.com/wp-content/uploads/2009/07/sinesynth_screenshot.gif" alt="Screenshot" width="250" height="200" /><p class="wp-caption-text">Screenshot</p></div>
<p>The past weeks I&#8217;ve been learning <a href="http://www.puremvc.org">PureMVC</a>. It had been on my mind for some time, and now that a project (a pianoroll type MIDI editor) became too complicated and the lack of structure took the fun out of programming I figured it was time for a nice new clean framework.</p>
<p><span id="more-136"></span><br />
I read the <a href="http://puremvc.org/component/option,com_wrapper/Itemid,35/http://puremvc.org/component/option,com_wrapper/Itemid,35/">&#8216;Framework Overview with UML&#8217;</a>, the <a href="http://puremvc.org/component/option,com_wrapper/Itemid,174/">&#8216;Implementation Idioms and Best Practices&#8217;</a> and memorized the famous <a href="http://puremvc.org/component/option,com_wrapper/Itemid,34/">conceptual diagram</a> with it&#8217;s interconnected cloud of meaningfull data blobs (see picture). I looked up some basic tutorials, <a href="http://www.as3dp.com/2007/12/27/minimalist-mvc-example-using-the-puremvc-framework/">&#8216;Minimalist MVC example using the PureMVC Framework&#8217;</a>, <a href="http://hubflanger.com/building-a-flash-site-using-puremvc/">&#8216;Building a Flash site using PureMVC&#8217;</a> and found this useful page: <a href="http://mariusht.com/blog/2009/05/21/puremvc-in-a-week/">&#8216;PureMVC in a week&#8217;</a>. And then felt ready for some PureMVC action of my own.</p>
<div class="wp-caption aligncenter" style="width: 440px"><a href="http://www.puremvc.org"><img title="The PureMVC conceptual diagram" src="http://www.hisschemoller.com/images/puremvc_diagram.jpg" alt="The PureMVC conceptual diagram" width="430" height="294" /></a><p class="wp-caption-text">The PureMVC conceptual diagram</p></div>
<p>And I must say: It&#8217;s not as complicated as I feared it would be. The first hurdle is a bit high with a lot of concepts and rules to remember, but then it quickly becomes clearer what part of the code goes where. My previous framework experience was with Cairngorm which is MVC based as well, so that definitely helped me to get my head round PureMVC.</p>
<p>Here is my first PureMVC test project, done to check how the audio programming stuff would integrate with the framework: It&#8217;s a small synthesizer that plays sine waves. Only sine waves. You can use keys on the computer keyboard to play the synth as a piano keyboard (see picture for the keys) and use Z and X to switch octaves and C and V to change the volume. This keyboard layout was taken from Ableton Live. I like the way it works there. So thank you <a href="http://www.ableton.com">Ableton</a>.</p>

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="puremvc"
			class="flashmovie"
			width="450"
			height="450">
	<param name="movie" value="http://www.hisschemoller.com/flash/v009_sine_puremvc/static/swf/puremvc.swf" />
	<param name="menu" value="false" />
	<param name="quality" value="best" />
	<param name="base" value="http://www.hisschemoller.com/flash/v009_sine_puremvc/static/swf" />
	<!--[if !IE]>-->
	<object	type="application/x-shockwave-flash"
			data="http://www.hisschemoller.com/flash/v009_sine_puremvc/static/swf/puremvc.swf"
			name="puremvc"
			width="450"
			height="450">
		<param name="menu" value="false" />
		<param name="quality" value="best" />
		<param name="base" value="http://www.hisschemoller.com/flash/v009_sine_puremvc/static/swf" />
	<!--<![endif]-->
		<br />
<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><br />

	<!--[if !IE]>-->
	</object>
	<!--<![endif]-->
</object>
<p>The source files are available again : <a href="http://hisschemoller.com/flash/v009_sine_puremvc/sine_puremvc.zip">Download the source files here.</a></p>
<p>Take note however that there is no FLA file. This is an ActionScript only project made in FDT. But if you want to compile it in Flash, it will probably work if you set App.as as the document root.</p>
<div class="wp-caption aligncenter" style="width: 460px"><img title="Use the computer keyboard to play" src="http://www.hisschemoller.com/images/keyboard_midi.jpg" alt="Use the computer keyboard to play" width="450" height="155" /><p class="wp-caption-text">Use the computer keyboard to play</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.hisschemoller.com/2009/sine-synthesizer-in-puremvc/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Step sequencer / drum machine</title>
		<link>http://www.hisschemoller.com/2009/step-sequencer-drum-machine/</link>
		<comments>http://www.hisschemoller.com/2009/step-sequencer-drum-machine/#comments</comments>
		<pubDate>Sun, 14 Jun 2009 19:16:13 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[ActionScript]]></category>

		<guid isPermaLink="false">http://www.hisschemoller.com/?p=112</guid>
		<description><![CDATA[Here is a basic step sequencer for creating rhythms. The sounds it plays are small MP3 files. Short sound clips of drum noises, blips and plings. So it&#8217;s more a sample player than a drum synth. But the main thing is that it loads and plays rhythm patterns and that the patterns can easily be [...]]]></description>
			<content:encoded><![CDATA[<div class="wp-caption alignright" style="width: 278px"><img title="Part of the sequencer" src="http://www.hisschemoller.com/images/stepseq_v008.gif" alt="Part of the sequencer" width="268" height="231" /><p class="wp-caption-text">Part of the sequencer</p></div>
<p>Here is a basic step sequencer for creating rhythms. The sounds it plays are small MP3 files. Short sound clips of drum noises, blips and plings. So it&#8217;s more a sample player than a drum synth. But the main thing is that it loads and plays rhythm patterns and that the patterns can easily be edited. That&#8217;s what I wanted to do here. </p>
<p>It plays patterns in the same way <a href="http://flstudio.image-line.com">FL Studio (FruityLoops)</a> does. There&#8217;s twelve tracks that each play their own sound and each track has sixteen steps that can be switched on or off by clicking the step buttons.</p>
<p>Besides that the volume of each step can be changed by holding the &#8220;1&#8243; (one) key on the computer keyboard while dragging the mouse up or down on the step button. The blue rectangle on the step will change in height to indicate the volume level.</p>
<p>The image of the waveform on the left of each track can be clicked to play the sound. And there are four patterns. Switch between them with the &#8216;1&#8242; to &#8216;4&#8242; buttons at the bottom.</p>
<p><span id="more-112"></span></p>
<p>Try it out below. This time I added play and stop buttons because in the previous two players I didn&#8217;t and that started to annoy me. Things on web pages should only make noise when they&#8217;re specifically told so.</p>

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="stepseq"
			class="flashmovie"
			width="500"
			height="500">
	<param name="movie" value="http://www.hisschemoller.com/flash/v008_stepseq/static/swf/midiXml.swf" />
	<param name="menu" value="false" />
	<param name="quality" value="best" />
	<param name="scale" value="noscale" />
	<param name="salign" value="tl" />
	<param name="base" value="http://www.hisschemoller.com/flash/v008_stepseq/static/swf/" />
	<!--[if !IE]>-->
	<object	type="application/x-shockwave-flash"
			data="http://www.hisschemoller.com/flash/v008_stepseq/static/swf/midiXml.swf"
			name="stepseq"
			width="500"
			height="500">
		<param name="menu" value="false" />
		<param name="quality" value="best" />
		<param name="scale" value="noscale" />
		<param name="salign" value="tl" />
		<param name="base" value="http://www.hisschemoller.com/flash/v008_stepseq/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><br >If you&#8217;re interested in any of the ActionScript code then download the full source of this project <a href="http://hisschemoller.com/flash/v008_stepseq/stepseq_v008.zip">here</a>. The ZIP includes all ActionScript classes, the samples and everything needed to compile and run the project.</p>
<p>A few notes on the source:</p>
<p>The project was made in FDT 3. There is no FLA file as a base to compile the SWF from. Instead you&#8217;ll need to set the class AppController (flash/classes/com/hisschemoller/AppController.as) as the main class in the project&#8217;s Run/Debug settings.</p>
<p>All visual elements of the projects were made in the Flash file flash/assets/assets.fla. That&#8217;s where all the button graphics are. This file is compiled to the SWC file assets.swc and that must be added to the class path in FDT. (Right click on the SWC file in FDT&#8217;s Flash explorer and choose &#8216;Add to Classpath&#8217;.) Then the scripts in FDT can find the MovieClips in the Flash library that were given a class name.</p>
<p>There might be all kinds of weird hidden Mac files in the ZIP. As well as the FDT launch and project setting files. I&#8217;m quite new to working on a Mac and I&#8217;m not shure what it adds that I don&#8217;t see. Sorry for that. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.hisschemoller.com/2009/step-sequencer-drum-machine/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Slicer with waveform display</title>
		<link>http://www.hisschemoller.com/2009/slicer-with-waveform-display/</link>
		<comments>http://www.hisschemoller.com/2009/slicer-with-waveform-display/#comments</comments>
		<pubDate>Sun, 10 May 2009 15:55:05 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[ActionScript]]></category>

		<guid isPermaLink="false">http://www.hisschemoller.com/?p=69</guid>
		<description><![CDATA[This slicer works the same as the previous one. Only difference is that is uses eight slices instead of sixteen.
The new stuff is in the interface: Waveforms to see what&#8217;s playing. And nicer to look at as well.
To use this app you can click the buttons as before to select a slice to play, and [...]]]></description>
			<content:encoded><![CDATA[<div class="wp-caption alignright" style="width: 285px"><img title="Slicer with waveform display" src="http://www.hisschemoller.com/images/waveformslicer.gif" alt="slicer with waveform display" width="275" height="198" /><p class="wp-caption-text">Slicer with waveform display</p></div>
<p>This slicer works the same as the previous one. Only difference is that is uses eight slices instead of sixteen.</p>
<p>The new stuff is in the interface: Waveforms to see what&#8217;s playing. And nicer to look at as well.</p>
<p>To use this app you can click the buttons as before to select a slice to play, and now you will see the waveform change to represent the slice.</p>
<p>The second way to change the slices is to click and drag on the waveforms itself. Drag up for later slices and down for earlier ones. Drag all the way down for an empty slice and silence.<span id="more-69"></span></p>
<p>Here it is! The music is from a track by <a href="http://www.flying-lotus.com">Flying Lotus</a>. I don&#8217;t know which one exactly: It&#8217;s track nr. 23 from a collection called &#8220;38 Cartoons&#8221;, but I couldn&#8217;t find any information about it online.</p>

<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="fm_waveformslicer_45128025"
			class="flashmovie"
			width="590"
			height="240">
	<param name="movie" value="http://www.hisschemoller.com/flash/v007_waveformslicer/static/swf/waveformslicer.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/v007_waveformslicer/static/swf/" />
	<!--[if !IE]>-->
	<object	type="application/x-shockwave-flash"
			data="http://www.hisschemoller.com/flash/v007_waveformslicer/static/swf/waveformslicer.swf"
			name="fm_waveformslicer_45128025"
			width="590"
			height="240">
		<param name="menu" value="false" />
		<param name="quality" value="best" />
		<param name="scale" value="noscale" />
		<param name="base" value="http://www.hisschemoller.com/flash/v007_waveformslicer/static/swf/" />
	<!--<![endif]-->
		<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><strong>How to get an image from MP3 sound data</strong></p>
<p>The way I did it is first to calculate how many samples of a slice represent one pixel of the image, then get the biggest amplitude of those samples. That will be a number between 0 and 1. Then multiply it by half of the images height to get the size of the line to draw. And finally draw the line to a BitMapData object.</p>
<p>It generates a simplified waveform: The positive and negative amplitudes are the same and it&#8217;s only the left channel. But it&#8217;s good enough for this purpose. It&#8217;s a good impression of the waveform.</p>
<p>Here is the main part of the code:</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('p69code16'); return false;">View Code</a> ACTIONSCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p6916"><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
</pre></td><td class="code" id="p69code16"><pre class="actionscript" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">var</span> mp3NumSamples : <span style="color: #0066CC;">Number</span> = mMp3Loop.<span style="color: #006600;">extract</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> ByteArray<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">41000</span> <span style="color: #66cc66;">*</span> <span style="color: #cc66cc;">60</span> <span style="color: #66cc66;">*</span> <span style="color: #cc66cc;">60</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> - mMp3StartOffset;
mMp3NumSamplesPerSlice = <span style="color: #0066CC;">Math</span>.<span style="color: #0066CC;">round</span><span style="color: #66cc66;">&#40;</span>mp3NumSamples <span style="color: #66cc66;">/</span> Model.<span style="color: #006600;">NUM_SLICES</span><span style="color: #66cc66;">&#41;</span>;
mBPM = TimeConversion.<span style="color: #006600;">numSamplesToBPM</span><span style="color: #66cc66;">&#40;</span>mp3NumSamples, <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
<span style="color: #000000; font-weight: bold;">var</span> sampleIndex : <span style="color: #0066CC;">int</span> = mMp3StartOffset;
<span style="color: #000000; font-weight: bold;">var</span> imageWidth : <span style="color: #0066CC;">int</span> = Model.<span style="color: #006600;">BUTTON_WIDTH</span>;
<span style="color: #000000; font-weight: bold;">var</span> samplesPerPixel : <span style="color: #0066CC;">int</span> = mMp3NumSamplesPerSlice <span style="color: #66cc66;">/</span> imageWidth;
&nbsp;
<span style="color: #808080; font-style: italic;">// loop through the slices</span>
<span style="color: #b1b100;">for</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">var</span> i : <span style="color: #0066CC;">int</span> = <span style="color: #cc66cc;">0</span>;i <span style="color: #66cc66;">&lt;</span> Model.<span style="color: #006600;">NUM_SLICES</span>; ++i<span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">var</span> byteArray : ByteArray = <span style="color: #000000; font-weight: bold;">new</span> ByteArray<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
	<span style="color: #000000; font-weight: bold;">var</span> numSamples : <span style="color: #0066CC;">int</span> = mMp3Loop.<span style="color: #006600;">extract</span><span style="color: #66cc66;">&#40;</span>byteArray, mMp3NumSamplesPerSlice, sampleIndex<span style="color: #66cc66;">&#41;</span>;
	<span style="color: #000000; font-weight: bold;">var</span> <span style="color: #0066CC;">position</span> : <span style="color: #0066CC;">int</span> = <span style="color: #cc66cc;">0</span>;
	<span style="color: #000000; font-weight: bold;">var</span> lineMiddle : <span style="color: #0066CC;">int</span> = <span style="color: #66cc66;">&#40;</span>Model.<span style="color: #006600;">DISPLAY_HEIGHT</span> <span style="color: #66cc66;">/</span> <span style="color: #cc66cc;">2</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
	byteArray.<span style="color: #0066CC;">position</span> = <span style="color: #cc66cc;">0</span>;
&nbsp;
	mMp3WaveformData<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span> = <span style="color: #000000; font-weight: bold;">new</span> BitmapData<span style="color: #66cc66;">&#40;</span>Model.<span style="color: #006600;">BUTTON_WIDTH</span>, Model.<span style="color: #006600;">DISPLAY_HEIGHT</span>, <span style="color: #000000; font-weight: bold;">true</span>, 0xFF0000<span style="color: #66cc66;">&#41;</span>;
	<span style="color: #000000; font-weight: bold;">var</span> bitmapData : BitmapData = mMp3WaveformData<span style="color: #66cc66;">&#91;</span>i<span style="color: #66cc66;">&#93;</span>;
&nbsp;
	<span style="color: #808080; font-style: italic;">// loop through the pixels of a waveform image's width</span>
	<span style="color: #b1b100;">for</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">var</span> j : <span style="color: #0066CC;">int</span> = <span style="color: #cc66cc;">0</span>;j <span style="color: #66cc66;">&lt;</span> imageWidth; ++j<span style="color: #66cc66;">&#41;</span>
	<span style="color: #66cc66;">&#123;</span>
		<span style="color: #000000; font-weight: bold;">var</span> waveHeight : <span style="color: #0066CC;">Number</span> = <span style="color: #cc66cc;">0.0</span>;
&nbsp;
		<span style="color: #808080; font-style: italic;">// get maximum of all samples within pixel</span>
		<span style="color: #b1b100;">for</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">var</span> k : <span style="color: #0066CC;">int</span> = <span style="color: #cc66cc;">0</span>; k <span style="color: #66cc66;">&lt;</span> samplesPerPixel ; ++k<span style="color: #66cc66;">&#41;</span>
		<span style="color: #66cc66;">&#123;</span>
			<span style="color: #b1b100;">if</span><span style="color: #66cc66;">&#40;</span><span style="color: #0066CC;">position</span> <span style="color: #66cc66;">&lt;</span> numSamples<span style="color: #66cc66;">&#41;</span>
			<span style="color: #66cc66;">&#123;</span>
				<span style="color: #000000; font-weight: bold;">var</span> l : <span style="color: #0066CC;">Number</span> = byteArray.<span style="color: #006600;">readFloat</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
				byteArray.<span style="color: #006600;">readFloat</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
			<span style="color: #66cc66;">&#125;</span>
			<span style="color: #b1b100;">else</span>
			<span style="color: #66cc66;">&#123;</span>
				l = <span style="color: #cc66cc;">0</span>;
			<span style="color: #66cc66;">&#125;</span>
&nbsp;
			waveHeight = <span style="color: #0066CC;">Math</span>.<span style="color: #0066CC;">max</span><span style="color: #66cc66;">&#40;</span>waveHeight, <span style="color: #0066CC;">Math</span>.<span style="color: #0066CC;">abs</span><span style="color: #66cc66;">&#40;</span>l<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
			<span style="color: #0066CC;">position</span> ++;
		<span style="color: #66cc66;">&#125;</span>
&nbsp;
		waveHeight <span style="color: #66cc66;">*</span>= lineMiddle;
		<span style="color: #000000; font-weight: bold;">var</span> <span style="color: #0066CC;">start</span> : <span style="color: #0066CC;">int</span> = lineMiddle - waveHeight;
		<span style="color: #000000; font-weight: bold;">var</span> <span style="color: #0066CC;">end</span> : <span style="color: #0066CC;">int</span> = lineMiddle + waveHeight;
&nbsp;
		<span style="color: #808080; font-style: italic;">// draw to bitmapdata</span>
		<span style="color: #b1b100;">for</span><span style="color: #66cc66;">&#40;</span>k = <span style="color: #0066CC;">start</span>; k <span style="color: #66cc66;">&lt;</span> <span style="color: #0066CC;">end</span> ; ++k<span style="color: #66cc66;">&#41;</span>
		<span style="color: #66cc66;">&#123;</span>
			bitmapData.<span style="color: #006600;">setPixel32</span><span style="color: #66cc66;">&#40;</span>j, k, 0xFFFFFFCC<span style="color: #66cc66;">&#41;</span>;
		<span style="color: #66cc66;">&#125;</span>
	<span style="color: #66cc66;">&#125;</span>
&nbsp;
	sampleIndex += mMp3NumSamplesPerSlice;
<span style="color: #66cc66;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.hisschemoller.com/2009/slicer-with-waveform-display/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A basic slicer</title>
		<link>http://www.hisschemoller.com/2009/a-basic-slicer/</link>
		<comments>http://www.hisschemoller.com/2009/a-basic-slicer/#comments</comments>
		<pubDate>Fri, 08 May 2009 14:51:45 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[ActionScript]]></category>

		<guid isPermaLink="false">http://www.hisschemoller.com/?p=27</guid>
		<description><![CDATA[This is it! The first one: A slicer.
It loads and plays an MP3 file. But not only that. It divides the file in sixteen equal parts and you can change the order in which the parts are played.
When it&#8217;s loaded the slicer plays all the parts in the right order. Part 1, 2, 3 and [...]]]></description>
			<content:encoded><![CDATA[<div id="v006_slicer_img" class="wp-caption alignright" style="width: 290px"><img title="Slicer" src="http://www.hisschemoller.com/flash/v006_slicer/static/images/v006_slicer.gif" alt="Part of the slicer" width="280" height="210" /><p class="wp-caption-text">Part of the slicer</p></div>
<p><strong>This is it! The first one: A slicer.</strong></p>
<p>It loads and plays an MP3 file. But not only that. It divides the file in sixteen equal parts and you can change the order in which the parts are played.</p>
<p>When it&#8217;s loaded the slicer plays all the parts in the right order. Part 1, 2, 3 and up until part 16. With the buttons you can change the order and for example play part 4, then 3, 11, 8 and so on. With the right MP3 loop this will create all kinds of interesting rhythmic variations.</p>
<p>It works best if the MP3 file is a short  piece of music with a steady rhythm that loops seamlessly (so the start and end of the sound fit together exactly). Then every slice has a little bit of rhythm in it. Just one or two sounds like a kick or snare drum.</p>
<p>Best to check it out for yourself. I will put the actual SWF files on the &#8216;Read more&#8217; pages of the posts, so they won&#8217;t all be playing at the same time and use up each other&#8217;s CPU cycles. <span id="more-27"></span></p>
<p><strong>The interface</strong></p>
<p>It&#8217;s a matrix! Sixteen buttons wide for the time slots, sixteen high for the slices. So the bottom left button selects slice one to be played first, the top left button plays slice sixteen at position one. Just click around and you&#8217;ll get it.</p>
<p><strong>The code</strong></p>
<p>The main thing in this application is the Sound.extract() method. Once the MP3 is loaded the total amount of samples in the file is divided by sixteen. Then it can store the duration in samples of a slice and at which sample exactly each slice starts. So the file isn&#8217;t actually split into sixteen parts. It only stores the starting point of each slice within the loop.</p>
<p>One thing I didn&#8217;t know but found out trying is how to get the total amount of samples in an MP3 file: Use extract() and request a length longer than you know the MP3 file is. For example one hour. Then extract() will get as many samples as it can. Which are all the samples in the file, and it returns that number:</p>

<div class="wp_codebox_msgheader wp_codebox_hide"><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('p27code18'); return false;">View Code</a> ACTIONSCRIPT</span><div class="codebox_clear"></div></div><div class="wp_codebox"><table><tr id="p2718"><td class="code" id="p27code18"><pre class="actionscript" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">var</span> oneHour : uint = <span style="color: #cc66cc;">44100</span> <span style="color: #66cc66;">*</span> <span style="color: #cc66cc;">60</span> <span style="color: #66cc66;">*</span> <span style="color: #cc66cc;">60</span>;
<span style="color: #000000; font-weight: bold;">var</span> numSamples : uint = mp3File.<span style="color: #006600;">extract</span><span style="color: #66cc66;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> ByteArray<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>, oneHour<span style="color: #66cc66;">&#41;</span>;</pre></td></tr></table></div>


<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
			id="fm_slicer_765580277"
			class="flashmovie"
			width="600"
			height="600">
	<param name="movie" value="http://www.hisschemoller.com/flash/v006_slicer/static/swf/slicer.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/v006_slicer/static/swf/" />
	<!--[if !IE]>-->
	<object	type="application/x-shockwave-flash"
			data="http://www.hisschemoller.com/flash/v006_slicer/static/swf/slicer.swf"
			name="fm_slicer_765580277"
			width="600"
			height="600">
		<param name="menu" value="false" />
		<param name="quality" value="best" />
		<param name="scale" value="noscale" />
		<param name="base" value="http://www.hisschemoller.com/flash/v006_slicer/static/swf/" />
	<!--<![endif]-->
		<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>If you recognized the loop but thought it was somehow different: You&#8217;re right! It&#8217;s Mr Oizo&#8217;s &#8220;Bobby Can&#8217;t Dance&#8221; from his album &#8220;Analog Worms Attack&#8221; (1999). But speeded up to 120 BPM. I liked it a bit faster. (The speeding up wasn&#8217;t done with this slicer by the way. No advanced ActionScript 3.0 timestretching algorithm yet I&#8217;m afraid.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.hisschemoller.com/2009/a-basic-slicer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
