<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>SSFRR</title><link href="http://ssfrr.com/" rel="alternate"></link><link href="http://ssfrr.com/feeds/all.atom.xml" rel="self"></link><id>http://ssfrr.com/</id><updated>2018-01-08T00:00:00-05:00</updated><entry><title>New Performance Video (from 2013)</title><link href="http://ssfrr.com/2018/01/08/new_performance_video/" rel="alternate"></link><updated>2018-01-08T00:00:00-05:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2018-01-08:2018/01/08/new_performance_video/</id><summary type="html">&lt;p&gt;I&amp;#8217;ve just uploaded an &lt;a href="https://youtu.be/P432WK7VP4o"&gt;performance from 2013&lt;/a&gt; for my sensor-augmented upright bass using the &lt;a href="http://ssfrr.com/projects/mousetrap/"&gt;mousetrap sensors&lt;/a&gt; I designed in 2007. You can see a more detailed overview video of the sensors &lt;a href="https://www.youtube.com/watch?v=xpAFJEpXnCc"&gt;here&lt;/a&gt;, as well as in the blog&amp;nbsp;archive.&lt;/p&gt;
&lt;iframe width="560" height="315" src="https://www.youtube.com/embed/P432WK7VP4o" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen&gt;&lt;/iframe&gt;</summary></entry><entry><title>Fast array slicing in Julia</title><link href="http://ssfrr.com/2017/11/03/julia_fast_array_slicing/" rel="alternate"></link><updated>2017-11-03T00:00:00-04:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2017-11-03:2017/11/03/julia_fast_array_slicing/</id><summary type="html">&lt;p&gt;I write a lot of stream-oriented code, where you&amp;#8217;re working with data in chunks and manipulating them as they pass through the system. Julia 0.6 introduced some new functionality for expressing array manipulations more efficiently, which are described in depth in &lt;a href="https://julialang.org/blog/2017/01/moredots"&gt;Steven G. Johnson&amp;#8217;s post here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When implementing &lt;code&gt;read&lt;/code&gt; and &lt;code&gt;write&lt;/code&gt; methods for streams you often end up copying chunks of data between arrays, so I wanted to explore how some of Julia&amp;#8217;s features work together to make that as efficient as possible. From reading the &lt;a href="https://docs.julialang.org/en/stable/manual/performance-tips/"&gt;performance tips&lt;/a&gt; section of the manual we already know that pre-allocating your result arrays is one way to reduce allocations and speed things up (assuming you&amp;#8217;ll be writing to the destination array many times), so we&amp;#8217;ll use that as a starting point and assume we have a result array &lt;code&gt;a&lt;/code&gt; that we&amp;#8217;re going to fill by doing some operations on &lt;code&gt;b&lt;/code&gt; and &lt;code&gt;c&lt;/code&gt; arrays.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll be using the following toy operation to test some variants and discuss what&amp;#8217;s going&amp;nbsp;on:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;Compat&lt;/span&gt; &lt;span class="c"&gt;# currently needed because of an issue with BenchmarkTools&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;BenchmarkTools&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; naive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And we can benchmark the code to see how long it takes to&amp;nbsp;run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="n"&gt;benchmark&lt;/span&gt; &lt;span class="n"&gt;naive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;BenchmarkTools&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Trial&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mf"&gt;31.75&lt;/span&gt; &lt;span class="n"&gt;KiB&lt;/span&gt;
  &lt;span class="n"&gt;allocs&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mi"&gt;4&lt;/span&gt;
  &lt;span class="o"&gt;--------------&lt;/span&gt;
  &lt;span class="n"&gt;minimum&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="mf"&gt;3.339&lt;/span&gt; &lt;span class="n"&gt;μs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.00&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;GC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;median&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="mf"&gt;3.760&lt;/span&gt; &lt;span class="n"&gt;μs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.00&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;GC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="mf"&gt;4.666&lt;/span&gt; &lt;span class="n"&gt;μs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;16.71&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;GC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;maximum&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="mf"&gt;95.044&lt;/span&gt; &lt;span class="n"&gt;μs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;87.97&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;GC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;--------------&lt;/span&gt;
  &lt;span class="n"&gt;samples&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="mi"&gt;10000&lt;/span&gt;
  &lt;span class="n"&gt;evals&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="mi"&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now it&amp;#8217;s a little hard to evaluate whether 3.8μs is a reasonable amount of time to spend, but almost &lt;span class="caps"&gt;32KB&lt;/span&gt; seems like a lot of memory to allocate when all our arrays are already allocated. Consider that we&amp;#8217;re moving around blocks of 1000 elements of type &lt;code&gt;Float64&lt;/code&gt;, so each block should be about 8000B (7.8KiB). So this allocation represents 4 copies plus some&amp;nbsp;extra.&lt;/p&gt;
&lt;p&gt;For reference, we can check against the following python code using &lt;code&gt;numpy&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;57&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;58&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;59&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;timeit&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;999&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;999&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1999&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;slowest&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;took&lt;/span&gt; &lt;span class="mf"&gt;30.76&lt;/span&gt; &lt;span class="n"&gt;times&lt;/span&gt; &lt;span class="n"&gt;longer&lt;/span&gt; &lt;span class="n"&gt;than&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;fastest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;This&lt;/span&gt; &lt;span class="n"&gt;could&lt;/span&gt; &lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;intermediate&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;being&lt;/span&gt; &lt;span class="n"&gt;cached&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;span class="mi"&gt;100000&lt;/span&gt; &lt;span class="n"&gt;loops&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;best&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;2.7&lt;/span&gt; &lt;span class="err"&gt;µ&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Trying my best to match methodologies&lt;sup id="fnref:python"&gt;&lt;a class="footnote-ref" href="#fn:python" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt;, our naïve Julia version ends up taking about 35% longer than the python equivalent with&amp;nbsp;numpy.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s discuss a little bit what happens when Julia executes this function. First we have the array slices &lt;code&gt;b[1:1000]&lt;/code&gt; and &lt;code&gt;c[1001:2000]&lt;/code&gt;, which will each create a new copy of the 1000 sliced elements. We&amp;#8217;re not modifying these arrays and throwing away these copies immediately after, so we&amp;#8217;d prefer to create a view into the same data. We could do this with &lt;code&gt;view(b, 1:1000)&lt;/code&gt;, but we can also use the &lt;code&gt;@views&lt;/code&gt; macro to turn both our indexing operations into&amp;nbsp;views:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; views&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This definitely improves our run&amp;nbsp;time:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="n"&gt;benchmark&lt;/span&gt; &lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;BenchmarkTools&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Trial&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mf"&gt;15.97&lt;/span&gt; &lt;span class="n"&gt;KiB&lt;/span&gt;
  &lt;span class="n"&gt;allocs&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mi"&gt;4&lt;/span&gt;
  &lt;span class="o"&gt;--------------&lt;/span&gt;
  &lt;span class="n"&gt;minimum&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="mf"&gt;1.615&lt;/span&gt; &lt;span class="n"&gt;μs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.00&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;GC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;median&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="mf"&gt;2.332&lt;/span&gt; &lt;span class="n"&gt;μs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.00&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;GC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="mf"&gt;2.757&lt;/span&gt; &lt;span class="n"&gt;μs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;12.35&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;GC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;maximum&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="mf"&gt;71.391&lt;/span&gt; &lt;span class="n"&gt;μs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;90.06&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;GC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;--------------&lt;/span&gt;
  &lt;span class="n"&gt;samples&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="mi"&gt;10000&lt;/span&gt;
  &lt;span class="n"&gt;evals&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We see we&amp;#8217;ve cut our allocations in half and runtime by about 40%. The allocation reduction makes sense as we&amp;#8217;ve avoided 2 copies by using views instead. Numpy uses views by default, which probably accounted for the initial performance edge of the numpy version over the naïve Julia&amp;nbsp;version.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s try another tactic and use dot broadcasting and loop fusion, as described in &lt;a href="https://julialang.org/blog/2017/01/moredots"&gt;&lt;span class="caps"&gt;SGJ&lt;/span&gt;&amp;#8217;s post&lt;/a&gt;. To summarize the issue (though I recommend reading the post for more details), elementwise operations between arrays often create temporary copies that we&amp;#8217;d like to avoid. For instance, &lt;code&gt;y = 3x.^2 + 5x + 2&lt;/code&gt; will create temporary arrays for &lt;code&gt;3x&lt;/code&gt;, and &lt;code&gt;5x&lt;/code&gt;, then another one for &lt;code&gt;3x.^2&lt;/code&gt;, and so on, until it finally assigns the identifier &lt;code&gt;y&lt;/code&gt; to the final result. Even if you pre-allocate &lt;code&gt;y&lt;/code&gt; and assign the elements with &lt;code&gt;y[:] = ...&lt;/code&gt; it will still allocate temporaries and then at the end copy the final result into &lt;code&gt;y&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The solution is to use dot syntax on the operators &lt;code&gt;y.= 3.*x.^2.+5.*x.+2&lt;/code&gt;, which is transformed (more or less)&amp;nbsp;into:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;eachindex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Which does all the processing in a single pass over the data without allocating any extra temporaries, and is super fast. Now that&amp;#8217;s a lot of dots and looks pretty ugly, so you can use the &lt;code&gt;@.&lt;/code&gt; macro to add the dots to all the operations in the&amp;nbsp;expression.&lt;/p&gt;
