# Symi 编辑器文档 ::u-page-hero --- class: dark:bg-gradient-to-b from-neutral-900 to-neutral-950 orientation: horizontal --- ![Example1](https://symi.rika.link/images/example1.png) #top :hero-background #title 基于文本的 :br[微分音乐编辑器]{.text-primary} #description Symi 是一种文本标记语言,用于描述音高和节奏,受 [simai语](https://w.atwiki.jp/simai/pages/1002.html){.text-primary rel=""nofollow""} 启发创作。其提供了多种表达方式,支持微分音和复杂节奏结构。 Symi编辑器支持实时回放、钢琴窗预览和导出MIDI,适合实验性音乐创作。 #links :::u-button --- size: xl to: https://symi.rika.link/getting-started trailing-icon: i-lucide-arrow-right --- 了解更多 ::: :::u-button --- color: neutral icon: i-lucide-download size: xl to: https://symi.rika.link/getting-started/installation variant: outline --- 下载安装 ::: :: ::u-page-section --- class: dark:bg-neutral-950 --- #title 主要功能 #links :::u-button --- color: neutral size: lg target: _blank to: https://ui.nuxt.com/docs/getting-started/installation/nuxt trailingIcon: i-lucide-arrow-right variant: subtle --- 速速阅读文档 ::: #features :::u-page-feature --- icon: i-lucide-keyboard-music --- #title 多种音高表记 #description 支持多种音高表示方法,包括频率、倍音、平均律、音分和音名等,甚至链接多种表示。 ::: :::u-page-feature --- icon: i-lucide-drum --- #title 多种节奏表记 #description 允许设置反常拍号、支持任意有理数比例的量化,还有语法糖来简化复杂节奏的表达。 ::: :::u-page-feature --- icon: i-lucide-guitar --- #title 和弦/多声部 #description 支持同时演奏多个音符,即使音高和节奏都不同。 ::: :::u-page-feature --- icon: i-lucide-piano --- #title 多彩钢琴窗 #description 即使是微分音,也可以在钢琴窗中可视化,并且以颜色标记音高,更直观地理解和声结构。 ::: :::u-page-feature --- icon: i-lucide-square-arrow-out-up-right --- #title 导出 MIDI #description 没错!可以通过多轨和弯音参数将微分音乐导出为 MIDI 文件,方便在其他 DAW 中使用。 ::: :::u-page-feature --- icon: i-lucide-ellipsis --- #title 更多 #description 该项目仍在锐意开发中,提出建议可能被采纳! ::: :: ::u-page-section{.dark:bg-gradient-to-b.from-neutral-950.to-neutral-900} :::u-page-c-t-a --- links: - label: 加入Discord to: https://discord.gg/pyZYtqXjeB target: _blank variant: subtle icon: i-simple-icons-discord - label: GitHub Issues to: https://github.com/RikaKagurasaka/symi/issues target: _blank variant: subtle icon: i-simple-icons-github class: dark:bg-neutral-950 description: 可以加入Discord,或在 GitHub 上提出 issue。 title: 还有想说的…… --- :stars-bg ::: :: # 介绍 Symi /sɪ'mai/ 是 **SY**nthesized **MI**crotone 的简写。 ## 为什么开发Symi? 现有的微分音乐记谱方法有基于MuseScore的五线谱,符号繁多而不便记忆;有基于PianoTeq的MIDI映射,在宿主中编辑不够直观且音高数量受限;还有基于文本的Xenpaper,虽然灵活但缺乏对复杂节奏的支持。 [simai语](https://w.atwiki.jp/simai/pages/1002.html){rel=""nofollow""}是一种用于舞萌DX模拟器的记谱语言,其主要重视节奏表达。受其启发诞生的Symi语在支持复杂节奏的同时,提供了更丰富的音高表示方法。并且尽管作为一种文本标记语言,其还可以导出为MIDI文件,方便在宿主中使用。 ## 设计理念 为了保证最大限度的灵活,Symi不对音高和节奏做任何先验假定(受技术和精度限制除外),时间单位以秒、音高单位以赫兹为一等公民。在此基础上,提供各种表记方法使之易于使用。 ## 接下来 你可以[下载](https://symi.rika.link/getting-started/installation)一个Symi Editor直接上手尝试,也可以先看看[语法](https://symi.rika.link/grammars)的介绍。 # 下载和安装 ## 直接下载 Symi Editor的发布在[Github Releases页面](https://github.com/RikaKagurasaka/symi/releases){rel=""nofollow"" target="\_blank"}进行,下面显示的可能不是最新版本,请前往该页面查看最新的发布信息。 :release-downloads --- ## 从源代码构建 该项目暂时没有提供32位系统的预构建二进制。如果你有需要,可以按照[仓库的指导](https://github.com/RikaKagurasaka/symi/blob/main/README.md){rel=""nofollow""}从源代码构建。 # 使用方法 ## 界面概览 Symi Editor 的主界面可以分为 4 个区域: - **左侧边栏**:新建、打开、保存、另存为、导出 MIDI、帮助,以及文件标签列表。 - **中央编辑区**:输入和编辑 Symi 文本。 - **底部钢琴卷帘窗**:可视化当前内容的音符分布与时间位置。 - **状态栏**:显示光标行列、小节/拍内位置、时间和音量。 你可以点击左上角折叠按钮收起侧边栏,把更多空间留给编辑器。 ## 基本功能 ### 文件与标签页 - 新建空白文件或打开本地 `.symi` / `.txt` 文件。 - 同时打开多个文件,并在侧边栏中切换活动标签页。 - 支持保存和另存为。 ### 编辑与预览 - 在编辑区直接编写 Symi 文本。 - 当有活动文件时,底部会显示钢琴卷帘窗用于可视化预览。 - 可通过中间分隔条上下拖动,调整编辑区与卷帘窗高度。 ### 导出与帮助 - 可将当前内容导出为 MIDI。 - 帮助面板内置快捷键说明,并可跳转在线文档。 ## 快捷键 > `Ctrl` 在 macOS 上对应 `Cmd`。 ### 通用 - `Ctrl+N`:新建文件 - `Ctrl+O`:打开文件 - `Ctrl+S`:保存当前文件 - `Ctrl+Shift+S`:另存为 - `Ctrl+W`:关闭当前标签页 ### 编辑器 - `Ctrl+Space`:播放/暂停 - `Ctrl+Z`:撤销 - `Ctrl+/`:切换当前行或选中区间所有行的注释(`//`) ### 钢琴卷帘窗 - `鼠标滚轮`:水平滚动 - `Shift+鼠标滚轮`:垂直滚动 - `Ctrl+鼠标滚轮`:水平缩放 - `Alt+鼠标滚轮`:垂直缩放 - `空格`:播放/暂停 - `Ctrl+鼠标左键`:跳转光标到点击位置 - `鼠标中键`:拖动视图 # 概述 Symi的语法实体大致可分为以下几类: - **控制信息**:定义BPM、拍号、基准音、量化等全局属性。这些定义在出现后会持续影响后续内容的解析,直到被新的定义覆盖。 - **音高**:通过倍音、频率、音名、平均律等方式指定的音高信息。 - **时间**:基于BPM、量化、时值等方式指定的时间信息。音高和时间信息共同描述一个音符事件。 - **宏**:宏分为 alias、simple、complex 三类。alias/simple 主要用于音高复用,complex 用于片段复用;它们都可以被调用以生成一个或多个音符事件。 - **注释**:`//`直到行末的内容被视为注释,不参与解析。 # 控制信息 ## 拍号 拍号定义了每小节的拍数和每拍的时值。格式为 `(拍数/每拍时值)`。例如: - `(4/4)` 表示每小节4拍,每拍四分音符。 - `(3/8)` 表示每小节3拍,每拍八分音符。 拍号实际上不影响音符事件的时间计算,但是由于Symi中每行表示一个小节,强烈建议定义正确的拍号,以允许编译器检查每小节时值是否正确。 理论上任何有理数都可以作为拍号,但是**不建议使用非二的幂次的时值作为分母**。受限于MIDI文件的格式,含有这种拍号的Symi无法导出为MIDI。 如果不定义拍号,默认在文件的开头使用 `(4/4)`。 ## BPM BPM(每分钟节拍数)定义了节奏的快慢。格式为 `(BPM)`,或 `([时值]=BPM)`。例如: - `(120)` 表示每分钟120个四分音符。 - `([8]=160)` 表示每分钟160个八分音符。 - `([8:3]=140)` 表示每分钟140个 **八分之三音符** 或 **附点四分音符**。 省略时值部分时,默认以**四分音符**为基准。[时值](https://symi.rika.link/time#%E5%88%86%E6%95%B0%E6%A0%87%E8%AE%B0)部分的具体语法参见后文。 如果不定义BPM,默认在文件的开头使用 `(120)`。 ## 基准音 基准音(参考音)定义了音高的参考频率。格式为 `<基准音名=音高链>`,其中两部分都可以分别和等号一同被省略。[音高](https://symi.rika.link/pitch)的具体语法参见后文。例如: ```text // 定义基准音C4为261.63Hz // 定义D4为基准音,其频率根据音名(以及之前定义的基准音)自动计算,即等同于或者 <440> // 定义基准音为440Hz,其音名根据频率(以及之前定义的基准音)自动计算,即等同于 <20c> // 定义基准音频率为之前基准音上调20音分,音名自动计算仍为C4,即等同于 // 右侧可使用音高链 a = 3/2@5/4 // alias macro // 右侧可引用 alias macro ``` 如果右侧使用了相对音高(如上例中的`20c`),其频率会根据之前定义的基准音计算。 省略音名时,基准音的音名会寻找与所给定音高最接近的音名。 右侧若使用标识符,必须解析为一个 alias macro(且能展开为单个音高链)。 如果不定义基准音,默认在文件的开头使用 ``。 ::tip 非常建议将歌曲的**主音**定义为基准音 :: ## 量化 量化定义了时间信息的基本单位。格式为 `{量化时值}`,例如: - `{4}` 表示以四分音符为量化单位。 - `{12}` 表示以**十二分音符**或**三连八分音符**为量化单位。 - `{8:3}` 表示以**八分之三音符**或**附点四分音符**为量化单位。 理论上控制信息可以在任何位置定义,但量化可能是你最常这样使用的一项。例如你可以写出这样的内容: ```text {4}C,D,E,{8}F,E, {12}D,E,D,{4}F,{2}G, ``` 但是过于频繁变动的量化会给阅读带来麻烦,量化并不是时间信息的**最小**单位,后文会介绍在不改变量化的情况下,处理更细分时间的方法。因此建议将量化定义为一个段落中大部分音符时值的最大公因数,比较方便操作。 # 音高 Symi支持多种方式来指定音高信息。 ## 频率 直接使用赫兹数值指定音高,例如: ```text 261.63,440,261.63,523.26, ``` 使用频率指定的音高不受基准音的影响。频率必须是正数,可以是整数或小数。 此外,由于频率在实际编曲中较少用到,在**平均律的语法糖**启用下,**整数**会被视作平均律级数而非频率值解析,具体场景见下文。 ## 音名 使用音名指定音高,例如: ```text C4, D#4, Bb3, ``` 音名后的八度数字是可选的,如果省略,则会解析为**从基准音向上数的第一个该音名**。例如: ```text A, // 解析为A4 B, // 解析为B4 C, // 解析为C5 ``` 可以使用`+`或`-`来指定相对于上述解析结果的八度偏移,具体可见[音高后缀](https://symi.rika.link/#%E9%9F%B3%E9%AB%98%E5%90%8E%E7%BC%80)语法。例如: ```text C, // 解析为C4 C+, // 解析为C5 C-, // 解析为C3 C++, // 解析为C6 ``` 音名对应的频率会受到基准音的影响,例如: ```text C, // 解析为440Hz A, // 解析为739.98Hz ``` ## 倍音 使用相对于基准音的频率倍数指定音高,语法为`分子/分母`,例如: ```text 1/1, // 解析为261.63Hz 3/2, // 解析为392.44Hz 2/1, // 解析为523.26Hz ``` 倍数必须写成分数的形式,并且分子分母都必须是正整数。 ## 平均律 使用相对于基准音的平均律级数指定音高,语法为`级数\平均律数`,例如: ```text 0\12, // 解析为261.63Hz 49\31, // 解析为782.54Hz -8\17, // 解析为188.81Hz ``` 级数可以是整数,但是平均律数必须是正整数。 在书写了一个平均律音高后,**平均律语法糖**被启用,此时**整数**会被解析为平均律级数而非频率值,例如: ```text 0\12, // 解析为261.63Hz 7, // 解析为7\12,即392.00Hz 5\31, // 解析为292.58Hz 29, // 解析为29\31,即500.38Hz ``` 如果需要关闭平均律语法糖,再书写一个小数频率即可,例如: ```text 0\12, // 解析为261.63Hz 10, // 解析为10\12 440.0, // 关闭平均律语法糖,解析为440Hz 5, // 解析为5Hz ``` ## 音分 使用相对于基准音的音分数值指定音高,语法为`音分数值c`,例如: ```text 0c, // 解析为261.63Hz 20c, // 解析为264.67Hz -140c, // 解析为241.30Hz ``` 音分数值只能是整数,正数表示升高,负数表示降低。 ## 音高链 音高链允许通过多个音高信息的组合来指定一个音高,运算符号`@`从右向左运算,例如: ```text -20c@G, // 解析为G4上降低20音分的音高 2/1@-140c@A, // 解析为A4上,降低140音分,再把频率乘以2的音高 ``` 技术上其实现方式为,临时将右侧的音设置为基准音,用于解析左侧的音高信息,如此递归进行。 音高链中的每一段都可以是: - 普通音高(音名、频率、倍音、平均律、音分) - 宏标识符(仅支持可展开为单个音高链的 alias macro) ## 音高后缀 `+` / `-` 任意音高项后都可以直接跟若干个`+`或`-`。 - `+` 等价于在该位置插入 `@2/1` - `-` 等价于在该位置插入 `@1/2` 示例: ```text 3/2+, // 等价于 3/2@2/1 3/2--, // 等价于 3/2@1/2@1/2 C4+@G-, // 混合用法 ``` 它们只是音高链语法糖,不改变`@`右结合的计算规则。 ## 与宏结合 音高链可直接与宏结合,例如: ```text a = 3/2@5/4 // alias macro(单行、无冒号) C4@a, ``` 当标识符出现在音高链中时,必须能解析为一个 alias macro。 更多宏语法见[宏](https://symi.rika.link/macro)。 # 时间 时间在Symi中是一个核心概念,所有事件都是基于时间发生的。本文使用**时间戳**来表示事件发生的时间点,使用**时值**来表示事件持续的时间长度。 ## 时间戳 ### 行内分隔记号 时间戳的主要推移方式是使用**逗号** `,`,每个 `,` 表示对应一个当前量化单位的时间。例如 ```text (60) {4}C,D,E,F, ``` 上述内容表示在BPM=60、量化为四分音符的情况下,C、D、E、F分别在0秒、1秒、2秒、3秒时发生。 ::warning 行末一般情况下都应该有一个逗号,以将时间戳推移到下一拍的开始。缺少逗号会导致后续内容被解析到当前拍,可能会引起混乱。 :: 使用**分号**`;`可以临时将当前量化细分为更小的单位,例如: ```text (60) {4}C;D;E,,,, ``` 这里的两个分号将当前的四分音符量化平均分为三份,因此C、D、E分别在0秒、0.333秒、0.667秒时发生,后续的逗号将时间戳推移到下一拍的开始,即1秒。 换言之,在两个逗号之间有`n`个分号时,每个分号以及最后的逗号将时间戳推移`1/(n+1)`倍量化。 使用**冒号**`:`可以分隔同时发生的事件,例如: ```text (60) {4}C:E:G, ``` 上述内容表示在0秒时C、E、G同时发生,即一个C大三和弦。 --- 上述记号可以组合使用,结合优先级为:冒号 > 分号 > 逗号。 根据上述描述可以发现,逗号**总是**将时间戳推移一个量化,而分号和冒号只是局部的细分和分组,并不会改变整体时间戳的推移。 ### 小节分隔记号 如果一行出现了逗号或分号,则行末换行时会开始下一小节。 在一行的开头使用**等号** `=`,表示在这一行结束时将时间戳重置回行首的时间戳,换言之这一行和下一行会同时播放。例如: ```text (60) ={4}D,C#-,B-,A-, ={4}F#,E,D,C#-, {4}A,G,F#,E, ``` 和 ```text (60) D:F#:A,C#-:E:G,B-:D:F#,A-:C#-:E, ``` 是等价的,但是显然前者更清晰易读。此外,前者还可以实现在同一小节中有节奏完全不同的两个声部同时演奏。 ## 时值 上述的逗号、分号、冒号等记号虽然会影响时间戳的推移,但并不直接表示事件的时值。 在没有时值标记的情况下,事件会持续到下一个分号或逗号的位置,例如: ```text (60) {4}C,,E,F, //第一拍是C,第二拍休止,第三拍是E,第四拍是F {4}C;;D, //第一拍的C持续1/3拍,休止1/3拍,再是1/3拍的D ``` ### 简易标记 通过使用`[]`括起逗号,可以额外延长事件的持续时间,例如: ```text (60) {4}C[,,],D, //第一拍是C,持续3拍,第四拍是D {4}C:D[,],E,F, //第一拍是C和D,共同持续2拍,第三拍是E,第四拍是F ``` ### 分数标记 通过 `[分母:分子]` 的形式可以将事件的持续时间指定为等同于若干分音符的时值。其中如果分子为1,可以和冒号一并省略。例如: ```text (60) {4}C[8],D[8],E[8],F[8], //C,D,E,F分别持续一个八分音符 {4}C[8:3],;D,E[2],F, //C持续一个八分之三音符,D在第二拍的后半拍开始,持续半拍,E持续二分音符,F持续四分音符 ``` 使用分数标记可以极为灵活地指定时值,可以令事件之间重叠、断奏。分子分母均为正整数即可,分母不必是二的幂次。 分数标记还可以是**负数**,这种情况下事件的结束时间会被移动到开始时间,而开始时间则由时值决定。例如: ```text (60) {4}C,D[-64]:E,-,F[-64]:G, //D和F在第2、4拍*之前*开始,并在第2、4拍结束,均持续一个64分音符。 ``` 这种语法主要用于便捷地实现装饰音,避免了计算复杂的量化和时间戳。 ### 延音符号 使用**短横线** `-` 可以延长事件的持续时间,其作用效果为**将所有结束在当前时间戳的事件的时值延长至自身的结束时间**。例如: ```text (60) {4}C,-,-,D, //第一拍是C,持续3拍,第四拍是D {4}C,-;D, //第一拍是C,持续1.5拍,D在第二拍的后半拍开始,持续半拍。 ``` 需要注意的是,延音符号会影响**所有**在当前时间戳(±0.1ms)结束的事件,无论是和弦、其他声部、之前已经被延长的事件甚至是宏中的事件,因此在复杂的环境中需要小心使用。 延音符号本身也可以被上述的其他方法指定时长以修改自身的持续时间,如`{4}C,-[8],`中的`-[8]`将使得延音符号持续一个八分音符的时值,从而使得C持续一个四分音符加一个八分音符的时值。 ## 综合运用 当被`:`分隔的事件中有被指定了时值的事件时,时值会从后向前生效,例如: ```text (60) {4}G:E[8]:C:C-[,,],, ``` `C`和`C-`均持续三拍,而`E`和`G`均持续一个八分音符。 ::warning 强烈建议只在音符组(即被`:`和`;`分隔的事件)的最后一个事件中使用简易标记`[,,]`。否则该标记中的逗号实际不会推移时间戳,这导致逗号的简写功能失效。 :: # 宏 宏是Symi中一种强大的抽象机制,允许你定义可重用的代码块,并在需要的地方调用它们,这在音乐的重复结构中尤其有用。 ## 定义宏 宏定义的基本形式都是: ```text 宏名 = ... ``` 其中宏名使用标识符(字母、数字、下划线组合,且不能以数字开头)。 当前版本中,宏分为三类: - alias macro:单行、无 `:`,表示一个音高链别名 - simple macro:单行、含 `:`,表示多个音高项 - complex macro:多行片段(或以非音高标记开头的单行片段) ## 别名宏 别名(alias)宏的 body 是一个音高链: ```text a = 3/2@5/4 b = C4+ ``` 别名宏可用于: - 在音高链中作为标识符被引用(例如 `C4@a`) - 直接作为宏调用(例如 `a,`、`a@D4,`) - 在基准音定义右侧被引用(例如 ``) ## 简单宏 简单(simple)宏用于定义一组音高项,内容由 `:` 分隔,例如: ```text arp = 1/1:3/2:2/1 ``` 上例定义了一个名为 `arp` 的简单宏,内部是一个三音组。 简单宏只负责音高内容复用,不在定义处固定时间戳推进;实际时值与节奏由调用位置决定。 ### 复杂宏 复杂(complex)宏用于定义完整的**行级片段**(可包含时间控制、和弦、分号细分、控制信息等)。 写法是将 `=` 后换行,然后在下一行(或多行)书写宏体,**最后用一个额外的空白行结束**: ```text riff = {4}C,E,G,E, D,F,A,F, ``` 如果宏体只有一行,也可以直接写在 `=` 后,但是宏体必须以非音高标记开头: ```text riff = {4}C,E,G,E, // 这是合法的单行复杂宏定义 riff = C,E,G,E, // 这样写会被解析为 alias/simple 路径,而不是 complex 宏 ``` 复杂宏的宏体在逻辑上是一段独立片段: - 宏体内部按自身内容推进时间; - 调用时会将宏体事件整体平移到调用位置; - 宏体可以包含多个小节(多行)。 ::tip [小节分隔记号](https://symi.rika.link/time#%E5%B0%8F%E8%8A%82%E5%88%86%E9%9A%94%E8%AE%B0%E5%8F%B7)看起来就像是没有名字的单行复杂宏,其实它就是对复杂宏的一种特殊语法糖。 :: ## 调用宏 宏调用的基础形式是直接写宏名: ```text arp, riff, a, ``` 调用时可以在宏名后追加音高链尾部(`@...`、`+`、`-`): ```text arp@D4, arp@3/2@10c, riff@A3, a+, ``` 其语义与[音高链](https://symi.rika.link/pitch#%E9%9F%B3%E9%AB%98%E9%93%BE)一致:调用尾部会拼接到宏内每个音符(或 alias 链)的音高链末尾,再按 `@` 右结合计算最终频率。 这对 alias/simple/complex 三类宏都生效。 ### 示例 ```text a = 3/2@5/4 arp = 1/1:3/2:2/1 riff = {4}C,E,G,E, D,F,A,F, {1}a, arp@D4, riff, , riff@A3, ``` 上例中: - `a` 作为 alias 宏可直接调用; - `arp@D4` 与 `riff@A3` 会把 `@D4` 追加到展开后的音高链末尾; - 该调用尾部只影响当前调用,不影响后续内容。 # LLM 本页说明如何在当前文档站中使用已经配置好的LLM支持 ## LLM支持 你可以复制以下两个链接或之中的内容到支持文本输入的LLM工具中(如ChatGPT、Claude等),以便在对话中引用文档: - [llms.txt](https://symi.rika.link/llms.txt):精简、结构化的文档索引,适合让模型先建立目录感知。 - [llms-full.txt](https://symi.rika.link/llms-full.txt):更完整的文档文本,适合上下文充足时直接检索。 # 更新日志 ## v0.1.5 - 编辑器新增注释切换快捷键:`Ctrl+/`(macOS 上为 `Cmd+/`)。 - 支持对当前行或选中区间所有行批量切换 `//` 注释。 - 改进了光标,编辑器现在支持多光标,钢琴窗支持光标位置的动画效果。 - 修复了一个和宏与音高链相关的Bug ## v0.1.4 - 上个发布版本忘记改版本号了……只好新发个版本了 ## v0.1.3 - 将单音简单宏改为Alias Macro(别名宏),允许其在更多的地方出现。 - 允许使用`+`或`-`来改变任何音高标记的八度,不再仅限于音名。 - 移除了之前专门用于音名的八度偏移标记。 - 允许在Base Pitch Def中使用音高链。 ## v0.1.2 - 修复了宏调用和音高链的一些Bug。 ## v0.1.1 - 修改了宏调用的语法,弃用`foo(pitch)`形式的调用,改为`foo@pitch`。 - 实装了音高链机制,可以使用`@`串联多个音高标记。 ## v0.1.0 - 完成基本功能