// ブザーを鳴らします。
const int BUZZER_PIN = 13; // ブザーピン
// 録音,再生フラグは2,3ピンを用いて割り込み処理により切り替え
bool REC = false, START = false; // 録音,再生フラグ
const int PLAYING_LED = A3; // 再生中状態LED(緑色)
const int WAITING_LED = A4; // 再生可能状態を示すLED(緑色)
const int REC_LED = A5; // 録音状態LED(赤色)
const int tone_time = 100;
// 音階を定義
const float BUZZER_HZ[10] ={
0, // 無音
261.63, // ド4
293.67, // レ4
329.63, // ミ4
349.23, // ファ4
392.00, // ソ4
440.00, // ラ4
493.88, // シ4
523.23, // ド5
587.34 // レ5
};
// 音階に対応付けられているスイッチピン番号を定義
const int BUZZER_HZ_SW_LIST[9] = {
12, // 12番ピン(ド4)
11, // 11番ピン(レ4)
10, // 10番ピン(ミ4)
9, // 9番ピン(ファ4)
8, // 8番ピン(ソ4)
7, // 7番ピン(ラ4)
6, // 6番ピン(シ4)
5, // 5番ピン(ド5)
4 // 4番ピン(ド5)
};
// 音階に対応づけられているスイッチピン番号の要素数を取得
const int BUZZER_HZ_SW_LIST_ENDPOINT = sizeof(BUZZER_HZ_SW_LIST) / sizeof(BUZZER_HZ_SW_LIST[0]); // 要素数を取得
// 録音データ(初期値はド4~レ5)
int rec_data[500] = {
1,2,3,4,5,6,7,8,9
};
// 録音データの最大容量
const int REC_DATA_ENDPOINT = sizeof(rec_data) / sizeof(rec_data[0]); // 配列の要素数
// 録音データのデータ数(初期値は9)
int rec_save_count = 9; // データ数
void setup() {
pinMode(BUZZER_PIN, OUTPUT); // ブザーピン
pinMode(PLAYING_LED, OUTPUT); // 再生中状態LED(黄色)
pinMode(WAITING_LED, OUTPUT); // 再生可能状態LED(緑色)
pinMode(REC_LED, OUTPUT); // 録音状態LED(赤色)
Serial.begin(9600);
attachInterrupt(0, toggleRec, RISING); // 録音の開始または停止
attachInterrupt(1, toggleStart, RISING); // 再生、停止
// 初期状態のLEDを点灯させる
analogWrite(WAITING_LED, 255); // 再生可能状態(点灯)
analogWrite(PLAYING_LED, 0); // 未再生状態(消灯)
}
void loop() {
// 録音フラグがtrueなら録音開始
if(REC){
rec(); // 録音開始
}
// 再生フラグがtrueなら再生開始
if(START){
play(); // 録音データを再生
}
}
void toggleRec(){
START = false;
REC = !(REC); // RECフラグを切り替え(ON/OFF)
// 録音状態をLEDにより可視化
if(REC){ // 録音実行状態
Serial.println("録音開始");
analogWrite(REC_LED, 255); // 録音実行状態(点灯)
analogWrite(WAITING_LED, 0); // 再生不可状態(消灯)
analogWrite(PLAYING_LED, 0); // 未再生状態(消灯)
}else{ // 録音終了状態
Serial.println("録音終了");
analogWrite(REC_LED, 0); // 録音停止状態(消灯)
analogWrite(WAITING_LED, 255); // 再生可能状態(点灯)
analogWrite(PLAYING_LED, 0); // 未再生状態(消灯)
}
}
void toggleStart(){
REC = false;
START = !(START); // STARTフラグを切り替え(ON/OFF)
// 再生状態をLEDにより可視化
if(START){ // 再生中状態
Serial.println("再生開始");
analogWrite(REC_LED, 0); // 録音停止状態(消灯)
analogWrite(WAITING_LED, 255); // 再生可能状態(点灯)
analogWrite(PLAYING_LED, 255); // 再生中状態(点灯)
}else{ // 再生停止状態
analogWrite(REC_LED, 0); // 録音停止状態(消灯)
analogWrite(WAITING_LED, 255); // 再生可能状態(消灯)
analogWrite(PLAYING_LED, 0); // 未再生状態
}
}
// 割り込み処理が影響しないほうの再生停止関数
void toggleStop(){
Serial.println("再生停止");
REC = false;
START = false; // STARTフラグfalse(OFF)
analogWrite(REC_LED, 0); // 録音停止状態(消灯)
analogWrite(WAITING_LED, 255); // 再生可能状態(消灯)
analogWrite(PLAYING_LED, 0); // 未再生状態
}
// 録音を鳴らす
void play(){
int i;
// 再生開始
for(i = 0; i < rec_save_count; i++){
// tone(ピン番号,周波数(Hz),出力時間)
tone(BUZZER_PIN, BUZZER_HZ[rec_data[i]], tone_time); // ドの音を発信
delay(tone_time); // 次の動作に入るのを避けるため、音を鳴らす間停止
// 再生フラグがfalseなら[停止]
Serial.print("START:");
Serial.println(START);
if(!(START)){
Serial.println("再生を停止します。");
return;
}
}
toggleStop(); // 再生を停止
delay(50); // 変数変更のタイミング誤差修正のため
}
// 録音する
void rec(){
int i,j;
// 録音開始
for(i = 0; i < REC_DATA_ENDPOINT; i++){
// 音階を設定
int active_SW = 0; // 音階の初期値(0番は無音)
for(j = 0; j < BUZZER_HZ_SW_LIST_ENDPOINT; j++){
if(digitalRead(BUZZER_HZ_SW_LIST[j]) == HIGH){
active_SW = j+1; // 0番目が無音の音階に設定されているため+1する(BUZZER_HZ)
}
}
// 音階番号を保存
rec_data[i] = active_SW; // 音階番号
// 録音時に音を聞けるように鳴らす
tone(BUZZER_PIN, BUZZER_HZ[active_SW], tone_time); // 任意音階を50ms鳴らす
// RECフラグがfalseなら録音終了
Serial.print("REC:");
Serial.println(REC);
if(!(REC)){
rec_save_count = i+1; // データ数を更新
return;
}
delay(tone_time); // 次に音を鳴らす時間分待つ
}
// 録音データの最大容量まで保存したため録音終了
rec_save_count = REC_DATA_ENDPOINT; // 容量の最大を割り当て
toggleRec(); // RECフラグをfalseに変更
}