惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
T
Threat Research - Cisco Blogs
O
OpenAI News
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Scott Helme
Scott Helme
AWS News Blog
AWS News Blog
NISL@THU
NISL@THU
The Hacker News
The Hacker News
Spread Privacy
Spread Privacy
Latest news
Latest news
S
Securelist
P
Proofpoint News Feed
I
Intezer
Security Archives - TechRepublic
Security Archives - TechRepublic
D
DataBreaches.Net
博客园 - 司徒正美
C
CERT Recently Published Vulnerability Notes
博客园 - 三生石上(FineUI控件)
Cisco Talos Blog
Cisco Talos Blog
AI
AI
Forbes - Security
Forbes - Security
爱范儿
爱范儿
博客园_首页
Last Week in AI
Last Week in AI
S
SegmentFault 最新的问题
P
Privacy International News Feed
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
H
Hacker News: Front Page
T
Tailwind CSS Blog
G
Google Developers Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
L
LINUX DO - 最新话题
博客园 - 【当耐特】
Vercel News
Vercel News
C
Cisco Blogs
博客园 - 叶小钗
MyScale Blog
MyScale Blog
U
Unit 42
C
Check Point Blog
B
Blog RSS Feed
C
Cybersecurity and Infrastructure Security Agency CISA
N
News | PayPal Newsroom
T
Troy Hunt's Blog
有赞技术团队
有赞技术团队
量子位
V
Visual Studio Blog
罗磊的独立博客
J
Java Code Geeks
Microsoft Azure Blog
Microsoft Azure Blog
PCI Perspectives
PCI Perspectives

博客园 - jiftle

opencode系统提示词加载机制 Qoder CN版本v1.4.2 (2026-06-27) 提供套餐余量查看 清理宝塔面板 桌面 AI 应用技术栈深度对比:腾讯元宝 vs WorkBuddy 【转载】编辑器之神与神的编辑器:Vim 与 Emacs 的传奇 OpenCode 源码解读报告 linux双网卡默认路由问题 通过4种方法来重置 UOS 操作系统中的用户密码 统信服务器系统【重置登录密码】解决方案 vscode插件Git Graph 怎么只提交单个文件 opencode 配置本地ollama模型编程 opencode编程工具 ollama模型导出 【转载】从源码看 Qwen Code 的设计思路 Qwen Code 代码分析 模型性能评测 职场真相:不是赏饭吃,是价值交换 vim插件AI结对编程辅助编程插件 千问网页版生成的代码不支持语法高亮 linux检查显存大小(集成显卡) golang测试模型的token输出速度 Go 实现本地 Ollama 模型基准测试工具 使用golang编写大语言模型的输出速度性能 ollama v0.18.2手工部署安装,linux, deepin 20.9 树莓派pico使用无源蜂鸣器播放小星星 树莓派pico播放玛丽有只小羊羔 树莓派 pico W(创客版)RP2020 W代码示例温度检测+液晶显示屏+HTTP服务器页面控制灯光 极简transformer,仅供理解原理
树莓派pico蜂鸣器播放音乐
jiftle · 2026-02-17 · via 博客园 - jiftle
"""
Micropython (Raspberry Pi Pico)
Plays music written on onlinesequencer.net through a passive piezo buzzer.
Uses fast arpeggios with a single buzzer to simulate polyphony
Also supports multiple buzzers at once for real polyphony
https://github.com/james1236/buzzer_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