Posted on 26 May 2012
I’ve just come back from EuroClojure 2012, where there were a number of Overtone talks and a number of tweets asking for music theory resources aimed at computer scientists. This will hopefully blog number 1 in a series on that theme.
Note that the code examples are designed to be pasted into a Clojure repl, so that you can take the code and play with it yourself.
The basic atoms of synthesizing sounds in Overtone are oscillators. An oscillator takes a frequency and makes a noise. Here are some examples:
(use 'overtone.live) (demo (sin-osc 440)) ; sine wave (demo (saw 440)) ; saw-tooth wave (demo (square 440)) ; square wave
In each of these, we’re making an oscillator and giving it a frequency of 440 Hz — or equivalently, 440 cycles per second (cps). The problem we find is that most music isn’t defined in terms of frequency, it’s defined in terms of notes of the scale: C D E F G A B C and all the sharps and flats in between. How do we play a tune on a sine wave generator when the tune is made of notes rather than frequencies?
First, let’s write some helpers to play a sequence of frequencies through a sine wave:
(definst sine-wave [freq 440] (sin-osc freq)) ;=> #<instrument: sine-wave> (defn play-freqs ([freqs] (play-freqs freqs (now) (sine-wave (first freqs)))) ([freqs time inst] (if-let [freqs (seq freqs)] (do (at time (ctl (:id inst) :freq (first freqs))) (apply-at (+ time 300) #'play-freqs [(rest freqs) (+ time 300) inst])) (at time (kill (:id inst)))))) ;=> #'user/play-freqs (play-freqs [440 660 330 440 220 880 220]) ; *beautiful melody* ;=> #<ScheduledJob id: 76, created-at: Sat 09:32:26s, initial-delay: 0, desc: "Overtone delayed fn", scheduled? false>
We define a simple intrument, sine-wave
, which has one parameter,
freq
. We can start the instrument with a particular frequency by
writing (sine-wave 440)
; this returns a map of data about the
particular oscillator instance which is generating the note. We can
change the freq parameter of a running instrument by using
(ctl (:id inst) :freq 660)
. Finally, we can stop a running inst with
(kill (:id inst))
. (And if it all goes horribly wrong, we can stop
absolutely everything with (stop)
).
Our goal is to be able to use play-freqs
to play tunes made of
keywords rather than frequencies: [:c4 :d4 :e4 :d4 :c4]
.
You can calculate frequency from pitch using only four fundamental axioms:
If going up an octave doubles the frequency, then going up twelve
semitones must also double the frequency. This means we must find the
number semitone
, where:
(nth (iterate #(* semitone %) 440) 12) ;=> 880
In other words, we want semitone^12 == 2
, so semitone must be the
twelfth root of 2:
; from the contrib library [org.clojure/math.numeric-tower "0.0.1"] (require '([clojure.math.numeric-tower :as 'math])) ;=> nil (def semitone (math/expt 2 1/12)) ;=> #'user/semitone (nth (iterate #(* semitone %) 440) 12) ;=> 880.0000000000003 ; or alternatively: (* (math/expt semitone 12) 440) ;=> 880.0000000000003
We can now define a function to find a frequency a given number of semitones from tuning A:
(defn semitones-from-a [semis] (* (math/expt semitone semis) 440)) ;=> #'user/semitones-from-a (semitones-from-a 0) ;=> 440.0 (semitones-from-a 12) ;=> 880.0000000000003 (semitones-from-a 3) ;=> 523.2511306011974 (semitones-from-a -9) ;=> 261.6255653005985
Normally, however, we use MIDI notes as a numerical representation of notes, rather than displacement from tuning A. In the MIDI note system, tuning A is defined to be 69, and going up or down one semitone increases or decreases the note value by one. So, for example, middle C is 60. We can get from midi notes to frequencies like this:
(defn midi-to-hz [midi-note] (semitones-from-a (- midi-note 69))) ;=> #'user/midi-to-hz (midi-to-hz 69) ;=> 440.0 (midi-to-hz 81) ;=> 880.0000000000003 (midi-to-hz 72) ;=> 523.2511306011974 (midi-to-hz 60) ;=> 261.6255653005985
In fact, Overtone provides a function midi->hz
to do exactly this
transformation:
(midi->hz 69) ;=> 440.0 (midi->hz 81) ;=> 880.0 (midi->hz 72) ;=> 523.2511306011972 (midi->hz 60) ;=> 261.6255653005986
So with a melody as MIDI notes, we can play it as follows:
(play-freqs (map midi->hz [60 62 64 62 60 72 67 60]))
If you’ve got this far, the maths is over. The last mile is to be able
to use keywords instead of raw MIDI values. Overtone provides a
function for this called note
:
(note :a4) ;=> 69 (note :a5) ;=> 81 (note :c5) ;=> 72 (note :c4) ;=> 60
So we can play our tune by chaining this with midi->hz
:
(play-freqs (map (comp midi->hz note) [:c4 :c5 :e4 :f4 :g4 :f4 :e4 :d4 :c4 :c4])) ; *beautiful music*
Posted on 28 April 2012
I was reading the Clojure source code the other day when I noticed this curious snippet in LispReader.java:
static public int read1(Reader r){ try { return r.read(); } catch(IOException e) { throw Util.sneakyThrow(e); } }
I immediately thought to myself: “what does sneakyThrow
do?” It
looks like it is a magic way to throw a checked exception without
needing a throws
declaration. But how does it work?
First, a little background. Checked exceptions are effectively a
static analysis tool: there are no runtime checks on checked
exceptions. Rather, javac
will refuse to compile code where a
checked exception is thrown with no catch
block to catch it nor
throws
declaration to declare its propagation.
It’s possible to throw a checked exception using bytecode manipulation, or Thread.stop(Throwable), and these techniques have been known for at least a decade. However bytecode manipulation is messy, and Thread.stop(Throwable) has been deprecated for at least a decade too. Is there a pure-Java way to throw a checked exception sneakily?
C-family languages normally provide typecasts, a trapdoor to escape
their static typing system when you think it is more hindrance than
help. So a first attempt might go something like throw
(RuntimeException) e;
. However if you try this in the above code, you
will get a ClassCastException
at runtime, because IOException
is
not an instance of RuntimeException
. It would seem that there is no
pure-Java way to throw a checked exception.
So how does sneakyThrow
work? Here it is, in all its glory:
/** * Throw even checked exceptions without being required * to declare them or catch them. Suggested idiom: * throw sneakyThrow( some exception ); */ static public RuntimeException sneakyThrow(Throwable t) { // http://www.mail-archive.com/javaposse@googlegroups.com/msg05984.html if (t == null) throw new NullPointerException(); Util.sneakyThrow0(t); return null; } @SuppressWarnings("unchecked") static private void sneakyThrow0(Throwable t) throws T { throw (T) t; }
That link in the comments gives credit to Reinier Zwitserloot who, as far as I know, had the first mention of this technique in 2009 on the java posse mailing list.
What we have here is a severe abuse of Java. Util.sneakyThrow(t) calls
Util.sneakyThrow0; then within sneakyThrow0() we
cast to the parameterized type T
. In this case that type is
RuntimeException
. At runtime, however, the generic types have been
erased, so that there is no T
type anymore to cast to, so the cast
disappears.
In other words, we’ve managed to convince the compiler and the runtime that they’re seeing different things. The compiler sees the code with the cast:
throw (RuntimeException) t;
so it allows the now-unchecked exception to propagate. The runtime doesn’t see the generic types, so it sees no cast:
throw t;
and therefore it doesn’t complain about a ClassCastException
.
There was one last nagging thought I had about the original code:
throw Util.sneakyThrow(e);
Given that Util.sneakyThrow(e) throws the exception itself, why does
the calling code also use throw
? The answer is, once more, to make
the compiler happy. Without the throw
, the compiler will demand a
return
statement afterwards.
Reinier Zwitserloot added this functionality to
Project Lombok as the
@SneakyThrows
annotation, so now you can propagate checked exceptions sneakily with
minimal boilerplate. The @SneakyThrows page also summarizes neatly
some use-cases for why you would ever actually want to throw a checked
exception:
new
String(someByteArray, "UTF-8")
, which declares that it throws
UnsupportedEncodingException but UTF-8 is guaranteed by the Java
spec to always be present.throws
declaration, and yet throwing an
exception is entirely appropriate — the canonical example is
Runnable.run(), which does not throw any checked exceptions.The first case is clear — the throws
declaration is a nuisance and
any solution to silence it with minimal boilerplate is welcome.
The second case has one common alternative: wrapping the checked
exception in a RuntimeException so that you can throw it. Both
approaches will have their critics. Wrapping an exception just to gain
the privelege of throwing it results in a stacktrace with spurious
exceptions which contribute no information about what actually went
wrong. On the other hand, throwing checked exceptions may violate the
principle of least surprise; it will no longer be enough to catch
RuntimeException
to be able to guarantee catching all possible
exceptions.
It will be up to any given project to decide which is the lesser of two evils and establish a standard on their codebase.
Posted on 12 February 2012
I’ve been working with Ruby and Sinatra this week to write some RESTful interfaces. I’m new to Ruby and Sinatra, but I’m not new to dynamic languages, RESTful services, or the Rack / WSGI / PSGI / Ring view of web applications. I figured that this shouldn’t be a difficult task. Boy was I wrong.
Sinatra offers a very nice DSL for describing HTTP controllers. For example, a simple “Hello, world” controller looks like this:
require 'sinatra/base' # this is 'modular' style class HelloWorld < Sinatra::Base get '/*' do 'Hello, world!' end end
Sinatra also conforms to the Rack specification: that is, Sinatra
controllers expose a call
method which (to a first approximation)
takes an HTTP request and returns an HTTP response. We thought that
having a nice simple interface to talk to the controller would make
testing and test-driving very easy; and in fact Rack::Test::Methods
provides a pleasing DSL for testing Rack applications through the call
method:
require 'rspec' require 'rack/test' require 'hello-world' describe 'Hello World application' do include Rack::Test::Methods def app HelloWorld end it 'should return Hello, world at root URL' do get '/' last_response.body.should match /Hello, world/ end end
The trouble started because we wanted to stub out dependencies of the controller. Our “Hello, world” controller grew to look something like this:
require 'sinatra/base' # this is 'modular' style class HelloWorld < Sinatra::Base def repository raise NotImplementedException end get '/*' do repository.get('foo') end end
We’re practising top-down TDD, where we don’t try to create dependencies until we’ve found a need for them at a higher level. At this point, we wanted a test to check this code. To do this, we’re going to have to stub out the repository with a test fake Here’s attempt #1:
require 'rspec' require 'rack/test' require 'hello-world' describe 'Hello World application' do include Rack::Test::Methods def app HelloWorld end it 'should return Hello, world at root URL' do mock_repo = mock('repository') mock_repo.stub(:get).with('foo').and_return('bar') app.stub(:repository).and_return(mock_repo) get '/' last_response.body.should == 'bar' end end
We figured that since app
defines the application under test, we
could just stub out the repository on the app and we’d be done. Sadly
not; the app called the real repository
method, not our stubbed
version.
Surprise #1: HelloWorld and HelloWorld.new are both Rack applications!
Sinatra provides your controller classes with a call
method, which
internally implements the Singleton pattern and will new up a
controller instance before delegating the call
to the controller
instance.
I have just one question: why?. Is it just so that I can save 4
characters by typing def app; HelloWorld; end
rather than def app;
HelloWorld.new; end
? Sure, it saved typing, but it confused the hell
out of us.
Okay, let’s leave the controller class magic behind. Here’s attempt two:
require 'rspec' require 'rack/test' require 'hello-world' describe 'Hello World application' do include Rack::Test::Methods def app HelloWorld.new #let's have an instance now end it 'should return Hello, world at root URL' do mock_repo = mock('repository') mock_repo.stub(:get).with('foo').and_return('bar') app.stub(:repository).and_return(mock_repo) get '/' last_response.body.should == 'bar' end end
Now, app
is pointing to a HelloWorld instance, so we should be able
to stub out its dependency, right? Wrong. It still calls the real
repository
method.
Surprise #2: HelloWorld.new doesn’t create an instance of HelloWorld.
Seriously, have a look yourself:
$ irb >> require 'hello-world' => true >> HelloWorld.new.class => Sinatra::ShowExceptions
WAT.
What is going on here? Well, Sinatra has overridden Object#new with its own new method, so that when you new up a Sinatra controller you get all sorts of Rack middleware for free. This middleware does nice things like catching and formatting exceptions. That’s all fine. But why is Sinatra’s method of attaching middleware the wholesale replacement of a core language feature?
What this means is that we weren’t stubbing repository
on our app at
all; we were stubbing it on Sinatra::ShowExceptions, the outermost
middleware layer. Deep down the middleware stack, our app still had
its real repository
method intact.
Thankfully, Sinatra aliases the original Object#new as new!
in your
code, so if you want a naked controller, you can still get one. Here’s
attempt #3:
require 'rspec' require 'rack/test' require 'hello-world' describe 'Hello World application' do include Rack::Test::Methods def app HelloWorld.new! #let's have an unadulterated instance now end it 'should return Hello, world at root URL' do mock_repo = mock('repository') mock_repo.stub(:get).with('foo').and_return('bar') app.stub(:repository).and_return(mock_repo) get '/' last_response.body.should == 'bar' end end
Unfortunately, this still doesn’t work, even though we have a real
instance of HelloWorld and we really are stubbing repository
on
it. Why?
Surprise #3: Sinatra
dup
s your controller before handling an HTTP request
From ‘sinatra/base.rb’:
# Rack call interface. def call(env) dup.call!(env) end
So when you call your Sinatra instance’s call
method, it’s not
your instance at all that handles it, it’s a dup
of that
instance. And the dup
doesn’t have its methods stubbed like the
original did.
At this point, I pause and realise that if I’m fighting something this hard, it’s probably because my mental model doesn’t match Sinatra’s, and that there’s probably a way to achieve what I want which doesn’t involve having to dig around in Sinatra’s source code to work out what deep magic it is wreaking with my controllers.
The problem I have is that I already have a mental model for web application development, which is based at the Rack level. I’ve used Ring and understood it; and that means I can then go and learn Rack in about 10 minutes. Rack is simple. I like Rack.
Sinatra, on the other hand, seems to be trying to hide Rack from me. It’s a shame, because Rack seems to be the only part of the system that I understand. As a result, I’m left flailing in Sinatra’s magical kingdom wondering why the ground keeps shifting under my feet.
Posted on 17 December 2011
Apologies for lack of November post; I’ve been somewhat snowed under recently. Normal service now resuming…
December’s Clojure dojo focused on difficult problems from 4clojure. I had dabbled with 4clojure before on some of the easier problems, but I honestly hadn’t anticipated just how difficult the hard problems can get!
Our team decided to go in gently, going for medium-difficulty problems rather than hard problems. This turned out to be one of our better ideas of the evening, since we only managed to complete one and a half medium problems in the time available!
The first problem we tackled was
Juxtaposition, in which you have
to reimplement the juxt
function. Our team took an approach where we
tried to develop solutions from first principles, rather than looking
up (source juxt)
, so I think it might be enlightening to compare our
solutions with the clojure.core
model answers. First, our solution:
(defn juxt [& fns] (fn [& args] (vec (map #(apply % args) fns))))
And the output of (source juxt)
produces something like this:
(defn juxt [& fs] (fn [& args] (reduce #(conj %1 (apply %2 args)) [] fs)))
…except that the original source has special cases for small numbers of arguments.
It’s interesting the difference of approaches here. We both use the
form (apply % args)
to apply the variable number of arguments to
each function in turn; however, we use map
to do this, producing a
sequence, which we then must traverse in order to convert to a vector.
The clojure.core
version, by contrast, starts with an empty vector
[]
, and conj
es each further result into the vector; in doing so,
it avoids traversing the list twice.
The second problem we attempted was Reductions. Here’s our attempt:
(defn my-red ([f coll] (if (seq coll) (cons (first coll) (map #(f % (first coll)) (my-red f (rest (seq coll))))) [])) ([f init coll] (my-red f (cons init coll))))
It performs well enough for bounded-length sequences:
(my-red + [1 2 3 4 5]) ;=> (1 3 6 10 15)
But it fails when it comes to infinite lazy sequences:
(take 5 (my-red + (range))) ;=> StackOverflowError
We were very confused on the night as to why this should fail. Isn’t
map
lazy by default? Why, then, do we get a stack overflow?
The problem, which I have only found out today, 4 days after the
event, is that map
is a function, and therefore its arguments are
evaluated before map
itself is. Therefore, every call to my-red
necessarily makes a recursive call, and thus exhausts the stack. The
solution is to add a lazy-seq
to the recursive call:
(defn my-red ([f coll] (if (seq coll) (cons (first coll) (map #(f % (first coll)) (lazy-seq (my-red f (rest (seq coll)))))) [])) ([f init coll] (my-red f (cons init coll))))
And thus, the previous example now works fine:
(take 5 (my-red + (range))) ;=> (0 1 3 6 10)
It still doesn’t pass all of the 4clojure unit tests, though. Work for another time, perhaps.
The clojure.core/reductions
source looks like this:
(defn reductions "Returns a lazy seq of the intermediate values of the reduction (as per reduce) of coll by f, starting with init." {:added "1.2"} ([f coll] (lazy-seq (if-let [s (seq coll)] (reductions f (first s) (rest s)) (list (f))))) ([f init coll] (cons init (lazy-seq (when-let [s (seq coll)] (reductions f (f init (first s)) (rest s)))))))
It’s a very similar approach to the problem, with some important differences:
if-let
and when-let
with the seq
function, relying on
the behaviour that for empty sequences, seq
returns nil, but also
binding the returned seq simultaneously.[f init coll]
version as the primitive form and
expresses [f coll]
in terms of [f init coll]
. We do it the other
way, purely because we implemented [f coll]
first. It’s ugly,
though, particularly in cases where init
is not the same type as
members of coll
.(reductions f [])
case —
where an empty sequence is provided, it returns (list (f))
.map
makes our solution quadratic rather than
linear in the length of the input sequence, because the item in the
nth position must be transformed by (n-1) fns and we don’t reuse the
intermediate results like the clojure.core version does.This has made me want to go back and give 4clojure a closer look. I had tried the first few problems, which seemed trivially easy, but now that I’ve seen that even the “Medium” problems present a significant challenge and raise all sorts of issues around laziness, algorithmic complexity, and efficiency, I can see I’ve a lot to learn from 4clojure.
The London clojure dojo happens on the last Tuesday of every month. During the dojo, we split into groups of four or five around a single computer, and each person takes a turn at the keyboard. This ensures that even if you have zero clojure experience, you will get the opportunity to write some code at the event.
Entry to the dojo is free, but advance booking is required. Listen for announcements on the London clojurians mailing list.
Posted on 03 December 2011
Today was the inaugural South East England Overtone Hack Day. We met up in Cambridge to hack on Overtone, a live music performance environment in Clojure. Here are some of the things we covered:
Tom (didn’t catch his surname, unfortunately) brought some AudioCubes, a set of control interfaces. They have infrared detectors and can detect nearby surfaces and other AudioCubes.
We discussed interfacing them to Overtone. They come with midi and OSC interfaces, which would be easy to work with; but the real power apparently comes from the C API, which allows you to discover the network topology of the AudioCubes. We discussed the possibilities for working with the C API from Clojure.
Tom and I also discussed some other controllers:
As is inevitable, some time was spent getting people set up with Eclipse, Counterclockwise, leiningen, overtone, and so on. I made use of my previous blogpost on lein eclipse, which i had totally forgotten about…
I went through my skillsmatter talk with Stefan, Tak and Edmund, to show them the basics of creating instruments, oscillators, and filters; and scheduling beats and tunes in time.
We also had an impromptu introduction to signal processing – time domain vs frequency domain, linear filters — low pass, high pass, band pass, Fourier series, and suchlike.
Finally, we discussed resources for learning clojure itself: labrepl and 4clojure.
I also made a start on writing a filters page for the overtone wiki.
We all had a great time, we all learned something and achieved something, and there was a lot of interest for another event next month in London. So I will see you all next time!