sound with arduino

arduinoで音を制御(録音, 再生etc)したい時用の個人的まとめです.

最終的には録音/再生ができるようにしています.

setting_rec-play.jpg

1. 再生

1-1. mp3を再生する

SDカードにmp3の音源を入れ, moduleを使用して再生します.

  • 良: moduleのおかげで簡単に再生できる
  • 悪: moduleが必要
  • 悪: 用意した音源しか再生できない

参照

『FN-M16P(DFPlayer Mini)』電子工作で音楽(MP3)を鳴らすなら、これ。Arduinoから制御もできるよ。

使用したmodule

FN-M16P Embedded MP3 Audio Module(DFPlayer Mini)

code

//『 FN-M16P Embedded MP3 Audio Module 』(DFPlayer Mini)のテスト。
//start(pin8)で再生start、next(pin9)で次の曲、stop(pin10)で停止
//シリアルコマンドを送る試験


#include <SoftwareSerial.h>

#define start 8        // 置き換え(start→ ”8”)
#define next 9        // 置き換え(next→ ”9”)
#define stop 10       // 置き換え(stop→ ”10”)
#define play 11       // 置き換え(play→ ”11”)

int s1=0,s2=0,s3=0,s4=0;

void setup() {
  Serial.begin (9600);    //シリアルポートを開き、転送速度を9600bpsに設定
  delay(1);                     // delay 1ms to set volume
  pinMode(start,INPUT);   // start(ピン8)を入力に設定
  pinMode(next,INPUT);    // next(ピン9)を入力に設定
  pinMode(stop,INPUT);    // next(ピン10)を入力に設定
  pinMode(play,INPUT);    // next(ピン10)を入力に設定
  //pinMode(13,OUTPUT);   // 13を出力に設定
}

void loop(){
  s1=digitalRead(start);
  if(s1==0){        // startが押されるまで待つ
    //ファイル指定再生
    Serial.write(0x7E);
    Serial.write(0xFF);
    Serial.write(0x06);
    Serial.write(0x0F);  //「フォルダ指定再生」コマンド
    Serial.write(0x00);
    Serial.write(2);  //この例では、「02」というFOLDER名が指定される
    Serial.write(1);  //この例では、「001.mp3」というファイル名のmp3が指定される
    Serial.write(0xEF);
    delay(10);
    while(1){
      s2=digitalRead(next);
      s3=digitalRead(stop);
      s4=digitalRead(play);
      if(s4==0){        // playが押されるまで待つ
        delay(100);
        Serial.write(0x7E);
        Serial.write(0xFF);
        Serial.write(0x06);
        Serial.write(0x0D); //再生コマンド
        Serial.write(0x00);
        Serial.write(0x00); //
        Serial.write(0x00); //
        Serial.write(0xEF);
        delay(100);
      }
      if(s2==0){        // nextが押されるまで待つ
        //次の曲へ
        delay(100);
        Serial.write(0x7E);
        Serial.write(0xFF);
        Serial.write(0x06);
        Serial.write(0x01); //次曲再生コマンド
        Serial.write(0x00);
        Serial.write(0x00); //
        Serial.write(0x00); //
        Serial.write(0xEF);
        delay(1000);
      }
      if(s3==0){        // stopが押されるまで待つ
        //停止
        Serial.write(0x7E);
        Serial.write(0xFF);
        Serial.write(0x06);
        Serial.write(0x0E); //ポーズCMD
        Serial.write(0x00);
        Serial.write(0x00); //
        Serial.write(0x00); //
        Serial.write(0xEF);
        delay(10);
        //break;
      }
    }
  }
}

1-2. arduinoのみで再生する

  • PWMのピンを利用し, 2.5Vを中心に0~5Vで電圧を揺らすことで, PWMピンから直接再生する
  • そのままのPWMだと遅くて(?)不適なのでFastPWMを利用
  • PROGMEMを使用してフラッシュメモリーに書き込みます(32KBなのでプログラム部分を除くと8000Hzで最大約4秒)
  • PWMなので音の振幅の解像度は8bit(256)
  • 音の波形を[0,255]で表現できれば良い. 作成方法は自由(WAV音源を変換する方法を下記では紹介).
  • 音源のサンプリングレートはdelayMicrosecondsで調整(例:8000Hzなら125[=1/8000]). ただし, プログラム内容によっては微調整が必要そう.
  • 悪: フラッシュメモリにはconstで事前に書き込むので録音等はできない

