<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://www.alexmaclean.ca/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.alexmaclean.ca/" rel="alternate" type="text/html" /><updated>2025-07-28T00:58:59+00:00</updated><id>https://www.alexmaclean.ca/feed.xml</id><title type="html">Alex MacLean</title><subtitle>Personal site of Alex MacLean, an immersive media artist based in London, Ontario.</subtitle><author><name>Alex MacLean</name></author><entry><title type="html">Soundscape Generator</title><link href="https://www.alexmaclean.ca/2017/12/01/soundscape-generator.html" rel="alternate" type="text/html" title="Soundscape Generator" /><published>2017-12-01T00:00:00+00:00</published><updated>2017-12-01T00:00:00+00:00</updated><id>https://www.alexmaclean.ca/2017/12/01/soundscape-generator</id><content type="html" xml:base="https://www.alexmaclean.ca/2017/12/01/soundscape-generator.html"><![CDATA[<p>So at the end of October I came across a hackathon that a company called Product Hunt was hosting throughout November. <a href="http://gregalexsmith.com/">Greg Smith</a> and I have always talked about doing a project together and this seemed like the perfect incentive to get us started on something.</p>

<p>Now at the end of the hackathon, we are very pleased to present… a Soundscape Generator!</p>

<p><img src="/assets/images/soundscape-generator.png" alt="Soundscape Generator" /></p>

<h2 id="the-idea">The Idea</h2>

<p>We were thinking of photos and what they’re lacking. It’s great to be able to look at pictures of moments and either imagine what it would be like, or remember what it <em>was</em> like to be there, but couldn’t they be a bit more immersive? Well of course! What if you could hear what it was like as well?</p>

<p>Users could simply choose or upload a photo and a list of objects in the image would be created. Then after the press of a button the app could find audio clips appropriate for each of the objects. Finally, playing all those clips together would create a realistic soundscape for the image!</p>

<h2 id="the-tech">The Tech</h2>

<p>We decided to go about this by creating a <a href="http://flask.pocoo.org/">Flask</a> app with <a href="https://reactjs.org/">React</a> on the frontend and use <a href="https://aws.amazon.com/codestar/">AWS Codestar</a> to run it on an EC2 instance.</p>

<h3 id="image-scanning">Image Scanning</h3>

<p>We still needed a few more things though. First of all, how were we going to get the features from the images? Luckily <a href="https://aws.amazon.com/rekognition/">AWS Rekognition</a> was perfect for this. By making one simple call to it we were able to get the features no problem.</p>

<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">detect_labels</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">bucket</span><span class="o">=</span><span class="n">BUCKET</span><span class="p">,</span> <span class="n">max_labels</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span> <span class="n">min_confidence</span><span class="o">=</span><span class="mi">80</span><span class="p">,</span>
                  <span class="n">region</span><span class="o">=</span><span class="s">"us-east-1"</span><span class="p">):</span>
    <span class="n">rekognition</span> <span class="o">=</span> <span class="n">boto3</span><span class="p">.</span><span class="n">client</span><span class="p">(</span><span class="s">"rekognition"</span><span class="p">,</span> <span class="n">region</span><span class="p">)</span>
    <span class="n">rek_results</span> <span class="o">=</span> <span class="n">rekognition</span><span class="p">.</span><span class="n">detect_labels</span><span class="p">(</span>
        <span class="n">Image</span><span class="o">=</span><span class="p">{</span>
            <span class="s">"S3Object"</span><span class="p">:</span> <span class="p">{</span>
                <span class="s">"Bucket"</span><span class="p">:</span> <span class="n">BUCKET</span><span class="p">,</span>
                <span class="s">"Name"</span><span class="p">:</span> <span class="n">key</span><span class="p">,</span>
            <span class="p">}</span>
        <span class="p">},</span>
        <span class="n">MaxLabels</span><span class="o">=</span><span class="n">max_labels</span><span class="p">,</span>
        <span class="n">MinConfidence</span><span class="o">=</span><span class="n">min_confidence</span><span class="p">,</span>
    <span class="p">)</span>
    <span class="n">labels</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="k">for</span> <span class="n">label</span> <span class="ow">in</span> <span class="n">rek_results</span><span class="p">[</span><span class="s">'Labels'</span><span class="p">]:</span>
        <span class="n">labels</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">label</span><span class="p">[</span><span class="s">'Name'</span><span class="p">])</span>
    <span class="k">return</span> <span class="n">labels</span></code></pre></figure>