&lt;p&gt;Now let&amp;#8217;s try this technique with our array slicing. We&amp;#8217;ll take out the views so we can separate out the two&amp;nbsp;effects:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; dotted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Benchmarking this version shows that it avoids 2 copies for temporary values, and also gives a tidy&amp;nbsp;speedup.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="n"&gt;benchmark&lt;/span&gt; &lt;span class="n"&gt;dotted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;BenchmarkTools&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Trial&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mf"&gt;15.92&lt;/span&gt; &lt;span class="n"&gt;KiB&lt;/span&gt;
  &lt;span class="n"&gt;allocs&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mi"&gt;3&lt;/span&gt;
  &lt;span class="o"&gt;--------------&lt;/span&gt;
  &lt;span class="n"&gt;minimum&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="mf"&gt;1.490&lt;/span&gt; &lt;span class="n"&gt;μs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.00&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;GC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;median&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="mf"&gt;1.712&lt;/span&gt; &lt;span class="n"&gt;μs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.00&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;GC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="mf"&gt;2.085&lt;/span&gt; &lt;span class="n"&gt;μs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;15.33&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;GC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;maximum&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="mf"&gt;57.836&lt;/span&gt; &lt;span class="n"&gt;μs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;89.50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;GC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;--------------&lt;/span&gt;
  &lt;span class="n"&gt;samples&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="mi"&gt;10000&lt;/span&gt;
  &lt;span class="n"&gt;evals&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Now the obvious question is whether we can combine these approaches, and of course we can! The following is exactly the same as our original function with both the macros&amp;nbsp;prepended:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt;&lt;span class="nf"&gt; dottedviews&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1001&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;So now we&amp;#8217;re creating the two views rather than copies, and using loop fusion to avoid the temporary copies. How does this affect our&amp;nbsp;benchmark?&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;julia&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="n"&gt;benchmark&lt;/span&gt; &lt;span class="n"&gt;dottedviews&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;BenchmarkTools&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Trial&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mi"&gt;96&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;
  &lt;span class="n"&gt;allocs&lt;/span&gt; &lt;span class="n"&gt;estimate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mi"&gt;2&lt;/span&gt;
  &lt;span class="o"&gt;--------------&lt;/span&gt;
  &lt;span class="n"&gt;minimum&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="mf"&gt;284.270&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.00&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;GC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;median&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="mf"&gt;304.295&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.00&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;GC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="mf"&gt;310.547&lt;/span&gt; &lt;span class="n"&gt;ns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.88&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;GC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;maximum&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="mf"&gt;3.001&lt;/span&gt; &lt;span class="n"&gt;μs&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;84.90&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;GC&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;--------------&lt;/span&gt;
  &lt;span class="n"&gt;samples&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="mi"&gt;10000&lt;/span&gt;
  &lt;span class="n"&gt;evals&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="mi"&gt;278&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;There&amp;#8217;s still some allocation, probably because views still allocate a small object that refers to the original array (there are improvements around the corner that would allow us to stack-allocate these as well), and this version now takes less than 10% as long as our&amp;nbsp;original.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;When trying to improve the performance of your code, checking for excessive allocation can be a very fruitful approach. Here we improved our performance by 10X by adding two macros to the front of our&amp;nbsp;expression.&lt;/p&gt;
