반응형

악보의 구성요소에 대응하는 코드 작성 방법을 살펴보고 그 방법에 따라 피에조 부저를 제어할 코드를 작성해 보자.

 

악보의 기본 구성요소는 아래 사이트와 기타 유튜브 악보 강좌들을 참조하였고 이 글에서는 코딩에 필요한 부분에 관해 설명하겠다.

악보 보는 방법에 대해 자세히 알고 싶다면 아래 사이트를 참조하기 바란다.

https://m.post.naver.com/viewer/postView.nhn?volumeNo=11821078&memberNo=15323549

 

코딩에 적용해야 할 악보 구성요소

1. 높은 음자리 / 낮은 음자리

옥타브를 적용하기 위해서 알아야 한다.

낮은 음자리는 음역대 C0 ~ C3이고 높은 음자리는 음역대 C4 ~ C9이지만 88 키보드 피아노에서는 C8까지이다.

따라서 피에조 부저 값에 적용할 옥타브의 값은 0 ~ 8을 사용하게 된다.

음역대 변경 조건은 악보상 기준 옥타브의 도 ~ 시(C ~ B) 12화음 범위를 벗어난 값에 따라 옥타브 값을 증감시키면 된다.

 

2. 12화음

익숙한 도 ~ 시 사이의 음을 얘기한다.

정확히는 "도, 도#(레b), 레, 레#(미b), 미, 파, 파#(솔b), 솔, 솔#(라b), 라, 라#(시b), 시" 이다.

음을 코딩하기 위해서는 아래의 영어 계이름에 익숙해지는 게 좋다.

라 시 도 레 미 파 솔
A  B  C  D  E  F  G
 A#    C# D#    F# G#
 Bb    Db Eb    Gb Ab

 오선보에 따른 영어 계이름

-- F ------------------
     E    
-- D ------------------
     C   
-- B ------------------
     A      
-- G ------------------
     F               
-- E ------------------

 Eddie's Green Boots Don't Fit / FACE

출처: 유튜브 https://www.youtube.com/watch?v=7Bv-JiFnoJ4

 

3. 음표와 쉼표

음의 길이 또는 박자의 길이를 적용시키기 위해 알아야 한다.

민음표와 민쉼표
점음표와 점쉼표

1) 민음표와 민쉼표 코딩 값

16분 음표/쉼표(1/4박) = 1 (기준)

기준에 따라

8분 음표/쉼표(1/2박) = 2

4분 음표/쉼표(1박) = 4

2분 음표/쉼표(2박) = 8

온음표/쉼표(4박)  = 16

 

2) 점음표와 점 쉼표 코딩 값

점 8분 음표/쉼표(3/4박) = 3

점 4분 음표/쉼표(1과 1/2박) = 6

점 2분 음표/쉼표(3박) = 12

 

4. 조표 / 변화표

계이름을 적용시키기 위해 알아야 한다.

조표에 표시된 모든 음은 반음 올리거나 내려야 한다.

'파', '도' 음에 조표가 있으므로, 해당 음인 초록색 표시 부분은 반음 올려주어야 한다.

조표의 종류는 #과 b으로 나누어진다.

# 조표 표시순서: 파-도-솔-레-라-미-시(F-C-G-D-A-E-B)  
b 조표 표시순서: 시-미-라-레-솔-도-파(B-E-A-D-G-C-F)

 

#의 개수에 따른 #조표 종류

1: 파(F)

2: 파-도(F-C)

3: 파-도-솔(F-C-G)

4: 파-도-솔-레(F-C-G-D)

5: 파-도-솔-레-라(F-C-G-D-A)

6: 파-도-솔-레-라-미(F-C-G-D-A-E)

7: 파-도-솔-레-라-미-시(F-C-G-D-A-E-B)

 

b의 개수에 따른 b조표 종류

1: 시(B)

2: 시-미(B-E)

3: 시-미-라(B-E-A)

4: 시-미-라-레(B-E-A-D)

5: 시-미-라-레-솔(B-E-A-D-G)

6: 시-미-라-레-솔-도(B-E-A-D-G-C)

7: 시-미-라-레-솔-도-파(B-E-A-D-G-C-F)

 

표시 순서에 따라 #조표 7개, b조표 7개 모두 14개가 있고, 조표가 없는 경우를 포함하면 경우의 수는 0 ~ 14가 된다.

 

해당 조표가 사용자 함수를 통해 처리되도록

조표가 없는 경우 = 0

조표에 b 1개인 경우 = 1

조표에 b 2개인 경우 = 2

조표에 b 3개인 경우 = 3

조표에 b 4개인 경우 = 4

조표에 b 5개인 경우 = 5

조표에 b 6개인 경우 = 6

조표에 b 7개인 경우 = 7

조표에 # 1개인 경우 = 8

조표에 # 2개인 경우 = 9

조표에 # 3개인 경우 = 10

조표에 # 4개인 경우 = 11

조표에 # 5개인 경우 = 12

조표에 # 6개인 경우 = 13

조표에 # 7개인 경우 = 14

로 정의하고 함수를 작성하겠다.

 

변화표가 붙은 경우에는 상기의 사용자 함수에 의해 자동으로 변경되지 않도록 하고 변화표의 적용 기준에 따라 음계를 수동으로 변경해 주면 된다. 

 

** 추가사항 

변화표를 적용하도록 코드를 추가해 주었다. 

제자리표는 localKey 값이 1, 내림표는 2, 올림표는 3, 겹내림표는 4, 겹올림표는 5를 입력하면 적용된다. 

 

변화표의 적용 기준

변화표가 붙은 음에서 현재 마디까지의 동일음은 모두 코드에 따라 올려지거나 내려지게 된다. 옥타브가 변경된 경우에도 적용된다.

 

상기의 악보 구성요소와 코딩 값을 이해하였다면 이제 악보를 보고 값을 따주기만 하면 되는데, 그에 앞서 아두이노에서  사용할 기준 함수 및 변수들을 살펴보자.

 

아두이노에서 적용할 계이름의 정의로 ESP32 개발 보드 라이브러리의 ledcWriteNote 함수와 그에 사용되는 변수 정의를 가져와서 사용하겠다. 만약 ESP32를 사용한다면 아래 함수는 라이브러리에 정의되어 있으므로 별도로 정의해 줄 필요는 없다.

 

** 12화음 이름 정의
typedef enum {
  NOTE_C, NOTE_Cs, NOTE_D, NOTE_Eb, NOTE_E, NOTE_F, NOTE_Fs, NOTE_G, NOTE_Gs, 
  NOTE_A, NOTE_Bb, NOTE_B, NOTE_MAX
} note_t;

** 화음별 피에조 부저 진동수 정의 및 옥타브에 따른 값 변경 함수
double ledcWriteNote(note_t note, uint8_t octave){
  const uint16_t noteFrequencyBase[12] = {
  //  C      C#     D      Eb     E      F     F#      G     G#      A     Bb      B
     4186,  4435,  4699,  4978,  5274,  5588,  5920,  6272,  6645,  7040,  7459,  7902
  };
  if(octave > 8 || note >= NOTE_MAX){
    return 0;
  }
  double noteFreq =  (double)noteFrequencyBase[note] / (double)(1 << (8-octave));
  return noteFreq;
}

 

상기에서 정의된 코딩용 계이름에 따라 조표를 적용시키기 위한 사용자 함수를 작성하였다.

