Raspberry Piでアナログシンセを制御する (1)CUI編

## 概要
* メイカーイベントの出展物として、音楽をテーマにしたものをつくりたいと思った。
* アナログシンセサイザー（ドラムマシン）の制御にRaspbery Piが使用できないかと考えた。 
* 回路図を探し、トランジスタ技術のバックナンバーに掲載の回路を使うこととした。

※アナログシンセサイザーとは？
　電子部品の特性を利用し、音声信号を合成することで音色を出力する電子楽器。
　1970年代の音楽で良く使われていたが、現在も当時の機材からサンプリングされた音が使われており、独特の魅力、音色から愛好家も多い。

電源部とバスドラムの回路をつくり、スイッチでテストしている様子
![スクリーンショット 2021-03-23 8.24.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701445/f9e4a3ce-2bdf-228a-fd79-d4967121e328.png)

他のパートも交えRaspberry Piと接続している様子
![19667890_1494514477271382_4849948105847660650_o.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701445/45fea560-fe12-8766-76a5-14018aa7f019.jpeg)

シーケンサーを開発している様子
![19488955_1494515827271247_4695634475758483470_o.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701445/5a3e14d0-db98-4878-8272-88c66ccbbf50.jpeg)

## 用意するもの
* Raspberry Pi3 Model B (4でもおそらく大丈夫)
* Raspberry Pi3 Model B B+ 対応 電源セット(5V 3.0A)
* トランジスタ技術 2016年2月号
* 必要な電子部品類
* ブレッドボード、ジャンパーワイヤ 
* DC9V 1.3A ACアダプター
* アンプ内蔵PCスピーカー（できればウーファー付き）

## 環境構築
* Raspberry PiのOSをセットアップし、I2Cを有効化する  
https://www.raspberrypi.org/downloads/  
https://www.indoorcorgielec.com/resources/raspberry-pi/raspberry-pi-i2c/  

## 組み立て
* トランジスタ技術 2016年2月号 P194〜P203の回路を参考にブレッドボード上に回路を作成する  
※著作物のため掲載は控えます

## プログラミング
* ボタンスイッチで発音する状態まで回路を組み上げ、Raspberry Piと接続する。
* ドラムマシンの5つのパートに対応し、発音するか否かを0と1で表したcsvファイルを用意しておく。  
* 起動時に引数で指定したcsvファイルを1行づつ読み込み、該当するGPIOピンを制御する。(3.3V/0V)
* ボタンスイッチに繋がる回路を、引数で指定したbpmでシーケンス制御できる

メインプログラム

