Dwa warianty (do wyboru 1):
Ciekawostka: ZTM Poznań udostępnia też trasy tramwajów, z odstępami między przystankami, pozwalając na stworzenie rekreacji przejazdu tramwajem.
Sonic Pi posiada wbudowany bank sampli - wcześniej przygotowanych fragmentów dźwiękowych.
Odpowiednikiem funkcji play jest funkcja sample :nazwa_sampla np:
sample :ambi_drone
sleep 1
sample :ambi_drone
Zauważ, że funkcja sample podobnie jak play nie oczekuje na zakończenie odtwarzania sampla!
Ponadto każdy odtwarzany sampel może mieć różną długość - aby zdobyć dlugość sampla używamy funkcji sample_duration:
sample :ambi_drone
sleep sample_duration(:ambi_drone)
sample :ambi_drone
Jeśli zmienimy parametry odtwarzania musimy te same parametry przekazać do funkcji sleep_duration!
Funkcja sample posiada (podobnie jak play) ADSR kontrolujący poziom głośności.
Ponadto dostępne jest:
:start (od 0 do 1, gdzie 0 to początek dźwięku, 0.5 to połowa, a 1 to koniec):finish (od 0 do 1, podobnie jak :start):rate (np. -1 odtworzy z tym samym tempem, ale od końca, 2 - dwa razy szybciej, 0.5 - dwa razy wolniej)Więcej parametrów opisanych jest w dokumentacji funkcji sample
Sample odtworzony od końca, dwa razy szybciej, z pominiętym 30% utworu od końca. Następinie ten sam sample, pierwsze 30%, dwa razy wolniej do przodu:
sample :loop_amen, finish: 0.7, rate: -2
sleep sample_duration(:loop_amen, finish: 0.7, rate: -2)
sample :loop_amen, finish: 0.3, rate: 0.5
Sonic Pi nie wspiera niektórych powszechnie używanych formatów plików! Rekomendowanym jest używanie plików wav lub ogg.
Poniższy przykład zakłada, że plik znajduje się w tej samej ścieżce co Sonic Pi. Rekomendowanym jest używanie pełnych ścieżek (absolute path).
Windows: \ należy zamienić na \\: ścieżka "C:\Users\test\test.wav" na "C:\\Users\\test\\test.wav"
use_bpm 60
tomatoes = "tomatoes.wav"
sample tomatoes, pitch: 12
sleep sample_duration(tomatoes)
12.times do |n|
rate = 1 + 0.25 * n
s = 0.4
f = 0.67
sample tomatoes, start: s, finish: f, rate: rate, lpf: :c7
sleep sample_duration(tomatoes, rate: rate, start: s, finish: f)
end
sample tomatoes, rate: 0.8, attack: 0, decay: 0, sustain: 0, release: sample_duration(tomatoes)
Zakładając, że w katalogu "/foo" znajdują się pliki wav/ogg, mamy możliwość wykorzystania katalogu jako bazy sampli - sample "/foo", 1 odtworzy drugą próbkę dźwiękową wewnątrz katalogu.
Zapoznaj się z dokumentacją funkcji sample by poznać dokładny algorytm działania.
# W przypadku fxów pomaga wcześniej załadować:
load_sample "tomatoes.wav"
with_fx :panslicer, smooth: 0.25 do
with_fx :reverb do
with_fx :flanger do
with_fx :ring_mod do
sample "tomatoes.wav"
end
end
end
end
Wykorzystujemy fakt, że :loop_amen dzieli się na 8 równych fragmentów:
Każda iteracja pętli :beat_slicer losuje indeks od 0 do 8, wedle którego odtworzymy jeden z 8 fragmentow :loop_amen.
Każdy fragment ma dlugość 1/8 utworu (slice_size).
Wyliczamy start (zmienna s) - jest to pominięcie poprzednich do wylosowanego fragmentów oraz koniec (zmiemma f) - jest to start przesunięty o dlugośc fragmentu.
Następnie możemy odtworzyć fragment z użyciem funkcji sample.
live_loop :beat_slicer do
slice_idx = rand_i(8)
slice_size = 1 / 8.0
s = slice_idx * slice_size
f = s + slice_size
sample :loop_amen, start: s, finish: f
sleep sample_duration :loop_amen, start: s, finish: f
end
Powyższy przykład można rozszerzyć poprzez nierównomierny podział sampla - każda sekcja może mieć inną długość. Aby osiągnąć ten efekt będziemy losować z tablicy, w której każdy element oznacza długość danego fragmentu. Pętla rozpoczyna się podobnie - od losowania indeksu, tym razem indeksu tablicy.
Następnie wyciągamy długość pojedyńczego fragmentu (slice_size = durations[slice_idx]) oraz liczymy sumę długości fragmentów pominiętych (s = durations[...slice_idx].sum) - zapis durations[...slice_idx]wyciąga elementy tablicy od 0 do slice_idx (bez slice_idx), natomiast .sum sumuje elementy tablicy.
Pozostała część kodu jest identyczna.
durations = [0.4, 0.1, 0.2, 0.1, 0.2]
live_loop :beat_slicer do
slice_idx = rand_i(durations.length)
slice_size = durations[slice_idx]
s = durations[...slice_idx].sum
f = s + slice_size
sample :loop_amen, start: s, finish: f
sleep sample_duration :loop_amen, start: s, finish: f
end