ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Audiveris 交互编辑器(Inter Editor)完全指南:句柄体系、吸附机制与源码实现

Audiveris 交互编辑器(Inter Editor)完全指南:句柄体系、吸附机制与源码实现 桌面应用计算机视觉图像处理OCR【免费下载链接】audiverisLatest generation of Audiveris OMR engine项目地址https://gitcode.com/gh_mirrors/au/audiveris点击查看免费下载本篇技术指南围绕 Audiveris OMR 引擎的交互式编辑器体系展开它是用户在已识别乐谱上手动修正Inter音符头、符干、谱号、连音线等音乐对象几何位置的核心工具。读完本文你将掌握默认编辑器与全部专用编辑器的句柄Handle布局与移动规则、各类对象的吸附Snap行为、谱线编辑器的 Lines/Global 两种模式以及编辑器底层的事件驱动与撤销/重做机制对应源码实现。1. 编辑器体系概览在 Audiveris 的数据模型中乐谱中的每个可编辑元素都是一个Inter实例如音符头、增时线、谱号、连音线等。编辑器的职责是当一个Inter进入编辑模式后在界面上渲染若干句柄Handle让用户通过鼠标拖拽或键盘方向键修改对象几何。本文档参考章节按字母序收集了所有Inter编辑器变体的描述重点说明每个句柄的角色及其可移动范围此外还介绍了Staff谱表编辑器的两个变体Lines逐线与Global整体模式。从源码结构看InterEditor.java所有交互编辑器都继承自InterEditor抽象类而InterEditor又继承自 ObjectEditor.java。每种Inter通过覆写getEditor()方法返回属于自己的编辑器实例例如 HeadInter.java 中返回new Editor(this)。若某Inter类未定义专用编辑器则回退到默认编辑器。2. 默认Inter编辑器默认编辑器适用于每一个Inter类如下例中的增时线 Augmentation dot除非该Inter类定义了更专用的编辑器。默认编辑器只在Inter中心提供一个句柄。这个最基本的编辑器允许把Inter向任意方向移动但无法调整其大小。其实现位于 DefaultEditor.java构造时记录originalBounds与latestBounds两份矩形数据句柄的move(dx, dy)方法把latestBounds与所有句柄点同步平移doit()将latestBounds写回Interundo()则恢复originalBounds。编辑过程中若该Inter关联了关系Relation——例如本例中音符头与增时线之间的 Augmentation 关系——关系会随着Inter的移动被动态更新上图中增时线被下移一线与它所增时音符的关系仍然保持。当对象被移动得离关联对象太远时关系自动消失。这一动态链接行为对应源码中的InterTrackerInterTracker.java当鼠标位置变化触发 Swing 重绘时Tracker 负责渲染正在移动的Inter并实时计算、绘制潜在的关联Links。以下各节描述所有专用编辑器按字母序排列。3. Barline / Bracket 编辑器小节线Barline只能水平移动且不能调整大小因为它被**吸附snapped**到谱表高度。在 Audiveris 数据模型中一条小节线从谱表顶线延伸到谱表底线不同谱表上对齐的小节线通常由所谓的 Connectors连接符相连。同一编辑器同样适用于 Bracket谱表连括线。4. Brace 编辑器中心句柄向任意方向平移整个花括线顶部与底部句柄垂直方向调整花括线长度。警告平移或缩放花括线仅适用于小幅微调。若想真正扩展或缩减某 Brace 实例所包含的谱表数量这是影响系统内 Part 定义的重型操作必须显式地通过添加或删除手动 Brace 来完成详见 Part merge 章节。5. Beam 编辑器中心句柄向任意方向移动整个符杠侧边句柄向任意方向移动该侧端点并将该侧**吸附到邻近的符干stem**上。源码实现位于 AbstractBeamInter.java 的Editor内部类中它提供三个句柄左端点吸附到左侧符干、中点整体移动同时尝试两侧吸附、右端点。move()中通过getSnapAbscissa(LEFT/RIGHT, systemStems)计算吸附横坐标当两侧都吸附到符干时还会用minBeamWidth常量检查宽度避免符杠塌缩成零宽。6. Clef 编辑器谱号编辑器只有一个中心句柄且只能水平在所在谱表的横向边界内移动垂直仅对部分谱号形状C_CLEF与F_CLEF/F_CLEF_SMALL允许如上图所示。当谱号被编辑——或通过拖放插入——时其参考点会与最近的一条合适谱线垂直对齐。谱线编号从下往上编号高音谱号G_CLEF的所有变体G_CLEF、G_CLEF_SMALL、G_CLEF_8VA、G_CLEF_8VB都对齐在第 2 线C_CLEF形状的可选位置第 4 线TENOR男高音第 3 线ALTO中音第 2 线MEZZO_SOPRANO次女高音第 1 线SOPRANO女高音F_CLEF与F_CLEF_SMALL形状的可选位置第 4 线BASS低音第 3 线BARITONE男中音低音谱号F_CLEF_8VA与F_CLEF_8VB保持对齐在第 4 线PERCUSSION打击乐谱号保持对齐在第 3 线。以上位置表与源码中的ClefKind枚举完全一致ClefInter.java例如TREBLE(Shape.G_CLEF, 2)、ALTO(Shape.C_CLEF, 0)、BASS(Shape.F_CLEF, -2)等。谱号垂直移动时其pitch与kind会被强制更新为目标值见Editor.move()中clef.setPitch(...)与kindOf(targetPitch, ...)的调用。谱号垂直移动时InterBoard 界面会同步更新以下为F_CLEF示例7. Ending 编辑器中心句柄向任意方向移动整个终止线侧边句柄水平移动该侧连同其侧腿如有底部句柄垂直调整腿的长度。8. Flag 编辑器符尾编辑器是默认编辑器的变体同样只有单个中心句柄但此处该句柄只能沿相关符干垂直移动。从源码看AbstractFlagInterAbstractFlagInter.java同样通过自定义Editor继承InterEditor实现这一约束。9. Head 编辑器音符头编辑器与默认编辑器类似只有单个中心句柄。唯一区别在于被移动的音符头会被吸附垂直方向吸附到下方谱线或加线当音符头被移出谱表时所需加线可能被动态创建水平方向吸附到邻近的符干左侧或右侧。当然这不适用于 WHOLE全音符或 BREVE二全音符形状因为它们不使用符干。源码层面HeadInter.java可找到完整的吸附逻辑getSnapAbscissa()L679-L703搜索邻近符干计算符干中心线在音符头中心高度处的横坐标返回符干外侧半宽偏移后的理论横坐标getSnapOrdinate()将中心点吸附到最近的谱线或加线deriveFrom()L251-L285拖放插入音符头时同样应用横/纵吸附必要时用精化后的落点重新派生preEdit()L1055-L1063编辑结束时追加所需加线的 AdditionTask即getNeededLedgerAdditions(...)。10. KeyAlter / Key 编辑器调号升降号KeyAlter编辑器允许水平移动调号中的某一个升降号成员。如果调号是整体手动的例如从 ShapePalette 拖放出来的整组调号则编辑器可水平整体平移整组调号。11. Ledger 编辑器加线Ledger使用自己的专用编辑器其源码同样继承InterEditorLedgerInter.java。12. 多小节休止符编辑器详细说明见 Multi-measure rest 章节。13. 八度移位编辑器单行版多行版详细说明见 Octave Shift 章节。14. Slur 编辑器最复杂的编辑器连音线Slur是最复杂的编辑器中心句柄向任意方向平移整个连音线侧边句柄向任意方向延伸该侧端点连同其相关的控制点控制点句柄移动其下方的控制点控制段中点句柄同时移动左右两个控制点。源码实现于 SlurInter.java共有 6 个句柄p1左端点、middle左右端点中点、p2右端点、c1左控制点、midC左右控制点中点、c2右控制点。其内在模型是一段三次贝塞尔曲线CubicCurve2D拖端点时关联控制点同步平移拖midC时两个控制点一起平移doit()时通过curve.setCurve(model.points, 0)把模型写回曲线并清空 bounds 触发重算。15. 谱线编辑器Lines 模式在 Lines 模式下谱表的所有谱线句柄均可单独垂直拖拽——每条谱线的每个定义点都是一个句柄。详见 Staff Editing 文档的 Lines mode 小节。16. 谱表整体编辑器Global 模式Global 模式下句柄位于谱表中线上但拖动时作用于所有谱线整体移动句柄时所有谱线保持平行侧边句柄左、右可同时垂直与水平拖拽从而拉伸或收缩谱表。若谱表被显著拉伸会自动插入新的定义点以及句柄这些插入的句柄用于对谱线进行精细的垂直微调非侧边句柄只能垂直拖拽。详见 Staff Editing 文档的 Global mode 小节。源码实现StaffEditor.java非常值得研读抽象基类StaffEditor extends ObjectEditor内含两种模式共用的基础设施收集每条谱线的内部 sectioncollectInternalSections()、收集可能受影响的水平外部 sectioncollectExternalSections()、按中位间距typicalDx对定义点做细化refinePoints()并在doit()/undo()中重建谱线 glyph、增删 hLag 上的 sectionsGlobalEditorL556-L720以谱表中线为驱动把每个定义点建模为Comb梳齿中线上一点 各谱线相对中线的纵向偏移dys。左右两侧使用OmniHandle任意方向移动中间使用VerticalHandle仅垂直checkInsertion()依据maxHandleXGapRatio常量默认 1.5 × typicalDx判断是否需要插入中间梳齿与句柄LinesEditorL744-L796每个谱线定义点对应一个VerticalHandle每个定义点仅垂直移动两种模式的共同点编辑完成后若检测到残留的水平 section 成为新谱线成员会被移除或重新插入。17. Stem / Arpeggiato / Connector 编辑器该编辑器同时适用于符干Stem、琶音Arpeggiato以及小节线/括线的连接符Connector。从源码结构看这些纵向对象共同继承AbstractVerticalInterAbstractVerticalInter.java其getEditor()返回同一套编辑器。18. TimeHalf / Time 编辑器如果拍号是被识别为两半的如 2/4 的两个数字则每一半本身就是一个Inter可仅水平移动。如果拍号是整体识别的则可作为整体水平平移。注意这也适用于所有被整体处理的拍号例如手动自定义拍号乃至整体识别的两部分拍号如 2/4。19. Wedge 编辑器下端线段上的句柄用于增大或减小楔形符号crescendo/diminuendo的垂直张角。20. Word 编辑器中心句柄向任意方向移动文字右侧句柄通过增大或减小字号来修改文字尺寸。21. 编辑器底层机制从拖拽到撤销/重做理解了各编辑器的句柄布局后再看 InterEditor.java 中记录的典型事件流程就能把拖拽一个句柄的完整生命周期串起来句柄移动用户拖拽选中句柄鼠标或键盘方向键触发其move(int dx, int dy)方法该方法一般会修改编辑器内部的数据模型吸附Snapping正是在这一步发生例如被拖拽的HeadInter总是垂直吸附到谱线/加线并可能水平吸附到邻近符干随后调用编辑器doit()把修改后的模型应用到Inter几何上。异步重绘Swing 在用户位置变化时异步重绘页面触发当前ObjectEditor的渲染InterTracker负责绘制移动中的Inter与动态计算出的关系Links——例如被拖离谱表的音符头会即时画出所需加线。持续编辑用户可继续按住并拖拽任意句柄。结束编辑用户在句柄外按下鼠标或按回车键触发endProcess()若对象确实移动过hasMoved则调用InterController.editInter(this)创建一个CtrlTask正式记录并执行该操作以便日后撤销/重做。CtrlTask依次执行build()通过Inter.preEdit(editor)追加EditingTask及相关的 links/unlinks子类还可追加额外任务例如HeadInter会为每条所需加线追加AdditionTask、performDo()调用doit()应用几何并顺序执行任务link 在 SIG 中插入边、unlink 移除边、publish()向 InterIndex、GlyphIndex、shape history 推送事件、epilog()更新受影响的 sheet step。历史记录CtrlTask成功后其任务序列被追加到InterController历史供用户撤销/重做performUndo()调用编辑器undo()恢复原始几何并逆序回滚任务。此外编辑过程中的几何校验逻辑值得注意doit()中Inter.setGlyph(null)表明——由于对象已移动其与原 glyph 的关联不再有效undo()则恢复originalGlyph并清理不再一致的 attachment。涉及集合体如和弦时updateEnsemble()会清除所在集合体的 bounds 缓存促使其按新成员几何重新计算。InterEditor的 Javadoc 中还附带了一张编辑流程时序图doc-files/Editor.png位于 omr/sig/ui 包内可辅助理解上述生命周期。22. 参考与延伸阅读本文档的原始来源参考章节 - Editors编辑器核心基类InterEditor.java、DefaultEditor.java、HorizontalEditor.java谱表编辑器StaffEditor.java含LinesEditor与GlobalEditor关键Inter编辑器实现ClefInter.java、HeadInter.java、AbstractBeamInter.java、SlurInter.java关联功能章节Staff Editing、Part mergeBrace 用法、Multi-measure rest、Octave shift赞分享桌面应用计算机视觉图像处理OCR【免费下载链接】audiverisLatest generation of Audiveris OMR engine项目地址https://gitcode.com/gh_mirrors/au/audiveris点击查看免费下载相关推荐Audiveris Inter 编辑完全指南编辑模式、手柄操作与各类编辑器深度解析Audiveris Inter 编辑完全指南编辑模式、手柄操作与各类编辑器深度解析 自 Audiveris 5.2 版本起谱面上的任意 Inter 符号实桌面应用计算机视觉图像处理OCRPlate 仓库 Changeset 编写规范为 platejs 多包发布写出高质量的版本变更记录Plate 仓库 Changeset 编写规范为 platejs 多包发布写出高质量的版本变更记录 导读 本文以 Plate 仓库基于 Slate 的富文本桌面应用计算机视觉图像处理OCRAudiveris 编辑器设计原理深入 SIG 数据模型与像素—Glyph—Inter—Relation 体系Audiveris 编辑器设计原理深入 SIG 数据模型与像素—Glyph—Inter—Relation 体系 本文基于 Audiveris 官方文档《Pri桌面应用计算机视觉图像处理OCR上一篇LogExpert5分钟掌握Windows平台最强大的图形化日志分析工具下一篇Notesnook 编辑器工具栏指南插入块、自定义分组与预设切换创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表