「Arduino NanoでZockの起動時の音とモノアイの動きの再現」の復習。
まずは、上で参考にさせていたサイトの例を見て手順をなぞりながら何をやっているのかを考える。
Windows10 Pro 64BIT
Audacity 2.3.0
参考「Audacityでmp3を編集する」
VMware Workstation 15 Player 15.0.2
ubuntu 18.04.1
VMwareでubuntuは以下を参照のこと。
「Windows10 + VMware Workstation Player + Ubuntu – インストール –」
「VMware Tools をインストールする。」
Arduino IDE 1.8.8
Arduino Nano Clone
Speaker
Audacityで音声ファイルを開いてステレオならモノラル化する。
データのサンプリング周波数を16kHz(上の参考サイトでは8kHz)に変更する。
ファイルに出力する。
この時の設定は以下の通り。
Other uncompressed files
Header:RAW(header-less)
Encoding:Unsigned 8-bit PCM
このファイルを仮に「konbanwa.raw」とする。
Ubuntuでターミナルを起動([Ctrl]+[Alt]+[T])して
xxd -i konbanwa.raw
と実行すればデータ形式でテキストが出力される。
xxd -i konbanwa.raw konbanwa.c
とかすればファイルに出力されるのでこの方がいいかも。
さて、ここからはスケッチの分析だ。
1 2 3 4 5 6 7 8 |
void setup() { pinMode(3, OUTPUT); TCCR2A = _BV(COM2B1) | _BV(WGM21) | _BV(WGM20); TCCR2B = _BV(CS20); play(); } |
pinMode(3, OUTPUT); はいいとして、それに続く
TCCR2A = _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
TCCR2B = _BV(CS20);
は全然わからない。
まず、
1 |
#define _BV(bit) (1 << (bit)) |
とのことで、例えば _BV(COM2B1) は 1 << COM2B1 と書き換えられる。 COM2B1、WGM21、WGM20はこの順にTCCR2A(Timer/Counter Control Resister A)の5、1、0ビット目を表すので、
1 2 |
TCCR2A = 1<<COM2B1 | 1<<WGM21 | 1<<WGM20; TCCR2A = 1<<5 | 1<<1 | 1<<0; |
と書き換えられる。
例えば1行目では COM2B1、WGM21、WGM20を1にセットしているってことらしく、結局のところ
TCCR2A = 0b00100011
同様に
TCCR2B = 0b00000001
ってことになる。
ここからはATmega328Pのデータシートを読む。
CS22、CS21、CS20はクロックを選択し、0b001 なので分周比1となる。
16000000 ÷ 1 ÷ 256 = 62500Hz
COM2B1、COM2B0はD3のPWM制御を決め、0b10 なのでタイマとOCR2Bとの比較でHighかLowかを出力する。
WGM22、WGM21、WGM20は波形の制御で、0b011 なのでFast PWMモードになる。
Fast PWMモードには2種類あるが、ここでのモードの場合は0x00~0xFFまでをカウントする設定だ。
0b111の場合には0x00~OCR2Aの値までをカウントする設定。
なお、FOC2A、FOC2BはanalogWrite()では使ってないのだそうだ。
COM2A1、COM2A0はD11の制御用なので、D3を使う今回の例では使っていない。
で、やっと、下が実際に音を出すための処理の部分だ。
1 2 3 4 5 6 |
void play() { for (int i = 0; i < sample_raw_len; i++) { OCR2B = pgm_read_byte_near(&sample_raw[i]); delayMicroseconds(125); } } |
OCR2Bの値との比較でON/OFFの時間が決まるのでこれをデータから読み込んで代入している。
125usのdelayは、上の参考サイトでの音のデータのサンプリング周波数の8kHzに合わせて決められている。
1 ÷ 8000Hz = 0.000125s = 125us
うちでは少し変更して、Timer1の割り込みで周波数を決めてOCR2Bの値を変更している。
サンプリング周波数も16kHzにしてある。
前回は機械音だったが、人の声はどうだろうということで、試してみた。
性別も言ってる内容も聞き取れるので、そこそこ使い物になると思う。
容量的には、この音質ならだいたい倍の長さまでは入れることが出来る。
PICでもやってみた。
「PIC32MM0064GPL028にスピーカーをつないで音声を鳴らす。」
関連記事
「Arduino NanoでZockの起動時の音とモノアイの動きの再現」
「ArduinoのPROGMEMにデータを置いてPWMで音声を鳴らす。」