note_t keySignature(note_t note) {
  if (localKey[noteNum] == 0) {
    if (KeySign == 1) { 
      if (note == NOTE_B) note = NOTE_Bb;
    } else if (KeySign == 2) { 
      if (note == NOTE_B) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_Eb;
    } else if (KeySign == 3) {
      if (note == NOTE_B) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Gs;
    } else if (KeySign == 4) { 
      if (note == NOTE_B) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Cs;
    } else if (KeySign == 5) { 
      if (note == NOTE_B) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Fs;
    } else if (KeySign == 6) {
      if (note == NOTE_B) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Fs;
      else if (note == NOTE_C) { note = NOTE_B; octaveTemp -= 1; } // 옥타브가 변경된다.
    } else if (KeySign == 7) { 
      if (note == NOTE_B) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Fs;
      else if (note == NOTE_C) { note = NOTE_B; octaveTemp -= 1; } // 옥타브가 변경된다.
      else if (note == NOTE_F) note = NOTE_E;
    } else if (KeySign == 8) { 
      if (note == NOTE_F) note = NOTE_Fs;
    } else if (KeySign == 9) {
      if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_C) note = NOTE_Cs;
    } else if (KeySign == 10) {
      if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_C) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Gs;
    } else if (KeySign == 11) { 
      if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_C) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Eb;
    } else if (KeySign == 12) {
      if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_C) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Bb;
    } else if (KeySign == 13) {
      if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_C) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_F;
    } else if (KeySign == 14) { 
      if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_C) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_F;
      else if (note == NOTE_B) { note = NOTE_C; octaveTemp += 1; } // 옥타브가 변경된다.
    }
  }
  else { // 변화표 적용 코드 1. natural(1일경우 코드 적용 없이 음계값 그대로 연주된다.)
    if (pgm_read_byte(&localKey[noteNum]) == 2) { // 2. b
      if (note == NOTE_C) { note = NOTE_B; octaveTemp -= 1; }
      else if (note == NOTE_D) note = NOTE_Cs;
      else if (note == NOTE_E) note = NOTE_Eb;
      else if (note == NOTE_F) note = NOTE_E;
      else if (note == NOTE_G) note = NOTE_Fs;
      else if (note == NOTE_A) note = NOTE_Gs;
      else if (note == NOTE_B) note = NOTE_Bb;
    }
    else if (pgm_read_byte(&localKey[noteNum]) == 3) { // 2. #
      if (note == NOTE_C) note = NOTE_Cs;
      else if (note == NOTE_D) note = NOTE_Eb;
      else if (note == NOTE_E) note = NOTE_F;
      else if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_G) note = NOTE_Gs;
      else if (note == NOTE_A) note = NOTE_Bb;
      else if (note == NOTE_B) { note = NOTE_C; octaveTemp += 1; }
    }
    else if (pgm_read_byte(&localKey[noteNum]) == 4) { // 4. bb
      if (note == NOTE_C) { note = NOTE_Bb; octaveTemp -= 1; }
      else if (note == NOTE_D) note = NOTE_C;
      else if (note == NOTE_E) note = NOTE_D;
      else if (note == NOTE_F) note = NOTE_Eb;
      else if (note == NOTE_G) note = NOTE_F;
      else if (note == NOTE_A) note = NOTE_G;
      else if (note == NOTE_B) note = NOTE_A;
    }
    else if (pgm_read_byte(&localKey[noteNum]) == 5) { // 5. ##
      if (note == NOTE_C) note = NOTE_D;
      else if (note == NOTE_D) note = NOTE_E;
      else if (note == NOTE_E) note = NOTE_Fs;
      else if (note == NOTE_F) note = NOTE_G;
      else if (note == NOTE_G) note = NOTE_A;
      else if (note == NOTE_A) note = NOTE_B;
      else if (note == NOTE_B) { note = NOTE_Cs; octaveTemp += 1; }
    }
  }
  return note;
}

 

상기 함수에서 localKey [noteNum] 변수는 현재음이 변화표가 붙어있는지의 여부를 표시하게 된다.  동요 같은 비교적 간단한 곡들은 변화표가 거의 붙어있지 않으나 변화표를 적용할 수 있도록 해당 변수를 사용하였다.

만약 localKey[noteNum] == 1이라면 조표에 따라 자동으로 반음을 올리거나 내리는 작동을 하지 않고 표기된 음 그대로 출력하게 된다.

 

상기의 변수를 포함한 악보의 음계를 따서 저장하기 위한 배열 4개와 변수들을 아래와 같이 정의하였다.

 

1. uint8_t KeySign = 0;
   조표값을 저장한다. 
   조표가 없는 경우의 값은 0, 조표에 b이 1개있는 경우는 1, 2개 있는 경우는 2, ... 7개 
   있는 경우는 7 그리고 #이 1개 있는 경우는 8, 2개 있는 경우는 9 ....  14까지 값이다. 
   
2. uint8_t octaveTemp = 4; 
   일반적인 높은 음자리 악보의 옥타브 값은 4(C4)이다. 
   상기에서 정의된 함수 keySignature(note_t note)상에서 조표에 맞게 계이름을 변경할 시 옥타브
   값이 변경되는 경우가 있다. 옥타브의 변경을 반영하기 위한 변수이다. 
   
3. uint8_t Tempo = 60;
   곡의 빠르기를 적용하는 부분이다. 1분에 60 박자면 값은 60이다.

4. float tempoRatio = float(Tempo)/60.0;
   곡의 빠르기를 1분의 값인 60을 기준으로 비율로 변경한 값이다.
   음계의 민음표와 민쉼표 또는 점음표와 점쉼표의 길이를 반영하여 루프 함수내의 딜레이 대체
   함수의 작동 기준에 적용된다. 

5. const uint8_t Mnote[] PROGMEM= { };
   상기에서 정의해준 각 음계를 저장해주는 배열이다. 
   NOTE_E, NOTE_E, NOTE_G, NOTE_B, 식으로 악보의 각 음계의 값을 앞에서 부터 순서대로 써준다. 

6. const uint8_t Moct[] PROGMEM= { };
   Mnote[] 배열의 음계와 일치 되도록 악보의 각 음계의 옥타브 값을 앞에서 부터 순서대로 써준다.
   높은 음자리 악보의 기준 옥타브가 C4라 할때 C4의 C ~ B(도 ~ 시) 12화음을 안에 있는 음계는 
   4의 값을 12화음을 벗어난 경우에는 해당 옥타브 값으로 증감 시켜준다.

7. const uint8_t localKey[] PROGMEM= { };
   악보의 각 음계에 변화표가 붙어있는지의 여부를 기록하는 배열이다. 
   변화표가 있으면 1, 없으면 0을 넣어준다. 대개의 경우 변화표가 없으므로 0의 값이 있는 배열이 된다.

8. const uint8_t Mdur[] PROGMEM= { };
   악보의 각 음계의 박자(길이)를 저장하는 배열이다. 
   - 민음표와 민쉼표
     16분 음표/쉼표(1/4박) = 1 (기준), 8분음표/쉼표(1/2박) = 2, 4분음표/쉼표(1박) = 4
     2분음표/쉼표(2박) = 8, 온음표/쉼표(4박) = 16
   - 점음표와 점쉼표
     점8분음표/쉼표(3/4박) = 3, 점4분음표/쉼표(1과1/2박) = 6, 점2분음표/쉼표(3박) = 12

악보의 멜로디를 따기 위한 사전 준비는 완료되었다.

 

 

악보를 보고 멜로디를 따 보자.

동요 겨울밤

동요 겨울밤 악보를 살펴보자.

1. 악보에서 조표를 확인하고 KeySign 변수의 값을 결정한다.

    상기 그림의 1번 표시의 높은 음자리표와 박자표 부분에 어떤 조표도 표시되어 있지 않다.

    따라서 값은 0. 만약 #이 2개 있다면 값은 9가 될 것이다.

    KeySign = 0;

 

2. 음계/쉼표를 Mnote [] 배열에 순서대로 저장한다.

    음계/쉼표를 읽으면 다음과 같다.

    G(솔) G(솔) G(솔) A(라) G(솔) F(파) E(미) E(미) E(미) 쉼표

    F(파) F(파) F(파) G(솔) F(파) E(미) D(레) D(레) D(레) 쉼표

   

    이 음계를 아두이노 코드에서 정의해 놓은 Note 값으로 변경해서 Mnote[] 배열에 써준다.

    G는 NOTE_G, A는 NOTE_A, F는 NOTE_F, E는 NOTE_E, D는 NOTE_D로 변경하여 써주고,

    이때 모든 쉼표는 NOTE_MAX가 된다. 쉼표도 반드시 값에 포함되어야 한다.

const note_t Mnote[] PROGMEM= {
NOTE_G, NOTE_G, NOTE_G, NOTE_A, NOTE_G, NOTE_F, NOTE_E, NOTE_E, NOTE_E, NOTE_MAX,
NOTE_F, NOTE_F, NOTE_F, NOTE_G, NOTE_F, NOTE_E, NOTE_D, NOTE_D, NOTE_D, NOTE_MAX,
};

 

