0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【SonicPi】楽譜をもとにして演奏してみた

Last updated at Posted at 2024-12-04

はじめに

当方、子ども向けのプログラミング教室を運営しているものですが、近くの中学生に「プログラムで演奏できないの」と聞かれました。

きらきらした目で聞かれたので、試してみることにしました。

SonicPi

手軽そうで、無償利用可能。久しぶりに Ruby を触ってみようか。
ということで、SonicPi を触ることにしました。

心配なところ

以前に Scratch3 で 「強風オールバックみたいなの」、「BlingBangBangBornみたいなの」を演奏させてみたことがあるのですが、次の点で苦労しています。

(1) 1音ごとに入れるためコードが大量になる
(2) 和声の演奏(同時に鳴らす)ときの小節のずれ

大量コードは 曲が長くなればしょうがないことなのですが、小節のずれがあると曲として成立しなくなるので、SonicPiでうまく回避できるか心配です。回避方法を試してみましょう。

入力に利用した楽譜

「Art Studio まほろば」さんサイトより
https://score.logical-arts.jp/item/203/

今回の楽譜では、ヴォーカル部、伴奏ピアノ高音部、伴奏ピアノ低音部があるものです。

SonicPi コードの要点

BPM

image.png

use_bpm 74

楽譜にある テンポ 74 は上記で決めることができます。
楽譜にあるテンポの指示は、四分音符が1分間に74個ですので、bpm = 74 となるように設定します。
( bpm はテンポのひとつの表現方法のひとつです。2024/12/6 修正)

SonicPi : 同期(sync)

同期をとるための live_loop を次のように作っておきます。

live_loop :metro do
    sleep 4
end

1小節に4つの四分音符の構成の曲なので、sleep 4 です。
なお、sleep は 停止する秒数ではなく、停止する『拍数』であることに注意しましょう。
use_bpm 74 のテンポのときは、1分間に 74拍あるので、sleep 4 は、(60.0 / 74) × 4 の秒数分停止することになります。

SonicPi : live_loop

ヴォーカル部、伴奏ピアノ高音部、伴奏ピアノ低音部の3個に対応した live_loop を作ることにします。

############################################
# ヴォーカル部
############################################
live_loop :vocal, sync: :metro do
    # ここでヴォーカル部-1小節分の音符を鳴らす
end

sync :metro により、live_loop :metro と同期をとり実行されまる。
これで1小節づつの開始がそろうはず。

############################################
# piano 高音部
############################################
live_loop :p1, sync: :metro do
    # ここで伴奏ピアノ高音部-1小節分の音符を鳴らす
end
############################################
# piano 低音部
############################################
live_loop :p2, sync: :metro do
    # ここで伴奏ピアノ低音部-1小節分の音符を鳴らす
end

音の記述

だらだらと1曲全体をかくと訳がわからなくなるので、1小節ずつを定義したいと思います。
こんな感じ。

ヴォーカル部、最初の小節の例
define :v000 do
    play :e4, amp:1, attack: 0, attack_level: 1.0, sustain: 0.1, sustain_level: 0.5, release: 0
    sleep 1
    play :e4, amp:0.3, attack: 0, attack_level: 1.0, sustain: 0.1, sustain_level: 0.5, release: 0
    sleep 1
    play :e4, amp:0.3, attack: 0, attack_level: 1.0, sustain: 0.1, sustain_level: 0.5, release: 0
    sleep 1
    play :e4, attack: 0, attack_level: 1.0, sustain: 0.5, sustain_level: 0.5, release: 0
    sleep 0.5
    play :g4, attack: 0, attack_level: 1.0, sustain: 0.5, sustain_level: 0.5, release: 0
    sleep 0.5
end

amp

音の大きさ。強調したくない音は amp:0.3 ぐらいで。

attack

音が立ち上がるときの長さ。ここでは基本的に attack : 0 として すぐに音が立ち上がるように意識している。

sustain

立ち上がった音が続く長さ。基本的に音符の長さ(拍数)とした。

release

音が減衰していく長さ。ここでは基本的に release : 0 として すぐに音が切れるように意識している。

定義した小節を鳴らす方法

上の例では define :v000 と名前をつけていますが、v001, v002 といった感じで小節番号に対応した名前をつけることにします(小節ごとに音を定義する)。このとき、live_loopの繰り返しごとに 番号をつけた define を実行すればよいわけです。

番号を変数で用意しておき +1 しながら 小節の定義名を作りだすことができそうです。
名前を決めることができたら send で該当する小節の定義を呼び出すことにします。

v_counter = 0
live_loop :vocal, sync: :metro do
    v_name = toName("v", v_counter)
    send v_name  # v_name に入っている名前の定義を呼び出す。
    v_counter += 1
end

ここで、toName メソッドは次のような感じで定義しておく

def toName(prefx, count)
    "#{prefx}#{sprintf('%03d', count)}"
end

実際には 諸事情あって 上記メソッドは少しだけ複雑になりましたが、構想的には上記の感じです。

演奏プログラムのデバッグ

これはひたすら聴くしかないのでがんばりましょう。曲が長いとそれだけデバッグには時間がかかります。
そのため、デバッグ用には Temp (use_bpm)を速くしておくとよいですね。

よく間違える点

sleep の合計 = 4.0 でないと、曲進行中に音がずれていきます。細かい音符の小節のときは 特に注意すること!。
1つの小節の最後の音符の後ろには 必ず sleep をつけて 小節の長さを確保しましょう。

