使用 JavaScript 演奏空气鼓

2025-05-24

使用 JavaScript 演奏空气鼓

去年,当我去参加周末工作旅行时,我和一位前同事谈到我一直想学打鼓,但实际上从未学过,因为它占用很多空间并且鼓组相当昂贵。

他突然把手伸进包里,掏出了 Freedrum 传感器。我以前从未听说过,但他告诉我,这些运动传感器可以连接到鼓槌和鞋子上,用来演奏空气鼓。你可以通过蓝牙将它们连接到手机或笔记本电脑上,然后就可以演奏了。

太巧了,他包里正好有这些鼓,我太兴奋了!这不仅能让我拥有一套更便宜、更便携的鼓,而且知道它可以通过蓝牙连接,这意味着我必须尝试用它做点什么。那个周末我试了一下,但没能成功。

几周前,我买了一套 Freedrum 鼓,上周末我花了一些时间调试,它成功了!!🎉🎉🎉

如果您想跳过其余部分并只查看代码,请随意检查freedrum.js

演示

它是如何工作的

我之前已经使用 JavaScript、蓝牙和硬件构建了一些项目,所以我知道在 Node.js 中,我可以使用noble 模块,并且直接在浏览器中,我可以使用Web 蓝牙 API

在开始之前,我做了一些研究,看看是否有人做过类似的事情,或者至少能找到一些 Freedrum 传感器的蓝牙规格。幸运的是,我找到了这个要点,但仅此而已……

我首先尝试连接到所提到的蓝牙服务,检查要点中的信息是否仍然正确。

当我看到要点中指出的 uuid 起作用时,我就开始研究这两个版本,一个是 Node.js 版本,另一个是使用 Web Bluetooth API 版本。

Web蓝牙API

该代码与任何 Web 蓝牙 API 示例没有太大区别:

const bluetoothLEMidi = '03b80e5a-ede8-4b33-a751-6ce34ec4c700';
const bleMidiCharacteristic = '7772e5db-3868-4112-a1a9-f2669d106bf3';
const uuid = "XrnS1FRG/q/kM7ecsfErcg==";

const options = {
  "filters": [
      {name: uuid},
      {services: [bluetoothLEMidi]}
  ],
};
return navigator.bluetooth.requestDevice(options)
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService(bluetoothLEMidi)
.then(service => service.getCharacteristic(bleMidiCharacteristic)
.then(characteristic => characteristic.startNotifications())
.then(characteristic => {
  characteristic.addEventListener('characteristicvaluechanged', function(e){
  let data = event.target.value;
  });
 })

我们首先请求一个设备,在我们的例子中是 Freedrum 传感器之一;我们连接到它,请求它的一项服务和特性来获取 BLE MIDI 数据,并订阅通知,以便我们实时接收数据。

Node.js 版本

与 Node.js 版本相同,代码类似于一个基本的贵族示例:

let state = {};
const sensorId = "XrnS1FRG/q/kM7ecsfErcg==";

function FreedrumsController(sensorId){
    noble.on('stateChange', function(state) {
        state === 'poweredOn' ? noble.startScanning() : noble.stopScanning();
      });

      noble.on('discover', function(peripheral){
        if(peripheral.id === sensorId){
          noble.stopScanning();
        }

        explore(peripheral);
      });

      function explore(peripheral){
        peripheral.connect(function(){
          peripheral.discoverSomeServicesAndCharacteristics([bluetoothLEMidi], [], function(error, services, characteristics){
              characteristics[0].on("read", function(event, isNotification){
                let data = event.toJSON().data;
                state = data;
                onStateChangeCallback(state);
              })
          })
        });
      }

      function onStateChangeCallback(e){
        return e;
      }

      return {
        onStateChange: function ( callback ) {
          onStateChangeCallback = callback;
        }
    }
}

我们首先扫描附近的设备,连接到具有正确 uuid 的设备,连接到提供的服务和特性并监听实时数据。

BLE MIDI 数据

一旦您订阅并从传感器接收数据,它会以 5 个整数的数组形式返回,例如 [128,128,153,60,90]。

前两个数字代表标头和时间戳字节。它们似乎总是返回 128,这没问题,因为我们根本不会用到它们。我们真正关心的是最后三个值。

数组的第三个值表示状态字节或 MIDI 命令。基本上,153 表示当音符应该播放时,noteOn 状态;137 表示当音符未播放时,noteOff 状态。

第四个值是 MIDI 音符本身。根据你敲击鼓槌的位置,会返回不同的数字(音符),你可以用它来触发不同的声音。

最后一个值代表速度,介于 0 到 127 之间,可用于设置音量。

差不多就是这样了!现在你已经用 JavaScript 获取了这些数据,可以触发任何你想要的声音和可视化效果了!

改进

目前,我只读取来自传感器的数据,但我知道如果您愿意,您也可以写入数据。

我也只使用过 BLE MIDI 服务,但还有一项获取原始运动数据的服务可能很有趣!


就是这样!如果你想查看代码,这里是repo

希望有帮助!💜

文章来源:https://dev.to/devdevcharlie/playing-air-drums-in-javascript-47jg
PREV
使用 PoseNet 和 Tensorflow.js 在浏览器中通过身体动作玩 Beat Saber
NEXT
使用 Node.js 中的反向 Shell 攻击获取计算机的远程访问权限