2017年3月2日木曜日

Raspberry Pi と Arduino で楽器作り(6) - python-sonic を使ってみる

python-sonic の使い方を学びます。


1. python-sonic を使う

python-sonic は(4)で紹介した Python で Sonic Pi を動かせるライブラリです。python-sonic に日本語の解説ページはなさそうですが、Sonic Pi ならあったので、基本的には Sonic Pi の使い方を調べて、それに該当する機能が python-sonic で使えるかというのを調べていきました。とりあえずは音が鳴らせて、拍がとれればそれでいいので、まずはそこからです。
Sonic Pi での音の鳴らし方
play 60, attack: 0.1, sustain: 0.1, release: 0.1
play という関数で音が鳴ります。60 という数字が音階を表し、ここではC4 (ド)を表します。そのあとの4つのパラメータは、音がどのようになるかを示しています。attack は音が鳴り始めてから音量MAXになるまでの時間、sustain が音量MAXをキープする時間、release は sustain が終わってから鳴りやむまでの時間だと思っていれば問題ないと思います。
python-sonic での音の鳴らし方
play(60, attack=0.1, sustain=0.1, release=0.1)
似たような関数でならせるみたいですね。基本的にはこんな感じで()でくくっていればなんとかなるように思います。
拍をとる sleep についても似たような感じなので省略します。しばらくは play と sleep だけでやっていくつもりです。

2. 音の割り当て

音の鳴らし方がわかったので音を鳴らすプログラムを書いていきます。距離センサからの距離に応じてドレミファソラシと鳴らせたらいいなと考え、ひたすら if-else 文で分岐しました。ところで、今回使った距離センサGP2Y0A21YK0Fは10 cm~80 cmを検出できるようですが、その電圧は線形ではなく非常に扱いづらいです。適当に品番で検索して出てきた式で線形に戻します。また、ある程度離れると精度も悪くなるので、今回は15 cmから初めて5 cmごとに区切って、15 cm~50 cmで条件分岐をさせました。コード全体は長くなるので省略しますが、以下のような感じです。

if str == 10:
    if note != 0:
        print("-")
        note = 0
    
elif str >= 15 and str < 20:
    play(60, attack=0.1, sustain=0.1, release=0.1)
    if note != 1:
        print("C4")
        note = 1

elif ...
str に距離を入れてます。 Arduino 側で15 より小さいときはすべて10と出力するようにしているので上のような分岐になってます。play 中のASRの値は、連続で鳴らしてもブツブツ切れて聴こえないように適当に調節しました。print しているのは演奏した音で、ターミナル上で鳴らした音がなんなのかわかるようにしています。連続で同じ音符がドド~っとでないようにif文で調整してます。if文のあとに sleep(0.1) で即音が鳴らないようにしてます。
なんかもうちょっと綺麗に書けたらなーと思うんですが思いつきませんでした。

3. 音を安定させる

上ので音はちゃんと鳴るんですけど、境界のところに手を置くと0.1秒ごとに切り替わったりしてせわしないです。音が安定するように、「0.1秒で10回センサを読んで、その中央値をとる」ようにコードを書き換えました(効果があるかは不明、あったほうがましな気がする)。

import numpy as np
...
notelist = []        #initialize to calc med            
i = 0
for i in range(10):    
    ser.write(b'R')    
    ser_input = ser.readline()
    ser_input = ser_input.strip()
    ser_input = int(ser_input)        
    notelist.append(ser_input)

str = int(np.median(notelist))
...
numpy という計算用のライブラリをわざわざ使っています。リストを作って10個どんどん追加していってその中央値を str に代入する、という流れです。
実装がC5のドまで鳴るようになっててちょっと違いますが、こんな感じの音が鳴ります。手があんまし映ってなくて意味不明ですが動かして鳴らしてます。レゴで Arduino をカバーしてますが気にしないでください。
かなり楽器っぽくなってきました。でもまだ「ドレミファソラシ」の7音しか鳴らせないので、もっと鳴らせるようにしたいですね。でもこれ以上距離をとるわけにもいかないし……というところを工夫していきます。

参考
GitHub - gkvoelkl python-sonic python-sonic 作成者様による解説なので一番良いです。英語だけど。
たぶん公式の Sonic Pi 説明書

0 件のコメント:

コメントを投稿