<h3 id="sample-searching">Sample Searching</h3>

<p>Once we had the features the next step was to get the audio clips for them. Was there a sound library out there with an API? You bet there was. After a quick search we found <a href="http://www.freesound.org/">Freesound</a> and it was just what we needed.</p>

<p>With the features returned by Rekognition we could query the Freesound library for clips that had those terms in their names.</p>

<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kd">function</span> <span class="nx">getSoundSearchResults</span><span class="p">(</span><span class="nx">keyword</span><span class="p">)</span> <span class="p">{</span>
    <span class="kd">const</span> <span class="nx">url</span> <span class="o">=</span> <span class="s2">`https://freesound.org/apiv2/search/text/?query=</span><span class="p">${</span><span class="nx">keyword</span><span class="p">}</span><span class="s2">`</span>
    <span class="kd">let</span> <span class="nx">headers</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Headers</span><span class="p">();</span>
    <span class="nx">headers</span><span class="p">.</span><span class="nx">append</span><span class="p">(</span><span class="dl">"</span><span class="s2">Authorization</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">Token &lt;token&gt;</span><span class="dl">"</span><span class="p">);</span>
    <span class="k">return</span> <span class="nx">fetch</span><span class="p">(</span><span class="nx">url</span><span class="p">,</span> <span class="p">{</span><span class="nx">headers</span><span class="p">})</span>
        <span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">response</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="nx">response</span><span class="p">.</span><span class="nx">json</span><span class="p">())</span>
        <span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="nx">json</span> <span class="o">=&gt;</span> <span class="nx">json</span><span class="p">.</span><span class="nx">results</span><span class="p">)</span>
        <span class="p">.</span><span class="k">catch</span><span class="p">((</span><span class="nx">err</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
            <span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">"</span><span class="s2">ERROR</span><span class="dl">"</span><span class="p">,</span> <span class="nx">err</span><span class="p">);</span>
            <span class="k">throw</span> <span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="nx">err</span><span class="p">);</span>
        <span class="p">});</span>
<span class="p">}</span></code></pre></figure>

<p>After retrieving the audio clips they could then each be streamed from Freesound either one at a time or all together. Don’t like one of the clips? That’s okay just hit the shuffle button and another result will be fetched!</p>

<p><img src="/assets/images/result.png" alt="Result" /></p>

<h3 id="room-settings">Room Settings</h3>

<p>The last goal we had was to add an appropriate amount of effects to match the types of environments where pictures were taken. Google’s <a href="https://aws.amazon.com/rekognition/">Resonance Audio</a> just happened to fall into our laps thanks to a post on <a href="https://news.ycombinator.com/">Hacker News</a> and boy we’re glad it did! It provides the ability to add reverb, as well as gain control and panning for the audio clips. We do our best to guess the types of room materials in the pictures from the features returned by Rekognition but there is definitely room for improvement here.</p>

<p><img src="/assets/images/environment.png" alt="Room Settings" /></p>

<h2 id="whats-next">What’s Next</h2>

<h3 id="video">Video</h3>

<p>Just as we were wrapping this hackathon project up, AWS announced at their re:Invent conference that Rekognition will now be supporting video! This is really exciting for us because we can very soon add that support to our app as well. With this option we have considered that video producers could even use our app to quickly create a soundscape to drop into a scene they’re working on.</p>

<h3 id="sharing">Sharing</h3>

<p>At the moment, users only have the ability to hop on the app and listen back to the results while they’re there. We would love for people to export their creations and share them on social media as well.</p>

<h2 id="conclusion">Conclusion</h2>