```Python:/home/pi/sequencer.py
import RPi.GPIO as GPIO

import time

import csv

import sys

argvs = sys.argv


PIN0 = 11

PIN1 = 12

PIN2 = 13

PIN3 = 15

PIN4 = 16


PTN0 = []

PTN1 = [PIN0]

PTN2 = [PIN1]

PTN3 = [PIN0,PIN1]

PTN4 = [PIN2]

PTN5 = [PIN0,PIN2]

PTN6 = [PIN1,PIN2]

PTN7 = [PIN0,PIN1,PIN2]

PTN8 = [PIN3]

PTN9 = [PIN0,PIN3]

PTN10 = [PIN1,PIN3]

PTN11 = [PIN0,PIN1,PIN3]

PTN12 = [PIN2,PIN3]

PTN13 = [PIN0,PIN2,PIN3]

PTN14 = [PIN1,PIN2,PIN3]

PTN15 = [PIN0,PIN1,PIN2,PIN3]

PTN16 = [PIN4]

PTN17 = [PIN0,PIN4]

PTN18 = [PIN1,PIN4]

PTN19 = [PIN0,PIN1,PIN4]

PTN20 = [PIN2,PIN4]

PTN21 = [PIN0,PIN2,PIN4]

PTN22 = [PIN1,PIN2,PIN4]

PTN23 = [PIN0,PIN1,PIN2,PIN4]

PTN24 = [PIN3,PIN4]

PTN25 = [PIN0,PIN3,PIN4]

PTN26 = [PIN1,PIN3,PIN4]

PTN27 = [PIN0,PIN1,PIN3,PIN4]

PTN28 = [PIN2,PIN3,PIN4]

PTN29 = [PIN0,PIN2,PIN3,PIN4]

PTN30 = [PIN1,PIN2,PIN3,PIN4]

PTN31 = [PIN0,PIN1,PIN2,PIN3,PIN4]



PTNNM = [PTN0,PTN1,PTN2,PTN3,PTN4,PTN5,PTN6,PTN7,PTN8,PTN9,PTN10,PTN11,PTN12,PTN13,PTN14,PTN15

,PTN16,PTN17,PTN18,PTN19,PTN20,PTN21,PTN22,PTN23,PTN24,PTN25,PTN26,PTN27,PTN28,PTN29,PTN30,PTN31]

GPIO.setmode(GPIO.BOARD)

GPIO.setup(PTN0,GPIO.OUT)

GPIO.setup(PTN1,GPIO.OUT)

GPIO.setup(PTN2,GPIO.OUT)

GPIO.setup(PTN3,GPIO.OUT)

GPIO.setup(PTN4,GPIO.OUT)

GPIO.setup(PTN5,GPIO.OUT)

GPIO.setup(PTN6,GPIO.OUT)

GPIO.setup(PTN7,GPIO.OUT)

GPIO.setup(PTN8,GPIO.OUT)

GPIO.setup(PTN9,GPIO.OUT)

GPIO.setup(PTN10,GPIO.OUT)

GPIO.setup(PTN11,GPIO.OUT)

GPIO.setup(PTN12,GPIO.OUT)

GPIO.setup(PTN13,GPIO.OUT)

GPIO.setup(PTN14,GPIO.OUT)

GPIO.setup(PTN15,GPIO.OUT)

GPIO.setup(PTN16,GPIO.OUT)

GPIO.setup(PTN17,GPIO.OUT)

GPIO.setup(PTN18,GPIO.OUT)

GPIO.setup(PTN19,GPIO.OUT)

GPIO.setup(PTN20,GPIO.OUT)

GPIO.setup(PTN21,GPIO.OUT)

GPIO.setup(PTN22,GPIO.OUT)

GPIO.setup(PTN23,GPIO.OUT)

GPIO.setup(PTN24,GPIO.OUT)

GPIO.setup(PTN25,GPIO.OUT)

GPIO.setup(PTN26,GPIO.OUT)

GPIO.setup(PTN27,GPIO.OUT)

GPIO.setup(PTN28,GPIO.OUT)

GPIO.setup(PTN29,GPIO.OUT)

GPIO.setup(PTN30,GPIO.OUT)

GPIO.setup(PTN31,GPIO.OUT)

CsvFile = csv.reader(open(argvs[1]),delimiter=',')

bpm = int(argvs[2])

repeat = int(argvs[3])

def main():

    wait = 60 / float(bpm) * 0.25 -0.01

    print('BPM' + str(bpm))

    line = []

    for i in CsvFile:

        line.append(i)

    for rep in range(repeat):

        for cnt in range(len(line)):

            PTNNO = 0

            instct = len(line[0])

            for instno in range(instct):

                PTNNO += int(line[cnt][instno]) * int(pow(2,instno))

            print(line[cnt])

            GPIO.output(PTNNM[PTNNO],True)

            time.sleep(0.01)

            GPIO.output(PTNNM[PTNNO],False)

            time.sleep(wait)

    GPIO.cleanup()

if __name__ == '__main__':

    main()
```

CSVファイルの例(8ビート)

```sh:/home/pi/8beat.csv 
1,0,0,0,1
0,0,0,0,0
0,0,0,0,0
0,0,0,0,0
0,1,1,0,0
0,0,0,0,0
0,0,1,0,0
0,0,0,0,0
1,0,1,0,0
0,0,0,0,0
1,0,1,0,0
0,0,0,0,0
0,1,1,0,0
0,0,0,0,0
0,0,1,0,0
0,0,0,0,0
1,0,1,0,0
0,0,0,0,0
0,0,1,0,0
0,0,0,0,0
0,1,1,0,0
0,0,0,0,0
0,0,1,0,0
0,0,0,0,0
1,0,1,0,0
0,0,0,0,0
1,0,1,0,0
0,0,0,0,0
0,1,1,0,0
0,0,0,0,0
0,0,1,0,0
0,0,0,0,0
```

## 注意点
* 特に電源回路を組み上げる際はショートに気をつけること。
* ICは複数のパートで使いまわしている。仕様はネットで検索し事前に把握しておくこと。

## 出展してみて
* 想像以上にアナログシンセサイザーに興味を持ってくださる方が多くいた。
* 数千円の安価なウーファー付きPCスピーカーでも十分な音量が出た。
* TkinterでGUIを作成し、分かりやすくCSVファイルを作成、保存、BPMの変更ができるようにした。  
→次記事に掲載する。