3. 각 음계/쉼표의 옥타브 값을 Moct [] 배열에 순서대로 저장한다.

    상기 악보상의 모든 음계는 기준 옥타브 C4 안에 있는 음이다. 따라서 모두 4가 된다.

    이때 쉼표도 표시를 해주어야 한다.  쉼표의 값은 0을 제외한 어떤 값이든 상관없다. 

const uint8_t Moct[] PROGMEM= { // 멜로디 옥타브 C ~ B, 4옥타브: 88키보드 가운데 도(C4) ~ 시(B4)
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
0, // 배열의 마지막에는 전체 멜로디 쉬는 시간을 위한 칸을 생성해준다.
};

    배열의 마지막에는 0 값이 붙게 되는데 이는 멜로디 종료 후 재 실행 시 쉬는 시간을 설정하기 위해 필요하다.

    다음에 생성할 음의 길이를 설정할 때는 반대로 배열의 처음에 위치하게 된다. 

 

4. 각 음계의 변화표의 유무를 localKey [] 배열에 순서대로 저장한다.

    상기 악보에는 변화표가 없다. 따라서 값은 모두 0이 된다. 쉼표 자리도 표기해주어야 한다.

const uint8_t localKey[] PROGMEM= {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, // 배열의 마지막에는 전체 멜로디 쉬는 시간을 위한 칸을 생성해준다.
};

 

5. 각 음계/쉼표의 길이를 Mdur [] 배열에 순서대로 저장한다.

    상기 악보에는 4분 음표/쉼표, 8분 음표가 있다. 4분 음표/쉼표는 4, 8분 음표는 2를 입력해 준다.

    이때 배열의 맨 처음 값으로 멜로디 재 실행 시 쉬는 시간을 설정해 준다.

const uint8_t Mdur[] PROGMEM= {
16, // 멜로디 재 실행시 4박 만큼 쉰다.
4, 4, 2, 2, 2, 2, 4, 4, 4, 4, 
4, 4, 2, 2, 2, 2, 4, 4, 4, 4,
};

 

이로써 악보를 보고 멜로디를 코딩하는 작업은 완료되었다.

 

이제 상기 멜로디를 아두이노 루프 함수에서 재생하는 코드를 살표 보자.

bool beepMelody = false;
unsigned long int beepTime = 0;

void loop() {
  if(Serial.available() > 0){
    String temp = Serial.readStringUntil('\n');
    Serial.println(temp);
    if (temp == "0") {
      beepMelody = !beepMelody;
      noteNum = 0; beepTime = 0;
    }
  }
  if (beepMelody) {
    if (millis() - beepTime >= pgm_read_byte(&Mdur[noteNum])*(1000/(4*tempoRatio))) {
      beepTime = millis();
      noTone(beepPin);
      octaveTemp = pgm_read_byte(&Moct[noteNum]);
      note_t KeyNote = keySignature(pgm_read_word(&Mnote[noteNum]));
      tone(beepPin, ledcWriteNote(KeyNote, octaveTemp));  // ledcWriteNote(uint8_t channel, note_t note, uint8_t octaveTemp);
      noteNum++;
      if (noteNum == sizeof(Mdur)) { // 초기화
        noTone(beepPin);  
        noteNum = 0; 
      }
    }
  } 
}

시리얼 모니터에 0을 입력하면 플래그 beepMelody가 반전하면서 delay() 함수 대체 코드인 millis() 함수를 작동시키게 된다. 최초에는 millis() 함수에 바로 진입하게 되고 noteNum이 0 값인 멜로디를 실행한 뒤에 noteNum을 1로 변경한 뒤 millis() 함수를 빠져나갔다가 음의 길이를 설정한 함수 Mdur [1] 값이 포함된 연산 값이 조건을 만족할 때까지 기다리게 된다. 조건이 만족되면 millis() 함수에 들어와서 noteNum이 1 값인 멜로디를 실행하고 반복하게 된다.

음의 길이가 멜로디 출력 후 조건에 걸리게 되므로 음의 길이를 저장하는 Mdur [] 배열의 값이 한 칸씩 밀리게 된다.

이렇게, 음의 길이가 한 칸씩 밀리는 것에 대응하여 배열의 마지막에 더미 값 0을 추가하여 배열의 총개수를 맞추어 준다.

 

2023년 2월 7일 업데이트 

상기 재생 코드에서는 한 음이 종료되면 무조건 noTone(beepPin);이 실행되게 되어 있습니다. 이는 같은 음 일 때 음 박자를 구분하고자 함입니다. 하지만 음이 변경된 상태에서도 실행되므로 출력음이 툭툭 끊기는 느낌이 납니다. 같은 음이 연속으로 실행될 때만 noTone(beepPin);이 실행되도록 코드를 수정해 주었습니다. 수정전과 멜로디 느낌이 약간 달라지게 됩니다. 

note_t oldKeyNote; // 이전 노트 키
uint8_t oldOctave = 255; // 이전 옥타브

void loop() {
  if(Serial.available() > 0){
    String temp = Serial.readStringUntil('\n');
    Serial.println(temp);
    if (temp == "0") {
      beepMelody = !beepMelody;
      noteNum = 0; beepTime = 0; oldOctave = 255;
      if (!beepMelody) noTone(beepPin);  
    }
  }
  if (beepMelody) {
    if (millis() - beepTime >= pgm_read_byte(&Mdur[noteNum])*(1000/(4*tempoRatio))) {
      beepTime = millis();
      octaveTemp = pgm_read_byte(&Moct[noteNum]);
      note_t KeyNote = keySignature(pgm_read_word(&Mnote[noteNum]));
      if (oldKeyNote == KeyNote && oldOctave == octaveTemp) noTone(beepPin); // 키와 옥타브가 이전과 같다면
      tone(beepPin, ledcWriteNote(KeyNote, octaveTemp));  
      oldKeyNote = KeyNote; oldOctave = octaveTemp;
      noteNum++;
      if (noteNum == sizeof(Mdur)) { // 초기화
        noTone(beepPin);  
        noteNum = 0; oldOctave = 255;
      }
    }
  } 
}

 

 

 

 

안드로이드 앱을 이용하여 멜로디 코딩하기

상기처럼 직접 음계, 옥타브, 변화표, 박자를 직접 배열에 입력해 주어도 되지만 악보가 복잡할수록 음을 코드로 변환할 때 오류가 발생할 확률이 높아지게 된다. 스마트폰에서 악보를 그려주면 상기의 코드가 생성되는 앱을 이용해 보자. 이때에는 생성된 코드를 아두이노에 복사하여 붙여 넣기 하면 코딩이 완료된다. 

자막에 설명 있습니다.

https://youtu.be/onkxA5WYSqc

앱은 1일 1회 악보 편집화면 이동시 전명광고를 게시합니다.


Simple Melody 앱 다운로드 - 상기의 아두이노 코드로 작동하는 앱이다.

play.google.com/store/apps/details?id=com.appybuilder.dfplayer_basic.DFcontroller_basic

 

1. 악보 편집화면으로 이동한다. Note 버튼 -> New 버튼 클릭

Piano 화면
Note 화면
New 화면

- 악보 설정
2. 멜로디 이름을 입력하고 저장을 클릭해 준다.
3. 악보의 조표를 입력한다.

조표가 없다면 C Major
b 한개: F Major
b 두개: Bb Major
b 세개: Eb Major
b 네개: Ab Major
b 다섯개: Db Major
b 여섯개: Gb Major
b 일곱개: Cb Major
# 한개: G Major
# 두개: D Major
# 세개: A Major
# 네개: E Major
# 다섯개: B Major
# 여섯개: F# Major
# 일곱개: C# Major


4. 악보의 빠르기(템포)와 박자표를 입력해 준다.
5. 악보의 한 절씩 표시하도록 Focus View를 활성화한다.
6. 한 절에 몇 마디를 표시할 건지 지정해 준다.

- 음계 입력
7. 변화표가 있다면 입력해 준다.
8. 음계/쉼표를 입력한다.
9. 옥타브를 입력한다.
10. 박자를 입력한다.
11. 현재 음을 수정한다면 Modify 버튼을 클릭하고, 추가한다면 Add 버튼을, 삭제한다면 Del 버튼을 클릭한다.
12. 모든 음계의 입력이 완료되면 저장을 한번 더 눌러 저장한다. 다운로드 폴더에 상기의 이름으로 저장된다.

 

