Stwórz krótki (około 30 sekund) utwór w Sonic Pi spełniający następujące wymagania:
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
Funkcja sample pozwala na odtworzenie plików dźwiękowych spoza banku zapisanych w Sonic Pi.
Wykonujemy to przez podanie łańcucha z ścieżką do pliku:
sample "/ścieżka/do/pliku.wav"
Sonic Pi nie wspiera niektórych powszechnie używanych formatów plików! Rekomendowanym jest używanie plików wav lub ogg.
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