&lt;h3&gt;Notes&lt;/h3&gt;
&lt;div class="footnote"&gt;
&lt;hr /&gt;
&lt;ol&gt;
&lt;li id="fn:python"&gt;
&lt;p&gt;For the python benchmark, &lt;code&gt;%timeit&lt;/code&gt; turns off garbage collection and gives the best mean from 3 runs, so the equivalent julia timing comes out to 3.64µs (calculated by running the benchmark 3 times, subtracting the &lt;span class="caps"&gt;GC&lt;/span&gt; time from the mean value, and picking the best result). There&amp;#8217;s also the caching warning printed by &lt;code&gt;%timeit&lt;/code&gt;, so the actual python runtime might be somewhat slower.&amp;#160;&lt;a class="footnote-backref" href="#fnref:python" rev="footnote" title="Jump back to footnote 1 in the text"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</summary></entry><entry><title>Exploring noise distribution in Pure Data</title><link href="http://ssfrr.com/2017/03/16/pd-noise-distribution/" rel="alternate"></link><updated>2017-03-16T00:00:00-04:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2017-03-16:2017/03/16/pd-noise-distribution/</id><summary type="html">&lt;p&gt;&lt;img alt="histogram of PD's noise object" src="/media/pd_noise_histogram_LP1000Hz-37.png" /&gt;&lt;/p&gt;
&lt;h2&gt;Defining some&amp;nbsp;terms&lt;/h2&gt;
&lt;p&gt;This post is all about noise, so lets start with a quick discussion of what noise is. In some contexts noise is defined as whatever part of a signal you don&amp;#8217;t care about and would rather ignore. It is a distractor and can obscure the information you want, and is usually what people mean when they&amp;#8217;re talking about &amp;#8220;signal-to-noise ratios&amp;#8221;. In electronics this noise often comes from small random voltage fluctuations in the components themselves, and manifests as a sort of hissing sound, similar to shhhhhh. When evaluating these systems, engineers found that they could model this noise as &lt;em&gt;Additive White Gaussian Noise&lt;/em&gt;, which we can break down&amp;nbsp;as:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;Additive&lt;/dt&gt;
&lt;dd&gt;The composite noisy signal is just the original pure signal with the noise added to&amp;nbsp;it&lt;/dd&gt;
&lt;dt&gt;White&lt;/dt&gt;
&lt;dd&gt;The noise has a flat spectrum, which means that all frequencies are present equally. In practice real systems always operate within a finite bandwidth, so to be white the noise just has to be flat within the bandwidth of interest. This term comes from an analogy with light, where light with all wavelengths in equal proportions looks white to human&amp;nbsp;eyes.&lt;/dd&gt;
&lt;dt&gt;Gaussian&lt;/dt&gt;
&lt;dd&gt;The values the noise takes follow a gaussian (&lt;span class="caps"&gt;AKA&lt;/span&gt; normal) distribution. This means that values near the mean (usually 0) are more likely than values further away. This part is the focus of this&amp;nbsp;post.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;While in most engineering contexts noise is considered unwanted, it turns out to be tremendously useful in many audio synthesis applications. Lots of real-world phenomena have noisy components, from wind to snare drums to raspy violin bowing. Because it&amp;#8217;s so common, most computer music and audio processing environments have some mechanism to generate noise, and I spent a little time exploring Pure Data&amp;#8217;s &lt;code&gt;[noise~]&lt;/code&gt; object.&lt;/p&gt;
&lt;h2&gt;Spectral&amp;nbsp;Properties&lt;/h2&gt;
&lt;p&gt;The first thing to do is to check the spectrum to see if &lt;span class="caps"&gt;PD&lt;/span&gt;&amp;#8217;s [noise~] object actually gives us white noise. To do this I put together a quick little spectrum viewer called &lt;code&gt;[specplot~]&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;img alt="specplot~ PD object" src="/media/specplot~.png" /&gt;&lt;/p&gt;
&lt;p&gt;And here&amp;#8217;s what the spectrum of &lt;code&gt;[noise~]&lt;/code&gt; looks&amp;nbsp;like:&lt;/p&gt;
&lt;p&gt;&lt;img alt="noise~ spectrum" src="/media/pd_noise_spectrum.gif" /&gt;&lt;/p&gt;
&lt;p&gt;Looks pretty flat to me, which confirms that this is white&amp;nbsp;noise.&lt;/p&gt;
&lt;h2&gt;Value&amp;nbsp;Distribution&lt;/h2&gt;
&lt;p&gt;The next question to ask is whether the noise is gaussian-distributed. To check this out we just build a simple match that periodically samples from the noise output and updates a histogram plot. The histogram shows us how often different value ranges show up in the&amp;nbsp;output.&lt;/p&gt;
&lt;p&gt;&lt;img alt="noise~ value histogram" src="/media/pd_noise_histogram.gif" /&gt;&lt;/p&gt;
&lt;p&gt;This is definitely not gaussian, but looks more like a uniform distribution. We see that values anywhere between -1 and 1 are equally likely to occur. This decision is likely due to three&amp;nbsp;factors:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Uniform random numbers are computationally cheaper to generate then gaussian-distributed&amp;nbsp;ones&lt;/li&gt;
&lt;li&gt;Uniformly distributed numbers are bounded, so the output of &lt;code&gt;[noise~]&lt;/code&gt; will never go outside of the -1 to 1&amp;nbsp;range&lt;/li&gt;
&lt;li&gt;Uniform and Gaussian noise sound the same as long as their spectral properties&amp;nbsp;match&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Filtering&amp;nbsp;Noise&lt;/h2&gt;
&lt;p&gt;White noise tends to sound pretty harsh as it has a lot of energy in high frequencies relative to most naturally-occurring sounds. It&amp;#8217;s common to use white noise as a starting point and then filter it to shape the sound more to your liking. First let&amp;#8217;s see what that looks like&amp;nbsp;spectrally:&lt;/p&gt;
&lt;p&gt;&lt;img alt="filtered noise~ spectrum" src="/media/pd_noise_spectrum_LP1000Hz.gif" /&gt;&lt;/p&gt;
&lt;p&gt;This doesn&amp;#8217;t look too dramatic because we&amp;#8217;re using a relatively shallow filter (&lt;span class="caps"&gt;PD&lt;/span&gt;&amp;#8217;s &lt;code&gt;[lop~]&lt;/code&gt; object is a 1-pole filter so it rolls off at 20dB / decade) and also because we&amp;#8217;re looking at a log-scaled plot, which makes it easier to compare signals with a large dynamic range. Still you can see that higher frequencies have been attenuated somewhat. Now lets&amp;#8217;s check out the value&amp;nbsp;histogram:&lt;/p&gt;
&lt;p&gt;&lt;img alt="filtered noise~ histogram" src="/media/pd_noise_histogram_LP1000Hz.gif" /&gt;&lt;/p&gt;
&lt;p&gt;Now this is interesting! Our uniform noise has become more gaussian after filtering. To explain this we can take a quick look at what a 1-pole filter looks&amp;nbsp;like:&lt;/p&gt;
&lt;p&gt;&lt;img alt="one-pole filter schematic" src="/media/one_pole_filter.png" /&gt;&lt;/p&gt;
&lt;p&gt;Inspecting the filter, we see that the output at time &lt;code&gt;n&lt;/code&gt; (&lt;code&gt;y[n]&lt;/code&gt;) is a combination of the input &lt;code&gt;x[n]&lt;/code&gt; and the previous output &lt;code&gt;y[n-1]&lt;/code&gt;. The previous output was itself a combination of that time-step&amp;#8217;s input and the output even further back, and so on. So this means that a given output is a combination of all the previous inputs, with exponentially-decreasing weights. We know from the &lt;a href="https://en.wikipedia.org/wiki/Central_limit_theorem"&gt;Central Limit Theorem&lt;/a&gt; that adding together a bunch of uniformly-distributed random variables gives us a gaussian-distributed random variable and the output of our filter is just such a&amp;nbsp;summation.&lt;/p&gt;
&lt;h2&gt;Summing&amp;nbsp;up&lt;/h2&gt;
&lt;p&gt;I&amp;#8217;ve never thought too much about the specifics of &lt;span class="caps"&gt;PD&lt;/span&gt;&amp;#8217;s &lt;code&gt;[noise~]&lt;/code&gt; object, but this little deep-dive had a few interesting rabbit holes to drop into, so I thought it was worth sharing. Let me know on Twitter if you enjoyed it or have questions or&amp;nbsp;comments.&lt;/p&gt;</summary></entry><entry><title>Async/Await and Types of Concurrency</title><link href="http://ssfrr.com/2016/09/07/concurrency-types/" rel="alternate"></link><updated>2016-09-07T00:00:00-04:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2016-09-07:2016/09/07/concurrency-types/</id><summary type="html">&lt;p&gt;I just watched &lt;a href="https://www.youtube.com/watch?v=E-1Y4kSsAFc"&gt;this talk&lt;/a&gt; by David Beazley about Python&amp;#8217;s newish &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; functionality. Beazley is also known for his &lt;a href="http://www.dabeaz.com/coroutines/"&gt;Curious Course on Coroutines and Concurrency&lt;/a&gt;, which is also wonderful. I&amp;#8217;m  not sure this talk really sells the paradigm to folks who haven&amp;#8217;t been bitten by concurrent programming though, and gets a little bogged down in the yield implementation.  I&amp;#8217;m also surprised he didn&amp;#8217;t reference previous async/await implementations like C#. That said, the talk is really engaging and well-done, and has a lot of great info on &lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I felt like this would be a reasonable time to jot down some thoughts I&amp;#8217;ve had about concurrent programming, which I&amp;#8217;ve mentioned conversations but haven&amp;#8217;t ever written down. I&amp;#8217;m certainly not an expert - this is informed by work in C++ using threads, bare-metal C using hardware interrupts and callbacks, Python using gevent, and Julia using the native Coroutine support, but there are probably other major types of concurrency that I&amp;#8217;m missing. Let me&amp;nbsp;know!&lt;/p&gt;
&lt;p&gt;I find myself dividing concurrency systems into several&amp;nbsp;types:&lt;/p&gt;
&lt;dl&gt;
&lt;dt&gt;preemptive multitasking, e.g. os-level&amp;nbsp;threads&lt;/dt&gt;
&lt;dd&gt;context-switches can happen at any point in your code, code might even be running in parallel (on multi-core). Accessing shared memory generally needs to be protected with synchronization primitives like&amp;nbsp;mutexes.&lt;/dd&gt;
&lt;dt&gt;cooperative multitasking, e.g. gevent-style green-threads, or Julia&amp;nbsp;Tasks&lt;/dt&gt;
&lt;dd&gt;context switches only happen when a task explicitly yields, or does something blocking like I/O. As long as you don&amp;#8217;t have any blocking calls in your critical section you should be safe. Unfortunately you have no idea if a function you&amp;#8217;re calling ends up calling something blocking (maybe it prints to a log). In gevent you actually monkey-patch the blocking &lt;span class="caps"&gt;IO&lt;/span&gt; functions so that instead of blocking the whole thread at the &lt;span class="caps"&gt;OS&lt;/span&gt; level it just blocks the current task and hands control back to the event&amp;nbsp;loop.&lt;/dd&gt;
&lt;dt&gt;explicit&amp;nbsp;callbacks&lt;/dt&gt;
&lt;dd&gt;this seems to have been pushed pretty far in Javascript, but as far as I know is less common now that there are nicer primitives. I don&amp;#8217;t really know &lt;span class="caps"&gt;JS&lt;/span&gt; though. One nice thing is that it&amp;#8217;s very explicit when the context switch happens. The downside is that sequential processes become nested callbacks, and branches (e.g. different success/error callbacks) are hard to&amp;nbsp;follow.&lt;/dd&gt;
&lt;dt&gt;&lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt; (found in C#,&amp;nbsp;python)&lt;/dt&gt;
&lt;dd&gt;To me this seems like a sweet spot where you can write sequential code, but anywhere that might possibly context-switch is marked by &lt;code&gt;await&lt;/code&gt;.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;The &lt;a href="http://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/"&gt;blog post&lt;/a&gt; linked in the video is well-worth reading. One issue I take is that there is an advantage to explicitly dividing functions into synchronous and asynchronous, in that you know when your task might block, and you can make sure it&amp;#8217;s not in the middle of a critical section. That said, if you&amp;#8217;re not using shared memory to pass information between tasks it&amp;#8217;s less of a problem. The reason Go&amp;#8217;s coroutine model works so well is because it&amp;#8217;s coupled with Channels as the main mechanism for passing information between coroutines, so you generally don&amp;#8217;t have to worry about unexpected context&amp;nbsp;switches.&lt;/p&gt;</summary></entry><entry><title>The Closure Problem in Python</title><link href="http://ssfrr.com/2012/08/04/the-closure-problem-in-python/" rel="alternate"></link><updated>2012-08-04T22:39:58+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2012-08-04:2012/08/04/the-closure-problem-in-python/</id><summary type="html">&lt;p&gt;I&amp;#8217;ve seen several posts now with people complaining about the following python&amp;nbsp;code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;funcs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
        &lt;span class="n"&gt;funcs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;funcs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;15&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Most people first looking at the code would expect the value of &lt;code&gt;funcs[1](5)&lt;/code&gt;
to be 6, which it is clearly not, but I&amp;#8217;ve found many confusing and sometimes
just wrong explanations for why this is so. I wanted to clarify my
understanding of the issue and hopefully provide a simple and clear reasoning
for others. Hopefully this is not one of those wrong explanations, and if
someone who didn&amp;#8217;t just learn about lexical scoping today wants to correct me
please do. I also may be playing a little fast and loose with some terminology,
so let me know if anything is&amp;nbsp;confusing.&lt;/p&gt;
&lt;p&gt;The surprise is the result of two non-obvious python&amp;nbsp;features:&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;for&lt;/code&gt; loops do not create their own isolated&amp;nbsp;scope&lt;/h3&gt;
&lt;p&gt;This is clearly demonstrated&amp;nbsp;with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
&lt;span class="mi"&gt;9&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Where you can see that not only is the loop variable &lt;code&gt;i&lt;/code&gt; maintained after the
for loop, but &lt;code&gt;j&lt;/code&gt; as well. This seems like a somewhat questionable design
decision to me, but perhaps that&amp;#8217;s because I&amp;#8217;m primarily a C&amp;nbsp;developer.&lt;/p&gt;
&lt;h3&gt;Expressions within the body of a function are evaluated when the function is called, not when it is&amp;nbsp;defined&lt;/h3&gt;
&lt;p&gt;This is also clearly demonstrated with a simple bit of&amp;nbsp;code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; 
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;
&lt;span class="ne"&gt;NameError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;i&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;defined&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;8&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;9&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;So you can see, even though &lt;code&gt;i&lt;/code&gt; didn&amp;#8217;t exist with the function was defined, the
interpreter happily allowed us to use it in the body of the function, and then
only attempted to evaluate it when it was actually&amp;nbsp;called.&lt;/p&gt;
&lt;p&gt;Putting these two things together it&amp;#8217;s clear why python evaluates our first
code example the way it does. The variable &lt;code&gt;i&lt;/code&gt; inside the body of the function
has nothing to do with the loop variable &lt;code&gt;i&lt;/code&gt; until the moment that the function
in the array is actually called, at which point python looks up the name &lt;code&gt;i&lt;/code&gt; in
the symbol table and finds the one that happens to have &amp;#8216;leaked out&amp;#8217; of the
&lt;code&gt;for&lt;/code&gt; loop.&lt;/p&gt;
&lt;p&gt;Solutions to this issue usually involve forcing evaluation of the variable so
that the function references the value instead of the name. My favorite version
involves adding the variable as a default value to the function, forcing
evaluation at definition time.&amp;nbsp;e.g.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;funcs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;inc&lt;/span&gt;
        &lt;span class="n"&gt;funcs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;funcs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;6&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;In this version &lt;code&gt;i&lt;/code&gt; is evaluated and the value stored in &lt;code&gt;inc&lt;/code&gt; when each copy
of &lt;code&gt;func&lt;/code&gt; is&amp;nbsp;defined.&lt;/p&gt;
&lt;h3&gt;Now we&amp;#8217;re cooking with&amp;nbsp;Closures&lt;/h3&gt;
&lt;p&gt;&lt;span class="caps"&gt;OK&lt;/span&gt;, so things get a little more complicated when we need to specify where
exactly the interpreter looks when it finds a variable in your defined function
that&amp;#8217;s not local to the function (a &amp;#8216;free&amp;#8217; variable). As mentioned above, the
interpreter looks up a value at the time of the call, but it looks in the scope
within which the function was defined. More&amp;nbsp;code!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;outer&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="n"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;outer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; 
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;outer&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;inc&lt;/span&gt;
&lt;span class="ne"&gt;NameError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;y&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;defined&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;outer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;So here we see that when &lt;code&gt;inc&lt;/code&gt; is called within the &lt;code&gt;outer&lt;/code&gt; scope, the
interpreter looks up &lt;code&gt;y&lt;/code&gt; within the original scope where &lt;code&gt;inc&lt;/code&gt; was defined, not
the scope from which it was called. After we define &lt;code&gt;y&lt;/code&gt; where it is in reach of
&lt;code&gt;inc&lt;/code&gt;, all is well and happy. This is where closures come into play, because
what if the scope in which the function was defined no longer exists? In a
language without closure support we&amp;#8217;d be out of luck, but with closures those
references stick around after the function that created the scope finishes&amp;nbsp;executing.&lt;/p&gt;</summary></entry><entry><title>‘Haskell Spectrograms 2: Array Slicing and Dicing’</title><link href="http://ssfrr.com/2012/05/11/haskell-spectrograms-2/" rel="alternate"></link><updated>2012-05-11T00:29:43+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2012-05-11:2012/05/11/haskell-spectrograms-2/</id><summary type="html">&lt;p&gt;&lt;img alt="Spectrogram of a short string loop" src="/media/spec.png" /&gt;&lt;/p&gt;
&lt;h2&gt;So we have a&amp;nbsp;vector&lt;/h2&gt;
&lt;p&gt;Given a vector of audio, the first step in making a spectrogram is to slice up
the audio into frames. This slicing process is defined by the frame size and
the hop. The frame size is the number of samples in each frame, the hop is the
number of samples between the beginning of adjacent frames. For instance, if
slicing the vector [1,2,3,4,5,6,7,8] with a frame size of 4 and a hop size of
2, the resulting frames would be [[1,2,3,4],[3,4,5,6],[5,6,7,8],[7,8,0,0]].
Note that the last frame was padded out with zeros because it extended beyond
the original&amp;nbsp;vector.&lt;/p&gt;
&lt;h2&gt;Slicing an Array in&amp;nbsp;Haskell&lt;/h2&gt;
&lt;p&gt;This is where the variety of vector/array libraries in Haskell started to
become a bit more of a drag. hsndfile supports Data.StorableVector or
Data.Vector as an output type. The
&lt;a href="http://hackage.haskell.org/package/dsp"&gt;haskell-dsp&lt;/a&gt; package (available
through cabal) uses the standard Haskell Array type. So my first order of
business was to convert my freshly-minted StorableVector into an&amp;nbsp;Array.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="k"&gt;qualified&lt;/span&gt; &lt;span class="nn"&gt;Data.StorableVector&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Array&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;

&lt;span class="nf"&gt;arrayFromVector&lt;/span&gt; &lt;span class="ow"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;V&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt; &lt;span class="kt"&gt;Double&lt;/span&gt; &lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="kt"&gt;Double&lt;/span&gt;
&lt;span class="nf"&gt;arrayFromVector&lt;/span&gt; &lt;span class="n"&gt;vect&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt;
   &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;V&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="n"&gt;vect&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="kr"&gt;in&lt;/span&gt;
      &lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zip&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;V&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unpack&lt;/span&gt; &lt;span class="n"&gt;vect&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The above code converts the Vector to a list with V.unpack, then uses the array
constructor to create an Array of Double (with Int indexes). Not the most
elegant or fast, but&amp;nbsp;effective.&lt;/p&gt;
&lt;p&gt;Next we need to take this array and slice it into frames. Lets call that
function &amp;#8220;getFrames&amp;#8221;, which will take a frames size and hop size and give back
a list of subarrays of the original&amp;nbsp;array.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nf"&gt;getFrames&lt;/span&gt; &lt;span class="ow"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="kt"&gt;Double&lt;/span&gt; &lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="kt"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;getFrames&lt;/span&gt; &lt;span class="n"&gt;inArr&lt;/span&gt; &lt;span class="n"&gt;frameSize&lt;/span&gt; &lt;span class="n"&gt;hop&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt;
   &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;getFrame&lt;/span&gt; &lt;span class="n"&gt;inArr&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="n"&gt;frameSize&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;  &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="kt"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="nf"&gt;getFrame&lt;/span&gt; &lt;span class="n"&gt;inVect&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pad&lt;/span&gt; &lt;span class="n"&gt;slice&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt;
   &lt;span class="kr"&gt;where&lt;/span&gt;
      &lt;span class="n"&gt;slice&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ixmap&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;inVect&lt;/span&gt;
      &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt; &lt;span class="n"&gt;length&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bounds&lt;/span&gt; &lt;span class="n"&gt;inVect&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Getting a subarray in Haskell is a little bit tricky. The Array library
provides an &amp;#8220;ixmap&amp;#8221; function that takes what you want the bounds of the new
array to be, as well as a transformation function to get an index into the old
array given an index into the new array. getFrames uses a list comprehension to
create a list of slices, each of which is created with getFrame using ixmap.
The bounds of the new array are 0 and the length-1, the transformation function
to get an index into the original array from the new array is just an offset
operation. the pad function comes from the &lt;span class="caps"&gt;DSP&lt;/span&gt; library, available through&amp;nbsp;cabal&lt;/p&gt;
&lt;h2&gt;The Furrier[sic]&amp;nbsp;Transform&lt;/h2&gt;
&lt;p&gt;Once we have ourselves a list of Arrays, the &lt;span class="caps"&gt;DSP&lt;/span&gt; library provides an fft
implementation for real signals called rfft, which returns the complex spectrum
of an input array. Applying the &lt;span class="caps"&gt;FFT&lt;/span&gt; to each frame in our list is a simple map
operation. Here we compose a getFrameMagnitude function with rfft, which takes
the complex signal and gives us something that we can plot as a&amp;nbsp;spectrogram.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nf"&gt;getFrameMagnitude&lt;/span&gt; &lt;span class="ow"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Complex&lt;/span&gt; &lt;span class="kt"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="kt"&gt;Double&lt;/span&gt;
&lt;span class="nf"&gt;getFrameMagnitude&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)`&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;\&lt;/span&gt;
      &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;magnitude&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)`&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)`&lt;/span&gt;&lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;`&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)]]&lt;/span&gt;
   &lt;span class="kr"&gt;where&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;A&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bounds&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;