** 쉼표 / 이음표의 입력

쉼표를 입력할 경우에는 음계에서 R을 선택하고 현재 옥타브와 쉼표의 박자를 입력해 준다.
이음표를 입력할 경우에는 음계에서 R을, 옥타브는 0을 선택하고, 이음표 박자를 입력해 준다.

 

저장된 코드의 확인

피아노 또는 노트 화면에서 Code 버튼을 클릭하면 저장된 코드를 확인할 수 있다.

 

아두이노에 생성된 코드 옮기기

컴퓨터의 메모장 프로그램에서 해당 note파일을 열면 아두이노 코드를 확인할 수 있고 그 코드를 복사하여 아두이노 코드에 붙여 넣기 해주면 된다.

겨울밤.note
0.00MB

 

아두이노 연결

 

피에조 부저 '+' -> 아두이노 10번핀

 

 

예제 코드

 

아두이노 멜로디 코드: 동요 겨울밤

피에조 부저 + 연결: 아두이노 10번핀(int beepPin = 10;)

arduinoUno_melody_progmem.ino
0.01MB

// --------------- note setup ----------------------------------

// 12화음 이름 정의
typedef enum {
  NOTE_C, NOTE_Cs, NOTE_D, NOTE_Eb, NOTE_E, NOTE_F, NOTE_Fs, NOTE_G, NOTE_Gs, 
  NOTE_A, NOTE_Bb, NOTE_B, NOTE_MAX
} note_t;

// 화음별 피에조 부저 진동수 정의 및 옥타브에 따른 값 변경 함수
double ledcWriteNote(note_t note, uint8_t octave){
  const uint16_t noteFrequencyBase[12] = {
  //  1      2      3      4      5      6     7       8     9       10    11      12
  //  C      C#     D      Eb     E      F     F#      G     G#      A     Bb      B
     4186,  4435,  4699,  4978,  5274,  5588,  5920,  6272,  6645,  7040,  7459,  7902
  };
  if(octave > 8 || note >= NOTE_MAX){
    return 0;
  }
  double noteFreq =  (double)noteFrequencyBase[note] / (double)(1 << (8-octave));
  return noteFreq;
}

// Note Code
// ---------------------------------------------------------------------- 동요: 겨울밤
uint8_t Tempo = 120; // 1, 1박자 = 1000/(tempoRatio), 비트수 = 2 = 2000
float tempoRatio = float(Tempo)/60.0;
uint8_t KeySign = 0; //  0 ~ 14, flat: 1 ~ 7, sharp: 8 ~ 14
uint8_t octaveTemp = 4; // 조표 변화시 옥타브 변경에 사용
//float beatTime = 2/4;

const note_t Mnote[] PROGMEM= { // 겨울밤
NOTE_G, NOTE_G, NOTE_G, NOTE_A, NOTE_G, NOTE_F, NOTE_E, NOTE_E, NOTE_E, NOTE_MAX,
NOTE_F, NOTE_F, NOTE_F, NOTE_G, NOTE_F, NOTE_E, NOTE_D, NOTE_D, NOTE_D, NOTE_MAX,
NOTE_C, NOTE_D, NOTE_E, NOTE_F, NOTE_G, NOTE_G, NOTE_G, NOTE_A, NOTE_G, NOTE_MAX,
NOTE_C, NOTE_G, NOTE_G, NOTE_A, NOTE_G, NOTE_F, NOTE_E, NOTE_F, NOTE_G, NOTE_MAX,
NOTE_C, NOTE_G, NOTE_G, NOTE_A, NOTE_G, NOTE_F, NOTE_E, NOTE_D, NOTE_C, NOTE_MAX,
};

const uint8_t Moct[] PROGMEM= { // 멜로디 옥타브 C ~ B, 4옥타브: 88키보드 가운데 도(C4) ~ 시(B4)
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
0,
};

const uint8_t localKey[] PROGMEM= {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0,
};

const uint8_t Mdur[] PROGMEM= {
16, 
4, 4, 2, 2, 2, 2, 4, 4, 4, 4, 
4, 4, 2, 2, 2, 2, 4, 4, 4, 4, 
4, 4, 4, 4, 2, 2, 2, 2, 4, 4, 
4, 4, 2, 2, 2, 2, 4, 4, 4, 4, 
4, 4, 2, 2, 2, 2, 4, 4, 4, 4, 
};
// ----------------------------------------------------------------------

uint8_t noteNum = 0;

note_t keySignature(note_t note) {
  if (pgm_read_byte(&localKey[noteNum]) == 0) {
    if (KeySign == 1) { // F Major (바장조)
      if (note == NOTE_B) note = NOTE_Bb;
    } else if (KeySign == 2) { 
      if (note == NOTE_B) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_Eb;
    } else if (KeySign == 3) {
      if (note == NOTE_B) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Gs;
    } else if (KeySign == 4) { 
      if (note == NOTE_B) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Cs;
    } else if (KeySign == 5) { 
      if (note == NOTE_B) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Fs;
    } else if (KeySign == 6) {
      if (note == NOTE_B) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Fs;
      else if (note == NOTE_C) { note = NOTE_B; octaveTemp -= 1; }
    } else if (KeySign == 7) { 
      if (note == NOTE_B) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Fs;
      else if (note == NOTE_C) { note = NOTE_B; octaveTemp -= 1; }
      else if (note == NOTE_F) note = NOTE_E;
    } else if (KeySign == 8) { 
      if (note == NOTE_F) note = NOTE_Fs;
    } else if (KeySign == 9) {
      if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_C) note = NOTE_Cs;
    } else if (KeySign == 10) {
      if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_C) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Gs;
    } else if (KeySign == 11) { 
      if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_C) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Eb;
    } else if (KeySign == 12) {
      if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_C) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Bb;
    } else if (KeySign == 13) {
      if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_C) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_F;
    } else if (KeySign == 14) { 
      if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_C) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_F;
      else if (note == NOTE_B) { note = NOTE_C; octaveTemp += 1; }
    }
  }
  else { // 1. natural
    if (pgm_read_byte(&localKey[noteNum]) == 2) { // 2. b
      if (note == NOTE_C) { note = NOTE_B; octaveTemp -= 1; }
      else if (note == NOTE_D) note = NOTE_Cs;
      else if (note == NOTE_E) note = NOTE_Eb;
      else if (note == NOTE_F) note = NOTE_E;
      else if (note == NOTE_G) note = NOTE_Fs;
      else if (note == NOTE_A) note = NOTE_Gs;
      else if (note == NOTE_B) note = NOTE_Bb;
    }
    else if (pgm_read_byte(&localKey[noteNum]) == 3) { // 3. #
      if (note == NOTE_C) note = NOTE_Cs;
      else if (note == NOTE_D) note = NOTE_Eb;
      else if (note == NOTE_E) note = NOTE_F;
      else if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_G) note = NOTE_Gs;
      else if (note == NOTE_A) note = NOTE_Bb;
      else if (note == NOTE_B) { note = NOTE_C; octaveTemp += 1; }
    }
    else if (pgm_read_byte(&localKey[noteNum]) == 4) { // 4. bb
      if (note == NOTE_C) { note = NOTE_Bb; octaveTemp -= 1; }
      else if (note == NOTE_D) note = NOTE_C;
      else if (note == NOTE_E) note = NOTE_D;
      else if (note == NOTE_F) note = NOTE_Eb;
      else if (note == NOTE_G) note = NOTE_F;
      else if (note == NOTE_A) note = NOTE_G;
      else if (note == NOTE_B) note = NOTE_A;
    }
    else if (pgm_read_byte(&localKey[noteNum]) == 5) { // 5. ##
      if (note == NOTE_C) note = NOTE_D;
      else if (note == NOTE_D) note = NOTE_E;
      else if (note == NOTE_E) note = NOTE_Fs;
      else if (note == NOTE_F) note = NOTE_G;
      else if (note == NOTE_G) note = NOTE_A;
      else if (note == NOTE_A) note = NOTE_B;
      else if (note == NOTE_B) { note = NOTE_Cs; octaveTemp += 1; }
    }
  }
  return note;
}

// --------------- note setup ----------------------------------

int beepPin = 10;

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

bool beepMelody = false;
unsigned long int beepTime = 0;

