Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

I'm committing all this strictly for historical purposes. This code s…

…ucks. It blew up

on me in Toronto. Actually it didn't. But it could have. It represents serious hackery
perpetrated in hopes of automating Ableton Live. It successfully automates Live but
doesn't sound that great.

The drums-only stuff is better. For Burning Man I'm going with drums only. And possibly
adding new features tonight and/or tomorrow. So I'm stashing all this in git just in case,
before I destroy it, because I need to throw it all away in order to get the Burning Man
shit hooked up.

To use this code, which you totally should not do, you need Ableton Live hooked up with
tracks on 10 channels, and each fader level hooked to a controller on channel 0. I think
I set it like controller 1, fader 1, through controller 10, fader 10, but I don't really
remember. There's probably some other shit in here I broke for no good reason.
  • Loading branch information...
commit 4d8c70db76714218e1098d3b9abf94ecd81252fc 1 parent 46d1d09
@gilesbowkett authored
View
2  ambient.rb
@@ -1,6 +1,6 @@
require 'lib/archaeopteryx'
-
+require 'rubyfringe'
View
39 db_drum_definition.rb
@@ -1,10 +1,32 @@
+# 0 Drums
+# 1 Pacific Heights
+# 2 Clarendon (dub)
+# 3 Over-reacted
+# 4 System (Matrix/Futurebound)
+# 5 Call Me
+# 6 Hustlin
+# 7 Feeling Blue (piano track)
+# 8 Mermaids
+# 9 Waves Breaking
+
+$lock_live = true
+$live_channels = [0,8]
+$beat_juggle = true
+
probabilities = {}
probabilities[:none] = [0.0] * 16
probabilities[:all] = [1.0] * 16
+# hip-hop
+# probabilities[36] = [1.0, 0.0, 0.5, 0.25, 0.0, 0.6, 0.0, 0.9, 0.9, 0.0, 1.0, 0.0, 0.5, 0.0, 0.3, 0.0]
+# probabilities[37] = [0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.0, 1.0, 0.0, 0.0, 0.0]
+
+# d&b
probabilities[36] = [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]
probabilities[37] = [0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0]
+
+# both
probabilities[38] = [0.2, 0.0, 0.3, 0.0, 0.3, 0.1, 0.3, 0.4, 0.0, 0.0, 0.2, 0.0, 0.4, 0.0, 0.0, 0.0]
probabilities[39] = [0.3, 0.0, 0.2, 0.6, 0.1, 0.0, 0.4, 0.1, 0.35, 0.15, 0.0, 0.0, 0.2, 0.0, 0.1, 0.0]
probabilities[40] = [0.0, 0.0, 0.2, 0.0, 0.4, 0.0, 0.0, 0.0, 0.2, 0.0, 0.3, 0.0, 0.3, 0.1, 0.3, 0.4]
@@ -14,6 +36,15 @@
probabilities[44] = [0.65] * 16
probabilities[45] = [0.85, 0.35] * 8
+# 0 DO NOT USE!
+# 1 distorted Roni Size
+# 2 Roni Size
+# 3 idm
+# 4 Trent Reznor
+# [2,5][rand(2)] hip-hop
+# 6 Zed
+# ((1..6).to_a)[rand(6)] madness
+
def note(midi_note_number)
Note.create(:channel => 2,
:number => midi_note_number,
@@ -25,10 +56,10 @@ def note(midi_note_number)
(36..45).each do |midi_note_number|
notes << Drum.new(:note => note(midi_note_number),
:when => L{|beat| false},
- :number_generator => L{1.0},
- :next => L{|queue| queue[queue.size - 1]},
- # :number_generator => L{rand},
- # :next => L{|queue| queue[rand(queue.size)]},
+ # :number_generator => L{0.3},
+ # :next => L{|queue| queue[queue.size - 1]},
+ :number_generator => L{rand},
+ :next => L{|queue| queue[rand(queue.size)]},
:probabilities => probabilities[midi_note_number] || probabilities[:none])
end
notes
View
34 doc_ock.rb
@@ -1,36 +1,17 @@
require 'lib/archaeopteryx'
-class Fader # < InfiniteStream
+class Fader
attr_accessor :midi_channel, :controller_number
- # def generating_loop
- # generate(109)
- # car = 109
- # cdr = 0
- # loop do
- # generate(cdr)
- # car, cdr = cdr, car
- # end
- # end
def toggle
[midi_channel, controller_number, self.next]
end
- # def value
- # @value ||= 100
- # case @value
- # when 0
- # @value = 100
- # when 100
- # @value = 0
- # end
- # @value
- # end
attr_accessor :value
end
class TapTempo
- def midi_channel; 0 ; end
- def controller_number ; 8 ; end
+ def midi_channel; 15 ; end
+ def controller_number ; 7 ; end
def value ; 127 ; end
end
@@ -44,7 +25,7 @@ def initialize(attributes)
:logging => attributes[:logging] || false)
@tap_tempo = TapTempo.new
@faders = []
- (0..7).each do |number|
+ (0..3).each do |number|
@faders[number] = Fader.new
@faders[number].midi_channel = 0
@faders[number].controller_number = number
@@ -54,9 +35,8 @@ def go
generate_beats = L do
(1..@measures).each do |measure|
(0..(@beats - 1)).each do |beat|
- chosen = rand(7)
- # @midi.send_controller_message(@tap_tempo) if 0 == beat % 2
- (0..7).each do |number|
+ chosen = rand(4)
+ (0..3).each do |number|
case number
when chosen
@faders[number].value = 100
@@ -80,7 +60,7 @@ def go
end
end
-DocOck.new(:clock => Clock.new(116),
+DocOck.new(:clock => Clock.new(175),
:evil_timer_offset_wtf => 0.2).go
View
14 eval_style.rb
@@ -1,8 +1,18 @@
require 'lib/archaeopteryx'
-Arkx.new(:clock => Clock.new(167),
+require 'rubyfringe'
+
+zed = Clock.new(15)
+hip_hop = Clock.new(90)
+drum_and_bass = {:clock => Clock.new(170), :drumfile => "db_drum_definition.rb"}
+techno = {}
+
+Arkx.new(:clock => drum_and_bass[:clock],
:measures => 4,
:logging => true,
:evil_timer_offset_wtf => 0.2,
- :generator => Rhythm.new(:drumfile => "db_drum_definition.rb",
+ :generator => Rhythm.new(:drumfile => drum_and_bass[:drumfile],
:mutation => L{|measure| 0 == (measure - 1) % 2})).go
+
+# if you move mutation definition into drum file you can alternate between 16-bar long loops
+# and 2-bar fills.
View
41 lib/arkx.rb
@@ -7,6 +7,14 @@ def initialize(attributes)
@evil_timer_offset_wtf = attributes[:evil_timer_offset_wtf]
@midi = LiveMIDI.new(:clock => @clock = attributes[:clock], # confusion!!!!!!!!!!
:logging => attributes[:logging] || false)
+ # doc ock hackery
+ @tap_tempo = TapTempo.new
+ @faders = []
+ (0..9).each do |number|
+ @faders[number] = Fader.new
+ @faders[number].midi_channel = 0
+ @faders[number].controller_number = number
+ end
end
def play(music)
music.each {|note| @midi.play(note)}
@@ -18,6 +26,29 @@ def go
(0..(@beats - 1)).each do |beat|
if [0, 4, 8, 12].include? beat
@midi.send_controller_message(15, 7, 127) # experimental tap-tempo scheduler
+ # this should almost certainly be something like
+ # trigger @generator.messages(beat)
+ end
+ # globals because I wrote this part on the plane - expect refactoring
+ if $lock_live
+ if $beat_juggle
+ chosen = [$live_channels[rand($live_channels.size)]]
+ else
+ chosen = $live_channels
+ end
+ (0..9).each do |channel|
+ if chosen.include? channel
+ @faders[channel].value = 100
+ @midi.send_controller_message(@faders[channel].midi_channel,
+ @faders[channel].controller_number,
+ @faders[channel].value)
+ else
+ @faders[channel].value = 0
+ @midi.send_controller_message(@faders[channel].midi_channel,
+ @faders[channel].controller_number,
+ @faders[channel].value)
+ end
+ end
end
play @generator.notes(beat)
@clock.tick
@@ -30,3 +61,13 @@ def go
end
end
end
+
+# there are two or three ways to refactor the tap tempo as far as I can tell.
+
+# 1 pass in a block
+# 2 control-message scheduler object
+# 3 pass in control messages for scheduling
+
+# 4 control message probability matrix
+# 5 control messages *IN* the existing probability matrix
+# trigger @generator.messages(beat)
View
6 lib/midi/practical_ruby_projects/live_midi.rb
@@ -47,7 +47,7 @@ def play(midi_note, on_time = @clock.time)
def send_controller_message(midi_channel, controller_number, value, on_time = @clock.time)
on_time += @clock.start
- puts "scheduling for #{on_time}"
+ # puts "scheduling for #{on_time}" if @logging
@timer.at(on_time) do
control(midi_channel, controller_number, value)
end
@@ -93,8 +93,8 @@ def program_change(channel, preset)
end
def pulse(channel, controller_id, value)
- puts "sending now: #{Time.now.to_f}"
- puts "#{[channel, controller_id, value].inspect}"
+ # puts "sending now: #{Time.now.to_f}" if @logging
+ # puts "#{[channel, controller_id, value].inspect}" if @logging
message(CONTROLLER | channel, controller_id, value)
end
alias :control :pulse
View
BIN  music_software_files/juice.rns
Binary file not shown
View
11 pulse.rb
@@ -5,9 +5,16 @@
@live_midi = LiveMIDI.new(:logging => false,
:clock => Clock.new(167))
-@live_midi.pulse(15, 7, 0) # channel, controller, value
+# tap tempo
+# @live_midi.pulse(15, 7, 0) # channel, controller, value
+# sleep 1
+# @live_midi.pulse(15, 7, 100)
+
+# doc ock
+@live_midi.pulse(0, 9, 0)
sleep 1
-@live_midi.pulse(15, 7, 100)
+@live_midi.pulse(0, 9, 100)
+
# so, I need to schedule these motions, just like I would schedule a MIDI note; and also I need to
# apply tweens, to make the motion fluid. I need to support the variety of different control styles
Please sign in to comment.
Something went wrong with that request. Please try again.