<p>So that’s our Soundscape Generator. It was a blast working on it and thanks to Product Hunt for the extra incentive as well as the helpful resources. You can check out the app <a href="http://ec2-34-231-21-21.compute-1.amazonaws.com/">here</a> and our GitHub repo is <a href="https://github.com/amaclean199/soundscape-generator">over here</a>. If you have any comments or questions about it please feel free to reach out :)</p>]]></content><author><name>Alex MacLean</name></author><category term="AI" /><category term="audio" /><category term="soundscape" /><category term="freesound" /><category term="rekognition" /><category term="resonance audio" /><category term="flask" /><category term="react" /><category term="codestar" /><summary type="html"><![CDATA[An app that easily create soundscapes for images.]]></summary></entry><entry><title type="html">Introduction and Timbre.js</title><link href="https://www.alexmaclean.ca/2016/01/15/introduction-and-timbrejs.html" rel="alternate" type="text/html" title="Introduction and Timbre.js" /><published>2016-01-15T00:00:00+00:00</published><updated>2016-01-15T00:00:00+00:00</updated><id>https://www.alexmaclean.ca/2016/01/15/introduction-and-timbrejs</id><content type="html" xml:base="https://www.alexmaclean.ca/2016/01/15/introduction-and-timbrejs.html"><![CDATA[<p>Hello everyone and welcome to my brand new blog! This is a place where I’ll be sharing my thoughts on music and technology, as well as self development: three things that I truly enjoy. I’m very excited to finally be getting this started so without further ado, here we go!</p>

<p>I would like to begin this new adventure with a post about a Javascript audio library and an open-source project I became involved with back in September. The project is called <a href="http://waterbearlang.com/">Waterbear</a> and it is a visual programming language with a great mascot:</p>

<p><img src="/assets/images/mascot-steampunk.jpg" alt="Waterbear Mascot" /></p>

<p>As one of the projects included in an interesting opportunity called <a href="http://ucosp.ca/">UCOSP</a>, as well as <a href="https://github.com/waterbearlang/waterbear/wiki/Contributors-and-Acknowledgements">some others</a>, many people have been involved with it throughout several years. It has already been through multiple iterations and continues to grow in all sorts of directions. The benefit of this being that each participant is welcome to contribute to it in any way he or she can imagine.</p>

<h3 id="what-to-do">What to do?</h3>

<p>For my contribution, it wasn’t long until I realized the opportunity I had to improve the sound blocks that were being offered to users. Originally, the audio library being used was <a href="http://createjs.com/soundjs">Sound.js</a>, a simple but limited option. After researching and considering other libraries I decided on <a href="https://mohayonao.github.io/timbre.js/">Timbre.js</a>, mainly because of the awesome examples in their documentation and the quality of their sounds.</p>

<p>We decided that out of all the functionality we could add to the sound portion of the Waterbear project, the top priorities were to be:</p>

<ul>
  <li>Playback of files</li>
  <li>Generation of sound effects</li>
  <li>Building songs from notes</li>
</ul>

<p>Fortunately, Timbre.js was capable of implementing all of these things so it was a perfect candidate for the job.</p>

<h3 id="the-basics">The Basics</h3>

<p><em>Note: You can play with these code examples on <a href="https://jsfiddle.net/">JSFiddle</a> after including <a href="https://mohayonao.github.io/timbre.js/timbre.js">this</a> as an external resource or just modify the examples on the <a href="https://mohayonao.github.io/timbre.js/">Timbre.js</a> site.</em></p>

<p>I began with generating some waveforms. The most primitive example that provides a sine wave looks something like this:</p>

<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">T</span><span class="p">(</span><span class="dl">"</span><span class="s2">sin</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span><span class="na">freq</span><span class="p">:</span><span class="mi">880</span><span class="p">}).</span><span class="nx">play</span><span class="p">();</span></code></pre></figure>

<p>Here the Timbre Object (‘T’) is being created with parameters for the type of waveform and the frequency. The dictionary attribute containing the frequency can include a number of additional parameters such as volume and envelope to further customize the synth. The play method is then called on that object to generate the tone.</p>

<p>Timbre.js synthesis has the ability to play single notes as well as chords:</p>

