吉他初学者学习网站搭建系列(5)——如何做一个在线节拍器

背景

我们看吉他谱时,经常看到拍号,例如6/8。它的含义是一拍是一个八分音符,一小节有六拍。四分音符的时长是一秒,即60拍/分钟。基于这样的背景知识,我们就可以根据一些定时循环的包来实现节拍器。
https://tryiscool.space/music-score

实现

这边依然采用的ToneJs。我们需要认识几个类,Transport、Loop。

Transport

Transport是一个计时器类。它有两个属性值得关注:bpm和timeSignature。
bpm表示每分钟的拍子数
timeSignature表示拍号,用数组表示,例如6/8拍表达为[6, 8]。需要注意的是,这个属性最后会返回 6 / 8 * 4 = 3,默认值是4,即标准的4/4拍。

Loop

Loop是一个循环类,用于循环执行一个回调方法,我们可以在这个回调中进行语音播放,实现打节拍的效果。
需要注意的是,如果只是在每一拍都播放一次声音,我们是无法区分重音和弱音的,因此,应该写两个循环,一个专门播放重音的拍子,一个播放所有的拍子。

代码

<template>
 <div>
   <div style="margin: 10px">
     <v-text-field v-model="bpm" label="bpm"></v-text-field>
     <v-select v-model="timeSignature" label="timeSignature" :items="timeSignatureList"></v-select>
     <v-btn @click="start">{{ isPlaying ? '暂停' : '开始' }}</v-btn>
   </div>
 </div>
</template>

<script>
import { Oscillator, Transport, Loop } from 'tone';

export default {
 name: 'Beat',
 data() {
   return {
     bpm: 0,
     timeSignature: '',
     timeSignatureList: ['2/4', '3/4', '4/4', '3/8', '6/8'],
     isPlaying: false,
   }
 },
 mounted() {
   this.bpm = 120;
   this.timeSignature = '4/4';
 },
 watch: {
   bpm(val) {
     Transport.bpm.value = val;
   },
 },
 beforeUnmount() {
   this.stop();
 },
 methods: {
   start() {
     if (this.isPlaying) {
       this.stop();
     } else {
       const osc1 = new Oscillator().toDestination();
       const osc2 = new Oscillator().toDestination();
       const res = this.timeSignature.split('/');
       Transport.timeSignature = res.map(a => Number(a)); // [6, 8] 返回 6 / 8 * 4 表示 实际拍数和标准拍数的比例
       // 创建一个每拍触发的事件
       this.loopA = new Loop((time) => {
         osc1.start(time).stop(time + 0.1);
       }, res[1] + "n").start(0);
       // 重音时间间隔:标准一拍的秒数 *(实际拍数 / 标准拍数) = 实际一拍的秒数
       this.loopB = new Loop((time) => {
         osc2.start(time).stop(time + 0.1);
       }, 60 / this.bpm * Transport.timeSignature).start(0);
       Transport.start();
     }
     this.isPlaying = !this.isPlaying;
   },
   stop() {
     Transport?.stop();
     this.loopA?.stop();
     this.loopB?.stop();
   }
 }
}
</script>

在线尝试

在这里插入图片描述

这个功能已经集成到了我的个人网站YUERGS中,快来试试吧😉

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HouGISer

HouGiser需要你的鼓励~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值