### 可以在线制作Buzz音乐的工具
源自:[[https://onlinesequencer.net|onlinesequencer]]
James的Buzz_music代码:
from machine import Pin, PWM
from math import ceil
tones = {
'C0':16,
'C#0':17,
'D0':18,
'D#0':19,
'E0':21,
'F0':22,
'F#0':23,
'G0':24,
'G#0':26,
'A0':28,
'A#0':29,
'B0':31,
'C1':33,
'C#1':35,
'D1':37,
'D#1':39,
'E1':41,
'F1':44,
'F#1':46,
'G1':49,
'G#1':52,
'A1':55,
'A#1':58,
'B1':62,
'C2':65,
'C#2':69,
'D2':73,
'D#2':78,
'E2':82,
'F2':87,
'F#2':92,
'G2':98,
'G#2':104,
'A2':110,
'A#2':117,
'B2':123,
'C3':131,
'C#3':139,
'D3':147,
'D#3':156,
'E3':165,
'F3':175,
'F#3':185,
'G3':196,
'G#3':208,
'A3':220,
'A#3':233,
'B3':247,
'C4':262,
'C#4':277,
'D4':294,
'D#4':311,
'E4':330,
'F4':349,
'F#4':370,
'G4':392,
'G#4':415,
'A4':440,
'A#4':466,
'B4':494,
'C5':523,
'C#5':554,
'D5':587,
'D#5':622,
'E5':659,
'F5':698,
'F#5':740,
'G5':784,
'G#5':831,
'A5':880,
'A#5':932,
'B5':988,
'C6':1047,
'C#6':1109,
'D6':1175,
'D#6':1245,
'E6':1319,
'F6':1397,
'F#6':1480,
'G6':1568,
'G#6':1661,
'A6':1760,
'A#6':1865,
'B6':1976,
'C7':2093,
'C#7':2217,
'D7':2349,
'D#7':2489,
'E7':2637,
'F7':2794,
'F#7':2960,
'G7':3136,
'G#7':3322,
'A7':3520,
'A#7':3729,
'B7':3951,
'C8':4186,
'C#8':4435,
'D8':4699,
'D#8':4978,
'E8':5274,
'F8':5588,
'F#8':5920,
'G8':6272,
'G#8':6645,
'A8':7040,
'A#8':7459,
'B8':7902,
'C9':8372,
'C#9':8870,
'D9':9397,
'D#9':9956,
'E9':10548,
'F9':11175,
'F#9':11840,
'G9':12544,
'G#9':13290,
'A9':14080,
'A#9':14917,
'B9':15804
}
#Time, Note, Duration, Instrument (onlinesequencer.net schematic format)
#0 D4 8 0;0 D5 8 0;0 G4 8 0;8 C5 2 0;10 B4 2 0;12 G4 2 0;14 F4 1 0;15 G4 17 0;16 D4 8 0;24 C4 8 0
class music:
def __init__(self, songString='0 D4 8 0', looping=True, tempo=3, duty=2512, pin=None, pins=[Pin(0)]):
self.tempo = tempo
self.song = songString
self.looping = looping
self.duty = duty
self.stopped = False
self.timer = -1
self.beat = -1
self.arpnote = 0
self.pwms = []
if (not (pin is None)):
pins = [pin]
i = 0
for pin in pins:
self.pwms.append(PWM(pins[i]))
i = i + 1
self.notes = []
self.playingNotes = []
self.playingDurations = []
#Find the end of the song
self.end = 0
splitSong = self.song.split(";")
for note in splitSong:
snote = note.split(" ")
testEnd = round(float(snote[0])) + ceil(float(snote[2]))
if (testEnd > self.end):
self.end = testEnd
#Create empty song structure
while (self.end > len(self.notes)):
self.notes.append(None)
#Populate song structure with the notes
for note in splitSong:
snote = note.split(" ")
beat = round(float(snote[0]));
if (self.notes[beat] == None):
self.notes[beat] = []
self.notes[beat].append([snote[1],ceil(float(snote[2]))]) #Note, Duration
#Round up end of song to nearest bar
self.end = ceil(self.end / 8) * 8
def stop(self):
for pwm in self.pwms:
pwm.deinit()
self.stopped = True
def tick(self):
if (not self.stopped):
self.timer = self.timer + 1
#Loop
if (self.timer % (self.tempo * self.end) == 0 and (not (self.timer == 0))):
if (not self.looping):
self.stop()
return False
self.beat = -1
self.timer = 0
#On Beat
if (self.timer % self.tempo == 0):
self.beat = self.beat + 1
#Remove expired notes from playing list
i = 0
while (i < len(self.playingDurations)):
self.playingDurations[i] = self.playingDurations[i] - 1
if (self.playingDurations[i] <= 0):
self.playingNotes.pop(i)
self.playingDurations.pop(i)
else:
i = i + 1
#Add new notes and their durations to the playing list
"""
#Old method runs for every note, slow to process on every beat and causes noticeable delay
ssong = song.split(";")
for note in ssong:
snote = note.split(" ")
if int(snote[0]) == beat:
playingNotes.append(snote[1])
playingDurations.append(int(snote[2]))
"""
if (self.beat < len(self.notes)):
if (self.notes[self.beat] != None):
for note in self.notes[self.beat]:
self.playingNotes.append(note[0])
self.playingDurations.append(note[1])
#Only need to run these checks on beats
i = 0
for pwm in self.pwms:
if (i >= len(self.playingNotes)):
pwm.duty_u16(0)
else:
#Play note
pwm.duty_u16(self.duty)
pwm.freq(tones[self.playingNotes[i]])
i = i + 1
#Play arp of all playing notes
if (len(self.playingNotes) > len(self.pwms)):
self.pwms[len(self.pwms)-1].duty_u16(self.duty)
if (self.arpnote > len(self.playingNotes)-len(self.pwms)):
self.arpnote = 0
self.pwms[len(self.pwms)-1].freq(tones[self.playingNotes[self.arpnote+(len(self.pwms)-1)]])
self.arpnote = self.arpnote + 1
return True
else:
return False
示例代码:example.py
from buzzer_music import music
from time import sleep
#Example songs
song = '0 A#4 1 1;2 F5 1 1;4 D#5 1 1;8 D5 1 1;11 D5 1 1;6 A#4 1 1;14 D#5 1 1;18 A#4 1 1;20 D#5 1 1;22 A#4 1 1;24 D5 1 1;27 D5 1 1;30 D#5 1 1;32 A#4 1 1;34 F5 1 1;36 D#5 1 1;38 A#4 1 1;40 D5 1 1;43 D5 1 1;46 D#5 1 1;50 A#4 1 1;52 D#5 1 1;54 G5 1 1;56 F5 1 1;59 D#5 1 1;62 F5 1 1;64 A#4 1 1;66 F5 1 1;68 D#5 1 1;70 A#4 1 1;72 D5 1 1;75 D5 1 1;78 D#5 1 1;82 A#4 1 1;84 D#5 1 1;86 A#4 1 1;88 D5 1 1;91 D5 1 1;94 D#5 1 1;96 A#4 1 1;100 D#5 1 1;102 A#4 1 1;104 D5 1 1;107 D5 1 1;110 D#5 1 1;114 A#4 1 1;116 D#5 1 1;118 G5 1 1;120 F5 1 1;123 D#5 1 1;126 F5 1 1;98 F5 1 1'
from machine import Pin
#One buzzer on pin 0
mySong = music(song, pins=[Pin(19)])
#Four buzzers
#mySong = music(song, pins=[Pin(0),Pin(1),Pin(2),Pin(3)])
while True:
print(mySong.tick())
sleep(0.04)