网站LOGO
六月是只猫 - 互联网技术分享指南
页面加载中
5月3日
网站LOGO 六月是只猫 - 互联网技术分享指南
生活,一半家长里短,一半山川湖海...
菜单
  • 六月是只猫 - 互联网技术分享指南
    生活,一半家长里短,一半山川湖海...
    用户的头像
    首次访问
    上次留言
    累计留言
    我的等级
    我的角色
    打赏二维码
    打赏博主
    使用javascript实现无源蜂鸣器
    点击复制本页信息
    微信扫一扫
    文章二维码
    文章图片 文章标题
    创建时间
  • 一 言
    确认删除此评论么? 确认
  • 本弹窗介绍内容来自,本网站不对其中内容负责。
    www.lyszm.com

    使用javascript实现无源蜂鸣器

    六月是只猫 · 原创 ·
    日常技术分享互联网 · 好玩的代码代码分享javascript
    共 4329 字 · 约 2 分钟 · 537

    前言

    JS 实现无源蜂鸣器,从而实现伪钢琴音乐

    演示

    把鼠标移动到这里

    源代码
    • 为指定 class 的标签设置触摸事件,每当该标签被触摸时,都会发出一次蜂鸣器声音

    由于浏览器安全限制,需要用户在站点进行任意操作后才会触发声音,否则直接触摸该标签不会发出声音
    例如:先点击一下该标签,之后每次触摸都会发出声音

    • 有两种方式实现打歌

    第一种方式是原代码作者方案:该代码原作者将所有蜂鸣器振动频率放到了一个以空格分开的字符串中,然后将字符串切割为数组
    该方案的案例是歌曲《天空之城》
    存放无源蜂鸣器振动频率的数组

    javascript 代码:
    // 为指定class的标签设置触摸事件
    element_classname = ["site-title"];
    
    window.AudioContext = window.AudioContext || window.webkitAudioContext,
    function () {
        if (window.AudioContext) {
            let e = new AudioContext;
            let t = "880 987 1046 987 1046 1318 987 659 659 880 784 880 1046 784 659 659 698 659 698 1046 659 1046 1046 1046 987 698 987 987 880 987 1046 987 1046 1318 987 659 659 880 784 880 1046 784 659 698 1046 987 1046 1174 1174 1174 1046 1046 880 987 784 880 1046 1174 1318 1174 1318 1567 1046 987 1046 1318 1318 1174 784 784 880 1046 987 1174 1046 784 784 1396 1318 1174 659 1318 1046 1318 1760 1567 1567 1318 1174 1046 1046 1174 1046 1174 1567 1318 1318 1760 1567 1318 1174 1046 1046 1174 1046 1174 987 880 880 987 880".split(" "); //天空之城
            let i = 0;
            let o = 1;
            for (const item of element_classname) {
                document.getElementsByClassName(item)[0].addEventListener("mouseenter", function () {
                    let r = t[i];
                    r || (i = 0, r = t[i]), i += o;
                    let c = e.createOscillator();
                    let l = e.createGain();
                    c.connect(l);
                    l.connect(e.destination);
                    c.type = "sine";
                    c.frequency.value = r;
                    l.gain.setValueAtTime(0, e.currentTime);
                    l.gain.linearRampToValueAtTime(1, e.currentTime + .01);
                    c.start(e.currentTime);
                    l.gain.exponentialRampToValueAtTime(.001, e.currentTime + 1);
                    c.stop(e.currentTime + 1);
                    n = !1;
                });
            }
        }
    }();
    

    第二种方式是我的方案:由于之前学习单片机时,学习过压缩的方式加载振动频率值,所以可以采用压缩的方式,先存储一个基本音数组,然后再存储曲谱数组,遍历曲谱数组中的音调转换为基本音的振动频率值数组
    该方案的案例是歌曲《天空之城》优化版(优化了所有连续音符,将连续音符改为单音符,使其更适合 JS 蜂鸣器)
    存放无源蜂鸣器振动频率的数组

    javascript 代码:
    // 为指定class的标签设置触摸事件
    element_classname = ["site-title"];
    
    // C大调钢琴音调
    const pitch = [
        262, 294, 330, 349, 392, 440, 494,
        523, 587, 659, 698, 784, 880, 988,
        1046, 1175, 1318, 1397, 1568, 1760, 1976,
    ];
    
    // 根据曲谱打歌
    const tone = [
        12, 13, 14, 13, 14, 16, 13,
        9, 9, 12, 11, 12, 14, 11,
        9, 9, 10, 9, 10, 14, 9,
        14, 14, 13, 10, 10, 13, 13,
        12, 13, 14, 13, 14, 16, 13,
        9, 9, 12, 11, 12, 14, 11,
        8, 9, 10, 14, 13, 14, 15, 16, 14,
        14, 13, 12, 13, 11, 12,
        14, 15, 16, 15, 16, 18, 15,
        11, 11, 14, 13, 14, 16, 16,
        12, 13, 14, 13, 15, 15, 14, 11, 11,
        17, 16, 15, 14, 16,
        16, 19, 19, 18, 18, 16, 15, 14,
        14, 15, 14, 15, 18, 16,
        16, 19, 19, 18, 18, 16, 15, 14,
        14, 15, 14, 15, 13, 12,
    ];
    
    // 将曲谱转换为钢琴音数组
    let music_list = [];
    for (let i = 0; i < tone.length; i++) {
        music_list.push(pitch[tone[i]]);
    }
    // console.log(music_list)
    
    window.AudioContext = window.AudioContext || window.webkitAudioContext,
    function () {
        if (window.AudioContext) {
            let e = new AudioContext;
            let t = music_list;
            let i = 0;
            let o = 1;
            for (const item of element_classname) {
                document.getElementsByClassName(item)[0].addEventListener("mouseenter", function () {
                    let r = t[i];
                    r || (i = 0, r = t[i]), i += o;
                    let c = e.createOscillator();
                    let l = e.createGain();
                    c.connect(l);
                    l.connect(e.destination);
                    c.type = "sine";
                    c.frequency.value = r;
                    l.gain.setValueAtTime(0, e.currentTime);
                    l.gain.linearRampToValueAtTime(1, e.currentTime + .01);
                    c.start(e.currentTime);
                    l.gain.exponentialRampToValueAtTime(.001, e.currentTime + 1);
                    c.stop(e.currentTime + 1);
                    n = !1;
                });
            }
        }
    }();
    

    至此完成

    声明:本文由 六月是只猫(博主)原创,依据 CC-BY-NC-SA 4.0 许可协议 授权,转载请注明出处。

    还没有人喜爱这篇文章呢

    发一条! 发一条!
    博客logo 六月是只猫 - 互联网技术分享指南 生活,一半家长里短,一半山川湖海... 51统计 百度统计
    MOEICP 萌ICP备20248888号 ICP 京ICP备2022028403号-1 ICP 京公网安备 11010502051304号 又拍云 本站由又拍云提供CDN加速/云存储服务

    🕛

    本站已安全运行 1 年 174 天 6 小时 57 分
    六月是只猫 - 互联网技术分享指南. © 2022 ~ 2024.
    网站logo

    六月是只猫 - 互联网技术分享指南 生活,一半家长里短,一半山川湖海...
     
     
     
     
    壁纸