参照

FastPWM
Arduino Nano の PWM 機能を使ってみた(FastPWM 編 その2) [Arduino]
Secrets of Arduino PWM
DelayからTimer割り込みに変更

arduinoとスピーカーだけで音を出す方法
Arduinoとスピーカだけで音声を出す [Arduino]
【Arduino】WAVまたはMP3ファイルを再生する

program memoryについて
avr/pgmspace.h : Program Space Utilities

配線

GND: スピーカーの-
  3: スピーカーの+

256の音源を作る

>
作成例

  1. test.wavを用意する
  2. rawにformat変換
    audacityでサンプリング周波数8000Hz, その他の非圧縮ファイル, RAW(header-less), Unsigned 8-bit PCMと指定してtest.rawを作る
  3. ターミナルでxxd -i sample.rawを実行して数値に変換する
  4. 0x7f, 0x80, 0x7f, ...みたいな数値列(16進数)ができた

最終的な数値は127, 128, 127, ...のように10進数であってもOK

code

(私の「あいう」の声が無限に流れますが悪しからず…)

#include <avr/pgmspace.h>
const unsigned char sample_raw[] PROGMEM = {
108,108,108,108,108,118,108,118,118,118,118,128,118,118,128,118,118,128,138,128,138,128,128,128,128,128,128,128,128,128,128,128,128,128,118,118,118,128,128,118,118,118,128,118,128,128,128,118,118,118,118,128,128,118,118,128,128,128,118,118,128,138,158,148,138,128,128,128,138,148,138,148,138,128,118,118,108,118,108,98,98,98,108,108,118,108,118,138,118,108,98,88,98,128,128,128,128,128,118,118,108,108,118,118,118,128,128,128,138,128,128,128,118,118,128,128,128,128,128,128,128,118,118,118,118,118,128,128,138,138,138,128,118,128,128,138,138,148,138,118,108,128,118,128,118,108,108,118,118,98,108,108,128,138,148,128,128,128,118,128,138,138,138,148,138,138,128,118,118,118,118,118,118,118,118,118,118,118,108,108,108,108,108,128,118,118,118,108,118,118,118,118,118,118,118,128,128,118,128,118,118,128,118,128,128,128,118,118,118,118,128,128,128,128,128,108,128,118,118,138,138,128,138,138,118,138,128,128,138,148,148,158,118,98,98,98,118,148,158,148,158,118,128,118,128,128,138,118,118,128,128,128,128,108,98,108,98,108,118,108,108,108,98,98,108,108,108,108,118,118,118,118,128,128,118,128,128,128,128,128,128,128,128,128,118,128,118,128,128,118,118,128,128,128,138,128,128,128,128,138,138,118,128,128,128,128,148,108,128,128,118,108,118,148,128,158,128,118,108,138,118,118,118,98,128,148,128,108,128,108,118,138,128,108,128,128,128,128,118,118,128,128,118,118,118,118,118,118,108,108,108,108,108,108,108,108,118,118,108,118,118,118,118,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,118,108,118,128,138,138,128,118,118,138,128,128,128,128,138,138,138,118,98,128,148,158,138,118,118,128,128,108,118,118,118,138,128,118,138,138,128,128,128,118,128,138,128,118,128,128,128,118,108,108,108,108,108,108,108,108,108,108,108,108,108,118,108,118,118,118,118,128,128,128,128,128,118,128,128,128,128,118,118,128,128,118,128,128,128,128,128,118,128,128,138,128,128,128,138,138,138,128,108,138,148,128,98,128,148,128,118,128,138,118,118,108,98,128,148,118,108,128,128,128,148,128,128,148,158,128,128,118,118,128,128,108,108,118,108,118,118,98,88,108,118,108,108,98,108,118,118,108,108,108,118,128,128,118,118,138,128,128,128,128,128,138,128,118,118,128,128,128,118,118,118,128,128,128,128,128,138,128,128,128,118,128,148,138,138,118,148,118,128,138,118,108,138,158,88,118,128,128,118,148,88,98,148,168,158,148,158,138,178,138,108,88,118,98,108,98,78,98,128,128,88,98,98,128,118,108,88,118,128,138,118,88,108,138,138,108,108,108,138,138,118,98,118,138,138,128,108,118,138,148,118,118,118,138,138,118,108,118,138,138,128,108,108,138,148,128,98,118,148,148,128,128,118,138,158,138,108,138,158,128,118,118,118,98,128,98,118,168,158,138,148,178,148,158,98,98,108,128,88,68,88,108,128,98,98,88,128,128,118,98,108,128,128,118,98,108,128,138,118,108,118,138,138,118,108,108,138,128,118,108,118,138,148,128,118,128,138,138,118,118,128,138,128,118,118,128,138,128,128,128,128,128,128,118,118,128,118,128,118,148,148,138,138,138,128,118,118,118,108,108,138,138,168,158,158,148,168,158,128,108,98,108,78,78,68,88,88,98,88,98,118,128,128,128,148,118,128,118,118,108,108,108,108,108,108,128,118,128,128,128,128,128,128,118,128,118,128,118,128,128,128,128,118,128,128,138,128,128,128,128,128,128,118,118,128,118,128,118,128,138,138,118,148,128,118,148,138,108,128,128,108,158,128,148,168,158,158,178,148,138,158,108,108,88,68,68,68,58,58,78,68,98,108,118,138,148,138,158,158,128,138,128,118,118,108,98,108,108,98,118,108,118,128,128,128,138,138,138,138,128,128,128,128,118,118,118,118,118,118,118,118,128,118,128,138,118,128,138,118,128,128,138,118,138,128,128,128,128,118,138,148,148,158,148,168,168,168,148,158,138,128,118,88,88,68,58,48,58,48,68,78,88,108,118,138,148,158,158,168,148,158,148,128,128,118,98,98,108,78,98,98,108,108,118,118,128,128,128,148,128,138,138,138,128,128,128,118,118,118,118,118,118,118,118,118,128,128,138,128,138,138,128,148,128,138,148,138,158,148,148,168,178,158,168,158,138,138,108,108,88,68,58,58,38,48,58,58,78,98,118,128,148,148,168,168,168,158,158,148,148,118,118,118,98,98,88,88,88,98,98,98,108,118,128,138,138,138,148,138,148,138,138,128,128,118,118,108,108,108,108,108,108,118,118,118,138,118,138,148,128,148,148,168,148,168,168,178,168,168,168,158,148,128,128,98,88,78,58,48,48,48,48,58,68,88,108,128,138,158,168,168,178,178,168,158,148,138,138,128,98,108,108,88,88,98,98,88,108,108,128,118,128,138,138,128,138,138,128,128,128,128,118,118,118,108,108,118,108,118,108,128,118,128,128,138,138,148,158,158,178,168,188,178,188,168,178,148,148,118,108,88,68,58,38,48,28,48,38,68,68,98,108,128,148,158,168,178,178,178,178,168,158,148,138,118,138,88,98,108,78,88,108,88,88,118,98,118,108,128,128,128,128,138,128,128,138,118,128,118,128,118,118,108,128,98,128,118,118,138,128,128,158,138,148,188,138,198,158,178,168,168,148,148,128,108,118,78,88,58,68,48,48,48,58,68,78,98,108,128,128,148,158,158,168,168,158,168,158,158,138,148,128,118,118,108,98,98,98,88,108,88,108,98,108,108,128,108,118,128,128,128,128,138,118,128,118,128,118,128,118,118,118,118,118,128,128,148,128,168,168,148,198,158,198,168,188,158,168,128,128,118,78,88,58,68,38,48,48,58,48,78,88,98,118,128,138,148,158,168,168,168,168,168,168,158,148,138,148,108,118,118,98,98,108,88,98,98,88,108,98,108,108,118,108,128,118,138,128,128,128,138,128,128,138,118,128,118,128,108,128,118,118,138,138,128,168,148,158,188,158,188,168,168,158,158,128,138,108,88,88,58,68,48,58,48,58,58,78,88,98,118,128,138,148,158,168,158,168,158,168,158,158,138,148,138,108,138,108,98,108,118,78,108,88,98,88,98,108,98,108,118,128,108,138,118,138,118,138,128,128,138,118,138,118,128,118,128,118,128,138,128,148,168,138,178,168,168,178,168,168,158,148,128,128,98,98,78,68,58,48,58,58,58,68,88,88,108,118,128,138,138,158,158,168,168,178,158,178,158,138,168,118,128,118,108,98,108,88,88,88,78,98,78,98,98,108,108,128,118,138,138,138,148,128,148,128,138,128,128,128,118,118,128,118,118,128,128,138,158,138,168,168,158,178,168,168,158,158,138,128,108,98,88,68,68,48,58,48,58,58,68,78,88,108,118,138,138,158,148,178,168,168,168,168,158,148,158,118,138,108,118,98,108,88,88,98,88,98,88,108,98,118,108,128,118,128,128,128,138,128,138,128,138,118,138,128,128,128,128,128,118,148,128,158,138,148,168,158,168,168,178,158,158,148,138,118,108,98,78,68,58,58,48,48,58,68,78,78,98,108,118,138,148,158,158,168,168,168,158,188,138,158,158,128,128,118,108,88,108,78,98,68,98,88,88,98,108,108,108,138,128,148,128,158,138,138,148,138,128,128,138,118,128,118,128,118,118,12,128,148,128,158,168,158,168,168,178,148,158,148,138,108,108,88,78,58,58,58,38,58,58,68,68,98,108,118,118,138,148,148,168,168,168,168,158,168,158,138,148,138,128,118,108,108,98,88,98,88,78,98,88,88,108,108,108,128,128,138,138,148,148,148,138,148,148,138,128,138,128,118,138,118,118,148,128,138,158,158,158,168,158,168,158,148,148,128,118,108,88,68,68,58,48,48,48,58,68,68,88,98,108,128,138,148,148,168,168,168,168,178,168,158,168,148,138,128,128,98,108,98,88,78,78,88,78,88,88,98,98,118,118,128,138,148,148,148,158,148,148,138,148,128,138,118,128,128,118,138,138,128,148,158,148,168,168,168,168,158,148,138,118,108,98,78,68,58,48,48,48,58,58,68,78,98,108,118,138,148,158,158,178,168,168,178,178,158,158,158,138,128,118,118,88,98,88,78,78,78,88,78,88,98,108,108,128,128,138,148,148,158,148,158,158,138,148,138,138,118,118,138,108,118,148,118,128,158,148,158,168,168,158,168,148,158,128,108,118,88,78,68,68,48,58,48,58,68,68,88,98,108,118,148,138,158,158,168,178,168,168,178,158,148,158,118,128,118,98,88,88,78,78,78,78,88,78,98,108,108,118,138,138,138,158,158,158,158,158,148,148,148,128,128,128,128,108,138,128,118,158,148,148,158,168,148,168,158,148,138,118,118,98,78,68,68,48,48,58,58,58,68,88,98,108,118,138,148,148,178,158,188,168,178,178,158,148,148,138,108,138,98,98,88,88,68,78,88,78,98,88,118,108,118,128,148,138,148,158,148,158,148,148,138,148,128,128,128,118,128,108,138,128,128,148,158,148,148,178,148,158,158,148,138,118,108,98,78,68,78,48,48,58,58,58,78,88,98,108,118,138,148,148,178,158,178,178,158,178,168,148,148,148,108,118,118,88,78,88,78,68,88,78,88,88,108,108,118,128,138,138,138,168,148,148,158,158,138,138,148,128,128,128,118,138,128,128,148,148,148,158,168,148,158,158,138,128,128,108,88,88,68,68,48,48,58,58,58,78,88,98,108,128,138,148,158,168,168,178,198,148,178,178,138,138,158,118,88,138,78,78,88,88,48,88,88,68,98,98,118,108,138,138,158,148,158,158,158,158,158,148,128,138,138,128,108,158,118,108,158,158,128,158,188,138,148,168,148,118,128,118,88,78,68,68,48,48,58,58,58,68,98,98,108,128,148,138,158,178,168,178,198,168,168,188,148,128,148,128,78,108,108,48,68,88,58,48,98,78,78,108,128,108,138,168,148,158,168,168,148,158,158,138,138,148,128,108,148,128,108,148,158,128,138,188,148,128,168,158,108,118,128,88,68,78,78,48,48,68,58,58,78,88,88,108,128,138,148,158,168,168,178,198,168,168,178,158,128,148,128,78,98,98,58,48,88,58,48,88,98,78,98,138,128,138,168,168,158,168,178,158,158,158,148,128,138,128,128,128,128,128,148,158,138,158,168,148,138,158,138,108,108,108,78,58,78,58,48,48,68,58,68,88,98,98,118,148,148,158,168,178,188,178,178,188,168,148,158,138,98,108,108,68,58,78,68,48,68,88,78,88,118,118,128,148,158,158,168,168,168,168,158,148,148,148,128,128,128,128,118,128,138,138,138,148,158,148,148,148,148,118,118,108,88,78,68,58,48,58,58,58,68,78,88,108,118,128,148,158,168,168,188,188,168,178,178,148,138,148,118,88,98,88,58,68,68,58,58,78,88,88,108,118,138,148,158,158,168,178,168,168,168,158,148,138,138,128,118,128,118,118,128,138,138,148,158,148,148,148,138,128,118,108,98,78,78,68,58,58,58,58,68,78,88,98,118,128,138,148,168,178,168,178,188,168,158,158,148,118,108,108,88,68,78,58,58,68,78,78,98,108,118,138,148,148,158,168,168,168,168,168,158,148,148,138,128,118,118,118,118,128,128,138,138,148,158,158,148,148,148,128,118,108,98,78,68,68,58,58,58,58,68,78,88,108,118,128,148,158,168,178,188,178,178,178,168,148,138,128,108,98,88,78,58,58,58,58,68,78,88,108,118,128,148,158,168,168,178,178,178,168,168,148,138,128,118,118,118,118,118,128,138,138,148,158,158,148,158,148,138,128,118,98,88,78,68,58,58,58,58,68,78,88,98,118,128,148,158,168,178,178,188,188,178,168,158,148,128,108,98,88,68,68,58,58,58,68,78,88,98,118,138,148,158,168,178,178,178,178,168,158,158,148,128,128,118,118,118,118,118,128,138,148,148,158,158,158,148,138,128,118,108,88,78,68,58,48,48,58,58,68,78,98,108,128,138,158,168,178,188,198,188,188,178,158,148,138,118,98,78,68,58,58,48,58,58,68,78,98,118,128,148,158,168,178,178,188,178,178,168,158,148,138,128,118,108,108,118,118,128,128,138,148,158,158,158,158,148,138,128,118,98,88,68,58,48,48,48,48,58,68,78,98,118,138,148,168,178,188,198,198,188,188,178,158,138,128,98,88,68,58,48,48,48,48,68,78,88,108,128,148,158,178,178,188,188,188,178,168,158,148,138,118,108,108,98,108,108,118,128,128,148,148,158,168,168,158,148,138,128,108
};
const unsigned int sample_raw_len = sizeof(sample_raw);

