/**
Mini piano for Arduino.
You can control the colorful buttons with your keyboard:
After starting the simulation, click anywhere in the diagram to focus it.
Then press any key between 1 and 8 to play the piano (1 is the lowest note,
8 is the highest).
Copyright (C) 2021, Uri Shaked. Released under the MIT License.
*/
#include "pitches.h"
#define SPEAKER_PIN 8
//const uint8_t buttonPins[] = { 12, 11, 10, 9, 7, 6, 5, 4 };
//const int buttonTones[] = {
// NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4,
// NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5
//};
//const int numTones = sizeof(buttonPins) / sizeof(buttonPins[0]);
//void setup() {
// for (uint8_t i = 0; i < numTones; i++) {
// pinMode(buttonPins[i], INPUT_PULLUP);
// }
// pinMode(SPEAKER_PIN, OUTPUT);
//}
//void loop() {
// int pitch = 0;
// for (uint8_t i = 0; i < numTones; i++) {
// if (digitalRead(buttonPins[i]) == LOW) {
// pitch = buttonTones[i];
//}
//}
// if (pitch) {
// tone(SPEAKER_PIN, pitch);
// } else {
// noTone(SPEAKER_PIN);
// }
//}
// 定义乐谱相关的数组
// 定义乐谱相关的数组
// 声明音符数组、音调数组和音符时长数组
// 声明音符数组、音调数组和音符时长数组
// 定义卡农乐谱相关的数组
const char* melody[] = {"E4", "G4", "A4", "B4", "A4", "G4", "E4", "C4",
"D4", "E4", "D4", "C4", "B3", "C4", "D4", "E4",
"G4", "A4", "B4", "A4", "G4", "E4", "C4", "E4",
"F4", "G4", "A4", "G4", "F4", "E4", "C4", "D4",
"F3", "F3", "F3", "F3", "F3", "F3", "F3", "E3",
"E3", "E3", "E3", "E3", "E3", "E3", "E3", "D3"};
const int durations[] = {2, 2, 2, 2, 2, 2, 4, 4,
2, 2, 2, 2, 2, 2, 4, 4,
2, 2, 2, 2, 2, 2, 4, 4,
2, 2, 2, 2, 2, 2, 4, 4,
2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 4, 4};
// 定义LED引脚
const int ledPin = 13;
void setup() {
// 初始化蜂鸣器引脚和LED引脚
pinMode(8, OUTPUT);
pinMode(ledPin, OUTPUT);
}
void loop() {
// 演奏卡农乐谱
for (int i = 0; i < sizeof(melody) / sizeof(melody[0]); i++) {
// 使用 tone 函数演奏音符
tone(8, frequency(melody[i]), 1000 / durations[i]);
// 闪烁LED
digitalWrite(ledPin, HIGH); // 点亮LED
delay(1000 / durations[i] / 2);
digitalWrite(ledPin, LOW); // 熄灭LED
delay(1000 / durations[i] / 2);
noTone(8); // 停止演奏音符
}
delay(1000); // 演奏完整个乐谱后延迟一秒
// 循环演奏乐谱
}
// 根据音符名称返回对应的频率
float frequency(const char* note) {
const char* notes[] = {"C0", "C#0/Db0", "D0", "D#0/Eb0", "E0", "F0",
"F#0/Gb0", "G0", "G#0/Ab0", "A0", "A#0/Bb0",
"B0", "C1", "C#1/Db1", "D1", "D#1/Eb1",
"E1", "F1", "F#1/Gb1", "G1", "G#1/Ab1",
"A1", "A#1/Bb1", "B1", "C2", "C#2/Db2",
"D2", "D#2/Eb2", "E2", "F2", "F#2/Gb2",
"G2", "G#2/Ab2", "A2", "A#2/Bb2", "B2",
"C3", "C#3/Db3", "D3", "D#3/Eb3", "E3",
"F3", "F#3/Gb3", "G3", "G#3/Ab3", "A3",
"A#3/Bb3", "B3", "C4", "C#4/Db4", "D4",
"D#4/Eb4", "E4", "F4", "F#4/Gb4", "G4",
"G#4/Ab4", "A4", "A#4/Bb4", "B4", "C5",
"C#5/Db5", "D5", "D#5/Eb5", "E5", "F5",
"F#5/Gb5", "G5", "G#5/Ab5", "A5", "A#5/Bb5",
"B5", "C6", "C#6/Db6", "D6", "D#6/Eb6",
"E6", "F6", "F#6/Gb6", "G6", "G#6/Ab6",
"A6", "A#6/Bb6", "B6", "C7", "C#7/Db7",
"D7", "D#7/Eb7", "E7", "F7", "F#7/Gb7",
"G7", "G#7/Ab7", "A7", "A#7/Bb7", "B7",
"C8", "C#8/Db8", "D8", "D#8/Eb8", "E8",
"F8", "F#8/Gb8", "G8", "G#8/Ab8", "A8",
"A#8/Bb8", "B8"};
const float frequencies[] = {16.35, 17.32, 18.35, 19.45, 20.6, 21.83,
23.12, 24.5, 25.96, 27.5, 29.14, 30.87,
32.7, 34.65, 36.71, 38.89, 41.2, 43.65,
46.25, 49, 51.91, 55, 58.27, 61.74,
65.41, 69.3, 73.42, 77.78, 82.41, 87.31,
92.5, 98, 103.83, 110, 116.54, 123.47,
130.81, 138.59, 146.83, 155.56, 164.81, 174.61,
185, 196, 207.65, 220, 233.08, 246.94,
261.63, 277.18, 293.66, 311.13, 329.63, 349.23,
369.99, 392, 415.3, 440, 466.16, 493.88,
523.25, 554.37, 587.33, 622.25, 659.26, 698.46,
739.99, 783.99, 830.61, 880, 932.33, 987.77,
1046.5, 1108.73, 1174.66, 1244.51, 1318.51, 1396.91,
1479.98, 1567.98, 1661.22, 1760, 1864.66, 1975.53,
2093, 2217.46, 2349.32, 2489.02, 2637.02, 2793.83,
2959.96, 3135.96, 3322.44, 3520, 3729.31, 3951.07,
4186.01, 4434.92, 4698.63, 4978.03};
for (int i = 0; i < sizeof(notes) / sizeof(notes[0]); i++) {
if (strcmp(note, notes[i]) == 0) {
return frequencies[i];
}
}
return 0.0; // 如果找不到对应音符的频率,则返回 0
}