&lt;span class="nf"&gt;main&lt;/span&gt; &lt;span class="ow"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="nb"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;main&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
   &lt;span class="n"&gt;audioVect&lt;/span&gt; &lt;span class="ow"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;readWavFile&lt;/span&gt; &lt;span class="n"&gt;sndFileName&lt;/span&gt;
   &lt;span class="n"&gt;drawSpec&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getFrameMagnitude&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;rfft&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;\&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getFrames&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arrayFromVector&lt;/span&gt; &lt;span class="n"&gt;audioVect&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;spec.png&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;getFrameMagnitude&lt;/code&gt; looks a little hairy, but the gist is that we&amp;#8217;re using list
comprehension to create a new list that&amp;#8217;s the second half of the input array,
where at each sample we take the magnitude, add one to it, then take the log.
We add 1 before taking the log so that the log-scaled output will start at 0,
for ease of&amp;nbsp;plotting&lt;/p&gt;
&lt;p&gt;Join us next time to see how drawSpec works and actually make some&amp;nbsp;spectrograms!&lt;/p&gt;</summary></entry><entry><title>‘Haskell Spectrograms 1: Loading a Sound File’</title><link href="http://ssfrr.com/2012/05/10/haskell-spectrograms-1/" rel="alternate"></link><updated>2012-05-10T23:19:43+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2012-05-10:2012/05/10/haskell-spectrograms-1/</id><summary type="html">&lt;p&gt;&lt;img alt="Spectrogram of a short string loop" src="/media/spec.png" /&gt;&lt;/p&gt;
&lt;h2&gt;Intro&lt;/h2&gt;
&lt;p&gt;So I took it up as a challenge to generate a spectrogram in Haskell. How hard
could it be? Turns out that what&amp;#8217;s a few lines of python code using numpy and
matplotlib took me down quite a rabbit&amp;nbsp;hole.&lt;/p&gt;
&lt;p&gt;For the impatient, you can find the finished code at
&lt;a href="https://github.com/ssfrr/scimitar"&gt;https://github.com/ssfrr/scimitar&lt;/a&gt; in the
&amp;#8220;haskell&amp;#8221;&amp;nbsp;directory.&lt;/p&gt;
&lt;blockquote&gt;Disclaimer: I am not an experienced Haskell programmer, and I&amp;#8217;m
likely doing things all wrong. Please correct me via Twitter&lt;/blockquote&gt;

&lt;h2&gt;hsndfile&lt;/h2&gt;
&lt;p&gt;I chose to use the hsndfile wrapper around Erik de Castro Lopo&amp;#8217;s immensely
useful libsndfile to load the file. This immediately forced me into the
abundance of vector libraries for Haskell. This was a huge sticking point for
me. There are literally about a dozen different libraries that one can use in
Haskell to represent a vector of floats (or vectors of anything storable, but I&amp;nbsp;digress).&lt;/p&gt;
&lt;p&gt;Luckily hsndfile only has bindings to 2 of them, which cut down my options. I
ended up using hsndfile-storablevector, which is available for installation
through cabal. Loading a sound using hsndfile looks a little&amp;nbsp;like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="k"&gt;qualified&lt;/span&gt; &lt;span class="nn"&gt;Sound.File.Sndfile&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;Snd&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="k"&gt;qualified&lt;/span&gt; &lt;span class="nn"&gt;Sound.File.Sndfile.Buffer.StorableVector&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;BV&lt;/span&gt;
&lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="k"&gt;qualified&lt;/span&gt; &lt;span class="nn"&gt;Data.StorableVector&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;

&lt;span class="nf"&gt;readWavFile&lt;/span&gt; &lt;span class="ow"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="ow"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;V&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt; &lt;span class="kt"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;readWavFile&lt;/span&gt; &lt;span class="n"&gt;fileName&lt;/span&gt; &lt;span class="ow"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;do&lt;/span&gt;
   &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="ow"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;Snd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;openFile&lt;/span&gt; &lt;span class="n"&gt;fileName&lt;/span&gt; &lt;span class="kt"&gt;Snd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;ReadMode&lt;/span&gt; &lt;span class="kt"&gt;Snd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;defaultInfo&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Just&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="kt"&gt;Snd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hGetContents&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt; &lt;span class="ow"&gt;::&lt;/span&gt; &lt;span class="nf"&gt;\&lt;/span&gt;
      &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Snd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;Maybe&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;BV&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Buffer&lt;/span&gt; &lt;span class="kt"&gt;Double&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
   &lt;span class="n"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;BV&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fromBuffer&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;To unpack this a little Snd.openFile takes in a filename, a mode, and an Info
