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 ...
なんかもうちょっと綺麗に書けたらなーと思うんですが思いつきませんでした。
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)) ...
実装がC5のドまで鳴るようになっててちょっと違いますが、こんな感じの音が鳴ります。手があんまし映ってなくて意味不明ですが動かして鳴らしてます。レゴで Arduino をカバーしてますが気にしないでください。やっと音階がきれいに出せた pic.twitter.com/24h00fCCkH— 高砂 (@takasa_five) 2017年2月25日
かなり楽器っぽくなってきました。でもまだ「ドレミファソラシ」の7音しか鳴らせないので、もっと鳴らせるようにしたいですね。でもこれ以上距離をとるわけにもいかないし……というところを工夫していきます。
参考
GitHub - gkvoelkl python-sonic python-sonic 作成者様による解説なので一番良いです。英語だけど。
たぶん公式の Sonic Pi 説明書
0 件のコメント:
コメントを投稿