void setup() {
  pinMode(3, OUTPUT);
  TCCR2A = _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
  TCCR2B = _BV(CS20);

}

void loop(){
  play();
  //delay(2000);
}

void play() {
  for (int i = 0; i < sample_raw_len; i++) {
    OCR2B = pgm_read_byte_near(&sample_raw[i]);
    delayMicroseconds(125);
  }
}

2. 録音

「録音する」といってもwavを作るとかではなく, 上記の「arduinoのみで再生する」を前提にした録音です. 必要であればPC等で適宜wav等に変換していただくということで…
ざっくりいって「analog-inの数値をSD-cardに記録するだけ」です.

  • micをanalog-inに接続して記録
  • ECM等だとオペアンプ+電圧シフトで2.5V中心の[0V, 5V]で電圧が揺れるようにする必要がある.
  • analog-inの10bitの数値を8bit(1byteで記録するため)に変換してSD cardに記録
  • printlnではなくwriteを利用しbyte(16進数. 00=0, 10=16 等)で記録する.
  • これは再生時に使用するreadがASCIIで読み込むため. printlnで記録すると10進数で記録されるため1桁ずつreadした後に1つ数値として復元する処理が必要になってしまい, 再生速度に間に合わなくなってしまう.

マイク

ECM等のマイクだと本来, 音を0Vを中心に+/-で微振動するのみ. arduinoのanalog inに突っ込んでもノイズと変わらないので検知できない. 故に

  • 信号増幅: マイクからの信号をオペアンプ等で100倍ほど増幅し, 振幅を5V程度にする
  • 電圧シフト: analog inが正値のみを受け取るため, 2.5Vを中心に[0V, 5V]で揺れるようにレベルシフトする

