Ruby 用 Sonic Pi 演奏东热片头曲

hxpax · 2019年01月29日 · 最后由 hxpax 回复于 2019年01月31日 · 5042 次阅读

16 年,SE-Radio 的 274 期SE-Radio Episode 274: Sam Aaron on Sonic Pi节目里,Sam Aaron 聊了它为什么做 Sonic Pi, 以及为什么用 Ruby 做 Sonic Pi, 虽然他最爱的语言是 Clojure.

听完这期,我迫不及待地安装了 Sonic Pi, 开始玩现场编程音乐,顺势在那年公司年会做了表演,曲目是超级马里奥。后来我又陆续用 Sonic Pi 写了其它一些曲子,然后束之高阁。

不知道社区里有没有其它人玩 Sonic Pi, 这里一曲东热,抛砖引玉,多多指教。

附:

class MyNotes
  attr_reader :n_beats

  def initialize(notes, note_group_len)
    @notes = notes
    @interval = 1.0 / note_group_len
    @n_beats = notes.length / note_group_len
  end

  def ite(times_speed_up = 1)
    gap = @interval / times_speed_up
    @notes.each do |note|
      yield note if note
      sleep gap
    end
  end

  def go
    ite {|note| play note}
  end
end

use_bpm 100

A = [:c6, :c6, :c6, :c6, :c6, :c6, :c6, :b5, nil, :b5, :c6, nil, :g5, :g5, :a5, nil,
     :c6, :c6, :c6, :c6, :c6, :c6, :c6, :b5, nil, :b5, :c6, nil, :g5, :g5, :a5, nil,
     :c6, :c6, :c6, :c6, :c6, :c6, :c6, :b5, nil, :b5, :c6, nil, :g5, :g5, :a5, nil]

B = [:a5, :a5, :a5, :a5, :a5, :a5, :a5, :a5, nil, :a5, :a5, nil, :e5, :e5, :g5, nil,
     :a5, :a5, :a5, :a5, :a5, :a5, :a5, :a5, nil, :a5, :a5, nil, :e5, :e5, :g5, nil,
     :a5, :a5, :a5, :a5, :a5, :a5, :a5, :a5, nil, :a5, :a5, nil, :e5, :e5, :g5, nil]

C = [:g5, :g5, :g5, :g5, :g5, :g5, :g5, :g5, nil, :g5, :g5, nil, :d5, :d5, :e5, nil,
     :g5, :g5, :g5, :g5, :g5, :g5, :g5, :g5, nil, :g5, :g5, nil, :d5, :d5, :e5, nil,
     :g5, :g5, :g5, :g5, :g5, :g5, :g5, :g5, nil, :g5, :g5, nil, :d5, :d5, :e5, nil]

D = [:e5, :e5, :e5, :e5, :e5, :e5, :e5, :e5, nil, :e5, :e5, nil, :b4, :b4, :c5, nil,
     :e5, :e5, :e5, :e5, :e5, :e5, :e5, :e5, nil, :e5, :e5, nil, :b4, :b4, :c5, nil,
     :f5, :f5, :f5, :f5, :f5, :f5, :f5, :f5, nil, :f5, :f5, nil, :c5, :c5, :c5, nil,
     :d5, :f5, :a5, :c6, :d6, :c6, :a5, :f5, :e5, :g5, :b5, :d6, :e6, :d6, :b5, :g5]

E = [:a2, nil, :a3, nil, :a2, nil, :a3, nil, :a2, nil, :a3, nil, :a2, nil, :a3, nil,
     :a2, nil, :a3, nil, :a2, nil, :a3, nil, :a2, nil, :a3, nil, :a2, nil, :a3, nil,
     :f2, nil, :f3, nil, :f2, nil, :f3, nil, :f2, nil, :f3, nil, :f2, nil, :f3, nil,
     :d3, nil, :d4, nil, :d3, nil, :d4, nil, :e3, nil, :e4, nil, :e3, nil, :e4, nil]

notes_a = MyNotes.new(A, 4)
notes_b = MyNotes.new(B, 4)
notes_c = MyNotes.new(C, 4)
notes_d = MyNotes.new(D, 4)
notes_e = MyNotes.new(E, 4)

raise '!' unless notes_a.n_beats == notes_b.n_beats &&
    notes_a.n_beats == notes_c.n_beats &&
    notes_a.n_beats == notes_d.n_beats &&
    notes_a.n_beats == notes_e.n_beats

live_loop :director do
  sleep notes_a.n_beats
end

live_loop :a do
  sync :director
  notes_a.go
end

live_loop :b do
  sync :director
  notes_b.go
end

live_loop :c do
  sync :director
  notes_c.go
end

live_loop :d do
  sync :director
  notes_d.go
end

live_loop :e do
  sync :director
  notes_e.go
end

有在线执行的地方么?或者录个视频也好。😃

束之高阁就对了,因为这只是个披着 ruby 外衣的东西,并不是 ruby...

话说 sonic Pi 算是 ruby 的什么版本,1.8.x?

Rei 回复

没有在线执行的地方,因为需要音频守护,部署服务器开销不菲吧。回头拍个视频

mizuhashi 回复

错了哦,这是标准的 Ruby 解释器,只是我写个东热的曲子没有必要写这么复杂。Sonic Pi 本身由 C/C++, erlang, Ruby 混合实现

Wire2Brain 回复

2.0 语法

还能这么玩,真是优秀😤

hxpax 回复

那你估计没在 sonicpi 里用过任何元编程技巧...

他的 liveload 机制会让你的类似 define method 之类的东西用不了,作用域也是有问题的,反正我之前用的时候是不行的,如果没有大量代码生成加持,你用这个做音序器不如任何一个合成器/编曲软件

mizuhashi 回复

确实没有在 Sonic Pi 里用到过元编程特性

需要 登录 后方可回复, 如果你还没有账号请 注册新账号