Arduinoにしゃべらせてみたトレース＆PCMデータの作り方

この記事は[IoTLT Advent Calendar 2016](http://qiita.com/advent-calendar/2016/iotlt)の14日目の記事です。

昨日は @narikei さんの[Electronで作ったデスクトップアプリとArduinoでシリアル通信して遊ぼう](http://qiita.com/narikei/items/d9470ec1f6d6ec6d7d05)でした。

---

はじめに（と言い訳）
---

今回、はやしよのすけさんの[【冬休みの工作】Arduinoをしゃべらせてみた](http://ameblo.jp/aretaumitohirunosunahama/entry-11442063598.html)をトレースしつつ、Arduinoを単体でWebAPIサーバにしてAPI叩くとしゃべるオモチャを作ろうと思っていました。

が、結局間に合わなかったのでArduinoをしゃべらせるためのPCMデータのカンタンな作り方解説にしたいと思います。

とりあえず作ったもの
---

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Arduino nanoと圧電スピーカーだけでしゃべらせてみた。 <a href="https://twitter.com/hashtag/arduino?src=hash">#arduino</a> <a href="https://t.co/G1ZQawtmSp">pic.twitter.com/G1ZQawtmSp</a></p>&mdash; 写真屋？＠ゲムマJ28 (@moomooya) <a href="https://twitter.com/moomooya/status/808723141694369792">2016年12月13日</a></blockquote> <script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

「がんばるぞい」

作り方
---

基本的には[【冬休みの工作】Arduinoをしゃべらせてみた](http://ameblo.jp/aretaumitohirunosunahama/entry-11442063598.html)のままです。

```cpp:zoi.ino
#include <avr/pgmspace.h>

// prog_ucharだと上手く行かなかったので、const unsigned charにした
const unsigned char VOICE[] PROGMEM ={
82,73,70,70,7,64,0,0,87,65,86,69,102,109,116,32,
16,0,0,0,1,0,1,0,64,31,0,0,64,31,0,0,
1,0,8,0,100,97,116,97,227,63,0,0,128,127,127,127,

// 中略、ここを作るのがめんどい

131,133,129,122,125,128,127,127,127,127,128,128,127,127,127,127,
127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,127,
127,127,127,127,127,127,127,127,127,127,127,127,127,127,127
};

void setup() {
  pinMode( 3,OUTPUT);
  TCCR2A = 0b00100011;
  TCCR2B = 0b00011001; 
  OCR2A = 255;
  OCR2B = 0;

  for(int i=0; i<16399; i++){ // ココはVOICE[]の要素数にあわせる
    OCR2B = pgm_read_byte_near(&VOICE[i]);
    delayMicroseconds(125);
  }
}

void loop() {
}
```

`VOICE[]`には8bit/8kHzのPCMデータを格納します。

今回はコレの作り方を中心に説明。

PCMデータの作り方
---

1. 適当に音声データを用意
    * UnoとかNanoのATmega328搭載のArduinoだとFlashROMが32kBなので約4秒まで
2. Audacityとかで以下の設定＆Microsoft PCM形式のwavファイルにして保存
    * 1ch(モノラル)
    * サンプリング周波数8kHz
    * サンプリングレート8bit
3. wavファイルをコマンドラインで1バイトごとのunsigned型で表示する

### wavファイルをコマンドラインで1バイトごとのunsigned型で表示する

ワンライナーが得意な方はコマンド一発で変換してしまってください。macOSでも使えるいいワンライナーが出来たら教えてください。

```bash
$ od -tu1 -An zoi.wav | perl -ple 's/^\s+//g' | perl -ple 's/\s+/ /g' > zoi.txt
```

でこんな感じのデータを出力する。

```:zoi.txt
82 73 70 70 7 64 0 0 87 65 86 69 102 109 116 32
16 0 0 0 1 0 1 0 64 31 0 0 64 31 0 0
1 0 8 0 100 97 116 97 227 63 0 0 128 127 127 127
128 128 127 127 128 128 127 127 128 128 127 127 128 128 127 127
128 128 127 127 128 128 128 128 128 128 128 128 129 128 128 127
128 128 128 128 128 128 128 128 127 128 127 127 127 128 127 127
127 128 127 127 127 127 127 127 127 127 127 127 127 127 126 127
127 127 127 127 127 128 127 127 127 127 128 127 127 127 127 128
128 127 127 128 128 128 128 128 128 128 128 128 128 128 128 128
128 127 128 128 128 128 128 128 128 128 127 127 128 128 127 127
127 128 127 127 127 127 127 127 127 127 127 127 127 127 127 127
(以下略)
```

空白と行末をカンマに置換して

```:zoi.txt
82,73,70,70,7,64,0,0,87,65,86,69,102,109,116,32,
16,0,0,0,1,0,1,0,64,31,0,0,64,31,0,0,
1,0,8,0,100,97,116,97,227,63,0,0,128,127,127,127,
128,128,127,127,128,128,127,127,128,128,127,127,128,128,127,127,
128,128,127,127,128,128,128,128,128,128,128,128,129,128,128,127,
128,128,128,128,128,128,128,128,127,128,127,127,127,128,127,127,
127,128,127,127,127,127,127,127,127,127,127,127,127,127,126,127,
(中略)
127,127,127,127,127,127,127,127,127,127,127,127,127,127,127
```

これで先述の`VOICE[]`の初期化に使えるようになりました。

あとは好きなようにしゃべらせましょう。

（IoTのI成分がない記事になってしまった……）

ちなみに回し者ではないですが、別の機会にボイス素材作る方法を検討していたときに[ココナラ](https://coconala.com/search/recommend?service_class=0&keyword=&parent_category_id=10&category_id=215&price_min=0&price_max=&delivery_average=)でわりと低価格でボイス素材の収録をお願いできそうな感じでした。ご参考までに。

---

明日は @iwata-n@github さんの[マインクラフトのTNTを現実世界から爆発させてみる（Wio Nodeを使います）](http://developers.gnavi.co.jp/entry/wionode-minecraft)です。