<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kd">var</span> <span class="nx">sine1</span> <span class="o">=</span> <span class="nx">T</span><span class="p">(</span><span class="dl">"</span><span class="s2">sin</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span><span class="na">freq</span><span class="p">:</span><span class="mi">440</span><span class="p">,</span> <span class="na">mul</span><span class="p">:</span><span class="mf">0.5</span><span class="p">});</span>
<span class="kd">var</span> <span class="nx">sine2</span> <span class="o">=</span> <span class="nx">T</span><span class="p">(</span><span class="dl">"</span><span class="s2">sin</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span><span class="na">freq</span><span class="p">:</span><span class="mi">660</span><span class="p">,</span> <span class="na">mul</span><span class="p">:</span><span class="mf">0.5</span><span class="p">});</span>
<span class="kd">var</span> <span class="nx">sine3</span> <span class="o">=</span> <span class="nx">T</span><span class="p">(</span><span class="dl">"</span><span class="s2">sin</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span><span class="na">freq</span><span class="p">:</span><span class="mi">880</span><span class="p">,</span> <span class="na">mul</span><span class="p">:</span><span class="mf">0.5</span><span class="p">});</span>

<span class="nx">T</span><span class="p">(</span><span class="dl">"</span><span class="s2">perc</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span><span class="na">r</span><span class="p">:</span><span class="mi">500</span><span class="p">},</span> <span class="nx">sine1</span><span class="p">,</span> <span class="nx">sine2</span><span class="p">,</span> <span class="nx">sine3</span><span class="p">).</span><span class="nx">on</span><span class="p">(</span><span class="dl">"</span><span class="s2">ended</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
  <span class="k">this</span><span class="p">.</span><span class="nx">pause</span><span class="p">();</span>
<span class="p">}).</span><span class="nx">bang</span><span class="p">().</span><span class="nx">play</span><span class="p">();</span></code></pre></figure>

<p>In this example, several sine waves are being combined inside of a <code class="language-plaintext highlighter-rouge">"perc"</code> Timbre object. <code class="language-plaintext highlighter-rouge">on()</code> is called on that object to add a listener to the end of the listeners array when the synth has <code class="language-plaintext highlighter-rouge">"ended"</code>. When the Timbre object has ended, the listener will pause the synth so it can be started again later without reloading the script. Then <code class="language-plaintext highlighter-rouge">bang()</code> sets playback to be a short burst of sound rather than an ongoing signal and <code class="language-plaintext highlighter-rouge">play()</code> begins the processing. The release time is set to 500ms with <code class="language-plaintext highlighter-rouge">"{r:500}"</code>.</p>

<p>The block that was created to define synths within Waterbear includes options for the waveform, attack time, and release time. This provides a reasonable amount of sound-shaping for people to get started with:</p>

<p><img src="/assets/images/synth_def.png" alt="Synth block" /></p>

<p>With this block a synth is being defined by the following:</p>

<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kd">var</span> <span class="nx">osc</span> <span class="o">=</span> <span class="nx">T</span><span class="p">(</span><span class="dl">"</span><span class="s2">sine</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">env</span> <span class="o">=</span> <span class="nx">T</span><span class="p">(</span><span class="dl">"</span><span class="s2">perc</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span><span class="na">a</span><span class="p">:</span><span class="mi">10</span><span class="p">,</span> <span class="na">r</span><span class="p">:</span><span class="mi">300</span><span class="p">});</span>
<span class="kd">var</span> <span class="nx">oscenv</span> <span class="o">=</span> <span class="nx">T</span><span class="p">(</span><span class="dl">"</span><span class="s2">OscGen</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span><span class="na">osc</span><span class="p">:</span><span class="nx">osc</span><span class="p">,</span> <span class="na">env</span><span class="p">:</span><span class="nx">env</span><span class="p">,</span> <span class="na">mul</span><span class="p">:</span><span class="mf">0.15</span><span class="p">}).</span><span class="nx">play</span><span class="p">();</span></code></pre></figure>

<p>To see an advanced example of what Timbre.js can do with audio synthesis check out <a href="https://mohayonao.github.io/timbre.js/chord.html">ChordWork</a> as well as the other examples they provide.</p>

<h3 id="playback-of-files">Playback of files</h3>

<p>Audio files can easily be played:</p>

<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">T</span><span class="p">(</span><span class="dl">"</span><span class="s2">audio</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span><span class="na">load</span><span class="p">:</span><span class="dl">"</span><span class="s2">/some/audio/file.wav</span><span class="dl">"</span><span class="p">}).</span><span class="nx">play</span><span class="p">();</span></code></pre></figure>

<p>But many effects such as <a href="https://mohayonao.github.io/timbre.js/chorus.html">chorus</a>, <a href="https://mohayonao.github.io/timbre.js/delay.html">delay</a>, <a href="https://mohayonao.github.io/timbre.js/phaser.html">phaser</a>, and <a href="https://mohayonao.github.io/timbre.js/reverb.html">reverb</a> can be added to playback as well.</p>

