Flaskで声質（Voice Quality）を測定するWebアプリを作ってみた

## 声質測定アプリ概要
音声分析にはフリーソフトウェア「**Praat**」が超有能で便利。声の高さ・強さなど、なんでも分析できる。
しかし、デスクトップでしか起動しないためローカルでしか使えないし、専門的なのでGUIでも使うの大変。
「けど誰もが自分の声の特徴をパッと知ることができれば面白いのでは？」と思ったのがことの始まり。
なので、声質の測定ができるWebアプリ「**Voice QUality**」を開発して、ブラウザで使用できるところまで漕ぎ着けてみた。

## Voice Qualityの使い方
### 1.wavファイルを作る
母音「あ」一発分の声を吹き込む（画面はPraat）
![代替テキスト](https://sound-upload-bucket.s3.ap-northeast-1.amazonaws.com/praat.png)
### 2.画面を開く
![代替テキスト](https://sound-upload-bucket.s3.ap-northeast-1.amazonaws.com/index.jpeg)
### 3.wavファイルを選択してアップロード
![代替テキスト](https://sound-upload-bucket.s3.ap-northeast-1.amazonaws.com/upload.jpeg)
### 4.結果表示
この場合はmodal
![代替テキスト](https://sound-upload-bucket.s3.ap-northeast-1.amazonaws.com/modal.jpeg)

breatyhならこんな感じ
SpectralTiltがかなり高く、Pitchが出ておらず、HNRが低い。
![代替テキスト](https://sound-upload-bucket.s3.ap-northeast-1.amazonaws.com/breatyh.jpeg)

creakyはこう
SpectralTiltがマイナス！
![代替テキスト](https://sound-upload-bucket.s3.ap-northeast-1.amazonaws.com/creaky.jpeg)

## ざっくり声質
1.**声質でわかること**
* 声の高さ
* 声の安定度
* 声のクリアさ
* 発声タイプ=喉の状態
通常時（modal）：喉や発声に異常がない
気息声（breathy）：息（ノイズ）が多めに混ざっている声（カスカスなイメージ）
力み声（creaky）：緊張しい、力んでいる声

2.**パラメータ**
* 母音の長さ（Vowel Duration）
* 高さ（Pitch）
* 第１フォルマント
口の開き方と母音の判定に役立つ。
* 第２フォルマント
舌の位置と母音の判定に役立つ。
* スペクトル傾斜
発声（声質のメインポイント）がわかる。マイナスだと力み声、プラスだと通常時だが増加すると気息声。
* HNR
声にどれだけ息が混じっているか。7.0dbを下回るとbreathy。
* シマー
声の高さの安定感。値が高いほど不安定。
* ジッター
出し方の安定感。値が高いほど声がぶれている。

確かに、modalと比べてシマー＆ジッターは値が高い！

## 何に役立つか？
* イケボ診断
* ボイトレ活用
* ボーカリスト/声優/アナウンサーの喉のケア
* 喉の病気や認知症の早期発見
* 患者の治療後の経過観察

## 今後の課題
* アーキテクチャの見直し
* クソダサUIの改善
* ロジックの修正
* UX向上のため、診断結果がユーザにわかりやすいように修正

# ここからは備忘録として開発フロー

## 開発環境
* Python
* Parselmouth 
Praatの機能を詰め込んだ素敵な外部ライブラリ！
* Flask
Webアプリ開発のフレームワーク。迅速な開発を目指してTemplate（画面）とView（バックエンド）しか用意していない。Model（DB)は後付けできる。個人的にこの思想は好き。
* AWS EC2, VPN 
お決まりのクラウド。

## 開発手順
1. FlaskでTemplateとViewを作成する
1. Gitにアップロードする
1. EC2インスタンスとVPCを作成する
1. Gitからデプロイ。
1. 仮想環境上で実行

## 実装
### FlaskでTemplateとViewを作成する
* TemplateはHTMLで音声フォルダのアップロード画面とパラメータ結果出力画面を作る（省略）。
* Viewにはバックエンド側の実装。音声処理はPraatの機能をパッケージ化したParselmouthをライブラリとして組み込む。
一部の機能の実例。ちゃんとFlask用のライブラリも組み込むのを忘れない。

```python:views.py
import parselmouth
from parselmouth.praat import call

# 音声ファイルを parselmouth.Sound で処理する
file = 'XXXX.wav'
soundID = parselmouth.Sound(file)
# ピッチを取得    
pitchID = call(soundID, "To Pitch", 0.0, 60, 250)
f0 = round(call(pitchID, "Get value at time", mid , "Hertz", "Linear"), 2)
# フォルマントを取得
formantID = call(soundID, "To Formant (burg)", 0.0, 5, 5500, 0.025, 50)

# 中間時間におけるフォルマントの値を取得
f1 = round(call(formantID, "Get value at time", 1, mid, "Hertz", "Linear"), 2)
f2 = round(call(formantID, "Get value at time", 2, mid, "Hertz", "Linear"),2)

```

### Gitからデプロイ
もろもろの設定後はコマンド打つだけ
```terminal:git clone
sudo git clone https://github.com/××××××××/××××××××
# この後、ユーザ名とPWが求められる。PWにはgithubのPWではなく、githubで生成するトークンを入れる。
```
### 仮想環境上で実行
* EC2でFlaskを仮想環境上で動かす。
* その後、起動ファイルを走らせたら出来上がり。
* EC2で動かしているので、EC2のIPアドレス+5000でブラウザからログインする。

```python
# 仮想環境を作る
[ec2-user@IPアドレス 実行ディレクトリ]$ python pipenv
[ec2-user@IPアドレス 実行ディレクトリ]$ pipenv shell
# 仮想環境に入れるので、起動ファイルを動かして組み込みサーバをたてる
(仮想環境) [ec2-user@IPアドレス 実行ディレクトリ]$ python server.py
# サーバのIPアドレスが出たら成功
    Running on http://127.0.0.1:5000
```
## リファレンス
* Praat
[Praat: doing phonetics by computer](https://www.fon.hum.uva.nl/praat/)
* Parselmouth
[parselmouth](https://parselmouth.readthedocs.io/en/stable/index.html)