define :p2_007 do
    play [:b2,:e2], attack: 0, attack_level: 0.5, sustain: 1.0, sustain_level: 0.2, release: 0
    sleep 1.0
    sleep 1.0
    play [:b1,:e2,:g2], attack: 0, attack_level: 0.5, sustain: 1.0, sustain_level: 0.2, release: 0
    sleep 1.0
    play [:b1,:fs2,:a2], attack: 0, attack_level: 0.5, sustain: 1.0, sustain_level: 0.2, release: 0
    sleep 1.0
end

上記の例では、sleep 1 が2行続くところがありますが、これは休符(四分休符)がある例です。
image.png

3連符

image.png

sleep 1.0/3 として 調整しましょう。 sustain は 0.3 で良い感じ。

define :v007 do
    play :a4, attack: 0, attack_level: 1.0, sustain: 0.5, sustain_level: 0.5, release: 0
    sleep 0.5
    play :g4, attack: 0, attack_level: 1.0, sustain: 0.5, sustain_level: 0.5, release: 0
    sleep 0.5
    play :g4, attack: 0, attack_level: 1.0, sustain: 0.3, sustain_level: 0.5, release: 0
    sleep 1.0/3
    play :fs4, attack: 0, attack_level: 1.0, sustain: 0.3, sustain_level: 0.5, release: 0
    sleep 1.0/3
    play :e4, attack: 0, attack_level: 1.0, sustain: 0.3, sustain_level: 0.5, release: 0
    sleep 1.0/3
    play :b4, attack: 0, attack_level: 1.0, sustain: 1.5, sustain_level: 0.5, release: 0
    sleep 1.5
    play :ds4, attack: 0, attack_level: 1.5, sustain: 0.5, sustain_level: 0.5, release: 0, amp: 1.5
    sleep 0.5
end

アウフタクト

image.png

4拍目から始まるとき、1拍目~3拍目の音はないのですが、1つの小節として考えると小節の長さは4拍分を確保しておかないといけません。

define :v000 do
    sleep 1
    sleep 1
    sleep 1
    play :e4, attack: 0, attack_level: 1.0, sustain: 0.5, sustain_level: 0.5, release: 0
    sleep 0.5
    play :g4, attack: 0, attack_level: 1.0, sustain: 0.5, sustain_level: 0.5, release: 0
    sleep 0.5
end

実際のコードでは、1拍目~3拍目に 意図的に小さな音を鳴らして拍子をとっています。
これは、「カラオケ」的にしたかったためです。
「演奏」を聴いて楽しみたい!というだけであれば、sleep 1 × 3 で十分です。

曲のキーを変更する

use_transpose -1

上の例では、キーを 1つ下げます。
今回の「ニーナ」の実装では使用していませんが、カラオケとして利用するときは、歌い手さんのキーにあわせることができそうですね。

Github

イタリアの曲で「ニーナ」を作りこんだ。28小節程度の短い曲だが、それなりにコード量(音符量)が多く、それなりに面倒くさく単調な作業が続く。試す気がある方にはもっと短い曲をおすすめする。

ソース例はここ ==> Github

動画

演奏している様子を動画にしてアップしている

動画はここ ==> Youtube

感想

当方は、子ども向けプログラミング教室を運営しているものですが、『SonicPi』は教材としては面白そうだと感じました。課題を10~20程度作って、曲を作りながらプログラミングを学習できそうです。

【特徴】

  • Ruby でコードプログラミングを体験できる
  • 始めるときのハードルはそんなに高くない
  • 簡単に音を鳴らすことができる
  • 曲を演奏できる
  • いろんな音を選べる
  • 音に効果をつけられる
  • それっぽく自作曲を作ることができる

【対象】

音楽に興味がある「生徒さん」が対象になります。興味がないと食いつきが悪いかもしれません。

SonicPi を使った教材集(課題集)を用意していきたいと思います。みんなにプログラミングを楽しんでもらいたいです。

追伸

『曲のキーを変更』することができると書きましたが、live_loop のなかで宣言すると、宣言したlive_loopの中だけがキーが変わります。あとでオクターブをあげたり下げたりしたくなったときに便利です。

こんな感じで書きます

サンプル
############################################
# ヴォーカル部
############################################
v_counter = Start_bar_no
live_loop :vocal, sync: :metro do
    use_synth :piano
    #################################
    # ヴォーカルだけ 1オクターブあげる
    #################################
    use_transpose +12 # <----- 12音で1オクターブ( -12 : マイナスのときは 1オクターブ下がる )
    
    v_name = toName("v", v_counter)
    if v_name == "" then
        stop # live_loop 停止
    else
        send v_name  # <--- ここで v_nameにある名前により defineで定義した演奏を実行します。
    end
    v_counter += 1
end
define の例( 名前を変えて小節ごとに用意しています)
define :v027 do
    play :e4, attack: 0, attack_level: 1.0, sustain: 2.0, sustain_level: 0.5, release: 0
    sleep 2.0
    sleep 1.0
    play :e4, attack: 0, attack_level: 1.0, sustain: 0.5, sustain_level: 0.5, release: 0
    sleep 0.5
    play :g4, attack: 0, attack_level: 1.0, sustain: 0.5, sustain_level: 0.5, release: 0
    sleep 0.5
end
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?