<h3 id="generation-of-sound-effects">Generation of sound effects</h3>

<p>For Waterbear there was a demand to have sound effects ready to play at certain points within a program. Things such as lasers and alarms can be used at key points to alert the user of an action. Thus, it was important for the chosen audio library to generate such sounds.</p>

<p>Here is how to create a laser sound effect with Timbre.js:</p>

<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kd">var</span> <span class="nx">table</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1760</span><span class="p">,</span> <span class="p">[</span><span class="mi">110</span><span class="p">,</span> <span class="dl">"</span><span class="s2">200ms</span><span class="dl">"</span><span class="p">]];</span>

<span class="kd">var</span> <span class="nx">freq</span> <span class="o">=</span> <span class="nx">T</span><span class="p">(</span><span class="dl">"</span><span class="s2">env</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span><span class="na">table</span><span class="p">:</span><span class="nx">table</span><span class="p">}).</span><span class="nx">on</span><span class="p">(</span><span class="dl">"</span><span class="s2">bang</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">VCO</span><span class="p">.</span><span class="nx">mul</span> <span class="o">=</span> <span class="mf">0.2</span><span class="p">;</span>
<span class="p">}).</span><span class="nx">on</span><span class="p">(</span><span class="dl">"</span><span class="s2">ended</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">VCO</span><span class="p">.</span><span class="nx">mul</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">});</span>
<span class="kd">var</span> <span class="nx">VCO</span> <span class="o">=</span> <span class="nx">T</span><span class="p">(</span><span class="dl">"</span><span class="s2">saw</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span><span class="na">freq</span><span class="p">:</span><span class="nx">freq</span><span class="p">,</span> <span class="na">mul</span><span class="p">:</span><span class="mi">0</span><span class="p">}).</span><span class="nx">play</span><span class="p">();</span>
<span class="nx">freq</span><span class="p">.</span><span class="nx">bang</span><span class="p">();</span></code></pre></figure>

<p>Several sound effects were created in this way and a block was made with a drop-down menu to choose an effect from:</p>

<p><img src="/assets/images/sound_effect_block.png" alt="Sound effect block" /></p>

<h3 id="building-songs-from-notes">Building songs from notes</h3>

<p>Another big feature request was to be able to define notes with specific frequencies and durations so that they could be used to drag-and-click out a melody. See the “Twinkling Song” example on Waterbear to get a feel for what it’s like to use a visual programming language to do so. For short parts it is quite convenient!</p>

<p>First, a synth must be defined, then optionally set the tempo (120bpm by default), and then notes can be added. When it is time to play the melody within the program, a play block must be dropped into Waterbear in the desired location:</p>

<p><img src="/assets/images/sound_notes.png" alt="Sound notes example" /></p>

<p>In order to queue up notes for playback the information collected from the blocks has to first be converted into <a href="http://www.musicmarkup.info/">Music Markup Language</a>:</p>

<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nb">global</span><span class="p">.</span><span class="nx">runtime</span> <span class="o">=</span> <span class="p">{</span>
	<span class="p">...</span>
	<span class="na">addNote</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">note</span><span class="p">,</span> <span class="nx">octave</span><span class="p">,</span> <span class="nx">beats</span><span class="p">){</span>
	    <span class="k">switch</span><span class="p">(</span><span class="nx">note</span><span class="p">){</span>
	        <span class="k">case</span> <span class="dl">"</span><span class="s2">A</span><span class="dl">"</span><span class="p">:</span>
	            <span class="nx">note</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">a</span><span class="dl">"</span><span class="p">;</span>
	            <span class="k">break</span><span class="p">;</span>
	        <span class="p">...</span>
	        <span class="k">case</span> <span class="dl">"</span><span class="s2">Rest</span><span class="dl">"</span><span class="p">:</span>
	            <span class="nx">note</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">r</span><span class="dl">"</span><span class="p">;</span>
	            <span class="k">break</span><span class="p">;</span>
	    <span class="p">}</span>
	    <span class="k">if</span> <span class="p">(</span><span class="nx">octave</span> <span class="o">&gt;</span> <span class="nx">current_octave</span><span class="p">)</span> <span class="p">{</span>
	        <span class="kd">var</span> <span class="nx">octave_diff</span> <span class="o">=</span> <span class="nx">octave</span> <span class="o">-</span> <span class="nx">current_octave</span><span class="p">;</span>
	        <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">octave_diff</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
	            <span class="nx">song</span> <span class="o">+=</span> <span class="dl">"</span><span class="s2">&lt;</span><span class="dl">"</span><span class="p">;</span>
	        <span class="p">}</span>
	    <span class="p">}</span>
	    <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">octave</span> <span class="o">&lt;</span> <span class="nx">current_octave</span><span class="p">)</span> <span class="p">{</span>
	        <span class="kd">var</span> <span class="nx">octave_diff</span> <span class="o">=</span> <span class="nx">current_octave</span> <span class="o">-</span> <span class="nx">octave</span><span class="p">;</span>
	        <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">octave_diff</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
	            <span class="nx">song</span> <span class="o">+=</span> <span class="dl">"</span><span class="s2">&gt;</span><span class="dl">"</span><span class="p">;</span>
	        <span class="p">}</span>
	    <span class="p">}</span>
	    <span class="nx">current_octave</span> <span class="o">=</span> <span class="nx">octave</span><span class="p">;</span>
	    <span class="kd">var</span> <span class="nx">length</span><span class="p">;</span>
	    <span class="k">switch</span><span class="p">(</span><span class="nx">beats</span><span class="p">){</span>
	        <span class="k">case</span> <span class="dl">"</span><span class="s2">1/32</span><span class="dl">"</span><span class="p">:</span>
	            <span class="nx">length</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">32</span><span class="dl">"</span><span class="p">;</span>
	            <span class="k">break</span><span class="p">;</span>
	        <span class="p">...</span>
	        <span class="k">case</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span><span class="p">:</span>
	            <span class="nx">length</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">1</span><span class="dl">"</span><span class="p">;</span>
	            <span class="k">break</span><span class="p">;</span>
	    <span class="p">}</span>
	    <span class="kd">var</span> <span class="nx">newNote</span> <span class="o">=</span> <span class="nx">note</span> <span class="o">+</span> <span class="nx">length</span><span class="p">;</span>
	    <span class="nx">song</span> <span class="o">+=</span> <span class="nx">newNote</span><span class="p">;</span>
	<span class="p">},</span>
	<span class="p">...</span>
