mlua-pulse 0.1.0

Lua-friendly music composition and audio export bindings built on tunes and mlua
Documentation
# 采样与 MIDI


## 你会学到什么


- 使用 `SampleClip` 把音频片段放进作品时间线。
- 使用 `ImportedMidi``MidiClip` 把外部 MIDI 作为编曲素材。
- 理解采样、MIDI、WAV、FLAC、PCM 和 MIDI 导出的关系。
- 避免把 MIDI 当作音频文件、把采样库管理当作本项目职责。

## 适合谁读


如果你的作品需要环境底色、过门、loop、导入旋律或 DAW 草稿,读本章。它面向离线导出,不讨论实时采样器的复杂资产管理。

## 前置知识


- [序列、乐句与编排]arrangement.md
- [WAV、FLAC、MIDI]../04-export/wav-flac-midi.md

## 心智模型


`SampleClip` 是一段音频素材的引用和处理说明。它可以裁剪、反向、循环、淡入淡出、音高/时间调整,然后像 sequence 一样加入 phrase 或 song。

`ImportedMidi` 是导入的 MIDI 文件。它可以直接导出,也可以变成 `MidiClip` 放进新作品。导入 MIDI 参与 WAV、FLAC、PCM 和播放时会被渲染为音频;导出 MIDI 时只保留 MIDI 能表达的符号事件。

## 最小可运行例子


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

local texture = pulse.sample("samples/texture.wav")
  :slice(0.0, 1.5)
  :loop_for(4.0)
  :normalize()
  :fade_in(0.03)
  :fade_out(0.08)
  :track("texture")
  :volume(0.32)
  :pan(-0.2)
  :effect("reverb", "room")

local midi = pulse.import_midi("input.mid"):at(0.5)
  :track("imported_theme")
  :volume(0.75)
  :repeat_times(2)

pulse.song()
  :tempo(96)
  :add_sample(texture)
  :add_midi(midi)
  :master_effect("limiter", "standard")
  :export_wav("output/samples-midi.wav", { normalize = "rms" })
```

## 参数和边界


`pulse.sample(path)` 只创建片段,真正读取发生在导出或渲染时。`:slice(start, finish)` 单位是秒,`finish` 必须大于 `start`。`:loop_for(duration)` 必须大于 0。`:time_stretch(factor)` 和 `:rate(value)` 都必须大于 0;前者尽量保持音高,后者会同时改变速度和音高。`:pitch_shift(semitones)` 使用半音。

`pulse.import_midi(path)` 返回导入 MIDI。它支持 `:at`、`:track`、`:volume`、`:pan`、`:repeat_times`、`:effect`,也支持 `:export_wav`、`:export_flac`、`:export_midi` 和 `:stream_pcm`。

MIDI 导出不会包含采样音频、混响、压缩、滤波器、合唱、母带限制器或响度标准化。WAV/FLAC/PCM 才是音频渲染结果。

## 常见陷阱


导出 `.mid` 后听不到采样是正常的。MIDI 文件没有音频轨,它只能告诉外部音源“什么时候发什么音”。

采样路径相对于运行时工作目录。示例从仓库根目录运行,所以推荐把素材路径写清楚,或由 Rust 宿主管理当前目录。

采样 `normalize()` 是片段级处理,不等于整首歌的 RMS 标准化。最终响度仍应在 `song:export_wav` 或 `song:export_flac` 选项里设置。

## 进阶用法


可以把采样作为段落内部元素,让它随 phrase 重复:

```lua
local fill = pulse.sample("samples/fill.wav")
  :fade_in(0.01)
  :fade_out(0.05)
  :gain(0.4)
  :at(3.5)

local chorus = pulse.phrase()
  :add_sample(fill)
  :add_midi(midi)
  :repeat_times(2)
```

这样 fill 会在每次 chorus 重复时出现,而不是只在整首歌时间线出现一次。

## 相关章节


- [WAV、FLAC、MIDI]../04-export/wav-flac-midi.md
- [PCM 流]../04-export/pcm-streaming.md
- [Lua API]../06-reference/lua-api.md
- [Rust 构造器]../05-rust-integration/rust-builders.md