라즈베리파이 부저로 예전에 음악처럼 만든 적이 있었습니다. 시간이 나서 한번 재현하려고 하다 파이썬을 이용하는 방법이 있어 게시글을 투고합니다.
사용 방법
pip install winsound
우선 이번에 이용할 모듈은 winsound라는 모듈입니다. 해당 모듈은 윈도우용으로 기본 소리 재생 장치들을 조작할 수 있습니다. 맥이나 리눅스를 사용하는 분은 다른 모듈을 참조하면 될 것 같습니다.
아래 링크는 windsound 모듈에 가이드입니다.
https://docs.python.org/ko/3/library/winsound.html
비프음을 예시 코드
imort winsound
winsound.Beep(440, 1000) # 440Hz, 1000ms
비프음을 사용하는 방법은 winsound 함수에 Beep 함수만 이용하면 됩니다. 여담으로 오케스트라가 악기를 맞추는 기준 음이 라(440Hz) 입니다.
음계별 주파수 (도레미파솔라시도)
음계 | 옥타브 | |||||||
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | |
C | 32.7 | 65.41 | 130.81 | 261.63 | 523.25 | 1046.5 | 2093 | 4186.01 |
C# | 34.65 | 69.3 | 138.59 | 277.18 | 554.37 | 1108.73 | 2217.46 | 4434.92 |
D | 36.71 | 73.42 | 146.83 | 293.66 | 587.33 | 1174.66 | 2349.32 | 4698.64 |
D# | 38.89 | 77.78 | 155.56 | 311.13 | 622.25 | 1244.51 | 2489.02 | 4978.03 |
E | 41.2 | 82.41 | 164.81 | 329.63 | 659.26 | 1318.51 | 2637.02 | 5274.04 |
F | 43.65 | 87.31 | 174.61 | 349.23 | 698.46 | 1396.91 | 2793.83 | 5587.65 |
F# | 46.25 | 92.5 | 185 | 369.99 | 739.99 | 1479.98 | 2959.96 | 5919.91 |
G | 49 | 98 | 196 | 392 | 783.99 | 1567.98 | 3135.96 | 6271.93 |
G# | 51.91 | 103.83 | 207.65 | 415.3 | 830.61 | 1661.22 | 3322.44 | 6644.88 |
A | 55 | 110 | 220 | 440 | 880 | 1760 | 3520 | 7040 |
A# | 58.27 | 116.54 | 233.08 | 466.16 | 932.33 | 1864.66 | 3729.31 | 7458.62 |
B | 61.74 | 123.47 | 246.94 | 493.88 | 987.77 | 1975.53 | 3951.07 | 7902.13 |
음계별 주파수 (단위 Hz)
우선 위의 표는 음계별 표준 주파수를 소수점 3번째 자리에서 반올림한 값입니다. 해당 표를 통해 알 수 있는 것은 각 옥타브로 넘어갈 때마다 주파수가 2배가 된다는 사실입니다. 또한 각 음계의 주파수는 아래의 규칙을 따른다는 것을 알 수 있습니다.
- 440 * 2 ^ (1 / 12) ≒ 466.16
이것을 12음계라고 부릅니다.
프로젝트에 적용하기 전 사람들이 쉽게 사용할 수 있도록 이것을 함수화 하도록 하겠습니다. 쉽게 구현하기 위해 기준이 되는 옥타브의 주파수를 매핑했습니다. 그리고 편의상 C부터 매핑했습니다.
import winsound
# 음계와 주파수 매핑
note_frequency = {
'C': 261.63,
'C#': 277.18,
'D': 293.66,
'D#': 311.13,
'E': 329.63,
'F': 349.23,
'F#': 369.99,
'G': 392.00,
'G#': 415.30,
'A': 440.00,
'A#': 466.16,
'B': 493.88
}
def play_note(note, octave, duration):
frequency = note_frequency[note]
winsound.Beep(int(frequency*(2**(octave-4))), int(duration * 1000))
# A음계를 1초 동안 재생
play_note('A', 4, 1)
키보드로 연주해 보자
마지막으로 키보드로 연주하는 예시를 구현해 보겠습니다.
키보드는 키보드 자판 배열에 쉽게 맞출 수 있도록 아래와 같이 설정했습니다.
W(C#4) | E(D#4) | T(F#4) | I(G#4) | O(A#4) | ||||
A(C4) | S(D4) | D(E4) | F(F4) | J(G4) | K(A4) | L(B4) | :(C5) |
위의 규칙을 바탕으로 키보드 모듈을 이용하여 소스 코드를 수정했습니다.
import winsound
import keyboard
# 음계와 주파수 매핑
note_frequency = {
'C': 261.63,
'C#': 277.18,
'D': 293.66,
'D#': 311.13,
'E': 329.63,
'F': 349.23,
'F#': 369.99,
'G': 392.00,
'G#': 415.30,
'A': 440.00,
'A#': 466.16,
'B': 493.88
}
def play_note(note, octave, duration):
frequency = note_frequency[note]
print(int(frequency*(2**(octave-4))))
winsound.Beep(int(frequency*(2**(octave-4))), int(duration * 1000))
while True:
if keyboard.is_pressed('A'):
play_note('C', 4, 0.25)
elif keyboard.is_pressed('S'):
play_note('D', 4, 0.25)
elif keyboard.is_pressed('D'):
play_note('E', 4, 0.25)
elif keyboard.is_pressed('F'):
play_note('F', 4, 0.25)
elif keyboard.is_pressed('J'):
play_note('G', 4, 0.25)
elif keyboard.is_pressed('K'):
play_note('A', 4, 0.25)
elif keyboard.is_pressed('L'):
play_note('B', 4, 0.25)
elif keyboard.is_pressed(':'):
play_note('C', 5, 0.25)
elif keyboard.is_pressed('W'):
play_note('C#', 4, 0.25)
elif keyboard.is_pressed('E'):
play_note('D#', 4, 0.25)
elif keyboard.is_pressed('T'):
play_note('F#', 4, 0.25)
elif keyboard.is_pressed('I'):
play_note('G#', 4, 0.25)
elif keyboard.is_presse('O'):
play_note('A#', 4, 0.25)
여기서 keyboard.is_pressed 함수는 키보드가 눌렸을 때 True를 출력하는 함수입니다. 해당 함수를 이용하여 각각의 키보드 입력을 구현하였습니다.
마지막으로 제가 블로그에 적은 부분으로 간단하게 음계를 표현할 수 있습니다. 만약에 키보드로 본격적으로 곡을 연주 하고 싶다면 Multiplayer Piano라는 웹사이트에서 피아노를 직접 연주하시는 것을 추천합니다.
'컴퓨터 > Python' 카테고리의 다른 글
Python (23) - 오라클과 연동하여 Blob이미지를 다운로드 해보자 (oracledb) (0) | 2024.03.26 |
---|---|
Python (22) - 로또 API이용하여 당첨번호를 크롤링해보자 (1) | 2024.01.29 |
Python (20) - CSV파일을 다뤄보자 (CSV) (1) | 2023.08.21 |
Python (19) - 구글 이미지를 크롤링 하는 방법 (Selenium) (0) | 2023.08.09 |
Python (18) - 공공데이터 API를 이용하여 기상청 날씨를 가져오자 (0) | 2023.06.15 |