を行う必要がある.
自分で回路を組んでも良いが,

等のオペアンプ付のマイクモジュールを利用すると楽.
(というか, 電気回路を自分で組むのはまだ上手くいってないです… どなたか教えて欲しい)

参照

マイクモジュール

回路全体

マイク

オペアンプ

書き込み

SDカード

arduino

ノイズ

配線

上記のモジュールであれば,

 5V: VCC (arduino以外の5V電源[電池等]を使うとノイズが減ります)
GND: GND (arduino以外の5V電源[電池等]を使うとノイズが減ります)
 A0: AUDIO

でOKです.
SD cardは, 以前の記事のように

 11: DI (MOSI)
 12: DO (MISO)
 13: CLK (SCK)
  9: CS (chip select)
GND: GND
 5V: VCC

で繋げばOKです(以前の記事とくらべて, 配線の並びを個人的美的感覚の関係でCSを4から9に変えました).

code

#include <SD.h>
const int chipSelect = 9;
File dataFile;
int count = 0;

void setup(){
  pinMode(SS, OUTPUT);
  SD.begin(chipSelect);
}

void loop(){
  count++;
  if(count == 1){
    openSDToRecord();
  }else if(count >= 10000){
    closeSD();
    count = 0;
  }else{
    recordValue();
  }
}