void loop() {
  if(Serial.available() > 0){
    String temp = Serial.readStringUntil('\n');
    Serial.println(temp);
    if (temp == "0") {
      beepMelody = !beepMelody;
      noteNum = 0; beepTime = 0;
      if (!beepMelody) noTone(beepPin);  
    }
  }
  if (beepMelody) {
    if (millis() - beepTime >= pgm_read_byte(&Mdur[noteNum])*(1000/(4*tempoRatio))) {
      beepTime = millis();
      noTone(beepPin);
      octaveTemp = pgm_read_byte(&Moct[noteNum]);
      note_t KeyNote = keySignature(pgm_read_word(&Mnote[noteNum]));
      tone(beepPin, ledcWriteNote(KeyNote, octaveTemp));  
      noteNum++;
      if (noteNum == sizeof(Mdur)) { // 초기화
        noTone(beepPin);  
        noteNum = 0; 
      }
    }
  } 
}

 

2023년 2월 7일 업데이트 코드 

arduinoUno_melody_progmem_update.zip

arduinoUno_melody_progmem_update.zip
0.00MB

 

ESP32 멜로디 코드: 동요 겨울밤

피에조 부저 + 연결: ESP32 25번핀(int beepPin = 25;)

esp32_melody.ino
0.01MB

// --------------- note setup ----------------------------------
// Note Code
// ---------------------------------------------------------------------- 동요: 겨울밤
uint8_t Tempo = 120; // 1, 1박자 = 1000/(tempoRatio), 비트수 = 2 = 2000
uint8_t tempoRatio = Tempo/60;
uint8_t KeySign = 0; //  0 ~ 14, flat: 1 ~ 7, sharp: 8 ~ 14
uint8_t octaveTemp = 4; // 조표 변화시 옥타브 변경에 사용
//float beatTime = 2/4; // 박자표 - 멜로디 코드에서는 사용하지 않는다.

const note_t Mnote[] PROGMEM= { // 겨울밤
NOTE_G, NOTE_G, NOTE_G, NOTE_A, NOTE_G, NOTE_F, NOTE_E, NOTE_E, NOTE_E, NOTE_MAX,
NOTE_F, NOTE_F, NOTE_F, NOTE_G, NOTE_F, NOTE_E, NOTE_D, NOTE_D, NOTE_D, NOTE_MAX,
NOTE_C, NOTE_D, NOTE_E, NOTE_F, NOTE_G, NOTE_G, NOTE_G, NOTE_A, NOTE_G, NOTE_MAX,
NOTE_C, NOTE_G, NOTE_G, NOTE_A, NOTE_G, NOTE_F, NOTE_E, NOTE_F, NOTE_G, NOTE_MAX,
NOTE_C, NOTE_G, NOTE_G, NOTE_A, NOTE_G, NOTE_F, NOTE_E, NOTE_D, NOTE_C, NOTE_MAX,
};

const uint8_t Moct[] PROGMEM= { // 멜로디 옥타브 C ~ B, 4옥타브: 88키보드 가운데 도(C4) ~ 시(B4)
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
0,
};

const uint8_t localKey[] PROGMEM= {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0,
};

const uint8_t Mdur[] PROGMEM= {
16, 
4, 4, 2, 2, 2, 2, 4, 4, 4, 4, 
4, 4, 2, 2, 2, 2, 4, 4, 4, 4, 
4, 4, 4, 4, 2, 2, 2, 2, 4, 4, 
4, 4, 2, 2, 2, 2, 4, 4, 4, 4, 
4, 4, 2, 2, 2, 2, 4, 4, 4, 4, 
};
// ----------------------------------------------------------------------

uint8_t noteNum = 0;

note_t keySignature(note_t note) {
  if (localKey[noteNum] == 0) {
    if (KeySign == 1) { // F Major (바장조)
      if (note == NOTE_B) note = NOTE_Bb;
    } else if (KeySign == 2) { 
      if (note == NOTE_B) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_Eb;
    } else if (KeySign == 3) {
      if (note == NOTE_B) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Gs;
    } else if (KeySign == 4) { // 
      if (note == NOTE_B) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Cs;
    } else if (KeySign == 5) { 
      if (note == NOTE_B) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Fs;
    } else if (KeySign == 6) {
      if (note == NOTE_B) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Fs;
      else if (note == NOTE_C) { note = NOTE_B; octaveTemp -= 1; }
    } else if (KeySign == 7) { //
      if (note == NOTE_B) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Fs;
      else if (note == NOTE_C) { note = NOTE_B; octaveTemp -= 1; }
      else if (note == NOTE_F) note = NOTE_E;
    } else if (KeySign == 8) { 
      if (note == NOTE_F) note = NOTE_Fs;
    } else if (KeySign == 9) {
      if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_C) note = NOTE_Cs;
    } else if (KeySign == 10) {
      if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_C) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Gs;
    } else if (KeySign == 11) { 
      if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_C) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Eb;
    } else if (KeySign == 12) {
      if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_C) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Bb;
    } else if (KeySign == 13) {
      if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_C) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_F;
    } else if (KeySign == 14) { 
      if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_C) note = NOTE_Cs;
      else if (note == NOTE_G) note = NOTE_Gs;
      else if (note == NOTE_D) note = NOTE_Eb;
      else if (note == NOTE_A) note = NOTE_Bb;
      else if (note == NOTE_E) note = NOTE_F;
      else if (note == NOTE_B) { note = NOTE_C; octaveTemp += 1; }
    }
  }
  else { // 1. natural
    if (localKey[noteNum] == 2) { // 2. b
      if (note == NOTE_C) { note = NOTE_B; octaveTemp -= 1; }
      else if (note == NOTE_D) note = NOTE_Cs;
      else if (note == NOTE_E) note = NOTE_Eb;
      else if (note == NOTE_F) note = NOTE_E;
      else if (note == NOTE_G) note = NOTE_Fs;
      else if (note == NOTE_A) note = NOTE_Gs;
      else if (note == NOTE_B) note = NOTE_Bb;
    }
    else if (localKey[noteNum] == 3) { // 3. #
      if (note == NOTE_C) note = NOTE_Cs;
      else if (note == NOTE_D) note = NOTE_Eb;
      else if (note == NOTE_E) note = NOTE_F;
      else if (note == NOTE_F) note = NOTE_Fs;
      else if (note == NOTE_G) note = NOTE_Gs;
      else if (note == NOTE_A) note = NOTE_Bb;
      else if (note == NOTE_B) { note = NOTE_C; octaveTemp += 1; }
    }
    else if (localKey[noteNum] == 4) { // 4. bb
      if (note == NOTE_C) { note = NOTE_Bb; octaveTemp -= 1; }
      else if (note == NOTE_D) note = NOTE_C;
      else if (note == NOTE_E) note = NOTE_D;
      else if (note == NOTE_F) note = NOTE_Eb;
      else if (note == NOTE_G) note = NOTE_F;
      else if (note == NOTE_A) note = NOTE_G;
      else if (note == NOTE_B) note = NOTE_A;
    }
    else if (localKey[noteNum] == 5) { // 5. ##
      if (note == NOTE_C) note = NOTE_D;
      else if (note == NOTE_D) note = NOTE_E;
      else if (note == NOTE_E) note = NOTE_Fs;
      else if (note == NOTE_F) note = NOTE_G;
      else if (note == NOTE_G) note = NOTE_A;
      else if (note == NOTE_A) note = NOTE_B;
      else if (note == NOTE_B) { note = NOTE_Cs; octaveTemp += 1; }
    }
  }
  return note;
}
// --------------- note setup ----------------------------------

int beepPin = 25;

void setup() {
  Serial.begin(115200);
  ledcSetup(0,1E5,12);  // ESP32 톤전용 ledcSetup: ledcSetup(channel,1E5,12);
  ledcAttachPin(beepPin,0);  // ledcAttachPin(uint8_t pin, uint8_t channel);
}

bool beepMelody = false;
unsigned long int beepTime = 0;

