mlua-pulse 0.1.0

Lua-friendly music composition and audio export bindings built on tunes and mlua
Documentation
# Lua API


## 查阅方式


本章是 Lua 用户的 API 百科。编辑器补全请使用 [`types/pulse.meta.lua`](https://github.com/limao996/mlua-pulse/blob/master/types/pulse.meta.lua);本章负责解释何时使用、参数含义、返回值形状和导出影响。若你想按教程学习,请从 [快速开始](../01-lua-composition/getting-started.md) 和 [序列、乐句与编排](../01-lua-composition/arrangement.md) 开始。

API 大致分为六组:顶层素材函数、链式编曲对象、采样和 MIDI、鼓机、导出与 PCM、播放预览。所有链式对象都返回自身或新对象,便于连续调用。

## 类型与函数


| 名称 | 何时使用 | 参数 | 返回 | 导出影响 |
| --- | --- | --- | --- | --- |
| `pulse.note(name)` |`"C4"` 转成频率 | 音名字符串 | number | WAV/FLAC/PCM 使用频率渲染;MIDI 会转换为音符号 |
| `pulse.scale(root, mode)` | 生成音阶材料 | 根音、调式 | number[] | 用于旋律或映射 |
| `pulse.chord(root, kind)` | 生成和弦材料 | 根音、和弦类型 | number[] | 用于 `Sequence:chords` |
| `pulse.transpose(value, semitones)` | 复用材料并移调 | 频率或数组、半音数 | 同输入形状 | 改变实际音高 |
| `pulse.sequence()` | 创建旋律或和声 || `pulse.Sequence` | 可进入所有音频导出和 MIDI 导出 |
| `pulse.phrase()` | 创建可重复段落 || `pulse.Phrase` | 加入 `Song` 后按段落展开 |
| `pulse.song()` | 创建完整作品 || `pulse.Song` | WAV/FLAC/MIDI/PCM/播放的主要入口 |
| `pulse.drum_grid()` | 手写鼓网格 || `pulse.DrumGrid` | 音频渲染为鼓声,MIDI 导出为鼓事件 |
| `pulse.drum_machine("808")` | 快速写 808 pattern | kit 名称 | `pulse.DrumMachine` |`:grid()` 后加入作品 |
| `pulse.sample(path)` | 引用音频素材 | 文件路径 | `pulse.SampleClip` | WAV/FLAC/PCM/播放会渲染;MIDI 不嵌入采样 |
| `pulse.import_midi(path)` | 导入 MIDI | 文件路径 | `pulse.ImportedMidi` | 可重新导出或作为 `pulse.MidiClip` 编曲 |
| `pulse.stream_pcm(value, callback, options)` | 探测式 PCM 流 | 可渲染对象、回调、选项 | integer 或 nil | 回调接收 userdata |
| `pulse.playback()` | 本机预览 || `pulse.PlaybackEngine` | 不影响导出文件 |

## `pulse.Sequence`


`pulse.Sequence` 表示旋律或和声轨。它支持 `:notes(number[])`、`:chords(number[][])`、`:durations(number[])`、`:instrument(name)`、`:at(offset)`、`:volume(value)`、`:pan(value)`、`:velocity(value)`、`:effect(name, options)`、`:synth(name, options)`、`:transpose(semitones)`。

数量规则很重要:notes 或 chords 的事件数量必须和 durations 数量一致。音量建议从 `0.2..0.8` 开始,pan 范围 `-1..1`,velocity 范围 `0..1`。`filter` 可以作为轨道效果,不能作为 master 效果。

```lua
local lead = pulse.sequence()
  :notes({pulse.note("C4"), pulse.note("E4"), pulse.note("G4")})
  :durations({0.25, 0.25, 0.5})
  :instrument("electric_piano")
  :volume(0.45)
  :pan(0.1)
```

## `pulse.SampleClip`


`pulse.SampleClip` 用于离线采样。常用方法包括 `:slice(start, finish)`、`:reverse()`、`:loop_for(duration)`、`:normalize()`、`:fade_in(duration)`、`:fade_out(duration)`、`:pitch_shift(semitones)`、`:time_stretch(factor)`、`:rate(playback_rate)`、`:gain(value)`、`:at(offset)`、`:track(name)`、`:volume(value)`、`:pan(value)`、`:effect(name, options)`。

采样真正读取发生在导出或渲染时。WAV、FLAC、PCM 和播放会听到采样;MIDI 导出不会嵌入采样音频。

## `pulse.MidiClip``pulse.ImportedMidi`


`pulse.ImportedMidi` 由 `pulse.import_midi(path)` 返回,可以直接 `:export_wav`、`:export_flac`、`:export_midi`、`:stream_pcm`,也可以通过 `:at`、`:track`、`:volume`、`:pan`、`:repeat_times`、`:effect` 变成 `pulse.MidiClip`。

`pulse.MidiClip` 可以加入 `Phrase:add_midi(midi)` 或 `Song:add_midi(midi)`。音频导出会渲染导入 MIDI 的音符、鼓事件、轨道音量、声像和轨道效果;MIDI 导出只保留 MIDI 文件能表达的事件、轨道名、program、CC7、CC10、velocity 和 pitch bend。

## `pulse.DrumGrid``pulse.DrumMachine`


`pulse.DrumGrid` 支持 `:track`、`:steps`、`:step_duration`、`:sound`、`:accent`、`:velocity`、`:volume`、`:pan`、`:repeat_times`、`:effect`。数组 pattern 使用 0 起始步号,字符串 pattern 的第一个字符也是第 0 步。

`pulse.DrumMachine` 当前支持 `"808"`,可设置 `:kick`、`:snare`、`:hihat`、`:open_hihat`、`:clap`,最后用 `:grid()` 转为 `pulse.DrumGrid`。

## `pulse.Phrase``pulse.Song`


`pulse.Phrase` 支持 `:add(sequence)`、`:add_drum_grid(grid)`、`:add_sample(sample)`、`:add_midi(midi)`、`:repeat_times(n)`。段落适合表示 intro、verse、chorus、drop、bridge。

`pulse.Song` 支持 `:tempo(bpm)`、`:add(sequence)`、`:add_drum_grid(grid)`、`:add_phrase(phrase)`、`:add_sample(sample)`、`:add_midi(midi)`、`:master_effect(name, options)`、`:export`、`:export_wav`、`:export_flac`、`:export_midi`、`:stream_pcm`、`:play`、`:play_at_rate`。

## `pulse.PcmChunk`


PCM 流回调收到的是 `pulse.PcmChunk` userdata,不是 table,也不是 string。它提供 `:frames()`、`:samples()`、`:bytes()`、`:sample_rate()`、`:channels()`、`:format()`、`:sample(index)`。顶层 `pulse.stream_pcm` 对不支持的值直接返回 `nil`。

## 错误条件


常见错误包括:无效音名、未知调式、未知和弦、未知乐器、未知鼓声、未知效果、未知合成器、未知生成器、duration 数量不匹配、volume/pan/velocity 越界、采样 slice 结束小于开始、rate 或 time_stretch 为 0、导出格式不支持、未启用 `gpu` 特性却请求 GPU。

Lua 侧建议使用 `pcall`:

```lua
local ok, err = pcall(function()
  pulse.sample("source.wav"):rate(0)
end)
if not ok then print(err) end
```

## 示例


```lua
local pulse = require("pulse")

local phrase = pulse.phrase()
  :add(
    pulse.sequence()
      :notes(pulse.scale("C4", "ionian"))
      :durations({0.25, 0.25, 0.25, 0.25, 0.5, 0.5, 0.5, 1.0})
      :instrument("electric_piano")
      :volume(0.45)
  )
  :add_drum_grid(
    pulse.drum_machine("808")
      :steps(16)
      :kick("x---x---x---x---")
      :snare("----x-------x---")
      :hihat("x-x-x-x-x-x-x-x-")
      :grid()
      :volume(0.45)
  )
  :repeat_times(2)

pulse.song()
  :tempo(112)
  :add_phrase(phrase)
  :master_effect("eq", "warm")
  :master_effect("limiter", "standard")
  :export_wav("output/lua-api.wav", { normalize = "rms", target_db = -16.0, true_peak_db = -1.0 })
```

## 相关章节


- [快速开始]../01-lua-composition/getting-started.md
- [采样与 MIDI]../01-lua-composition/samples-midi.md
- [PCM 流]../04-export/pcm-streaming.md
- [LuaLS 注解]https://github.com/limao996/mlua-pulse/blob/master/types/pulse.meta.lua