台灣使用簡譜習慣使用數字來標記,國外則是使用 ABC Notation,各位讀者可以參考這個 Nota ABC網站的教學。
ABC 樂譜是一種用於樂譜的純文字格式。它由 Chris Walshaw 於 1990 年代初開發,旨在為西方起源的傳統曲調提供一種易於閱讀和編寫的格式。
讀者可以參考 https://notabc.app/abc-converter/ 這個網站的轉換工具
我們用 小星星 這首歌來舉例:
X:1
T: 小星星
R: reel
M: 4/4
L: 1/4
CCGG | AAG2 | FFEE | DDC2:|
w: 一 閃 一 閃 亮 晶 晶, 滿 天 都 是 小 星 星
另外也有 abcjs 這樣的 JavaScript 函式庫可以用,您可以在您的網頁裡,加入這樣的工具協助您轉換您想要播放的音樂。
玩學機主要的發聲器是內建蜂鳴器。如果使用者希望外接音訊,可以透過內建 DAC (左右聲道 Pin 25、26)來發出語音或音樂,但若不希望蜂鳴器發出聲音(干擾),可利用 Pin 17 關閉蜂鳴器。
反過來說,想要聽見buzzer 發出聲音,就要先打開 pin 17 為 high 電位,才能聽見聲音。
如果使用 toneng,使用者不需要像上面 撥放馬力歐遊戲音樂 的方式寫這麼多程式,只需要專心把音樂轉成簡譜檔,就能很輕鬆地撥放音效。
Toneng 支援撥放的簡譜規則
我們來看看這段非常精練的 toneng 原始碼:
# WiFiBoy OK:ESP32 Tone Engine v1.0
# (C) 2020 WiFiBoy Computing Lab, tklua@wifiboy.org
import machine
try:
if tone: tone.deinit()
except: tone = machine.Timer(1)
try:
if snd: snd.deinit()
except: pass
snd=machine.PWM(machine.Pin(25, 3),timer=2)
machine.Pin(17,3).value(1);snd.duty(0)
counter=0;octave=3;tempo=50;nduty=0;ndutyd=15;initduty=90;ps="";playing=0
freq = [round(110*2**(x/12)) for x in range(88)]
def toneEngine(timer):
global counter,ps,octave,tempo,nduty,ndutyd,playing
if counter>0:
counter-=1; nduty-=ndutyd
if nduty>=0 and nduty<=99: snd.duty(nduty)
else:snd.duty(0);
if counter==0:
if len(ps)>0:
n = ps[0]; ps=ps[1:]
if (n>="A" and n<="G") or n==".":
if n=="A":nn=9
elif n=="B":nn=11
elif n=="C":nn=0
elif n=="D":nn=2
elif n=="E":nn=4
elif n=="F":nn=5
elif n=="G":nn=7
elif n==".":nn=-99
if len(ps)>0:
if ps[0]=="#": nn+=1; ps=ps[1:]
elif ps[0]=="b": nn-=1; ps=ps[1:]
if len(ps)>0:
if ps[0].isdigit(): counter=tempo//int(ps[0]); ps=ps[1:]
else:counter=tempo//4
else: counter=tempo//4
nduty=initduty
if nn>=0:snd.freq(freq[octave*12+nn]);
else: nduty=0; snd.duty(0)
playing=1
elif n=="O":octave=int(ps[0]); ps=ps[1:]
elif n==">":octave+=1
elif n=="<":octave-=1
elif n=="T":tempo=int(ps[0:3]); ps=ps[3:]
else: snd.duty(0); playing=0
tone.init(period=10, mode=machine.Timer.PERIODIC, callback=toneEngine)
import machine
try:
if tone: tone.deinit()
except: tone = machine.Timer(1)
try:
if snd: snd.deinit()
except: pass
snd = machine.PWM(machine.Pin(25, 3), timer=2)
machine.Pin(17, 3).value(1)
snd.duty(0)
counter=0;octave=3;tempo=50;nduty=0;ndutyd=15;initduty=90;ps="";playing=0
freq = [round(110*2**(x/12)) for x in range(88)]
freq 的範圍:
global counter, ps, octave, tempo, nduty, ndutyd, playing
定義全域變數這樣能讓 MicroPython 執行時,也能對這些變數進行操作。
if counter > 0:
counter -= 1
nduty -= ndutyd
if nduty >= 0 and nduty <= 99:
snd.duty(nduty)
else:
snd.duty(0)
if counter == 0:
if len(ps) > 0:
n = ps[0]
ps = ps[1:]
if (n >= "A" and n <= "G") or n == ".":
if n == "A": nn = 9
elif n == "B": nn = 11
elif n == "C": nn = 0
elif n == "D": nn = 2
elif n == "E": nn = 4
elif n == "F": nn = 5
elif n == "G": nn = 7
elif n == ".": nn = -99
if len(ps) > 0:
if ps[0] == "#": nn += 1; ps = ps[1:]
elif ps[0] == "b": nn -= 1; ps = ps[1:]
if len(ps) > 0:
if ps[0].isdigit(): counter = tempo // int(ps[0]); ps = ps[1:]
else: counter = tempo // 4
else: counter = tempo // 4
nduty = initduty
if nn >= 0:
snd.freq(freq[octave * 12 + nn])
else:
nduty = 0
snd.duty(0)
playing = 1
,代表音樂正在播放elif n == "O": octave = int(ps[0]); ps = ps[1:]
elif n == ">": octave += 1
elif n == "<": octave -= 1
elif n == "T": tempo = int(ps[0:3]); ps = ps[3:]