Przygotowanie krótkiego utworu (~30s) w środowisku Sonic Pi, spełniającego następujące wymagania:
Za tworzenie i wysyłanie komunikatów MIDI odpowiada rodzina funkcji midi*.
Każda z nich akceptuje parametr port:, który pozwala na wybranie docelowego portu.
Domyślną wartością jest * wysyłająca na wszystkie porty.
midi :c4.
Przyjmuje dodatkowe parametry vel odpowiadające za „siłę uderzenia w klawisz” (0-127) oraz sustain określające długość wciśnięcia klawisza.velmidi_note_on vel: 010.times do |i|
midi :c4, vel: i * 10, sustain: 1
sleep 1
end
use_real_time
in_thread do
use_midi_defaults port: "timidity_timidity_port_0_136_0"
midi_pc 24 # AcousticGuitarNylon
loop do
midi scale(:c4, :major).tick
sleep 1
end
end
in_thread do
use_midi_defaults port: "timidity_timidity_port_1_136_1"
midi_pc 19 # Church Organ
loop do
midi scale(:c2, :major).tick
sleep 4
end
end
midi_all_notes_off
input = "midi_through_midi_through_port-0_14_0"
out1 = "midi_through_midi_through_port-1_14_1"
out2 = "midi_through_midi_through_port-2_14_2"
out3 = "midi_through_midi_through_port-3_14_3"
live_loop :chan1 do
use_real_time
n, vel = sync "/midi:#{input}:1/note_on"
midi_note_on n, vel, port: out1
end
live_loop :chan2 do
use_real_time
n, vel = sync "/midi:#{input}:2/note_on"
midi_note_on n, vel, port: out2
end
live_loop :chan3 do
use_real_time
n, vel = sync "/midi:#{input}:3/note_on"
midi_note_on n, vel, port: out3
end
port = "midi_through_midi_through_port-0_14_0"
synths = Hash.new
define :release do |s|
in_thread do
control s, amp: 0, amp_slide: 0.1
sleep 0.2
s.kill
end
end
live_loop :receive do
use_real_time
n, v = sync "/midi:#{port}:*/note_on"
if v == 0 then
if synths[n]
release synths[n]
synths[n] = nil
end
else
if synths[n]
release synths[n]
synths[n] = nil
end
synths[n] = synth :tech_saws, note: n, sustain: 99999, amp: 0.3
end
end
Sonic Pi zbudowany jest na podstawie języka Ruby, przez co jego mechanizm tworzenia funkcji (deklaracja def) działa w wykorzystywanej wersji.
Twórca zaznaczył jednak, że nie rekomenduje wykorzystywanie mechanizmów z języka Ruby.
define :getRandomNumber do
4 # chosen by fair dice roll
# guaranteed to be random
end
print(getRandomNumber())
print getRandomNumber
define :add do |a, b|
a + b
end
print(add(11, 22))
define :fib do |n|
if n <= 1 then
return 1
else
return n * fib(n-1)
end
end
print(fib(8))
define :test do |x|
x
end
live_loop :foo do
play test(60)
sleep 1
end
live_loop :bar do
f = tick
define :test do |x|
x + f
end
sleep 2
end
ns = [:fs3, :cs3, :e3, :g3, :c3, :d3, :gs3,:b3, :a3, :ds3, :as3, :f3]
rytm = [1, 1/2r, 2, 1/4r, 3/4r, 1/8r, 4, 3/8r, 3/2r, 3, 1/16r, 6]
dyna = [0.33, 0.45, 0.27, 0.55, 0.1, 0.2, 0.7, 0.91, 0.82, 0.51, 0.4, 0.37]
for i in 0..12
play ns[i], amp: dyna[i], duration: rytm[i]
sleep rytm[i].to_f
end
Seria składająca się z odległości pomiędzy dźwiękami (w półtonach). Transformacje zachowują relatywne odległości między kolejnymi dźwiękami. Pozwala to na wyznaczenie czterech możliwych serii na podstawie trzech przekształceń.
Podstawowe przekształcenia to:
Wyznacza to 4 serie:
0, 11, 3, 4, 8, 7, 9, 5, 6, 1, 2, 10
2, 10, 11, 6, 7, 3, 5, 4, 8, 9, 1, 0
10, 2, 1, 6, 5, 9, 7, 8, 4, 3, 11, 0
2, 10, 11, 6, 7, 3, 5, 4, 8, 9, 1, 0
Operacje P, I, R, RI wraz z złożeniem funkcji jako działaniem tworzą grupę abelową znaną jako Grupa Czwórkowa Kleina, gdzie P jest elementem neutralnym.