void loop() {
  if(Serial.available() > 0){
    String temp = Serial.readStringUntil('\n');
    Serial.println(temp);
    if (temp == "0") {
      beepMelody = !beepMelody;
      noteNum = 0; beepTime = 0;
      if (!beepMelody) ledcWrite(0,0);
    }
  }
  if (beepMelody) {
    if (millis() - beepTime >= Mdur[noteNum]*(1000/(4*tempoRatio))) {
      beepTime = millis();
      ledcWrite(0,0); 
      octaveTemp = Moct[noteNum];
      note_t KeyNote = keySignature(Mnote[noteNum]);
      ledcWriteNote(0, KeyNote, octaveTemp);  // ledcWriteNote(uint8_t channel, note_t note, uint8_t octaveTemp);
      noteNum++;
      if (noteNum == sizeof(Mdur)) { // 초기화
        ledcWrite(0,0);  //  noTone() - ledcWrite(uint8_t channel, uint32_t duty);
        noteNum = 0; 
      }
    }
  } 
}

2023년 2월 7일 업데이트 코드 

esp32_melody_update.zip

esp32_melody_update.zip
0.00MB

 

 

 

피에조 부저 동요별 멜로디 코드

1. 동요: 겨울밤

uint8_t Tempo = 120; // 1, 1박자 = 1000/(tempoRatio), 비트수 = 2 = 2000
float tempoRatio = float(Tempo)/60.0;
uint8_t KeySign = 0; //  0 ~ 14, flat: 1 ~ 7, sharp: 8 ~ 14
uint8_t octaveTemp = 4; // 조표 변화시 옥타브 변경에 사용

const note_t Mnote[] PROGMEM= { // 겨울밤
NOTE_G, NOTE_G, NOTE_G, NOTE_A, NOTE_G, NOTE_F, NOTE_E, NOTE_E, NOTE_E, NOTE_MAX,
NOTE_F, NOTE_F, NOTE_F, NOTE_G, NOTE_F, NOTE_E, NOTE_D, NOTE_D, NOTE_D, NOTE_MAX,
NOTE_C, NOTE_D, NOTE_E, NOTE_F, NOTE_G, NOTE_G, NOTE_G, NOTE_A, NOTE_G, NOTE_MAX,
NOTE_C, NOTE_G, NOTE_G, NOTE_A, NOTE_G, NOTE_F, NOTE_E, NOTE_F, NOTE_G, NOTE_MAX,
NOTE_C, NOTE_G, NOTE_G, NOTE_A, NOTE_G, NOTE_F, NOTE_E, NOTE_D, NOTE_C, NOTE_MAX,
};

const uint8_t Moct[] PROGMEM= { // 멜로디 옥타브 C ~ B, 4옥타브: 88키보드 가운데 도(C) ~ 시(B)
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
0,
};

const uint8_t localKey[] PROGMEM= {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0,
};

const uint8_t Mdur[] PROGMEM= {
16, 
4, 4, 2, 2, 2, 2, 4, 4, 4, 4, 
4, 4, 2, 2, 2, 2, 4, 4, 4, 4, 
4, 4, 4, 4, 2, 2, 2, 2, 4, 4, 
4, 4, 2, 2, 2, 2, 4, 4, 4, 4, 
4, 4, 2, 2, 2, 2, 4, 4, 4, 4, 
};

2. 동요:  작은 별

uint8_t Tempo = 120; // 1, 1박자 = 1000/(tempoRatio), 비트수 = 2 = 2000
float tempoRatio = float(Tempo)/60.0;
uint8_t KeySign = 0; //  0 ~ 14, flat: 1 ~ 7, sharp: 8 ~ 14
uint8_t octaveTemp = 4; // 조표 변화시 옥타브 변경에 사용

const note_t Mnote[] PROGMEM= { 
NOTE_C, NOTE_C, NOTE_G, NOTE_G, NOTE_A, NOTE_A, NOTE_G, NOTE_F, NOTE_F, NOTE_E, NOTE_E,
NOTE_D, NOTE_D, NOTE_C, NOTE_G, NOTE_G, NOTE_F, NOTE_F, NOTE_E, NOTE_E, NOTE_D,
NOTE_G, NOTE_G, NOTE_F, NOTE_F, NOTE_E, NOTE_E, NOTE_D, NOTE_C, NOTE_C, NOTE_G, NOTE_G, 
NOTE_A, NOTE_A, NOTE_G, NOTE_F, NOTE_F, NOTE_E, NOTE_E, NOTE_D, NOTE_D, NOTE_C,
};

const uint8_t Moct[] PROGMEM= { // 멜로디 옥타브 C ~ B, 4옥타브: 88키보드 가운데 도(C) ~ 시(B)
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
0,
};

const uint8_t localKey[] PROGMEM= {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0,
};

const uint8_t Mdur[] PROGMEM= {
16, 
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4,  
4, 4, 8, 4, 4, 4, 4, 4, 4, 8,
4, 4, 4, 4, 4, 4, 8, 4, 4, 4, 4,  
4, 4, 8, 4, 4, 4, 4, 4, 4, 8,
};

3. 동요: 둥근 해가 떴습니다

uint8_t Tempo = 120; // 1, 1박자 = 1000/(tempoRatio), 비트수 = 2 = 2000
float tempoRatio = float(Tempo)/60.0;
uint8_t KeySign = 0; //  0 ~ 14, flat: 1 ~ 7, sharp: 8 ~ 14
uint8_t octaveTemp = 4; // 조표 변화시 옥타브 변경에 사용

const note_t Mnote[] PROGMEM= { 
NOTE_E, NOTE_D, NOTE_C, NOTE_D, NOTE_E, NOTE_C, NOTE_C, NOTE_A, NOTE_G, NOTE_E, NOTE_C, NOTE_D, NOTE_E, NOTE_G, NOTE_E, NOTE_D, NOTE_MAX,
NOTE_E, NOTE_D, NOTE_C, NOTE_D, NOTE_E, NOTE_C, NOTE_C, NOTE_A, NOTE_G, NOTE_A, NOTE_C, NOTE_D, NOTE_E, NOTE_D, NOTE_C, NOTE_MAX,
NOTE_C, NOTE_C, NOTE_A, NOTE_C, NOTE_A, NOTE_G, NOTE_G, NOTE_E, NOTE_A, NOTE_A, NOTE_G, NOTE_G, NOTE_E, NOTE_D, NOTE_D, NOTE_E, 
NOTE_E, NOTE_D, NOTE_C, NOTE_D, NOTE_E, NOTE_C, NOTE_C, NOTE_A, NOTE_G, NOTE_A, NOTE_C, NOTE_D, NOTE_E, NOTE_D, NOTE_C, NOTE_MAX,
NOTE_E, NOTE_D, NOTE_C, NOTE_D, NOTE_E, NOTE_C, NOTE_C, NOTE_A, NOTE_G, NOTE_E, NOTE_C, NOTE_D, NOTE_E, NOTE_G, NOTE_E, NOTE_D, NOTE_MAX,
NOTE_E, NOTE_D, NOTE_C, NOTE_D, NOTE_E, NOTE_C, NOTE_C, NOTE_A, NOTE_G, NOTE_A, NOTE_C, NOTE_D, NOTE_E, NOTE_D, NOTE_C, NOTE_MAX,
};

const uint8_t Moct[] PROGMEM= { // 멜로디 옥타브 C ~ B, 4옥타브: 88키보드 가운데 도(C) ~ 시(B)
4, 4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
5, 5, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
0,
};

const uint8_t localKey[] PROGMEM= {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
};

const uint8_t Mdur[] PROGMEM= {
16, 
3, 1, 3, 1, 4, 4, 8, 8, 3, 1, 3, 1, 4, 3, 1, 12, 4,
3, 1, 3, 1, 4, 4, 8, 8, 3, 1, 3, 1, 4, 4, 12, 4,
4, 4, 4, 2, 2, 4, 4, 8, 4, 4, 4, 3, 1, 4, 4, 8,
3, 1, 3, 1, 4, 4, 8, 8, 3, 1, 3, 1, 4, 4, 12, 4,
3, 1, 3, 1, 4, 4, 8, 8, 3, 1, 3, 1, 4, 3, 1, 12, 4,
3, 1, 3, 1, 4, 4, 8, 8, 3, 1, 3, 1, 4, 4, 12, 4,
};

4. 동요: 어린 음악대

uint8_t Tempo = 120; // 1, 1박자 = 1000/(tempoRatio), 비트수 = 2 = 2000
float tempoRatio = float(Tempo)/60.0;
uint8_t KeySign = 8; //  0 ~ 14, flat: 1 ~ 7, sharp: 8 ~ 14
uint8_t octaveTemp = 4; // 조표 변화시 옥타브 변경에 사용