//##########################################################
void openSDToRecord(){
  SD.remove("data.txt");
  dataFile = SD.open("data.txt", FILE_WRITE);
}

void recordValue(){
  int valuePre = analogRead(0);
  int value = int(float(valuePre)/4.0);
  dataFile.write(value);
}

void closeSD(){
  if (dataFile) {
    dataFile.close();
  }
}

録音したdataの形(確認)

DATA.TXTという形で録音したデータを保存していますが, それをPCのテキストエディタで開いてみると

76a8 bc94 9e76 6c76 8a76 9476 626c 7680
948a 6c6c 626c 7680 7680 7680 8a9e 9e76
.
.
.

という感じで16進数で保存されているのがわかります.

3. 録音した音声を再生

配線

GND: スピーカーの-
  3: スピーカーの+
 11: DI (MOSI)
 12: DO (MISO)
 13: CLK (SCK)
  9: CS (chip select)
GND: GND
 5V: VCC

code

#include <SD.h>
const int chipSelect = 9;

void setup(){
  Serial.begin(9600);
  pinMode(3, OUTPUT);
  TCCR2A = _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
  TCCR2B = _BV(CS20);
  pinMode(SS, OUTPUT);
  SD.begin(chipSelect);
  Serial.println(OCR2B);

}

void loop(){
  File dataFile = SD.open("data2.txt");
  if (dataFile) {
    while (dataFile.available()) {
      OCR2B = dataFile.read();
      delayMicroseconds(100);
    }
    //Serial.println(value);
    dataFile.close();
  }
  Serial.println(OCR2B);
  delay(2000);
}

