So, it's clear to me that we would benefit from some sort of framework for discussion and collaborative learning. I therefore propose we adopt something similar to the infamous Ruby Quiz - a weekly programming challenge. However, rather than run through Project Euler, wouldn't it be cool if we could have a weekly challenge that promoted musical creativity.
So, without further ado, here's the first Overtone Jam Challenge:
= Non-Cyclic Baseline =
The task is simple:
* Fork/clone the code from here: git://github.com/overtone-jam-challenge/001.git
* Get it playing through your speakers (email this list if you have any issues with this)
* Listen for 20 seconds
* Get very bored by the repeating monotony
* Hack, hack hack until it no longer obviously repeating and sounds interesting (however you may define that)
* Submit your jam to this thread by next Monday (4th October)
* Grab hold of everyone else's jam and play about and discuss them!
So let's have fun and learn together :-)
Sam
The definst is total magic to me. I'm not touching that. You define an instrument by doing some math?
So then there's a metronome and the at fn. I've seem (at (now)) so I guess metronome returns now + msec * beat? If this is the case, how can I fumble with the timing, and play it in swing for example?
Is apply-at some kind of recur? And why is this: #'bass-player
I understand notes are midi note numbers. But what are vel and dur?
Also, using overtone.live form the lein repl doesn't work, so I'm having a hard time toying with this stuff.
Groeten,
Pepijn de Vos
--
Sent from my iPod Shuffle
http://pepijndevos.nl
On 28 Sep 2010, at 11.27 am, Pepijn de Vos wrote:
> Okay, I'm trying to understand what it all does.
Don't worry too much - there are a lot of moving parts here, and it will take time to become accustomed to them.
>
> The definst is total magic to me. I'm not touching that. You define an instrument by doing some math?
Yup, you have it. You're also right - treat it like total magic for now. All you should care about for this challenge is that it creates a fn that you can call to make sound :-)
> So then there's a metronome and the at fn. I've seem (at (now)) so I guess metronome returns now + msec * beat? If this is the case, how can I fumble with the timing, and play it in swing for example?
OK, let's take these in turn.
Metronome
=========
The metronome is a slightly tricksy thing. We'll go into more detail in future jam challenges. For now, you just need to know that it has two faces:
* It's a counter counting the number of beats that have taken place
* It's a fn for converting a given beat count to a timestamp
The following creates a metronome called metro representing 100 BPM:
(def metro (metronome 100))
You can do two things with this metronome:
(metro) ;=> get the current value of the beat counter.
(metro 12345) ;=> get the timestamp for the 12345th beat
at
==
At is a macro. Any osc-calls scheduled within it are automatically bundled together with the supplied timestamp. This allows you to schedule musical events ahead of time. If were to rely on the JVM for timing then we'd start to get annoyed with the thread scheduler and garbage collector getting in the way of precise timing. With a timestamped OSC bundle, we rely on SuperCollider for the timing.
Swing
=====
OK, so to emulate a swing beat, you need to mess about with the result of (metro beat) which is passed to the at macro at the top of the bass-player fn. If you add/remove some ms to the result of that then you can effect the timeliness of the beat:
(at (swing beat (metro beat))
where swing can modify the timestamp returned by (metro beat) depending on the beat count:
(defn swing [beat timestamp] (if (swingable? beat) (+ 100 timestamp) timestamp))
Obviously, I don't know how to codify a swing beat, but this should give you an idea...
>
> Is apply-at some kind of recur? And why is this: #'bass-player
This is similar to apply, except it schedules the evaluation for a future time. In fact it actually schedules the evaluation for a small period of time *before* the specified time. (I have a version of this in my code which I call apply-before.) So it can be used in a similar fashion to recur - only the recur will happen at a future time on a potentially different thread.
> And why is this: #'bass-player
I'm not fully down on this reader-syntax, but the result is that you can re-eval bass-player and it will automatically take effect in the looping construct. This is great for live coding and getting quick feedback.
>
> I understand notes are midi note numbers. But what are vel and dur?
OK, let's break open a little of the definst magic. The arglist of definst defines controllable parameters to the instrument created. In this case we have:
[note 58 vel 0.4 dur 0.2]
We can therefore call the bass fn with values for these params:
(bass 58 0.4 0.2)
The values you see are also the defaults so the following would produce the same result:
(bass)
These arguments can be anything you can control in SuperCollider so it's up to the instrument designer to choose sensible names. In this case we can assume vel means velocity and dur means duration. Try different values to see how things change.
>
> Also, using overtone.live form the lein repl doesn't work, so I'm having a hard time toying with this stuff.
OK, so you haven't been able to hear the base line?
Have you tried:
lein repl
(use 'jam-challenge-001.core)
Sam
That metronome part is nice, but how would I make 1/8 notes? Or is the metronome the smallest unit?
That would mean to have 1/16 you'd actually have to quadruple the bpm.
I guess you could just do the math with the timestamps. So that'd be (+ beat1 (/ (- beat2 beat1) 2)) for the offbeat.
Swing is usually turning 1/8 1/8 into triplets of 1/4 1/8.
It gives this lazy sound, which is very appropriate for Clojure, even more so because of a certain GUI lib.
The metronome is another place that could use some abstraction in my opinion. I'm at the moment cooking up an idea for a nested list where ever item can be a note or a list and the length of a note could be determined by the length of the list and its nesting.
I was able to hear the bass line. but just loading ovetone didn't work. Re-read that sentence carefully to find out why.
Thanks for the explanation. I'll toy with it for a bit.
Groeten,
Pepijn de Vos
--
Sent from my iPod Shuffle
http://pepijndevos.nl
On 28 Sep 2010, at 1.52 pm, Pepijn de Vos wrote:
>
> That metronome part is nice, but how would I make 1/8 notes? Or is the metronome the smallest unit?
> That would mean to have 1/16 you'd actually have to quadruple the bpm.
The metronome is just a helper. It's probably simplest to treat it as generating atomic time units. However, it's a part of Overtone that could definitely do with some heavy use and modification/abstraction based on experience. Treat all this stuff as iteration 1 :-) Discussions on how to improve/replace things like the metronome are discussions I'm looking forward to having.
>
> I guess you could just do the math with the timestamps. So that'd be (+ beat1 (/ (- beat2 beat1) 2)) for the offbeat.
Give it a try :-) I look forward to hearing your experience with this approach.
>
> Swing is usually turning 1/8 1/8 into triplets of 1/4 1/8.
> It gives this lazy sound, which is very appropriate for Clojure, even more so because of a certain GUI lib.
hehe
>
> The metronome is another place that could use some abstraction in my opinion. I'm at the moment cooking up an idea for a nested list where ever item can be a note or a list and the length of a note could be determined by the length of the list and its nesting.
Absolutely! See above.
>
> I was able to hear the bass line. but just loading ovetone didn't work. Re-read that sentence carefully to find out why.
I re-read it but still didn't fully understand. How careful is carefully? With the jam challenge stuff you shouldn't need to use overtone.live explicitly as the jam's namespace does this for you. Clearly I'm missing something obvious here...
Sam
The definst is total magic to me. I'm not touching that. You define an instrument by doing some math?
So then there's a metronome and the at fn. I've seem (at (now)) so I guess metronome returns now + msec * beat? If this is the case, how can I fumble with the timing, and play it in swing for example?
Is apply-at some kind of recur? And why is this: #'bass-player
Tried to get the Jam Challenge stuff running, just to help learn how to play overtone. Running init--jam -challenge gives me this:
******************************************************************************************
Preparing you for the Jam Challenge...
======================================
Pulling this Jam's deps...
Copying 2 files to /Users/iain/Code/overtone-jam-challenge-jam-001-b3fb795/lib
Pulling in Overtone as a checkout for your curious perusal...
You need to run this command from the toplevel of the working tree.
You need to run this command from the toplevel of the working tree.
Pulling Overtone's deps...
Copying 2 files to /Users/iain/Code/overtone-jam-challenge-jam-001-b3fb795/lib
Merging deps...
cp: lib/*: No such file or directory
*************************
* OK, get your code on! *
*************************
soulflyer:overtone-jam-challenge-jam-001-b3fb795 iain$ lein repl
"REPL started; server listening on localhost:50240."
user=> (use 'jam-challenge-001.core)
java.io.FileNotFoundException: Could not locate overtone/live__init.class or overtone/live.clj on classpath: (core.clj:1)
user=>
******************************************************************************************
Any ideas what I have missed/missassumed this time?
Iain
did you run the script from within the jam-challenge dir? I only knocked it up quickly and it assumes your location...
Sam
yes I ran it from inside the jam challenge directory. What does your script assume?
Iain
It assumes that your CWD is the jam challenge directory. This is how I got it up and running just now:
∴ /Users/sam/foo
λ git clone git://github.com/overtone-jam-challenge/jam-001.git
Cloning into jam-001...
remote: Counting objects: 46, done.
remote: Compressing objects: 100% (36/36), done.
remote: Total 46 (delta 16), reused 0 (delta 0)
Receiving objects: 100% (46/46), 4.73 KiB, done.
Resolving deltas: 100% (16/16), done.
∴ /Users/sam/foo
λ ls
jam-001
∴ /Users/sam/foo
λ cd jam-001
∴ /Users/sam/foo/jam-001
λ ls
README.md checkouts init-jam-challenge project.clj src test
∴ /Users/sam/foo/jam-001
λ ./init-jam-challenge
Preparing you for the Jam Challenge...
======================================
Pulling this Jam's deps...
Copying 2 files to /Users/sam/foo/jam-001/lib
Pulling in Overtone as a checkout for your curious perusal...
Submodule 'checkouts/overtone' (git://github.com/overtone/overtone.git) registered for path 'checkouts/overtone'
Cloning into checkouts/overtone...
remote: Counting objects: 4224, done.
remote: Compressing objects: 100% (1772/1772), done.
remote: Total 4224 (delta 2857), reused 3481 (delta 2344)
Receiving objects: 100% (4224/4224), 2.48 MiB | 382 KiB/s, done.
Resolving deltas: 100% (2857/2857), done.
Submodule path 'checkouts/overtone': checked out '349c4603b34868cfa30431d4b32f925f90d2d99b'
Pulling Overtone's deps...
[INFO] snapshot scenegraph:scenegraph:0.0.1-SNAPSHOT: checking for updates from central
[INFO] snapshot scenegraph:scenegraph:0.0.1-SNAPSHOT: checking for updates from clojure
[INFO] snapshot scenegraph:scenegraph:0.0.1-SNAPSHOT: checking for updates from clojure-snapshots
[INFO] snapshot scenegraph:scenegraph:0.0.1-SNAPSHOT: checking for updates from clojars
[INFO] snapshot scenegraph:decora-runtime:0.0.1-SNAPSHOT: checking for updates from clojure
[INFO] snapshot scenegraph:decora-runtime:0.0.1-SNAPSHOT: checking for updates from clojure-snapshots
[INFO] snapshot scenegraph:decora-runtime:0.0.1-SNAPSHOT: checking for updates from clojars
[INFO] snapshot scenegraph:decora-runtime:0.0.1-SNAPSHOT: checking for updates from clojars.org
[INFO] snapshot overtone:osc-clj:0.2.1-SNAPSHOT: checking for updates from central
[INFO] snapshot overtone:osc-clj:0.2.1-SNAPSHOT: checking for updates from clojure
[INFO] snapshot overtone:osc-clj:0.2.1-SNAPSHOT: checking for updates from clojure-snapshots
[INFO] snapshot overtone:osc-clj:0.2.1-SNAPSHOT: checking for updates from clojars
[INFO] snapshot overtone:byte-spec:0.2.0-SNAPSHOT: checking for updates from central
[INFO] snapshot overtone:byte-spec:0.2.0-SNAPSHOT: checking for updates from clojure
[INFO] snapshot overtone:byte-spec:0.2.0-SNAPSHOT: checking for updates from clojure-snapshots
[INFO] snapshot overtone:byte-spec:0.2.0-SNAPSHOT: checking for updates from clojars
[INFO] snapshot overtone:midi-clj:0.2.0-SNAPSHOT: checking for updates from central
[INFO] snapshot overtone:midi-clj:0.2.0-SNAPSHOT: checking for updates from clojure
[INFO] snapshot overtone:midi-clj:0.2.0-SNAPSHOT: checking for updates from clojure-snapshots
[INFO] snapshot overtone:midi-clj:0.2.0-SNAPSHOT: checking for updates from clojars
[INFO] snapshot overtone:scsynth-jna:0.1.2-SNAPSHOT: checking for updates from central
[INFO] snapshot overtone:scsynth-jna:0.1.2-SNAPSHOT: checking for updates from clojure
[INFO] snapshot overtone:scsynth-jna:0.1.2-SNAPSHOT: checking for updates from clojure-snapshots
[INFO] snapshot overtone:scsynth-jna:0.1.2-SNAPSHOT: checking for updates from clojars
[INFO] snapshot java-osc:java-osc:cvs-SNAPSHOT: checking for updates from clojure
[INFO] snapshot java-osc:java-osc:cvs-SNAPSHOT: checking for updates from clojure-snapshots
[INFO] snapshot java-osc:java-osc:cvs-SNAPSHOT: checking for updates from clojars
[INFO] snapshot java-osc:java-osc:cvs-SNAPSHOT: checking for updates from clojars.org
[INFO] snapshot vijual:vijual:0.1.0-SNAPSHOT: checking for updates from central
[INFO] snapshot vijual:vijual:0.1.0-SNAPSHOT: checking for updates from clojure
[INFO] snapshot vijual:vijual:0.1.0-SNAPSHOT: checking for updates from clojure-snapshots
[INFO] snapshot vijual:vijual:0.1.0-SNAPSHOT: checking for updates from clojars
[INFO] snapshot org.clojure:clojure:1.1.0-alpha-SNAPSHOT: checking for updates from clojure
[INFO] snapshot org.clojure:clojure:1.1.0-alpha-SNAPSHOT: checking for updates from clojure-snapshots
[INFO] snapshot org.clojure:clojure:1.1.0-alpha-SNAPSHOT: checking for updates from clojars
[INFO] snapshot org.clojure:clojure:1.1.0-alpha-SNAPSHOT: checking for updates from central
Downloading: org/clojure/clojure/1.1.0-alpha-SNAPSHOT/clojure-1.1.0-alpha-SNAPSHOT.pom from clojure
Downloading: org/clojure/clojure/1.1.0-alpha-SNAPSHOT/clojure-1.1.0-alpha-SNAPSHOT.pom from clojure-snapshots
Downloading: org/clojure/clojure/1.1.0-alpha-SNAPSHOT/clojure-1.1.0-alpha-SNAPSHOT.pom from clojars
Downloading: org/clojure/clojure/1.1.0-alpha-SNAPSHOT/clojure-1.1.0-alpha-SNAPSHOT.pom from central
[INFO] snapshot org.clojure:clojure-contrib:1.0-SNAPSHOT: checking for updates from clojure
[INFO] snapshot org.clojure:clojure-contrib:1.0-SNAPSHOT: checking for updates from clojure-snapshots
[INFO] snapshot org.clojure:clojure-contrib:1.0-SNAPSHOT: checking for updates from clojars
[INFO] snapshot org.clojure:clojure-contrib:1.0-SNAPSHOT: checking for updates from central
Copying 19 files to /Users/sam/foo/jam-001/checkouts/overtone/lib
Merging deps...
*************************
* OK, get your code on! *
*************************
∴ /Users/sam/foo/jam-001
λ lein repl
"REPL started; server listening on localhost:5407."
user=> (use 'jam-challenge-001.core)
WARNING: partition-by already refers to: #'clojure.core/partition-by in namespace: vijual, being replaced by: #'clojure.contrib.seq-utils/partition-by
WARNING: frequencies already refers to: #'clojure.core/frequencies in namespace: vijual, being replaced by: #'clojure.contrib.seq-utils/frequencies
WARNING: shuffle already refers to: #'clojure.core/shuffle in namespace: vijual, being replaced by: #'clojure.contrib.seq-utils/shuffle
WARNING: reductions already refers to: #'clojure.core/reductions in namespace: vijual, being replaced by: #'clojure.contrib.seq-utils/reductions
WARNING: partition-all already refers to: #'clojure.core/partition-all in namespace: vijual, being replaced by: #'clojure.contrib.seq-utils/partition-all
WARNING: group-by already refers to: #'clojure.core/group-by in namespace: vijual, being replaced by: #'clojure.contrib.seq-utils/group-by
WARNING: flatten already refers to: #'clojure.core/flatten in namespace: vijual, being replaced by: #'clojure.contrib.seq-utils/flatten
Nov 16, 2010 10:53:08 AM sun.reflect.NativeMethodAccessorImpl invoke0
INFO: boot-internal: 30560
Nov 16, 2010 10:53:08 AM sun.reflect.NativeMethodAccessorImpl invoke0
INFO: booting internal audio server listening on port: 30560
Using vector unit: no
Loading synthdefs from default path: /Users/sam/Library/Application Support/SuperCollider/synthdefs
Number of Devices: 3
0 : "Built-in Microphone"
1 : "Built-in Input"
2 : "Built-in Output"
"Built-in Microphone" Input Device
Streams: 1
0 channels 2
"Built-in Output" Output Device
Streams: 1
0 channels 2
mSafetyOffset 17
mNumberBuffers 1
mDataByteSize 0 4096
<-SC_CoreAudioDriver::Setup world 19819E50
SC_AudioDriver: sample rate = 44100.000000, driver's block size = 512
->SC_CoreAudioDriver::DriverStart
start UseSeparateIO?: 1
<-SC_CoreAudioDriver::DriverStart
SuperCollider 3 server ready..
<SOUND!>
Sam
>
> On 16 Nov 2010, at 10:16, Iain Wood wrote:
>>
>> yes I ran it from inside the jam challenge directory. What does your script assume?
>
> It assumes that your CWD is the jam challenge directory. This is how I got it up and running just now:
>
There must be a missing path or something cos that's what I was doing too :-(
soulflyer:overtone-jam-challenge-jam-001-b3fb795 iain$ pwd
/Users/iain/Code/overtone-jam-challenge-jam-001-b3fb795
soulflyer:overtone-jam-challenge-jam-001-b3fb795 iain$ ./init-jam-challenge
Preparing you for the Jam Challenge...
======================================
Pulling this Jam's deps...
Copying 2 files to /Users/iain/Code/overtone-jam-challenge-jam-001-b3fb795/lib
Pulling in Overtone as a checkout for your curious perusal...
You need to run this command from the toplevel of the working tree.
You need to run this command from the toplevel of the working tree.
Pulling Overtone's deps...
Copying 2 files to /Users/iain/Code/overtone-jam-challenge-jam-001-b3fb795/lib
Merging deps...
cp: lib/*: No such file or directory
*************************
Sam
> How weird. What version of git are you using? Could you try updating to the latest from Git-scm.org?
>
it's up to date now and still the same symptoms :-(
Iain
that's most odd.
Could you crack open init-jam-challenge and go through each line by hand and let me know what you see?
Sam
It's the 2 git commands. I've skipped them and downloaded overtone to the checkouts directory by hand and now I hear sounds :-)
Iain
> It's the 2 git commands. I've skipped them and downloaded overtone to the checkouts directory by hand and now I hear sounds :-)
>
How strange. What version of git are you running and how do they fail?
Cool that you finally hear sounds!!
Sam