const note_t Mnote[] PROGMEM= { 
NOTE_D, NOTE_G, NOTE_G, NOTE_B, NOTE_D, NOTE_D, NOTE_C, NOTE_B, NOTE_A, NOTE_G, NOTE_A, NOTE_MAX,
NOTE_D, NOTE_G, NOTE_G, NOTE_B, NOTE_D, NOTE_D, NOTE_C, NOTE_B, NOTE_A, NOTE_A, NOTE_G, NOTE_MAX,
NOTE_G, NOTE_D, NOTE_B, NOTE_G, NOTE_D, NOTE_D, NOTE_B, NOTE_B, NOTE_A, NOTE_MAX,
NOTE_G, NOTE_D, NOTE_B, NOTE_G, NOTE_C, NOTE_C, NOTE_A, NOTE_A, NOTE_G, NOTE_MAX,
};

const uint8_t Moct[] PROGMEM= { // 멜로디 옥타브 C ~ B, 4옥타브: 88키보드 가운데 도(C) ~ 시(B)
4, 4, 4, 4, 5, 5, 5, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 5, 5, 5, 4, 4, 4, 4, 4,  
4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 
4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 
0,
};

const uint8_t localKey[] PROGMEM= {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0,
};

const uint8_t Mdur[] PROGMEM= {
16, 
2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 6, 2, 
2, 2, 4, 2, 2, 4, 2, 2, 2, 2, 6, 2, 
6, 2, 6, 2, 2, 2, 2, 2, 6, 2, 
6, 2, 6, 2, 2, 2, 2, 2, 6, 2, 
};

5. 동요: 바둑이 방울

uint8_t Tempo = 120; // 1, 1박자 = 1000/(tempoRatio), 비트수 = 2 = 2000
float tempoRatio = float(Tempo)/60.0;
uint8_t KeySign = 0; //  0 ~ 14, flat: 1 ~ 7, sharp: 8 ~ 14
uint8_t octaveTemp = 4; // 조표 변화시 옥타브 변경에 사용

const note_t Mnote[] PROGMEM= { 
NOTE_C, NOTE_E, NOTE_E, NOTE_E, NOTE_E, NOTE_E, NOTE_D, NOTE_F, NOTE_F, NOTE_F, NOTE_F, NOTE_F, NOTE_E, NOTE_G, NOTE_G, NOTE_G, NOTE_E, 
NOTE_D, NOTE_F, NOTE_E, NOTE_D, NOTE_C, NOTE_MAX, NOTE_C, NOTE_C, NOTE_G, NOTE_G, NOTE_A, NOTE_C, NOTE_B, NOTE_A, NOTE_G, NOTE_MAX,
NOTE_C, NOTE_C, NOTE_G, NOTE_G, NOTE_A, NOTE_C, NOTE_B, NOTE_A, NOTE_G, NOTE_F, NOTE_E, NOTE_D, NOTE_C, NOTE_E, NOTE_E, NOTE_E, NOTE_E, NOTE_E, 
NOTE_D, NOTE_F, NOTE_F, NOTE_F, NOTE_F, NOTE_F, NOTE_E, NOTE_G, NOTE_G, NOTE_G, NOTE_E, NOTE_D, NOTE_F, NOTE_E, NOTE_D, NOTE_C, NOTE_MAX,
};

const uint8_t Moct[] PROGMEM= { // 멜로디 옥타브 C ~ B, 4옥타브: 88키보드 가운데 도(C) ~ 시(B)
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 5, 5, 4, 4, 4, 5, 4, 4, 4, 4,
5, 5, 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
0,
};

const uint8_t localKey[] PROGMEM= {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
0,
};

const uint8_t Mdur[] PROGMEM= {
16, 
2, 2, 2, 2, 4, 4, 2, 2, 2, 2, 4, 4, 2, 2, 4, 4, 4, 
2, 2, 2, 2, 6, 2, 4, 4, 4, 4, 2, 2, 2, 2, 6, 2, 
4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 4, 
2, 2, 2, 2, 4, 4, 2, 2, 4, 4, 4, 2, 2, 2, 2, 6, 2,  
};

6. 동요: 귀여운 꼬마

uint8_t Tempo = 120; // 1, 1박자 = 1000/(tempoRatio), 비트수 = 2 = 2000
float tempoRatio = float(Tempo)/60.0;
uint8_t KeySign = 3; //  0 ~ 14, flat: 1 ~ 7, sharp: 8 ~ 14
uint8_t octaveTemp = 4; // 조표 변화시 옥타브 변경에 사용

const note_t Mnote[] PROGMEM= { 
NOTE_E, NOTE_E, NOTE_G, NOTE_B, NOTE_B, NOTE_G, NOTE_C, NOTE_C, NOTE_G, NOTE_B, NOTE_B, NOTE_A, NOTE_A, NOTE_F, NOTE_G, NOTE_G, NOTE_G, NOTE_E, 
NOTE_F, NOTE_F, NOTE_D, NOTE_E, NOTE_E, NOTE_E, NOTE_E, NOTE_G, NOTE_B, NOTE_B, NOTE_G, NOTE_C, NOTE_C, NOTE_G, NOTE_B, NOTE_B, NOTE_A, NOTE_A, NOTE_F,
NOTE_G, NOTE_G, NOTE_E, NOTE_F, NOTE_F, NOTE_F, NOTE_D, NOTE_E, NOTE_B, NOTE_G, NOTE_E, NOTE_MAX, NOTE_E, NOTE_G, NOTE_F, NOTE_F, NOTE_F, 
NOTE_D, NOTE_B, NOTE_B, NOTE_G, NOTE_E, NOTE_MAX, NOTE_E, NOTE_G, NOTE_F, NOTE_F, NOTE_F, NOTE_D, NOTE_B, NOTE_E, NOTE_E, NOTE_G, NOTE_B, NOTE_B, NOTE_G, 
NOTE_C, NOTE_C, NOTE_G, NOTE_B, NOTE_B, NOTE_A, NOTE_A, NOTE_F, NOTE_G, NOTE_G, NOTE_E, NOTE_F, NOTE_F, NOTE_F, NOTE_D, NOTE_E, 
};

const uint8_t Moct[] PROGMEM= { // 멜로디 옥타브 C ~ B, 4옥타브: 88키보드 가운데 도(C) ~ 시(B)
4, 4, 4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 
5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
0,
};

const uint8_t localKey[] PROGMEM= {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0,
};

const uint8_t Mdur[] PROGMEM= {
16, 
4, 2, 2, 4, 2, 2, 4, 2, 2, 4, 4, 4, 2, 2, 2, 2, 2, 2, 
4, 2, 2, 8, 2, 2, 2, 2, 4, 2, 2, 4, 2, 2, 4, 4, 4, 2, 2, 
4, 2, 2, 2, 2, 2, 2, 8, 6, 2, 2, 2, 2, 2, 4, 2, 2, 
4, 4, 6, 2, 2, 2, 2, 2, 4, 2, 2, 4, 4, 4, 2, 2, 4, 2, 2, 
4, 2, 2, 4, 4, 4, 2, 2, 4, 2, 2, 2, 2, 2, 2, 8,
};

7. 동요: 어린 송아지

uint8_t Tempo = 120; // 1, 1박자 = 1000/(tempoRatio), 비트수 = 2 = 2000
float tempoRatio = float(Tempo)/60.0;
uint8_t KeySign = 9; //  0 ~ 14, flat: 1 ~ 7, sharp: 8 ~ 14
uint8_t octaveTemp = 4; // 조표 변화시 옥타브 변경에 사용

const note_t Mnote[] PROGMEM= { 
NOTE_D, NOTE_D, NOTE_D, NOTE_D, NOTE_D, NOTE_D, NOTE_F, NOTE_F, NOTE_F, NOTE_F, NOTE_F, NOTE_F, 
NOTE_A, NOTE_A, NOTE_A, NOTE_D, NOTE_A, NOTE_MAX, NOTE_D, NOTE_D, NOTE_A, NOTE_MAX, NOTE_D,
NOTE_D, NOTE_A, NOTE_F, NOTE_F, NOTE_F, NOTE_F, NOTE_E, NOTE_E, NOTE_D, NOTE_MAX,
};