<span class="p">}</span></code></pre></figure>

<p>So that a string such as <code class="language-plaintext highlighter-rouge">song="o4 l4 V12 cd"</code> is created, then that string is passed to Timbre.js with the play block:</p>

<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">T</span><span class="p">(</span><span class="dl">"</span><span class="s2">mml</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span><span class="na">mml</span><span class="p">:</span><span class="nx">song</span><span class="p">},</span> <span class="nx">sound</span><span class="p">).</span><span class="nx">on</span><span class="p">(</span><span class="dl">"</span><span class="s2">ended</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">sound</span><span class="p">.</span><span class="nx">pause</span><span class="p">();</span>
    <span class="k">this</span><span class="p">.</span><span class="nx">stop</span><span class="p">();</span>
<span class="p">}).</span><span class="nx">start</span><span class="p">();</span></code></pre></figure>

<p>Alternatively, uses can enter in MML directly to a different block:</p>

<p><img src="/assets/images/mml_block_example.png" alt="MML block example" /></p>

<h3 id="conclusion">Conclusion</h3>

<p>The code that used Timbre.js resides in <a href="https://github.com/waterbearlang/waterbear/blob/master/js/runtime.js#L999">runtime.js</a> and the HTML for the sound blocks is in <a href="https://github.com/waterbearlang/waterbear/blob/master/playground.html#L225">playground.html</a>. There are even more sound blocks than discussed here so I urge you to go and explore the rest on your own.</p>

<p>I found this project to be a great experience with taking an audio library and implementing it in an interesting way. Visual programming languages are meant to teach people to think like coders so a lot of consideration was put into making all options visible and understandable in order for users to quickly grasp what’s available to them.</p>

<p>So thanks very much for reading and I hope you enjoyed my overerview of these musical technologies. If you have any thoughts or opinions then please feel free to share them in the comments below or send me a message!</p>]]></content><author><name>Alex MacLean</name></author><category term="intro" /><category term="beginner" /><category term="timbrejs" /><category term="tutorial" /><category term="waterbear" /><summary type="html"><![CDATA[An introduction to the blog and a tutorial on Timbre.js.]]></summary></entry></feed>