4. 再生と録音をスイッチで制御

上記の再生と録音に加えてスイッチを組み合わせることで, 簡単なサンプラーを作ることができます.
(チチチ…という謎のノイズがマイク, スピーカーにのってしまっています. 調べ中)

配線

GND: スピーカーの-
  3: スピーカーの+
 5V: VCC (arduino以外の5V電源[電池等]を使うとノイズが減ります)
GND: GND (arduino以外の5V電源[電池等]を使うとノイズが減ります)
 A0: AUDIO
 11: DI (MOSI)
 12: DO (MISO)
 13: CLK (SCK)
  9: CS (chip select)
GND: GND
 5V: VCC
5V & GND & 5: 録音スイッチ
5V & GND & 6: 再生スイッチ
setting_rec-play.jpg

code

再生後に録音する際にFastPWMを直すために

  OCR2B = 0;

を追加しています.

#include <SD.h>
const int chipSelect = 9;
const int pinRecordSW = 5;
const int pinPlaySW  = 6;
const int pinPlaySound = 3;

int stateRecordSW;
int countRecordSW;
int statePlaySW;
int countPlaySW;
boolean isRecordMode;
boolean isPlayMode;
File dataFile;


void setup(){
  Serial.begin(9600);

  pinMode(pinPlaySound, OUTPUT);
  TCCR2A = _BV(COM2B1) | _BV(WGM21) | _BV(WGM20);
  TCCR2B = _BV(CS20);

  pinMode(SS, OUTPUT);
  SD.begin(chipSelect);

  //pinMode(pinRecordSW,  INPUT_PULLUP);
  pinMode(pinRecordSW,  INPUT);
  pinMode(pinPlaySW,  INPUT);
  stateRecordSW = 0;
  countRecordSW = 0;
  isRecordMode = false;
  statePlaySW = 0;
  countPlaySW = 0;
  isPlayMode = false;
}