const uint8_t Moct[] PROGMEM= { // 멜로디 옥타브 C ~ B, 4옥타브: 88키보드 가운데 도(C) ~ 시(B)
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 5, 4, 4, 5, 5, 4, 4, 5, 
5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
0,
};

const uint8_t localKey[] PROGMEM= {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0,
};

const uint8_t Mdur[] PROGMEM= {
16, 
3, 1, 3, 1, 4, 4, 3, 1, 3, 1, 4, 4, 
4, 4, 4, 4, 12, 2, 2, 8, 4, 2, 2, 
8, 8, 3, 1, 3, 1, 4, 4, 12, 4,
};

8. 동요: 옹달샘

uint8_t Tempo = 120; // 1, 1박자 = 1000/(tempoRatio), 비트수 = 2 = 2000
float tempoRatio = float(Tempo)/60.0;
uint8_t KeySign = 8; //  0 ~ 14, flat: 1 ~ 7, sharp: 8 ~ 14
uint8_t octaveTemp = 4; // 조표 변화시 옥타브 변경에 사용

const note_t Mnote[] PROGMEM= { 
NOTE_B, NOTE_D, NOTE_G, NOTE_B, NOTE_D, NOTE_C, NOTE_E, NOTE_E, NOTE_D, NOTE_F, NOTE_A, NOTE_C, NOTE_B, NOTE_A, NOTE_G, NOTE_MAX,
NOTE_G, NOTE_B, NOTE_D, NOTE_C, NOTE_B, NOTE_A, NOTE_D, NOTE_F, NOTE_A, NOTE_C, NOTE_B, NOTE_A, NOTE_G,
NOTE_B, NOTE_D, NOTE_G, NOTE_B, NOTE_D, NOTE_C, NOTE_E, NOTE_E, NOTE_D, NOTE_F, NOTE_A, NOTE_C, NOTE_B, NOTE_A, NOTE_G, NOTE_MAX,
};

const uint8_t Moct[] PROGMEM= { // 멜로디 옥타브 C ~ B, 4옥타브: 88키보드 가운데 도(C) ~ 시(B)
3, 4, 4, 3, 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 
4, 4, 5, 5, 4, 4, 4, 4, 4, 5, 4, 4, 4, 
3, 4, 4, 3, 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 
0,
};

const uint8_t localKey[] PROGMEM= {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
0,
};

const uint8_t Mdur[] PROGMEM= {
16, 
2, 2, 2, 2, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 8, 4, 
4, 4, 4, 6, 2, 4, 4, 2, 2, 4, 6, 2, 4, 
2, 2, 2, 2, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 8, 4, 
};

9. 동요: 동네 한 바퀴

uint8_t Tempo = 120; // 1, 1박자 = 1000/(tempoRatio), 비트수 = 2 = 2000
float tempoRatio = float(Tempo)/60.0;
uint8_t KeySign = 1; //  0 ~ 14, flat: 1 ~ 7, sharp: 8 ~ 14
uint8_t octaveTemp = 4; // 조표 변화시 옥타브 변경에 사용

const note_t Mnote[] PROGMEM= { 
NOTE_F, NOTE_F, NOTE_G, NOTE_A, NOTE_F, NOTE_G, NOTE_G, NOTE_E, NOTE_E, NOTE_F, 
NOTE_A, NOTE_A, NOTE_A, NOTE_B, NOTE_C, NOTE_C, NOTE_A, NOTE_B, NOTE_B, NOTE_G, NOTE_G, NOTE_A,
NOTE_C, NOTE_C, NOTE_C, NOTE_C, NOTE_C, NOTE_D, NOTE_C, NOTE_B, NOTE_B, NOTE_C, NOTE_B, NOTE_A,
NOTE_A, NOTE_A, NOTE_A, NOTE_A, NOTE_A, NOTE_B, NOTE_A, NOTE_G, NOTE_G, NOTE_A, NOTE_G, NOTE_F,
NOTE_F, NOTE_F, NOTE_F, NOTE_F, NOTE_F, NOTE_F, NOTE_F, NOTE_F, NOTE_C, NOTE_C, NOTE_C, NOTE_C, NOTE_F,
};

const uint8_t Moct[] PROGMEM= { // 멜로디 옥타브 C ~ B, 4옥타브: 88키보드 가운데 도(C) ~ 시(B)
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 
5, 5, 5, 5, 5, 5, 5, 4, 4, 5, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
0,
};

const uint8_t localKey[] PROGMEM= {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
};

const uint8_t Mdur[] PROGMEM= {
16, 
4, 3, 1, 4, 4, 3, 1, 3, 1, 8, 
3, 1, 3, 1, 3, 1, 4, 3, 1, 3, 1, 8,
3, 1, 3, 1, 4, 3, 1, 3, 1, 3, 1, 8, 
3, 1, 4, 3, 1, 3, 1, 3, 1, 3, 1, 8, 
3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 8,
};

10. 동요: 다람쥐

uint8_t Tempo = 60; // 1, 1박자 = 1000/(tempoRatio), 비트수 = 2 = 2000
float tempoRatio = float(Tempo)/60.0;
uint8_t KeySign = 3; //  0 ~ 14, flat: 1 ~ 7, sharp: 8 ~ 14
uint8_t octaveTemp = 4; // 조표 변화시 옥타브 변경에 사용

const note_t Mnote[] PROGMEM= { // 다람쥐
NOTE_B, NOTE_B, NOTE_G, NOTE_C, NOTE_B, NOTE_B, NOTE_B, NOTE_MAX, NOTE_C, NOTE_C, NOTE_B, NOTE_E, NOTE_G, NOTE_MAX,
NOTE_F, NOTE_G, NOTE_F, NOTE_C, NOTE_B, NOTE_C, NOTE_B, NOTE_A, NOTE_G, NOTE_F, NOTE_G, NOTE_F, NOTE_B, NOTE_E, NOTE_MAX,
NOTE_F, NOTE_F, NOTE_D, NOTE_D, NOTE_E, NOTE_D, NOTE_E, NOTE_F, NOTE_G, NOTE_G, NOTE_A, NOTE_B, NOTE_C, NOTE_B, NOTE_B, NOTE_G, NOTE_MAX,
NOTE_B, NOTE_E, NOTE_C, NOTE_B, NOTE_C, NOTE_B, NOTE_G, NOTE_E, NOTE_G, NOTE_G, NOTE_F, NOTE_C, NOTE_B, NOTE_G, NOTE_F, NOTE_E, 
};

const uint8_t Moct[] PROGMEM= { // 멜로디 옥타브 C ~ B, 4옥타브: 88키보드 가운데 도(C) ~ 시(B)
4, 4, 4, 5, 4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 
4, 4, 4, 5, 4, 5, 4, 4, 4, 4, 4, 4, 3, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 
4, 5, 5, 4, 5, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 
0,
};

const uint8_t localKey[] PROGMEM= {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
};

const uint8_t Mdur[] PROGMEM= {
16, 
3, 1, 2, 2, 2, 2, 2, 2, 3, 1, 2, 2, 6, 2, 
3, 1, 2, 2, 1, 1, 1, 1, 4, 3, 1, 2, 2, 6, 2, 
2, 2, 2, 2, 3, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 
2, 4, 2, 1, 1, 2, 2, 2, 3, 1, 2, 2, 2, 1, 1, 4,
};

 

 

[arduino] - arduino - Simple Melody 이용 피에조 부저 멜로디 코딩하기, Esp01, EEPROM

[Simple Melody] - Simple Melody - 화사 마리아 멜로디 code 파일 (Hwa Sa Maria)

[Simple Melody] - Simple Melody - 방탄소년단 DNA 멜로디 code 파일 (BTS DNA)

[Simple Melody] - Simple Melody - BTS Dynamite 멜로디 code 파일

[arduino] - 아두이노 - 피에조 부저 멜로디 BTS DNA

[arduino] - 아두이노 - 피에조 부저 멜로디 Hwasa Maria

[arduino] - 아두이노 - 피에조 부저 멜로디 BTS Dynamite

[Piezo Buzzer] - BTS (방탄소년단) - Butter ㅣ piezo buzzer

 

 

 

+ Recent posts