大家好,我是溪夜。Reaper 的强大无需多言。无论是 Action List 中琳琅满目的功能,亦或是 SWS Extension 和 ReaPack 带来的超强拓展,对每一个从传统 DAW 转过来的人都是极大的惊喜。毕竟 Reaper 最大的问题不是它能不能做到,而是你能不能想到。通常你能想到的问题和需求,都能通过在 Reaper 找到对应功能或脚本来搞定。但你是否好奇过 ReaPack 中那些脚本是怎么写出来的?你是否曾不满于现有的脚本的功能?这篇文章会帮助你解决这些疑惑,让我们彻底从头学习一下脚本的构建。
本系列文章阅读需要的前置知识:- 有一定的英文基础,能够看懂 ReaScript 文档。最好有在 Cockos 论坛上搜索答案的能力。- 了解过一门编程语言,有 Lua 基础最好。零基础也不怕,我会快速讲解一下 Lua 语法基础,非常简单。- 对 Reaper 的功能比较了解,并已安装好 ReaPack。- 掌握基本的 GUI 设计知识。
本文目录:
ReaScript 基础
1.1. 补完 Reaper 效率链的最后一环
1.2. 为什么要做这系列教程
1.3. ReaScript API 基础
1.3.1. 简介
1.3.2. 支持的编程语言
1.4. 简单实例
Lua 基础
2.1. 数据类型
2.2. 逻辑判断
2.3. 循环语句
2.4. 循环控制语句
如何阅读 ReaScript 文档?
3.1. 原版文档与优化后文档的取舍
3.1.1. 原版文档
3.1.2. X-Raym 版优化文档
3.1.3. Mike Lacey 版 Wiki 文档
3.2. 如何在文档中找到想要的 API
3.3. 通过实例学习文档的阅读方法
通过实例学习如何创建带 UI 的 ReaScript 脚本
4.1. 如何打开 Reaper 中的开发环境?
4.2. 抽象出功能逻辑
4.3. 选择 API
4.4. 编写功能代码
4.5. 绘制 GUI
4.6. 连接 GUI 与功能代码
4.7. 完成效果
通过举一反三学会更多脚本
致谢
接下来讲什么?
ReaScript 基础
1.1. 补完 Reaper 效率链的最后一环
既然 Reaper 现有的功能已经这么厉害,为什么还要学 ReaScript 来自己写脚本?其实我们很容易发现,在声音设计或者音乐混音的工作中,很多需求都需要去定制才能做到,只用现有的脚本和功能是远远不够的。举个例子,在 WAAPI 中有通过“制表符分割文件”进行自动导入音频文件的 API,即通过文本文件中定义的文件名、文件路径、属性等信息,自动导入并创建 Wwise 中的对象。但显然,Reaper 本身没有功能能做到从文件中读取信息并创建轨道且设置相关属性的功能。我们先用脚本小白的思维做一下探索,试着搜索一下有没有人已经做过类似的脚本。
X-Raym 曾做过一个
Import tracks from file
脚本,可以快速的从 txt 或 csv 文件中创建音轨,但这个脚本做不到同时导入音频文件,只能快速创建音轨标题。继续搜索,会发现他还做过一个付费的脚本
Import items and regions from CSV
,功能虽比上一个稍多一点,但也不做不到我们的要求。
当然,在这篇文章里我不会讨论搜索技巧,或者如何撞大运找到现成的轮子。我们真正要思考的问题是:
现在有个现成的轮子无法满足我们,怎么在它的基础上增改代码以符合我们的需求?
如果真没现成的脚本,该如何从零搭个新的?
如果你对技术尚存追求,那么学习 ReaScript 就是你必修的一门 Reaper 功课。
1.2. 为什么要做这系列教程
在创作这篇文章之前,国内领域也有一些朋友做了关于 ReaScript 的教程。比如 Moy 老师曾做过几篇关于 ReaScript 的实例教学,在知乎、音频应用、声音设计论坛等社区中也有些朋友在分享自己所做的脚本。之所以我还要做一系列新的教程,原因有几点:
这个领域应该有一套更友好且更系统的教程,尤其要解答初学者在学习与使用 ReaScript 时的一些疑惑。
补充一些重要的内容,比如阅读文档的方法、给脚本设计 UI、在 Reaper 外调用 ReaScript 等。
奔着开源精神触发,我希望更多有创意的脚本被大家开发出来。
下面就让我们一起先从 ReaScript 基础开始。
1.3. ReaScript API 基础
1.3.1. 简介
ReaScript API 是 Reaper 中重要的功能补充,与 Action 的不同之处就是它更贴近底层。我们都知道,Reaper 的 Action 能瞬间完成一个具体的功能(这个功能实际上帮你一下子完成了多个功能步骤)。但在 API 中想是做到同样的效果,就要把这个功能拆解成细小步骤,并用代码实现每一步的操作后才能做到同样的事情。Action 和在 ReaPack 中下载的诸多脚本其实一样,本质上是一种对底层多步骤操作的封装。而我们“做脚本”这件事,就是重新封装属于我们自己的“功能想象”。拿 Item edit: Move position of item under mouse to edit cursor
举例,当我们执行这个 Action,当前鼠标光标下的对象会直接移动到光标处,听起来似乎非常简单。但如果用脚本来实现,步骤就多了很多:
获取鼠标下的对象:
BR_GetMouseCursorContext_Item()
获取游标的位置:
GetCursorPosition()
把对象的左边缘移动到游标的位置:
SetMediaItemInfo_Value()
可以看到,除了把这个 Action 拆成了三个步骤外,我还找到了对应的 API 功能,这是复刻这条 Action 的基础。Reaper 脚本的原理,即要想办法把我们的需求不断拆解,最终达到每个细节步骤都能通过调用一条 API 完成(如上例所示)。最后再通过基本的程序结构为它们设计执行逻辑,就能得到具有功能性的脚本。
把大象放进冰箱需要三步,打开冰箱门,把大象放进去,把冰箱门关上。
很多人都听说过小品中的这句话,但可思考过它背后的逻辑?拆解一个看似想当然的行为,这也是脚本开发的基础逻辑。而事实上把大象放进冰箱里还有着很多前提:冰箱(容器)能否装载这么大的动物(数据类型),这个大象是否需要麻醉(类似 Profiler 中时间点的概念),通过什么工具运载大象到冰箱里(中间变量,甚至压缩算法)……让读者有能力进行功能的拆解和找到对应的 API,这也是本系列文章所讲解的一个重点。我认如果你学明白这部分,剩下的组装程序与 GUI 开发其实也就没什么难度了。Reaper 脚本开发的另一个优势在于已它已内置了编码工具,不需要配置开发环境就能直接在内部进行脚本编程(此处不包括 Python)。甚至,无需 Juce 这种框架就能进行插件(JSFX)的开发。
上图为我在脚本开发时的截图。虽图片被压缩,但仍容易看出,凭 Reaper 和 ReaPack 提供的开发工具,我们在 Reaper 中能获得从代码到 GUI 构建器一整套开发工作流。
1.3.2. 支持的编程语言
ReaScript 支持三种脚本编程语言,分别是 Reaper 自有的 EEL、Lua 和 Python(2.7-3.X)。其中 EEL 不仅可用于 ReaScript 的开发,亦可用于 JS 插件的开发。(ReaScript 对于 C/C++ 也有支持,但在本文暂不予讨论)。本文会着重讨论 ReaScript 通过 Lua 的实现。因为本人目前不熟悉 EEL,且 Python 在 Reaper 内的性能没有 EEL 或 Lua 好,亦无法实现 UI 或图形显示。不过对于在 Reaper 外调用 API 我们会在下一篇有额外的讨论,在那里我们会用到 Python。
1.4. 简单实例
既然是实例,我希望更有针对性。作为国际惯例,先从 Hello Reaper 开始。这种基本的字符串输出实例的意义就是一条,代表你跑通了当前的开发环境。
reaper.ShowConsoleMsg("Hello Reaper!")
之后回过来看一下开头提到的那条 Action:Item edit: Move position of item under mouse to edit cursor