void loop(){
  readPIN();

  controlRecordMode();
  if (isRecordMode){
    recordValue();
    //delay(1000);
  }

  controlPlayMode();
  if (isPlayMode){
    playValue();
  }  
}

//##########################################################
//##########################################################
//##########################################################

void controlRecordMode(){
  if (stateRecordSW == 1){
    countRecordSW++;
    if (countRecordSW == 10){

      if (!isRecordMode){
        if (isPlayMode){
          isPlayMode = false;
          closeSD();
        }
        isRecordMode = true;
        openSDToRecord();
        if (!dataFile) {
          openSDToRecord();
        }
      } else if (isRecordMode){
        isRecordMode = false;
        closeSD();
      }

      delay(1000);
    }
  } else {
    countRecordSW = 0;
  }
}

void controlPlayMode(){
  if (statePlaySW == 1){
    countPlaySW++;
    if (countPlaySW == 10){

      if (!isPlayMode){
        if (isRecordMode){
          isRecordMode = false;
          closeSD();
        }
        isPlayMode = true;
        openSDToPlay();
        if (!dataFile) {
          openSDToPlay();
        }
      } else if (isPlayMode){
        isPlayMode = false;
        closeSD();
      }

      delay(1000);
    }
  } else {
    countPlaySW = 0;
  }
}

void readPIN(){
  stateRecordSW = digitalRead(pinRecordSW);
  statePlaySW  = digitalRead(pinPlaySW);
}

void openSDToRecord(){
  SD.remove("data.txt");
  dataFile = SD.open("data.txt", FILE_WRITE);
  Serial.println("SD was opened to Record");
}

void openSDToPlay(){
  dataFile = SD.open("data.txt");
  Serial.println("SD was opened to Play");
}

void recordValue(){
  //int value = analogRead(0);
  int valuePre = analogRead(0);
  int value = int(float(valuePre)/4.0);
  dataFile.write(value);
  //Serial.print("Record:");
  //Serial.println(value);
}

void playValue(){
  while (dataFile.available()) {
    OCR2B = dataFile.read();
    //delayMicroseconds(150);
    delayMicroseconds(150);
    //int value = dataFile.read();
    //Serial.println(value);
  }
  isPlayMode = false;
  closeSD();
}

void closeSD(){
  if (dataFile) {
    dataFile.close();
    Serial.println("SD was closed");
  }
  OCR2B = 0;
}

動画