- 桌面应用
- 计算机视觉
- 图像处理
- OCR
【免费下载链接】audiveris
Latest generation of Audiveris OMR engine
小节重复记号(bar repeat)是乐谱中常见的一类缩写记号,用于指示"前面已写出的若干小节必须原样重复"。本文以 Audiveris OMR 引擎为对象,系统讲解该引擎自 release 5.3 起对 1、2、4 斜杠小节重复记号及其上方可选小节计数的识别模型、形状面板手工编辑流程,以及 MusicXML 导出时的具体行为,并结合仓库源码给出可验证的实现依据。读完本文,你将能够在 Audiveris 中正确识别、修正并导出包含小节重复记号的乐谱。
小节重复记号在整页乐谱中的真实分布示例(图片源自 bar_repeats.png)
一、什么是小节重复记号
在乐谱记谱法中,**小节重复记号(bar repeat / measure repeat)**表示"其前方已经写出的若干小节必须被原样重复"。它通常以带斜杠的记号形态出现在小节内部或小节线上方:
- 记号的斜杠数量(1、2 或 4)决定了要重复的前置小节数量;
- 记号上方可选的小节计数(如数字"2")进一步明确重复范围,在规范记谱中应与斜杠数量一致。
在 Audiveris 的源码中,这一语义被直接固化在形状定义里。打开 Shape.java 可以看到三个核心逻辑形状:
REPEAT_ONE_BAR("Repeat last bar"), REPEAT_TWO_BARS("Repeat last two bars"), REPEAT_FOUR_BARS("Repeat last four bars"),对应的斜杠数量由 Shape.getSlashCount() 统一返回:
public int getSlashCount () { return switch (this) { case REPEAT_ONE_BAR -> 1; case REPEAT_TWO_BARS -> 2; case REPEAT_FOUR_BARS -> 4; default -> 0; }; }可见"斜杠数 = 重复小节数"这一对应关系是引擎识别与导出的基础约定。
二、示例解读:一个、两个与四个小节重复
先看上文整页示例(bar_repeats.png)所描述的场景:
- 全曲包含两个系统(system):第一个系统有 4 个小节(#1、#2、#3、#4),第二个系统有 3 个小节(#5、#6、#7);
- 第一个系统中,小节 #2 和 #3 内部各有一个单小节重复记号(one-bar repeat),其含义是"重复小节 #1 两次",即 #2 重复 #1、#3 再重复 #1;
- 第二个系统中,小节 #6 与 #7 之间的小节线上方出现一个两小节重复记号(two-bar repeat),表示重复其前方两个小节(#4 和 #5),即 #6、#7 的内容分别等于 #4、#5;
- 同理,还可能遇到四小节重复记号(four-bar repeat),用于重复前方四个小节。
也就是说,一个重复记号实际"吃掉"了斜杠数量个物理小节,这些小节在谱面上不必再写出完整音符,但在导出的结果中会被展开成真实内容(详见第五节)。
三、识别模型:从形状到符号解释
3.1 识别能力(release 5.3 起)
根据官方文档,Audiveris OMR 引擎自 release 5.3 起能够自动识别两类信息:
- 重复记号本身,支持 1、2 或 4 条斜杠三种形态;
- 记号上方的可选小节计数,该计数应与其斜杠数量一致。
文档中的bar_repeat_2.png展示了带计数与不带计数的典型形态:
单小节重复记号的两种形态:是否携带上方小节计数(图片源自 bar_repeat_2.png)
3.2 形状集合的归属
在 ShapeSet.java 中,三个重复记号形状被归入RepeatBars列表:
/** Repeat bars. */ public static final List<Shape> RepeatBars = Arrays.asList( REPEAT_ONE_BAR, REPEAT_TWO_BARS, REPEAT_FOUR_BARS);而 Barlines 形状集合(即形状面板中的Barlines组)则把常规小节线、反复号(左右反复/背靠背反复)、花括号、括号、反复点(REPEAT_DOT)与上述RepeatBars全部收纳在一起,这正是文档所述"三个符号位于Barlines集合中"的源码出处。
用于标注重复小节数的计数形状则定义在 MeasureCounts 列表中,包含自定义数字NUMBER_CUSTOM以及TIME_ONE~TIME_EIGHT等时间样式数字;Times 集合由MeasureCounts、TIME_CUSTOM(自定义)与WholeTimes组成,对应文档所述"小节计数可从Times集合中选取"。
3.3 符号解释(Inter)与关系建模
自动识别时,InterFactory.java 会将识别出的三个形状统一实例化为MeasureRepeatInter:
// Measure repeat signs case REPEAT_ONE_BAR: case REPEAT_TWO_BARS: case REPEAT_FOUR_BARS: return MeasureRepeatInter.create(glyph, shape, grade, closestStaff); // Staff is OKMeasureRepeatInter.java 是这一功能的符号解释核心类,其关键设计包括:
- JAXB 根元素名称为
measure-repeat,可直接序列化进工程文件; - 实例被
added()后自动登记到所在MeasureStack(小节栈),remove()时同步从栈中移除,保证与节奏/小节体系联动; - 支持手动创建的构造函数(
glyph为 null 的 ghost 对象),供形状面板拖放使用; - 编辑器为
HorizontalEditor,拖放时通过deriveOnStaffMiddleLine将其定位到谱表中线,便于对齐。
小节重复记号与其上方计数之间的关联由 MeasureRepeatCountRelation.java 建模,其 JAXB 名称为measure-repeat-count,是Support类型的单源单目标关系;源码注释明确说明:重复记号本身并不强制要求计数,因为斜杠数已经表达了重复次数,计数仅作为补充信息。
在小节层面,Measure.java 用LinkedHashSet<MeasureRepeatInter> repeatSigns保存本小节内的重复记号,并对外提供只读视图 getMeasureRepeats()。值得一提的是,旧版本中曾使用SimileMarkInter(同前记号)表达此类语义,现已被repeatSigns取代,并在加载旧工程时通过 SimileMarkInter.replace() 自动迁移,体现了模型演进脉络。
四、手工编辑:从形状面板分配与拖放
当自动识别不理想(例如记号被误判、位置偏移)时,可以手动处理:
- 重复记号本身:从形状面板的
Barlines集合中选择REPEAT_ONE_BAR、REPEAT_TWO_BARS或REPEAT_FOUR_BARS三个符号之一,手动分配(assign)或直接拖放到目标位置。面板形态见下图:
Barlines形状面板中的小节重复记号与相关符号(图片源自 bar_repeat_palette.png)
- 小节计数(可选):从形状面板的
Times集合中选取。两种途径:- 选择
Parts数字中的预定义项(如TIME_ONE~TIME_EIGHT等现成数字形状); - 或选择自定义
0项(NUMBER_CUSTOM/TIME_CUSTOM),再手动输入所需数值。
- 选择
注:
Times面板截图见仓库中的 time_palette.png。计数并非必需——如前所述,斜杠数已隐含重复次数,计数应与其保持一致。
拖放/编辑过程由MeasureRepeatInter的getEditor()(返回HorizontalEditor)与deriveFrom()(定位到谱表中线)共同驱动,可参考 MeasureRepeatInter.java。若计数与记号建立了关联,MeasureRepeatCountRelation会在关系增删时对其执行异常检查(checkAbnormal),帮助及时发现不一致。
五、MusicXML 输出行为
5.1 导出逻辑
Audiveris 的 MusicXML 导出器在 PartwiseBuilder.java 中处理小节重复记号,其核心流程是:
- 若当前小节带有重复记号(
repeats非空),取记号形状的斜杠数slashes; - 在小节属性中插入
<measure-repeat>元素,写入slashes与type="start":
final MeasureStyle measureStyle = factory.createMeasureStyle(); final MeasureRepeat repeat = factory.createMeasureRepeat(); repeat.setSlashes(new BigInteger("" + slashes)); repeat.setType(StartStop.START); measureStyle.setMeasureRepeat(repeat); getAttributes().getMeasureStyle().add(measureStyle);- 随后向前回溯
slashes个不含重复记号的前置小节(getPrecedingInScore()逐级前移),若中途遇到另一个重复记号且尚未收集到内容,则记录告警"Abnormal measure sequence before repeat sign"并安全终止; - 将回溯到的小节按逻辑内容逐一复制展开,每个斜杠对应一个小节,展开小节的编号形如
stack.getScoreId(...) + "+" + (i + 1)(例如4+1、4+2)。
源码中// TODO: take into account the number symbol if any above the measure repeat sign表明:当前版本导出时以斜杠数为准复制展开小节,记号上方的小节计数暂未参与展开计算,这一点在实际使用时需要注意。
5.2 显示与播放的已知差异
文档明确记录了在不同软件中观察到的行为差异,这是导出后验证的重要参考:
- 显示方面:
- 使用Finale(版本 27)读取时,重复记号按预期显示;
- 使用MuseScore(版本 3.6.2)读取时,重复记号本身不显示,但被重复的小节如同被"物理复制"一样完整呈现;
- 播放方面:
- 无论 Finale 还是 MuseScore,重复小节都能正确发声,即播放效果符合乐谱意图。
换言之,Audiveris 导出的 MusicXML 在语义上是正确的(播放无误),差异主要出现在部分阅读器对<measure-repeat>元素的可视化支持程度不同。
六、小结
小节重复记号是 Audiveris 自 release 5.3 起完整支持的记谱元素,其技术链路清晰可查:
| 环节 | 载体 | 说明 |
|---|---|---|
| 形状定义 | Shape.java | REPEAT_ONE_BAR/REPEAT_TWO_BARS/REPEAT_FOUR_BARS |
| 斜杠计数 | Shape.getSlashCount() | 返回 1、2、4 |
| 面板分组 | ShapeSet.java | Barlines集合(含RepeatBars)与Times集合 |
| 自动识别 | InterFactory.java | 实例化MeasureRepeatInter |
| 符号解释 | MeasureRepeatInter.java | 与小节栈联动、支持手动编辑 |
| 计数关系 | MeasureRepeatCountRelation.java | 记号与计数的一对一关联 |
| MusicXML 导出 | PartwiseBuilder.java | 写入<measure-repeat>并复制展开前置小节 |
实操建议:识别完成后,先核对记号斜杠数是否符合预期;如需要计数标注,从Times集合选取预定义数字或自定义值;导出 MusicXML 后,在 Finale 中检查记号显示,在 MuseScore 中核对小节是否被正确展开,并以播放验证语义完整性。
- 桌面应用
- 计算机视觉
- 图像处理
- OCR
【免费下载链接】audiveris
Latest generation of Audiveris OMR engine
相关推荐
Audiveris 节拍器标记(Metronome Mark)全解析:自动识别、手动编辑与 MusicXML 导出
Audiveris 节拍器标记(Metronome Mark)全解析:自动识别、手动编辑与 MusicXML 导出 导读:节拍器标记(Metronome Mar
桌面应用计算机视觉图像处理OCRAudiveris 多小节休止符(Multi-Measure Rest)识别与编辑实战指南
Audiveris 多小节休止符(Multi Measure Rest)识别与编辑实战指南 本文基于 Audiveris 官方文档 multi_rest.md
桌面应用计算机视觉图像处理OCRAudiveris 指法与拨弦标注(Fingering & Plucking)识别、手动插入与 MusicXML 导出实战指南
Audiveris 指法与拨弦标注(Fingering & Plucking)识别、手动插入与 MusicXML 导出实战指南 本篇技术指南聚焦 Audiver
桌面应用计算机视觉图像处理OCR
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考