ArMusic / app.py
Drbrain0620's picture
Update app.py
202a956 verified
import gradio as gr
import math
import tempfile
import os
# notes.py λ‚΄μš©μ„ 직접 포함
A4_INDEX = 48
TOTAL_KEYS = 88
NOTE_NAMES = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
ENHARMONIC_EQUIVS = {
'C#': 'Db',
'D#': 'Eb',
'F#': 'Gb',
'G#': 'Ab',
'A#': 'Bb',
'Db': 'C#',
'Eb': 'D#',
'Gb': 'F#',
'Ab': 'G#',
'Bb': 'A#',
'Cb': 'B',
'B#': 'C',
'E#': 'F',
'Fb': 'E',
}
# 주파수 λ”•μ…”λ„ˆλ¦¬ 생성
freqs = {}
for i in range(TOTAL_KEYS):
n = i - A4_INDEX
freq = 440 * (2 ** (n / 12))
freq = round(freq, 2)
note_index = (i + 9) % 12
octave = (i + 9) // 12
note = NOTE_NAMES[note_index]
note_name = f"{note}{octave}"
freqs[note_name] = freq
if note in ENHARMONIC_EQUIVS:
enharmonic = ENHARMONIC_EQUIVS[note]
enharmonic_name = f"{enharmonic}{octave}"
freqs[enharmonic_name] = freq
special_equivs = {
'Cb': 'B',
'B#': 'C',
'Fb': 'E',
'E#': 'F',
}
for key in list(freqs.keys()):
note = key[:-1]
octave = int(key[-1])
if note in special_equivs:
mapped_note = special_equivs[note]
if note == 'Cb':
mapped_octave = octave - 1
elif note == 'B#':
mapped_octave = octave + 1
else:
mapped_octave = octave
mapped_key = f"{mapped_note}{mapped_octave}"
if mapped_key in freqs:
freqs[key] = freqs[mapped_key]
def convert_music_to_arduino(text_input):
"""ν…μŠ€νŠΈ μž…λ ₯을 λ°›μ•„ Arduino μ½”λ“œλ‘œ λ³€ν™˜ν•˜κ³  νŒŒμΌμ„ 생성"""
try:
if not text_input.strip():
return "μž…λ ₯이 λΉ„μ–΄μžˆμŠ΅λ‹ˆλ‹€.", None
lines = text_input.strip().split('\n')
lines = [line.split() for line in lines if line.strip()]
lines = [x for x in lines if x]
if len(lines) < 3:
return "μ΅œμ†Œ 3μ€„μ˜ 섀정이 ν•„μš”ν•©λ‹ˆλ‹€ (PIN, REPEAT, BPM).", None
PIN = lines[0][1]
REPEAT = lines[1][1] == 'TRUE'
BPM = lines[2][1]
SPB = 60 / float(BPM)
arduino_code = ""
if REPEAT:
arduino_code += 'void setup() {\n'
arduino_code += f' pinMode({PIN}, OUTPUT);\n'
arduino_code += ' Serial.begin(9600);\n'
arduino_code += '}\n'
arduino_code += 'void loop() {\n'
else:
arduino_code += 'void setup() {\n'
arduino_code += f' pinMode({PIN}, OUTPUT);\n'
arduino_code += f' Serial.begin(9600);\n'
for line in lines[3:]:
if len(line) < 2:
continue
note = line[0]
duration = SPB * float(line[1]) * 1000 # Convert to milliseconds
if note in freqs:
freq = freqs[note]
arduino_code += f' tone({PIN}, {freq}, {duration});\n'
elif note == 'W':
arduino_code += f' delay({int(duration)});\n'
elif note == 'BPM': # set new BPM
BPM = float(line[1])
SPB = 60 / float(BPM)
if REPEAT:
arduino_code += '}\n'
else:
arduino_code += '}\n'
arduino_code += 'void loop() {}\n'
# μž„μ‹œ 파일 생성
temp_file = tempfile.NamedTemporaryFile(mode='w', suffix='.ino', delete=False)
temp_file.write(arduino_code)
temp_file.close()
return arduino_code, temp_file.name
except Exception as e:
return f"였λ₯˜ λ°œμƒ: {str(e)}", None
# Gradio μΈν„°νŽ˜μ΄μŠ€ ꡬ성
with gr.Blocks(title="μ΄μš°μ§„μ˜ 아두이노 μž‘κ³‘ μ›Ήμ‚¬μ΄νŠΈ", theme=gr.themes.Soft()) as demo:
with gr.Row():
# μ™Όμͺ½: μž…λ ₯
with gr.Column():
text_input = gr.Textbox(
label="μŒμ•… 데이터",
placeholder="PIN 13\nREPEAT TRUE\nBPM 120\nC4 1\nD4 1\nE4 1",
lines=8,
max_lines=8
)
with gr.Row():
example1_btn = gr.Button("λ„λ ˆλ―ΈνŒŒ", size="sm")
example2_btn = gr.Button("μƒμΌμΆ•ν•˜", size="sm")
example3_btn = gr.Button("λΉ„ν”„μŒ", size="sm")
convert_btn = gr.Button("λ³€ν™˜ν•˜κΈ°", variant="primary", size="lg")
# 였λ₯Έμͺ½: κ²°κ³Ό
with gr.Column():
output_text = gr.Code(
label="Arduino μ½”λ“œ",
language="cpp",
lines=8
)
download_file = gr.File(
label="λ‹€μš΄λ‘œλ“œ",
interactive=False
)
# ν•˜λ‹¨: μ‚¬μš©λ²•
with gr.Accordion("μ‚¬μš©λ²•", open=False):
gr.Markdown("""
**μž…λ ₯ ν˜•μ‹:**
```
PIN 13 ← Arduino ν•€ 번호
REPEAT TRUE ← 반볡 μž¬μƒ μ—¬λΆ€ (TRUE/FALSE)
BPM 120 ← λΆ„λ‹Ή λΉ„νŠΈ 수
C4 1 ← λ…ΈνŠΈλͺ… μ§€μ†μ‹œκ°„
D4 1
E4 1
W 0.5 ← WλŠ” 무음(μ‰Όν‘œ)
```
""")
# 이벀트 처리
convert_btn.click(
fn=convert_music_to_arduino,
inputs=[text_input],
outputs=[output_text, download_file]
)
# μ˜ˆμ‹œ λ²„νŠΌ 이벀트
def load_example1():
return """PIN 13
REPEAT TRUE
BPM 120
C4 1
D4 1
E4 1
F4 1
G4 1
A4 1
B4 1
C5 1"""
def load_example2():
return """PIN 13
REPEAT FALSE
BPM 140
C4 0.5
C4 0.5
D4 1
C4 1
F4 1
E4 2"""
def load_example3():
return """PIN 13
REPEAT TRUE
BPM 200
C6 0.25
W 0.25
C6 0.25
W 0.25"""
example1_btn.click(fn=load_example1, outputs=[text_input])
example2_btn.click(fn=load_example2, outputs=[text_input])
example3_btn.click(fn=load_example3, outputs=[text_input])
if __name__ == "__main__":
demo.launch()