在你的项目中使用 dapume-js

dapume-js 是一个零依赖的 TypeScript 库,可在 Node 与浏览器中把线性乐谱解析为乐谱对象,并渲染为 MIDI。本站正是基于它构建的示例。

npm versionnpm downloadslicensebundle sizevscode marketplace

安装

用你喜欢的包管理器安装:

pnpm add dapume-js
# 或:npm install dapume-js / yarn add dapume-js

核心 API

库暴露两个核心函数:parse() 把 dapume 文本解析为乐谱对象,toMidi() 把乐谱对象渲染为 MIDI 文件字节(Uint8Array)。

import { parse, toMidi } from 'dapume-js';

const score = parse(`1=C 120bpm
1234567`);

console.log(score.notes.length); // 7
const midi: Uint8Array = toMidi(score);

在 Node 中使用

解析并渲染为 MIDI,然后写入文件:

import { writeFileSync } from 'node:fs';
import { render } from 'dapume-js';

// render(text) 等价于 toMidi(parse(text))
writeFileSync('output.mid', render('1=C 120bpm\n1234567'));

在浏览器中使用

得到 MIDI 字节后,用 Blob 触发下载:

import { render } from 'dapume-js';

const bytes = render(scoreText);
const blob = new Blob([bytes], { type: 'audio/midi' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'score.mid';
a.click();
URL.revokeObjectURL(url);

更多工具函数

render() 一步完成「解析 + 渲染」;tokenize() 返回语法高亮词法单元;activeNotesAt() 返回正在发声的音符;activeEventsAt() 还会返回当前休止符;paramsAt() 返回某时刻生效的调号与速度。

import { parse, render, tokenize, activeNotesAt, activeEventsAt, paramsAt } from 'dapume-js';

const mid = render('1=C\n1234567');          // 解析 + 渲染
const tokens = tokenize('1=C\n[4M7]2');        // 语法高亮词法单元
const score = parse('1=D 90bpm\n1234567');
const sounding = activeNotesAt(score, 300);     // 第 300ms 正在发声的音符
const timeline = activeEventsAt(score, 300);    // includes rests
const { key, bpm } = paramsAt(score, 300);      // 第 300ms 生效的调号/速度 → "D", 90

类型一览

interface DapumeScore {
  tracks: DapumeNote[][];     // 按音轨分组(渲染 MIDI 用)
  notes: DapumeNote[];        // 扁平列表,按开始时刻升序
  events: DapumeEvent[];      // 时间轴事件(含休止符)
  trackCount: number;
  durationMs: number;
  durationBeats: number;      // 精确总拍数,不受 BPM 影响
  sections: DapumeSection[];  // 各参数段(调号/速度随时间变化)
}

interface DapumeNote {
  trackNo: number;
  pitch: number;     // MIDI 音高,中央 C = 60
  startTime: number; // 毫秒
  duration: number;  // 毫秒
  startBeat: number; // 从乐谱开头累计的精确拍位
  durationBeats: number;
  srcStart: number;  // 源字符起始下标(用于高亮)
  srcEnd: number;
  isChord: boolean;
}

interface DapumeSection {
  startTime: number; // 该段起始时刻(毫秒)
  startBeat: number; // 该段起始拍位
  tonic: number;     // 主音 MIDI
  bpm: number;
  key: string;       // 调号标签,如 "C"、"Bb."
}

HTTP 接口

线上站点还提供三个由 dapume-js 驱动的 HTTP 接口(Cloudflare Pages Functions);相同请求体会被缓存,render 在响应头返回音符数 / 音轨数 / 时长。

POST/api/parsetext/plainapplication/json
POST/api/to-midiapplication/jsonaudio/midi
POST/api/rendertext/plainaudio/midi+ X-Note-Count / X-Track-Count / X-Duration-Ms

出于安全考虑,这些接口仅允许同域(本站)调用。

在线测试

输入 dapume 文本,调用线上接口查看实时返回。

VSCode 扩展

本仓库还提供一个 VSCode 扩展:为 .dapume 文件提供语法高亮,并在编辑器标题栏提供「渲染为 MIDI」按钮(内部即调用 dapume-js)。可在 GitHub Actions 的构建产物中下载 .vsix 安装。

1=C 120bpm
[1]1234[5]567