instance (check
&lt;a href="http://hackage.haskell.org/packages/archive/hsndfile/0.5.2/doc/html/Sound-File-Sndfile.html"&gt;this&lt;/a&gt;
out for more details on the individual datatypes), and gives you a handle to
the file (wrapped up in an &lt;span class="caps"&gt;IO&lt;/span&gt; monad, of&amp;nbsp;course).&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Snd.hGetContents&lt;/code&gt; takes a handle and gives you a &lt;span class="caps"&gt;IO&lt;/span&gt;-wrapped pair. The first
item is another Info instance that describes the soundfile you just read, and
the second might be a buffer (or Nothing). The tricky bit here is that Haskell
doesn&amp;#8217;t know what type that it&amp;#8217;s supposed to be, so  you need to make the type
explicit with the annotation shown above to make it a buffer of Doubles. The
cool thing here is that if the datatype  you request does not match the
datatype of the original sound, hsndfile will do the conversion for&amp;nbsp;you.&lt;/p&gt;
&lt;p&gt;Once you have the buffer of doubles, you use the fromBuffer function to get
back a normal StorableVector.Vector that you can do other fun things with. Come
back next time for some of those fun&amp;nbsp;things!&lt;/p&gt;</summary></entry><entry><title>libmanta released!</title><link href="http://ssfrr.com/2012/03/24/libmanta-released/" rel="alternate"></link><updated>2012-03-24T22:07:06+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2012-03-24:2012/03/24/libmanta-released/</id><summary type="html">&lt;p&gt;&lt;img alt="Snyderphonics Manta" src="/media/snyderphonics-manta2-460-85.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;(photo nabbed from &lt;a href="http://www.musicradar.com/gear/all/computers-software/peripherals/input-devices/midi-controllers/controllers/manta-218739/review"&gt;MusicRadar)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After more than a year(sporadically), several re-writes, and much learning about &lt;span class="caps"&gt;USB&lt;/span&gt;, cross-platform threading, concurrency, &lt;span class="caps"&gt;OSX&lt;/span&gt; device driver loading, and many more, the libmanta library and the included &lt;span class="caps"&gt;PD&lt;/span&gt; and Max/&lt;span class="caps"&gt;MSP&lt;/span&gt; objects are finally ready for&amp;nbsp;release.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ssfrr/libmanta"&gt;Get The Source&lt;/a&gt;
&lt;a href="http://ssfrr.github.com/libmanta/"&gt;Read The&amp;nbsp;Documentation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;libmanta is a cross-platform &lt;span class="caps"&gt;API&lt;/span&gt; for the Snyderphonics Manta control surface. The low-level &lt;span class="caps"&gt;USB&lt;/span&gt; communication uses hidapi to communicate with the Manta, and provides a way to subscribe to the different events the Manta can generate, as well as methods to set the&amp;nbsp;LEDs.&lt;/p&gt;
&lt;p&gt;There are currently binaries available for Pure Data on linux and &lt;span class="caps"&gt;OSX&lt;/span&gt;. Max/&lt;span class="caps"&gt;MSP&lt;/span&gt; binaries should be available shortly, as soon as Jeff (the inventor of the Manta) finishes the help patch and a wrapper that gives the new libmanta-based object the same interface as the old&amp;nbsp;one.&lt;/p&gt;</summary></entry><entry><title>gendy~ PD + Max/MSP object and libgendy 0.6.0 released!</title><link href="http://ssfrr.com/2010/05/17/gendy-pd-maxmsp-object-and-libgendy-0-6-0-released/" rel="alternate"></link><updated>2010-05-17T13:52:16+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2010-05-17:2010/05/17/gendy-pd-maxmsp-object-and-libgendy-0-6-0-released/</id><summary type="html">&lt;p&gt;&lt;img alt="" src="/media/gendyv0602.png" /&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been working off and on for a bit on a C++ library to implement a variant of Dynamic Stochastic Synthesis, a technique developed by Iannis Xenakis. (For a great history and more details check out &lt;a href="http://www.sergioluque.com/texts/luque_stochastic.pdf"&gt;Sergio Luque&amp;#8217;s thesis&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The library is still pretty rough around the edges and more or less completely undocumented, but the &lt;span class="caps"&gt;PD&lt;/span&gt; object that uses it should be pretty functional. Included with the code is a helpfile (gendy~-help.pd), as well as a gui (gendy-gui.pd) that should make it pretty easy to jump right&amp;nbsp;in.&lt;/p&gt;
&lt;p&gt;The basic idea of &lt;span class="caps"&gt;DSS&lt;/span&gt; is to describe a waveform with a set of &amp;#8220;breakpoints&amp;#8221; and interpolate between them to generate the actual audio signal. The set of breakpoints forms a single cycle of a waveform, and each time one cycle gets played, the breakpoints each move for the next cycle. So each breakpoint ends up on a two-dimensional random&amp;nbsp;walk.&lt;/p&gt;
&lt;p&gt;One improvement I&amp;#8217;ve made to some traditional &lt;span class="caps"&gt;DSS&lt;/span&gt; implementations is the use of cubic spline interpolation instead of linear, which improves the aliasing considerably. It&amp;#8217;s not a truly bandlimited signal, but is&amp;nbsp;differentiable.&lt;/p&gt;
&lt;p&gt;The other modification is the introduction of selectable center waveforms that the breakpoints will gravitate towards. Right now I only have flat, square, and sine implemented, but I&amp;#8217;m planning on including basic triangle and sawtooth as well. The &amp;#8220;h_pull&amp;#8221; and &amp;#8220;v_pull&amp;#8221; controls effect how much the breakpoints are pulled towards the center&amp;nbsp;waveform.&lt;/p&gt;
&lt;p&gt;The external requires Thomas Grill&amp;#8217;s Flext library. Once you have it installed simply&amp;nbsp;run&lt;/p&gt;
&lt;p&gt;&lt;code&gt;FLEXTDIR/build.sh pd gcc&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;From the base gendy directory (Where &lt;span class="caps"&gt;FLEXTDIR&lt;/span&gt; is the location of your flext install) and you should have a shiny new binary in the pd-linux directory. The arguments to build.sh will vary depending on your&amp;nbsp;system.&lt;/p&gt;
&lt;p&gt;Downloads:
&lt;a href="http://code.airwav.es/attachments/download/4/gendy-0.6.0.tar.gz"&gt;Source Tarball&lt;/a&gt;
&lt;a href="http://code.airwav.es/attachments/download/3/gendy~.pd_linux"&gt;x86_64 &lt;span class="caps"&gt;PD&lt;/span&gt;&amp;nbsp;Binary&lt;/a&gt;&lt;/p&gt;</summary></entry><entry><title>LTSpice Tutorial #1 - Basic Schematic Capture and Simulation</title><link href="http://ssfrr.com/2010/04/20/ltspice-tutorial-1-basic-schematic-capture-and-simulation/" rel="alternate"></link><updated>2010-04-20T22:53:18+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2010-04-20:2010/04/20/ltspice-tutorial-1-basic-schematic-capture-and-simulation/</id><summary type="html">&lt;p&gt;&lt;a href="/media/ltspice_voltagedivider2.png"&gt;&lt;img alt="" src="/media/ltspice_voltagedivider2.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is the first in a series of tutorials intended to introduce LTSpice to the
uninitiated. LTSpice has some rather unusual interface conventions that take
some getting used to, but it&amp;#8217;s an incredibly powerful tool that&amp;#8217;s available for&amp;nbsp;free!&lt;/p&gt;
&lt;p&gt;The first step is to download it from Linear Technology&amp;#8217;s
&lt;a href="http://www.linear.com/designtools/software/"&gt;website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Unfortunately it&amp;#8217;s a windows-only application, but the main developer, Mike
Engelhardt has gone out of his way to make it work well under &lt;span class="caps"&gt;WINE&lt;/span&gt;, so Linux
users aren&amp;#8217;t left out of the&amp;nbsp;fun.&lt;/p&gt;
&lt;p&gt;In these tutorials I&amp;#8217;m going to spend more time talking about using LTspice
specifically rather than about the electronics themselves, so I will sometimes
assume a certain level of circuit design&amp;nbsp;knowledge.&lt;/p&gt;
&lt;h3&gt;Adding&amp;nbsp;Components&lt;/h3&gt;
&lt;p&gt;&lt;a href="/media/ltspice-voltagesource2.png"&gt;&lt;img alt="" src="/media/ltspice-voltagesource2.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When you first start LTspice you&amp;#8217;re presented with an empty workspace. The
first thing to do is pretty &lt;span class="caps"&gt;CTRL&lt;/span&gt;+n to open up a new schematic. Then we can
start placing&amp;nbsp;parts.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;ll start our circuit with a simple ideal voltage source. F2 brings up a
library of components divided into folders, we&amp;#8217;ll leave most of them for later.
The ideal voltage source we&amp;#8217;re interested in is located in the default folder,
so you can either scroll over to it or begin typing &amp;#8220;voltage&amp;#8221; into the text
field and it will be selected. Press &lt;span class="caps"&gt;ENTER&lt;/span&gt; or double-click on &amp;#8220;voltage&amp;#8221; and
you&amp;#8217;ll see the window disappear and your cursor change to the voltage source
icon. Click once on the left side of the screen to place a voltage source, then
either right-click or press Escape to go back to selection&amp;nbsp;mode.&lt;/p&gt;
&lt;p&gt;You don&amp;#8217;t have to go to the library for all components. Pressing r, l, c, d, or
g will change your cursor into a resistor, inductor, capacitor, diode, or
ground icon, respectively. You can rotate the cursor by pressing &lt;span class="caps"&gt;CTRL&lt;/span&gt;+r, and
place the components with your trusty left mouse button. As before, right
clicking or pressing Escape will get you back to the default&amp;nbsp;mode.&lt;/p&gt;
&lt;p&gt;Press &amp;#8216;r&amp;#8217; and place two resistors one over the other, as in the schematic
above. Press Escape or right-click to&amp;nbsp;finish.&lt;/p&gt;
&lt;p&gt;Now press &amp;#8220;g&amp;#8221; and place two ground points as above. As in most schematic
capture software, all the ground connections are considered to be wired to each
other, and always provide a ground reference that reads 0V. Any voltages
measured in the circuit are relative to this ground. &lt;strong&gt;You also always need at
least one grounded node in your&amp;nbsp;circuit.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;Moving and&amp;nbsp;Deleting&lt;/h3&gt;
&lt;p&gt;Occasionally you will make a mistake, and want to delete a part or move it from
where you originally placed it. LTspice follows the &lt;span class="caps"&gt;UI&lt;/span&gt; convention that first
you specify an action, and then you select the parts you want to act on. To
delete parts simply press your Delete key, then click on the items you want
gone. You can also box-select around a group of items to be&amp;nbsp;deleted.&lt;/p&gt;
&lt;p&gt;To move items, press F8, or click the closed fist icon, then click on the item
you want to move, and you can place it anew. You can also press F7 or selected
the open hand icon, which will also move components. The difference is that the
closed-fist version will also drag along any connected wires, while the
open-hand will leave them&amp;nbsp;be.&lt;/p&gt;
&lt;h3&gt;Wiring it&amp;nbsp;up&lt;/h3&gt;
&lt;p&gt;Press F3 to change your cursor to crosshairs, and you&amp;#8217;re ready to wire. Simply
click where you want the wire to start, then click again where you want it to
end. You can click at any point on the canvas to put add intermediary points.
Holding down &amp;#8216;ctrl&amp;#8217; lets you put diagonal wires while still snapping the
endpoints to the&amp;nbsp;grid.&lt;/p&gt;
&lt;p&gt;Go ahead and place the wires as in the above&amp;nbsp;picture.&lt;/p&gt;
&lt;h3&gt;Changing Part&amp;nbsp;Properties&lt;/h3&gt;
&lt;p&gt;&lt;a href="/media/ltspice_properties2.png"&gt;&lt;img alt="" src="/media/ltspice_properties2.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Once the
components are placed, right-click on the component icon to change its
parameters. You can use &lt;span class="caps"&gt;SI&lt;/span&gt; prefixes like k(kilo), m(milli), and u(micro), but
you have to use &lt;span class="caps"&gt;MEG&lt;/span&gt; for&amp;nbsp;mega.&lt;/p&gt;
&lt;p&gt;Set the resistance of the two resistors to 500k and &lt;span class="caps"&gt;1MEG&lt;/span&gt; (ohms), and the
voltage source to 10&amp;nbsp;(Volts).&lt;/p&gt;
&lt;h3&gt;Simulation&lt;/h3&gt;
&lt;p&gt;Now we actually get to see what &lt;span class="caps"&gt;SPICE&lt;/span&gt; is all about:&amp;nbsp;Simulation.&lt;/p&gt;
&lt;p&gt;Click on the little running man icon on top to bring up the simulation menu.
For &lt;span class="caps"&gt;DC&lt;/span&gt; circuits you&amp;#8217;ll want to click on the &amp;#8220;&lt;span class="caps"&gt;DC&lt;/span&gt; op pnt&amp;#8221; tab and click &lt;span class="caps"&gt;OK&lt;/span&gt;. This
will find out the steady state of your circuit. The first thing you&amp;#8217;ll see is a
text list of the voltages at all the nodes and the currents through each
component. It&amp;#8217;s not immediately obvious which node is which, so if you close
the text window you can just let your mouse hover over a node or component and
see the pertinent info on the status bar at the&amp;nbsp;bottom.&lt;/p&gt;
&lt;p&gt;A note about currents: Watch your signs! When you hover your mouse over a
component, the current is taken to be positive if it is running down or right,
and negative if it is running up or&amp;nbsp;left.&lt;/p&gt;
&lt;h3&gt;Next&amp;nbsp;Time&lt;/h3&gt;
&lt;p&gt;Hopefully this basic example has introduced you to the most basic elements of
LTspice. As we continue I&amp;#8217;ll introduce more sophisticated simulation types,
parametric sweeps, and&amp;nbsp;more!&lt;/p&gt;</summary></entry><entry><title>A cute python scheduler</title><link href="http://ssfrr.com/2010/03/03/a-cute-python-scheduler/" rel="alternate"></link><updated>2010-03-03T01:29:57+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2010-03-03:2010/03/03/a-cute-python-scheduler/</id><summary type="html">&lt;p&gt;&lt;img alt="The Python Logo" src="http://blog.motane.lu/wp-content/uploads/2009/06/python_logo_without_textsvg.png" /&gt;&lt;/p&gt;
&lt;p&gt;I spent a couple of hours on Sunday whipping up this little scheduler in&amp;nbsp;python.&lt;/p&gt;
&lt;p&gt;It was mostly to have something fun to do in Python, and doesn&amp;#8217;t do much that&amp;#8217;s useful, but it does demonstrate some general process scheduling&amp;nbsp;concepts.&lt;/p&gt;
&lt;p&gt;It provides base classes for &amp;#8220;Processes&amp;#8221; and &amp;#8220;Events&amp;#8221;. Subclass a process to do something when it&amp;#8217;s &amp;#8220;run()&amp;#8221; function is called. A process can also tell the scheduler that it wants to wait on an an &amp;#8220;Event&amp;#8221;. Any event that has a process waiting on it gets its &amp;#8220;occured()&amp;#8221; function polled, which returns true when the event has occurred, and the process that was waiting on it wakes up(it&amp;#8217;s run() function starts being called&amp;nbsp;again).&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve got some examples of a timer event that goes off after a time interval. There&amp;#8217;s also a filewatcher event that goes off when a given file is&amp;nbsp;created.&lt;/p&gt;
&lt;p&gt;This is meant to simulate a scheduler that would run at the root of an &lt;span class="caps"&gt;OS&lt;/span&gt;, so it loops through as fast as it can and will take up %100 &lt;span class="caps"&gt;CPU&lt;/span&gt; while it&amp;#8217;s&amp;nbsp;running.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;git clone git://github.com/ssfrr/pysched.git&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/ssfrr/pysched/tarball/master"&gt;Download the&amp;nbsp;tarball&lt;/a&gt;&lt;/p&gt;</summary></entry><entry><title>Back from Tour!</title><link href="http://ssfrr.com/2009/07/07/back-from-tour/" rel="alternate"></link><updated>2009-07-07T13:05:46+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2009-07-07:2009/07/07/back-from-tour/</id><summary type="html">&lt;p&gt;Just a quick announcement that Capillary Action has finally returned from our ridiculous 4-month &lt;span class="caps"&gt;US&lt;/span&gt;-&lt;span class="caps"&gt;UK&lt;/span&gt;-Europe-&lt;span class="caps"&gt;US&lt;/span&gt; tour (except for 5 more east coast dates in another week and a&amp;nbsp;half).&lt;/p&gt;
&lt;p&gt;It was long and amazing and draining and eye-opening, and now I&amp;#8217;m glad to be&amp;nbsp;home.&lt;/p&gt;
&lt;p&gt;My next project is to stop starting new projects and work on documenting the work I&amp;#8217;ve already done, so check in soon for updated/better&amp;nbsp;info!&lt;/p&gt;</summary></entry><entry><title>Volume management without Nautilus</title><link href="http://ssfrr.com/2008/11/21/volume-management-without-nautilus/" rel="alternate"></link><updated>2008-11-21T16:40:05+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2008-11-21:2008/11/21/volume-management-without-nautilus/</id><summary type="html">&lt;p&gt;So I&amp;#8217;ve been playing around with &lt;span class="caps"&gt;WMII&lt;/span&gt; for a while now, soaking in the glory of tiling window managers. One thing that&amp;#8217;s a bit inconvienient is easy automounting. I don&amp;#8217;t want to have to manually create a directory in /media and mount each and every teeny-tiny usb drive I might plug into my&amp;nbsp;system.&lt;/p&gt;
&lt;p&gt;Turns out that recently the Ubuntu/Gnome folks have decided that Nautilus will be handling the automounting of drives and such instead of the gnome-volume-manager. This is all well and good if you&amp;#8217;re using nautilus, but for console-junkies it&amp;#8217;s not so&amp;nbsp;helpful.&lt;/p&gt;
&lt;p&gt;The gnome-volume-manager package in the repo is compiled with the &amp;#8220;&amp;#8212;disable-automount&amp;#8221; configure option, so to enable it we have to&amp;nbsp;recompile:&lt;/p&gt;
&lt;p&gt;First make sure you have all the required libraries to&amp;nbsp;build:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;sudo aptitude build-dep gnome-volume-manager&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Then download the&amp;nbsp;source:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;apt-get source gnome-volume-manager&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;configure:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cd gnome-volume-manager-2.24.0&lt;/code&gt;
&lt;code&gt;./configure --enable-automount --disable-dependency-tracking&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;build and&amp;nbsp;install:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;make&lt;/code&gt;
&lt;code&gt;sudo make install&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Then just add &lt;code&gt;/usr/local/libexec/gnome-volume-manager --sm-disable&lt;/code&gt; to your startup script and you should be up and&amp;nbsp;running.&lt;/p&gt;
&lt;p&gt;Don&amp;#8217;t forget to use &lt;code&gt;gnome-volume-properties&lt;/code&gt; to configure the volume manager to actually&amp;nbsp;automount.&lt;/p&gt;</summary></entry><entry><title>My first openembedded image</title><link href="http://ssfrr.com/2008/10/17/my-first-openembedded-image/" rel="alternate"></link><updated>2008-10-17T04:43:16+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2008-10-17:2008/10/17/my-first-openembedded-image/</id><summary type="html">&lt;p&gt;&lt;a href="/media/beagle-helloworld1.png"&gt;&lt;img alt="" src="/media/beagle-helloworld1.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After installing openembedded from &lt;a href="http://http://wiki.openembedded.net/index.php/Getting_Started"&gt;these
directions&lt;/a&gt;,
I&amp;#8217;ve successfully compiled the helloworld-image target and have it running on
my beagleboard! After running &lt;code&gt;bitbake helloworld-image&lt;/code&gt; and &lt;code&gt;bitbake
virtual/kernel&lt;/code&gt; and finding something else to do for a few hours while
everything compiled, I had a usable rootfs and kernel image. I already had my
&lt;span class="caps"&gt;SD&lt;/span&gt; card partitioned, so I just erased the old Ångstrom image and copied the new
stuff&amp;nbsp;over.&lt;/p&gt;
&lt;p&gt;To install the image to the &lt;span class="caps"&gt;SD&lt;/span&gt; card (Where &lt;span class="caps"&gt;BUILDDIR&lt;/span&gt; is the directory form which
you ran bitbake, MMC_BOOT is the boot partition on your &lt;span class="caps"&gt;MMC&lt;/span&gt; card, and MMC_ROOT
is the root&amp;nbsp;partition:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;code&gt;BUILDDIR/tmp/deploy/glibc/images/beagleboard&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cp MLO-beagleboard /media/MMC_BOOT/MLO&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cp u-boot-beagleboard.bin /media/MMC_BOOT/u-boot.bin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cp uImage-beagleboard.bin /media/MMC_BOOT/uImage&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd /media/MMC_ROOT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sudo tar -xvf BUILDDIR/tmp/deploy/glibc/images/beagleboard/helloworld-image-beagleboard.tar&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Boot time is about 8 seconds from when it starts to unpack the kernel to
executing userspace&amp;nbsp;code.&lt;/p&gt;</summary></entry><entry><title>Installing PDa to the beagle board</title><link href="http://ssfrr.com/2008/10/08/installing-pda-to-the-beagle-board/" rel="alternate"></link><updated>2008-10-08T15:33:06+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2008-10-08:2008/10/08/installing-pda-to-the-beagle-board/</id><summary type="html">&lt;p&gt;&lt;a href="/media/pda-screen11.png"&gt;&lt;img alt="" src="/media/pda-screen11.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Well, today I got Günter Geiger&amp;#8217;s &lt;a href="http://gige.xdv.org/pda/"&gt;PDa&lt;/a&gt; version of
Pure Data compiled on the Beagle Board. I haven&amp;#8217;t gotten &lt;span class="caps"&gt;HDMI&lt;/span&gt; output to work
properly to my &lt;span class="caps"&gt;TV&lt;/span&gt; so I&amp;#8217;m relying on X-forwarding for the &lt;span class="caps"&gt;GUI&lt;/span&gt;, which is pretty
painfully slow at the moment, but I did get some sound out. Here are the steps
I&amp;nbsp;took:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install &lt;code&gt;libtk-dev&lt;/code&gt; and &lt;code&gt;libtcl-dev&lt;/code&gt; packages using opkg. I had to use the
   &lt;code&gt;-force-depends&lt;/code&gt; option because opkg complained about some missing
   dependencies. Hope it doesn&amp;#8217;t come back to bite me&amp;nbsp;later.&lt;/li&gt;
&lt;li&gt;Install the compiler packages &lt;code&gt;gcc&lt;/code&gt; and &lt;code&gt;gcc-symlinks&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Download the source code from &lt;a href="http://gige.xdv.org/pda/release/src/"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Unpack the source into a directory of your&amp;nbsp;choosing&lt;/li&gt;
&lt;li&gt;Edit the makefile in the &lt;code&gt;src&lt;/code&gt; subdirectory and change &lt;code&gt;libtk8.4.a&lt;/code&gt; to &lt;code&gt;libtk8.4.so&lt;/code&gt; and &lt;code&gt;libtcl8.4.a&lt;/code&gt; to &lt;code&gt;libtcl8.4.so&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;type&amp;nbsp;&amp;#8220;make&amp;#8221;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You should now have a &lt;code&gt;pd&lt;/code&gt; executable in the &lt;code&gt;bin&lt;/code&gt; subdirectory.&lt;/p&gt;</summary></entry><entry><title>the arrival of the beagle board</title><link href="http://ssfrr.com/2008/10/05/the-arrival-of-the-beagleboard/" rel="alternate"></link><updated>2008-10-05T17:51:51+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2008-10-05:2008/10/05/the-arrival-of-the-beagleboard/</id><summary type="html">&lt;p&gt;&lt;a href="/media/dsc009541.jpg"&gt;&lt;img alt="" src="/media/dsc009541.jpg" /&gt;&lt;/a&gt;I have just received a beagleboard, flyswatter &lt;span class="caps"&gt;JTAG&lt;/span&gt;, &lt;span class="caps"&gt;4GB&lt;/span&gt; &lt;span class="caps"&gt;SD&lt;/span&gt; card, &lt;span class="caps"&gt;USB&lt;/span&gt; ethernet adapter, and &lt;span class="caps"&gt;USB&lt;/span&gt; hub. Everything I should need to get started with embedded&amp;nbsp;development.&lt;/p&gt;
&lt;p&gt;I created the proper filesystem setup on the &lt;span class="caps"&gt;SD&lt;/span&gt; card as per &lt;a href="http://code.google.com/p/beagleboard/wiki/LinuxBootDiskFormat"&gt;these instructions&lt;/a&gt;, and installed &lt;a href="http://www.angstrom-distribution.org/demo/beagleboard/"&gt;koen&amp;#8217;s demo image&lt;/a&gt; for the Ångstrom embedded linux distribution.&lt;a href="/media/dsc009511.jpg"&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After hooking up the Flyswatter to the serial connector through the Flyswatter/Beagleboard adapter I got a boot prompt. My &lt;span class="caps"&gt;TV&lt;/span&gt; is complaining that it doesn&amp;#8217;t recognize the input format, so I&amp;#8217;m probably going to have to figure out a custom modeline in the &lt;code&gt;xorg.conf&lt;/code&gt;, but I can live with a command prompt for&amp;nbsp;now.&lt;/p&gt;
&lt;p&gt;For those unfamiliar, the Beagle Board is a platform for embedded development based on Texas Instruments&amp;#8217; &lt;span class="caps"&gt;OMAP3530&lt;/span&gt; System-on-chip board. Basically it&amp;#8217;s a computer three inches square. It has handy input and output connectors for easy experimentation. Stay tuned for updates.&lt;a href="/media/dsc009511.jpg"&gt;
&lt;/a&gt;&lt;/p&gt;</summary></entry><entry><title>official launch!</title><link href="http://ssfrr.com/2008/09/28/official-launch/" rel="alternate"></link><updated>2008-09-28T20:02:53+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2008-09-28:2008/09/28/official-launch/</id><summary type="html">&lt;p&gt;As of 4:00pm today my old Columbia site has been decommissioned and redirected to this one. The site is dead, long live the&amp;nbsp;site.&lt;/p&gt;
&lt;p&gt;Stay tuned for more frequent posting, now that I&amp;#8217;m getting a couple projects off the ground and I&amp;#8217;m pretty much done futzing around with the site&amp;nbsp;layout/architecture.&lt;/p&gt;</summary></entry><entry><title>recent/upcoming performances</title><link href="http://ssfrr.com/2008/03/19/recentupcoming-performances/" rel="alternate"></link><updated>2008-03-19T14:30:30+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2008-03-19:2008/03/19/recentupcoming-performances/</id><summary type="html">&lt;p&gt;So it&amp;#8217;s been a while since I&amp;#8217;ve posted any info here. Since a recent re-wire of the sensorBib to switch all solid-core wiring with stranded(a mistake I will not make again), I&amp;#8217;ve been working on putting music together to perform on my new sensor-augmented upright bass. My premier performance in Columbia University&amp;#8217;s Dodge Hall was a smashing success. I was also able to do an in-class demonstration for George Lewis&amp;#8217;s course &amp;#8220;Jazz in the Global Imagination&amp;#8221; that included a short group improvisation alongside George, with Mario Diaz de Leon and Steve Lehman. A video of the event will be posted soon to Columbia&amp;#8217;s new jazz website, Jazz Studies&amp;nbsp;Online.&lt;/p&gt;
&lt;p&gt;On Thursday March 27th I&amp;#8217;ll be performing alongside New York jazz drumming psychopath Kevin Shea, with a possible third member as yet undetermined. We&amp;#8217;ll be performing as part of the Columbia Computer Music Center&amp;#8217;s &amp;#8220;&lt;span class="caps"&gt;CMC&lt;/span&gt; Fün Nite,&amp;#8221; a monthly concert series to perform new electronic music. If you&amp;#8217;re in New York City you should come on up to Prentis Hall at 632 W. 125th&amp;nbsp;St.&lt;/p&gt;</summary></entry><entry><title>it is finished(sort of)</title><link href="http://ssfrr.com/2007/09/03/it-is-finishedsort-of/" rel="alternate"></link><updated>2007-09-03T14:28:07+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2007-09-03:2007/09/03/it-is-finishedsort-of/</id><summary type="html">&lt;p&gt;I finished the hardware portion of my sensor array right before I left for a tour and recording session with Capillary Action, but didn&amp;#8217;t get a chance to post pictures, so here they are, only a month late. In the coming weeks I&amp;#8217;ll be working on refining the &lt;span class="caps"&gt;PD&lt;/span&gt; patches that do the actual audio processing, as well as doing some composition. Keep an eye out for new videos and&amp;nbsp;mp3s.&lt;/p&gt;
&lt;p&gt;&lt;a href="/media/finished12.jpg"&gt;&lt;img alt="" src="/media/finished12.jpg" /&gt;&lt;/a&gt; &lt;a href="/media/finished22.jpg"&gt;&lt;img alt="" src="/media/finished22.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;</summary></entry><entry><title>paper pattern</title><link href="http://ssfrr.com/2007/07/19/'121'/" rel="alternate"></link><updated>2007-07-19T14:24:17+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2007-07-19:2007/07/19/'121'/</id><summary type="html">&lt;p&gt;I successfully printed out my pattern onto a bunch of 8.5x11 sheets of paper, taped them together and cut them out. I taped the patterns onto my bass to make sure that it all fits the way my model said it should, and so far so good. This also let me figure out exactly where I wanted to put the electrodes, MouseTrap boxes, and the Arduino on the bass itself, in places where the copper would be easily accessible, but the sensor boxes wouldn&amp;#8217;t be in my way. I also tried to keep the boxes on the sides of the bass, to minimize their effect on the bass&amp;#8217;s resonance. Now it&amp;#8217;s off to a fabric store and then to track down a sewing&amp;nbsp;machine.&lt;/p&gt;
&lt;p&gt;&lt;a href="/media/paperbib12.jpg"&gt;&lt;img alt="" src="/media/paperbib12.jpg" /&gt;&lt;/a&gt;&lt;a href="/media/paperbib22.jpg"&gt;&lt;img alt="" src="/media/paperbib22.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;</summary></entry><entry><title>bib design</title><link href="http://ssfrr.com/2007/07/17/bib-design/" rel="alternate"></link><updated>2007-07-17T14:20:51+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2007-07-17:2007/07/17/bib-design/</id><summary type="html">&lt;p&gt;&lt;a href="/media/bib22.jpg"&gt;&lt;img alt="" src="/media/bib22.jpg" /&gt;&lt;/a&gt;&lt;a href="/media/bib32.jpg"&gt;&lt;img alt="" src="/media/bib32.jpg" /&gt;&lt;/a&gt;&lt;a href="/media/sewingpattern.png"&gt;&lt;img alt="" src="/media/sewingpattern.png" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been playing around in Blender and QCad to figure out how I want to mount the sensors onto my bass, and I&amp;#8217;ve come up with a design for a cloth covering that will house the sensors in pockets on the bass. Much thanks to Chromo for reminding me of those bass bibs that some players use. This will allow me to remove the sensor apparatus if I want to play acoustically, and also to non-permanently mount the sensors onto a different bass if I&amp;#8217;m traveling. I put together a sewing pattern, so as soon as I get to a fabric store and select a cloth, I should be able to sew this up without too much&amp;nbsp;trouble.&lt;/p&gt;</summary></entry><entry><title>video with 5 sensors</title><link href="http://ssfrr.com/2007/07/13/video-with-5-sensors/" rel="alternate"></link><updated>2007-07-13T14:10:29+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2007-07-13:2007/07/13/video-with-5-sensors/</id><summary type="html">&lt;iframe width="400" height="300" src="//www.youtube.com/embed/xpAFJEpXnCc" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;So now that I&amp;#8217;m mostly done with the physical design part of this project, I
thought it would be a good time to whip up another video demo to show it in
action. I&amp;#8217;m using a couple of custom abstractions that I&amp;#8217;ve made make the
sensor data as usable as possible, but the software processing is still very
much in development, so I&amp;#8217;ll put some releases up once I have something a
little more stable. For now, enjoy the strange sounds coming out of your
computer speakers and let me know if you have any suggestions. The sound
translates pretty poorly to laptop speakers, so you might want to use
headphones or external speakers to hear what&amp;#8217;s going&amp;nbsp;on.&lt;/p&gt;</summary></entry><entry><title>5 boxes done</title><link href="http://ssfrr.com/2007/07/09/5-boxes-done/" rel="alternate"></link><updated>2007-07-09T14:05:50+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2007-07-09:2007/07/09/5-boxes-done/</id><summary type="html">&lt;p&gt;&lt;a href="/media/sensorarray.jpg"&gt;&lt;img alt="" src="/media/sensorarray.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I built 5 more sensor circuits and boxed them all up in these snazzy black boxes you can see in the picture. They even match my ThinkPad! I&amp;#8217;ve been working on &lt;span class="caps"&gt;PD&lt;/span&gt; patches to explore different ways to map the sensor streams onto parameters. On Douglas Repetto&amp;#8217;s suggestion I started looking at higher-order systems, and realized that if I look at the change in adjacent sensor samples, throw out high positive and negative values, and then run them into an accumulator, the output tracks slow-moving input, but ignores anything fast. This allows you to pump the value up or down by repeatedly moving slowly in one direction, than quickly in the other. You can also make a value stick if you pull your hand away quickly enough. Be on the lookout for some video examples. I also made a patch to detect when you&amp;#8217;ve tapped the sensor, to be used for things like setting a tempo or delay&amp;nbsp;time.&lt;/p&gt;</summary></entry><entry><title>enclosed</title><link href="http://ssfrr.com/2007/07/06/enclosed/" rel="alternate"></link><updated>2007-07-06T14:04:31+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2007-07-06:2007/07/06/enclosed/</id><summary type="html">&lt;p&gt;&lt;a href="/media/arduinobox.jpg"&gt;&lt;img alt="" src="/media/arduinobox.jpg" /&gt;&lt;/a&gt;
&lt;a href="/media/firstbox.jpg"&gt;&lt;img alt="" src="/media/firstbox.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nearing some sort of finality in this design, I&amp;#8217;ve put the circuit in a box. I also put my arduino board in a box, which involved de-soldering the power connector and the header sockets, as well as cutting off the corners with a bandsaw, so I would probably advise using a bigger box if you&amp;#8217;re planning on doing the same. Hopefully in the next couple of days I&amp;#8217;ll give the main MouseTrap info page an update with the new developments, as well as part numbers for the boxes and all the connectors I used. I decided to go with a standard &lt;span class="caps"&gt;DC&lt;/span&gt; power jack, banana jacks for the &lt;span class="caps"&gt;DC&lt;/span&gt; output and ground, and a binding post to attach the electrode. Definitely an improvement. The boxes also have a solid feel to them without being&amp;nbsp;heavy.&lt;/p&gt;</summary></entry><entry><title>new pcbs!</title><link href="http://ssfrr.com/2007/07/02/new-pcbs/" rel="alternate"></link><updated>2007-07-02T13:18:35+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2007-07-02:2007/07/02/new-pcbs/</id><summary type="html">&lt;p&gt;&lt;a href="/media/finalcircuit.jpg"&gt;&lt;img alt="" src="/media/finalcircuit.jpg" /&gt;&lt;/a&gt;
&lt;a href="/media/newboard.jpg"&gt;&lt;img alt="" src="/media/newboard.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I received my 10 PCBs from Advanced Circuits today. They&amp;#8217;re a big step up from the ones I&amp;#8217;ve been making on the &lt;span class="caps"&gt;CNC&lt;/span&gt; machine, mostly because I don&amp;#8217;t have to worry about solder bridges. The completed circuit you see in the picture worked the first time after putting it together, which was a lot nicer than the 20 minutes or so I had to spend after each &lt;span class="caps"&gt;CNC&lt;/span&gt; prototype fixing my sloppy soldering. They also gave me a circuit board coaster and 2 bags of microwave popcorn. You can see I&amp;#8217;ve drilled out the corners so that they&amp;#8217;ll fit in the project enclosures that I bought from Mouser. Construction details to&amp;nbsp;follow&amp;#8230;&lt;/p&gt;</summary></entry><entry><title>new audio demo</title><link href="http://ssfrr.com/2007/06/26/new-audio-demo/" rel="alternate"></link><updated>2007-06-26T12:31:51+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2007-06-26:2007/06/26/new-audio-demo/</id><summary type="html">&lt;p&gt;&lt;a href="/media/bass3sensors.jpg"&gt;&lt;img alt="" src="/media/bass3sensors.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I put together something a bit more sonically interesting than the video that I
posted earlier. I recorded myself improvising on double bass, and then
processed the recording with a puredata patch that I wrote to use the 3 sensors
that I have built so far. It&amp;#8217;s pretty bass-heavy, and not &lt;span class="caps"&gt;EQ&lt;/span&gt;&amp;#8217;ed or anything, so
it probably won&amp;#8217;t sound good on speakers without good bass response. All of the
processing was done in one pass, and the only interface between myself and the
computer was the 3 sensors. So if I had the sensors mounted on the bass, I
could theoretically have performed this live with no pre-recording. The patch
requires my granulator external, which is downloadable on my PureData&amp;nbsp;page.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;note - this used to be available at api.soundcloud.com/tracks/14146648 but it
seems to be removed&amp;nbsp;now&lt;/em&gt;&lt;/p&gt;</summary></entry><entry><title>New video up</title><link href="http://ssfrr.com/2007/06/23/new-video-up/" rel="alternate"></link><updated>2007-06-23T14:40:30+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2007-06-23:2007/06/23/new-video-up/</id><summary type="html">&lt;iframe width="400" height="300" src="//www.youtube.com/embed/stV6BBksVuc" frameborder="0" allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;Here&amp;#8217;s a quick video I made of me waving my hands around the MouseTrap sensors,
and sending the data through an arduino board into my laptop running puredata.
The video footage was pretty out of sync with the audio, which is why there&amp;#8217;s
more screen capture than video. All that the patch is doing is modulating the
amplitude of 3 oscillators running at 400, 500, and 600 Hz. Soon I&amp;#8217;m going to
set up some sort of media gallery so that there&amp;#8217;s a more permanent home for
things like this, but this is it for&amp;nbsp;now.&lt;/p&gt;</summary></entry><entry><title>3 sensors built</title><link href="http://ssfrr.com/2007/06/22/'46'/" rel="alternate"></link><updated>2007-06-22T14:40:15+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2007-06-22:2007/06/22/'46'/</id><summary type="html">&lt;p&gt;&lt;a href="/media/3sensorsarduino.jpg"&gt;&lt;img alt="" src="/media/3sensorsarduino.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve got 3 of the MouseTrap distance sensors built, and I have just a little bit more tweaking before the the design will be ready. The blue board that you see the sensors connected to is an Arduino, which converts the analog signals to digital numbers and sends them to my computer over &lt;span class="caps"&gt;USB&lt;/span&gt;&lt;/p&gt;</summary></entry><entry><title>rev3 board milled and stuffed</title><link href="http://ssfrr.com/2007/06/12/'45'/" rel="alternate"></link><updated>2007-06-12T14:15:20+00:00</updated><author><name>Spencer Russell</name></author><id>tag:ssfrr.com,2007-06-12:2007/06/12/'45'/</id><summary type="html">&lt;p&gt;&lt;a href="/media/dsc00309-resized2.jpg"&gt;&lt;img alt="" src="/media/dsc00309-resized2.jpg" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Today I milled out Revision 3 of my MouseTrap board, after realizing some mistakes in Rev. 2. After stuffing the board I&amp;#8217;m happy to announce that it seems to be working great! I had to change some component values because the &lt;span class="caps"&gt;PCB&lt;/span&gt; acts differently than the breadboard, but performance seems good. One of the pads ended up being connected to an adjacent trace, but I moved it over a bit in the newest board layout, so we should be ready to&amp;nbsp;go.&lt;/p&gt;</summary></entry></feed>