【脳波測定】Pythonライブコーディングで集中力を音でフィードバックするシステム

#[MA2018にも応募・展示しています。](https://protopedia.net/prototype/ef2a4be5473ab0b3cc286e67b1f59f44)
FESTA会場で、脳波測定デモやります。
youtubeに[ビデオプロトタイプ](https://www.youtube.com/watch?v=E8MrO2ptmUw)もありますので、こちらも見ていってください。
#注意
この記事のプログラムはPython2です。
#動機
自分の集中力の度合いを脳波から知ることができることを知り、測ってみたいと思ったことがきっかけ。
python2.7系はあまり触ったことがなかったので、こちらのリンクを参考にしました。
[MindWaveからPythonを使って脳波の値を取得し、好きなプログラムで利用する方法 - Ambivalent Wanderer](http://mikenerian.hatenablog.com/entry/2017/12/18/222633)
#使用する脳波センサ
[Amazon | NeuroSky社製 MindWave Mobile 2 脳波センシングヘッドセット ［Brainwave Starter Kit］［型番80027-032］[正規輸入品] | 脳トレ・学習ゲーム | ホビー](https://www.amazon.co.jp/NeuroSky%E7%A4%BE%E8%A3%BD-MindWave-Mobile-%E8%84%B3%E6%B3%A2%E3%82%BB%E3%83%B3%E3%82%B7%E3%83%B3%E3%82%B0%E3%83%98%E3%83%83%E3%83%89%E3%82%BB%E3%83%83%E3%83%88-Kit%EF%BC%BD%EF%BC%BB%E5%9E%8B%E7%95%AA80027-032%EF%BC%BD/dp/B07D72LGLQ/ref=pd_lpo_sbs_21_t_0/355-4455552-9686014?_encoding=UTF8&psc=1&refRID=3SW96BJ161SCPRQ0J5Y7)
![images.jpeg](https://qiita-image-store.s3.amazonaws.com/0/285932/6e8fcc6b-2531-1bca-9526-cc81fe18725f.jpeg)
・[NeuroSky社](http://neurosky.com)が開発した脳波センサ
・α波、β波、θ波、γ波などの波形が一通り取れる。
・独自のアルゴリズムで、**集中度(attention)、瞑想度(meditation)**を取得できる。
#使用する開発環境
Python2.7系
専用のライブラリであるthinkgearをpip2でインストール
Bluetooth
#セットアップ
基本的に、mindwaveに付属している説明書の手順に沿えば、MacでもWindowsでもiOSでもAndroidでも接続することはできます。

PCの場合、ThinkGearConnectorというアプリがプラットフォームになっているようです。

脳波の値は、Bluetoothによるシリアル通信でまずここで取得され、他のアプリへと送信されます。

その値をpython2で処理するためにthinkgearライブラリを導入。

ちなみに、python3でも同様のライブラリが存在しますが、ストリングエラーを解決した上で実際に動かしてみても、脳波の値を取得できませんでした。ライブラリそのものが古くて、最新のPython3系に対応できていないのかもしれません。

```
$ pip2 install thinkgear
```
と入力してthinkgearライブラリをMacにインストール
次に、

```
$ ls /dev/tty.*
```
と入力して、Bluetooth接続されている機器一覧を取得。

その中から、tty.MindWave~となっている値をコピペして、次のプログラムで脳波の値を取得します。

```python:mind.py
import thinkgear

PORT = '/dev/tty.MindWaveMobile-SerialPo'
for packets in thinkgear.ThinkGearProtocol(PORT).get_packets():
    for p in packets:
        if isinstance(p, thinkgear.ThinkGearRawWaveData):
            continue
        print p
```

#パッケージの内容変更
```python:thinkgear.py

import sys

import serial

import StringIO

import struct

from collections import namedtuple

import logging
import logging.handlers

##中略

class ThinkGearPoorSignalData(ThinkGearData):
    '''POOR_SIGNAL Quality (0-255)'''
    code = 0x02
    _strfmt = 'POOR SIGNAL: %(value)s'
    _decode = staticmethod(ord)


class ThinkGearAttentionData(ThinkGearData):
    '''ATTENTION eSense (0 to 100)'''
    code = 0x04
    _strfmt = 'ATTENTION eSense: %(value)s'
    _decode = staticmethod(ord)


class ThinkGearMeditationData(ThinkGearData):
    '''MEDITATION eSense (0 to 100)'''
    code = 0x05
    _strfmt = 'MEDITATION eSense: %(value)s'
    _decode = staticmethod(ord)


class ThinkGearRawWaveData(ThinkGearData):
    '''RAW Wave Value (-32768 to 32767)'''
    code = 0x80
    _strfmt = 'Raw Wave: %(value)s'
    _decode = staticmethod(lambda v: struct.unpack('>h', v)[0])
    # There are lots of these, don't log them by default
    _log = False


EEGPowerData = namedtuple('EEGPowerData', 'delta theta lowalpha highalpha lowbeta highbeta lowgamma midgamma')
class ThinkGearEEGPowerData(ThinkGearData):
    '''Eight EEG band power values (0 to 16777215).
    
    delta, theta, low-alpha high-alpha, low-beta, high-beta, low-gamma, and
    mid-gamma EEG band power values.
    '''

    code = 0x83
    _strfmt = 'ASIC EEG Power: %(value)r'
    _decode = staticmethod(lambda v: EEGPowerData(*struct.unpack('>8L', ''.join( '\x00'+v[o:o+3] for o in xrange(0, 24, 3)))))


def main():
    global packet_log
    packet_log = []
    logging.basicConfig(level=logging.DEBUG)

    for pkt in ThinkGearProtocol('/dev/rfcomm9').get_packets():
        packet_log.append(pkt)

if __name__ == '__main__':
    main()

```

今回は、ATTENTIONとMEDITATIONの出力を、冒頭の数値が1か2かによって分類するプログラムを作成したので、それぞれ以下のようにしました。

```python:
ATTENTION: _strfmt = '1%(value)s'

MEDITATION: _strfmt = '2%(value)s'

#その他のパラメータ
_strfmt = ''

```
今回は、音で集中力を知ることができるシステムを制作するために、thinkgear同様、pipからsynthesizerライブラリをインストールして、脳波を楽器にする。

```python:neurobot.py
#coding:utf-8
#タイマーかけて、1分間で何回100に到達できるかを競っても面白い。
import thinkgear
from synthesizer import Player, Synthesizer, Waveform

# オーディオデバイス出力用クラス
player = Player()
# 引数を指定しなければデフォルトの出力デバイスが選択されます
player.open_stream()
synth = Synthesizer(osc1_waveform=Waveform.sine, osc1_volume=1.0, use_osc2=False)


attention = 0
meditation = 0

PORT = '/dev/tty.MindWaveMobile-SerialPo'

for packets in thinkgear.ThinkGearProtocol(PORT).get_packets():
	for pkt in packets:
		if isinstance(pkt, thinkgear.ThinkGearRawWaveData):
			continue

		t = str(pkt)

		if t != '':
			differencer = t[0:1]
			if int(differencer) == 1:
				attention = t[1:]
			#if int(differencer) == 2:
			#	meditation = t[1:]

		if int(attention) == 0:# or int(meditation) == 0:
			continue
		print "attention", attention
		#print "meditation", meditation

		attention = int(attention)
		#meditation = float(meditation)
		player.play_wave(synth.generate_constant_wave((attention * 5), 0.1))
```
# 集中したら音が高くなっていきます！

**脳波を音に翻訳して、あなただけの音を鳴らしてみましょう！**
どんな時に音が高くなるのかいろいろ試してみようと思います。

この他にも、脳波を使えば、こんなこともできるようですね。究極のデバイス、究極のインターフェースになるかも⁉︎
[「脳波でうごくVTuber」の作り方 - Qiita](https://qiita.com/Fujitsu_IncubationCenter/items/111223ddbe01a23f9d68)