JUCE - 入门
注:本文档由JUCE官方教程翻译而来。JUCE官网:https://juce.com
1、开始使用 Projucer
本教程将向您展示如何安装 JUCE 以及如何使用 Projucer 创建新的跨平台 JUCE 项目。您还将学习如何将项目导出到 IDE(例如 Xcode 或 Visual Studio)以开发、运行和调试您的 JUCE 应用程序。
级别:初学者
平台: Windows、macOS、Linux、iOS、Android
1.1、入门
JUCE下载地址:https://juce.com/get-juce/
解压 JUCE 文件夹并将其放在计算机上的某个位置。您的用户主文件夹是一个方便的位置。
进入刚刚安装的 JUCE 文件夹。启动位于此处的 Projucer。
1.2、新的项目窗口
首次启动 Projucer 时,系统会显示新项目窗口。(您也可以稍后从Projucer 的主菜单中选择新项目...来启动此窗口。):
1.2.1、选择项目类型
在窗口的左侧,选择您想要创建的项目类型。
对于每种项目类型,Projucer 将生成所有项目文件并添加适当的最小代码来设置一切。这样,在创建项目后,您可以立即开始开发实际功能。
如果您是第一次探索 JUCE 并且不知道从哪里开始,请选择 GUI 应用程序 — — 这将为您设置可运行的应用程序的所有基础知识,适用于桌面和移动平台。
以下是所有当前支持的项目类型的概述。
项目类型 | 描述 |
---|---|
申请/空白 | 这将创建一个空白的 JUCE 应用程序。 |
应用程序/GUI | 这将创建一个带有空应用程序窗口的最小 JUCE 应用程序。您可以从这里开始,使用 JUCE 提供的各种类添加更多功能,例如更多 GUI 组件。 |
应用程序/音频 | 这将创建一个最小的 JUCE 应用程序,类似于Application/GUI,但会自动添加所有设置代码,以便轻松获取音频输入和输出。您可以将其用于游戏、多媒体应用程序等。 |
应用程序/控制台 | JUCE 对于开发没有任何 GUI 的命令行应用程序也非常有用。使用此项目类型来创建这样的应用程序。 |
应用/动画 | 这将创建一个绘制动画图形显示的应用程序。例如,您可以从这里开始创建动画移动应用程序。 |
应用程序/OpenGL | 这将创建一个空白的 JUCE 应用程序,类似Application/GUI,但增加了对 OpenGL 绘制功能的支持,包括 3D 模型导入和 GLSL 着色器。 |
插件/基本版 | 这将创建一个基本的音频插件。所有支持 VST、AudioUnit 和 AAX 插件格式的代码都会自动添加。根据您的设置,此项目类型可能需要一些额外的准备步骤才能正常工作。有关更多信息,请参阅教程:创建基本的音频/MIDI 插件,第 1 部分:设置。 |
库/静态、库/动态 | 此项目类型对于创建基于 JUCE 的可重复使用软件库非常有用。Projucer 支持创建静态和动态链接库。 |
还有许多示例项目可以作为您项目的另一个起点,它们位于子文件夹中,可以通过单击“打开示例”JUCE/examples
选项卡进行浏览。
1.2.2、创建新项目
选择合适的项目类型后,您可以在窗口右侧填写一些额外的项目设置:
- 项目名称-在这里,您可以为您的应用程序选择一个名称。
- 模块- JUCE 框架代码被组织成模块。在这里,您可以选择项目中包含哪些模块,并在下面的部分中指定
modules
您之前安装的 JUCE 文件夹内的子文件夹的位置。 - 导出器- 在这里,您可以选择要使用哪些本机 IDE 来构建和调试您的应用。这还定义了您的应用将支持的桌面和移动平台。别担心,这不是最终选择 - 使用 Projucer,您可以稍后添加其他平台和 IDE。
Projucer 目前拥有适用于以下 IDE、构建系统和平台的导出器:
目标操作系统 | 支持的构建系统 |
---|---|
OSX | XCode |
Windows | Visual Studio,Code::Blocks |
Linux | Makefile、Code::Blocks |
iOS | Xcode |
安卓 | Android Studio |
- 文件创建选项(File Create Options)- 根据项目类型,此字段可能会提供一些关于自动生成哪些代码的选项。如果您是 JUCE 新手,默认选择通常是自动生成您所需的一切并让您快速上手的最佳方式。
- 检查完所有设置后,单击“创建项目...”按钮在指定位置生成项目。
1.2.3、导出项目并在本机IDE中打开
创建项目后,您可以直接从 Projucer 启动本机 IDE 并运行您的项目。使用顶部附近的按钮:
现在您已经打开了 IDE(Xcode、Visual Studio 等),您可以编译并运行 JUCE 应用程序,然后开始编码!
注意:您需要在计算机上安装适当的原生 IDE/构建系统才能使用它。对于某些平台,您可能还需要安装其他依赖项,例如,您需要安装 Android SDK 才能为 Android 进行开发。
所有导出目标(即原生 IDE 项目)都是在您创建 Projucer 项目时生成的。每次您在 Projucer 中保存项目时,它们也会更新。您可以随时创建新的导出目标,以便为您的项目添加对更多 IDE 和平台的支持。
1.3、打开现有项目
要打开现有的 Projucer 项目,您可以双击.jucer
项目文件夹中的文件,也可以单击向导中的“打开现有项目” 。(您也可以从 Projucer 的主菜单导航到“打开...” 。)
1.3.1、打开PIP文件
在学习其他 JUCE 教程时,您可能会遇到Projucer 即时项目(PIP) 文件。这些文件本质上是具有常用.h
扩展名的头文件,它们为 Projucer 提供元数据,以便自动从单个文件创建具有正确模块和导出器的项目。
可以通过从 Projucer 主菜单的打开...对话框中选择文件或简单地将其拖放到 Projucer 界面窗口来打开 PIP 文件。
2、管理你的Projucer项目
您学习了如何创建新的 JUCE 项目、将其导出到本机 IDE 并开始编码。然而,Projucer 的作用不仅限于此 — 它还是一个非常强大的跨平台工具,可用于管理项目的所有设置、添加源文件等等。在您开发 JUCE 应用程序的过程中,Projucer 将是您整个过程中的忠实伙伴。本教程概述了一些基本功能。
2.1、Projucer 项目的结构
让我们仔细看看 Projucer 项目的结构。以下是 Projucer 为您生成的 JUCE 项目的文件夹结构:
最顶层是 .jucer 文件(上面突出显示),其中包含所有项目设置。双击此文件可在 Projucer 中打开项目。除了该.jucer
文件外,还会生成三个子文件夹:
文件夹 | 内容 |
---|---|
Source |
您的 JUCE 应用程序的 C++ 源代码。 |
Builds |
Projucer 生成的导出目标。Xcode 项目文件和 Visual Studio 解决方案在上面的屏幕截图中作为示例突出显示。打开这些文件以开始编码、调试和运行您的 JUCE 应用程序。(当然,您也可以只使用 Projucer 中的“ 在...中打开”按钮。) |
JuceLibraryCode |
以下是一些通过 JUCE 模块自动生成的包含 JUCE 库代码的头文件。请注意,实际的 JUCE 库代码不在此处,而是在您之前安装的全局 JUCE 文件夹中。 |
2.2、管理项目
现在我们将了解在开发 JUCE 应用程序时经常使用的 Projucer 的最重要功能。
2.2.1、添加和编辑源文件
projucer 提供文件浏览器和 C++ 源文件的基本代码编辑器。它位于左侧的文件资源管理器选项卡下。它的外观如下:
使用 Projucer,您可以向项目添加新的源文件,删除或重命名现有文件,以及将文件组织成组。要执行此操作(以及访问其他功能),请单击左侧文件资源管理器选项卡中的“+”符号,或右键单击文件或组,然后从弹出菜单中选择要执行的操作。
注意:组与文件夹不同。如果您在 Projucer 中以组的形式创建文件,系统还会询问您将文件保存在哪个文件夹中。这样,就可以拥有与组结构不同的文件夹结构。但是,强烈建议您的组遵循文件夹的结构和名称,这是一种很好的做法。
如果您更改文件结构,然后保存项目,则您的更改将反映在所有导出的原生 IDE 项目中。通过这种方式,您可以轻松地在所有开发平台上保持项目的文件结构一致。
警告:您永远不应在本机 IDE(例如 Xcode、Visual Studio)中添加、重命名和/或删除 JUCE 项目中的源文件。下次在 Projucer(每次都会重新生成本机 IDE 项目)中保存项目时,这些更改将被覆盖。相反,请始终使用 Projucer 本身进行此类更改。
2.2.2、管理JUCE模块
JUCE 库代码被组织成不同的模块。默认情况下,将添加项目类型所需的所有模块。
大多数 JUCE 模块都需要其他 JUCE 模块才能正确编译。如果您删除了项目中其他模块所依赖的模块,那么 Projucer 会用红色突出显示现在“损坏”的模块。然后您必须删除“损坏”的模块或添加缺失的模块。
如果您单击“模块”选项卡中的设置图标,则会打开模块设置页面。它提供了所有当前使用的模块的概览,并允许您设置它们的路径。要一次更改所有模块的路径,请在其中一个模块中输入正确的路径,选择它,然后单击“设置所有模块的路径...”
或者,您可以选择使用模块的全局搜索路径,方法是单击启用/禁用模块的全局路径...要设置全局搜索路径,请导航至菜单项Projucer > MacOS 上的全局搜索路径或Windows 和 Linux 上的文件> 全局搜索路径。
如果您在浏览器中单击单个模块,则可以访问特定于模块的设置和属性。在那里,您可以检查特定模块的版本和许可证,并设置特定模块正在使用的附加依赖项(如 SDK 和外部库)的路径。通常,默认设置就可以正常工作,您很少需要进入此页面。
2.2.3、导出目标、配置和构建设置
您之前创建的不同导出器目标(Xcode、Visual Studio 等)可以在 Exporters 选项卡中找到。如果您在浏览器中单击这些目标,则可以访问此导出目标的构建设置。这是指定其他编译器和链接器标志以及其他特定于平台的构建设置的地方。
要为其他 IDE 和平台创建新的导出目标,请单击“+”符号。您可以随时执行此操作。例如,如果您最初为 Windows 和 OSX 创建了 JUCE 应用程序,但后来您决定也添加对 Linux 的支持,则可以轻松完成此操作。
您还可以通过右键单击并选择“删除此导出器”来删除导出目标。
Projucer 为每个导出目标创建构建配置,您的原生 IDE 将使用这些配置来实际编译和运行您的应用。默认情况下,每个导出目标都会添加两个配置Debug和Release。通过单击这些配置,您可以访问此特定配置的特定于平台的构建设置:
您还可以添加其他配置。例如,对于 Visual Studio 导出目标,Projucer 使用 64 位添加Debug和Release配置。但是,您可能还想为 Windows 应用添加 32 位支持。为此,您可以复制两个现有配置(右键单击配置并选择创建此配置的副本),分别将副本重命名为Debug32和Release32,然后将两个配置的配置构建设置Architecture从 64 位更改为 32 位。
3、创建基本音频/MIDI插件
本教程将帮助您设置计算机并创建一个 Projucer 项目,以便使用 JUCE 开发音频插件(VST3 和 AudioUnit)。最后,我们将得到一个显示“Hello, World!”的音频插件,并且可以加载到 Cubase 或 REAPER 等 VST3 主机中。
级别:中级
平台: Windows、macOS、Linux
插件格式: VST3、AU、独立
3.1、下载并安装插件依赖项
3.1.1、VST3 和 AudioUnit
创建 VST3 和 AU(仅限 MacOS)插件所需的所有文件都与 JUCE 一起打包(只要您使用的是最新版本的 JUCE)。
3.2、使用 Projucer 创建音频插件项目
要使用 JUCE 创建音频插件,请在 Projucer 中创建一个新项目,并选择音频插件作为项目类型。
在 Projucer 的新项目配置设置中,您可以更改项目设置,例如要导出的插件类型以及插件是否接收或生成 MIDI 音符(以及许多其他内容)。您可以随时更改这些设置。
在本教程中,我们将创建一个 VST3 插件,因此请确保在“插件格式”字段中勾选VST3设置。然后在下面的“插件特性”字段中勾选插件 MIDI 输入和插件 MIDI 输出。
这就是您需要的所有配置!现在单击“保存项目”并在 IDE 中打开...您的新项目将打开。单击“构建”按钮以验证您的插件是否已构建以及是否已正确设置所有内容。
3.3、设置插件调试(可选)
构建插件的挑战之一是测试它们。幸运的是,JUCE 让测试变得简单,因为它有一个内置的插件主机。要访问主机,请转到 Projucer 所在目录下的的extras/AudioPluginHost
目录,并使用 Projucer 打开 .jucer 文件。点击“Save Project amd Open in IDE...”,然后在你的 IDE 中构建项目以创建二进制文件(在 Mac OS X 上,您可以在 extras/AudioPluginHost/Builds/MacOSX/build
找到)。
运行该应用程序,您将看到如下所示的图形节点编辑器:
按“Cmd-P”(或转到选项 > 编辑可用插件列表...)将允许您更新系统上的插件列表(每个项目只需执行一次此操作)。单击弹出窗口底部的选项按钮,然后单击扫描新的或更新的 VST3 插件...。在 macOS 上,JUCE Audio 插件会自动复制到~/Library/Audio/Plug-Ins/VST3
,主机应用程序会自动搜索该文件夹,因此您无需手动指定查找位置 - 只需单击扫描即可。在 Windows 上,您需要手动将您构建的 VST3 从项目的构建文件夹复制到 VST3 安装文件夹,该文件夹通常为C:\Program Files\Common Files\VST3
。
扫描完成后,返回节点编辑器并单击右键,然后从上下文菜单中选择您的插件(默认情况下,它将位于名为“yourcompany”的公司下 - 您可以在 Projucer 中编辑它)。连接节点,以便 MIDI 输入和音频输入节点路由到插件的输入,并且插件的音频输出路由到音频输出节点。
双击插件启动 GUI。默认插件不执行任何操作,只是显示Hello world。
您可以选择“选项”>“更改音频设备设置...”以确保您的输入和输出都到达正确的位置(如果没有出现绿色的端点,在这里设置)。点击“文件”>“保存”可轻松检索此配置。
以这种方式使用插件主机可以为您提供一个非常简单的插件测试环境,但我们还可以做更多。我们可以配置主机以启用插件的逐步调试。要在 macOS 上执行此操作,请返回 Xcode 中的插件项目,单击产品 > 方案 > 编辑方案...,然后在运行下从可执行文件下拉菜单中选择其他...并找到插件主机.app。确保勾选了调试可执行文件。在 Windows 上的 Visual Studio 中,您应该转到 VST3 构建目标的属性页面,选择“调试”窗格,然后在“命令”字段中设置 AudioPluginHost 可执行文件的路径。
现在,当您构建并运行插件时,它将自动启动主机,并且当您的插件加载到主机内时,您可以设置断点并进行逐步调试。
以Visual Studio为例(笔者下面选择的构建目标有误,选的是StandalonePlugin,应该选VST3那个):
注意:要构建 AAX 插件(用于 Pro Tools),您需要联系 Avid 获得开发者许可才能访问其 SDK。如果您确实获得了 AAX SDK 的访问权限,您会注意到 Projucer 有一个路径,您可以在其“全局首选项”窗口中设置该路径。
3.4、编写插件代码
级别:中级
平台: Windows、macOS、Linux
插件格式: VST、VST3、AU、独立
类: AudioProcessorEditor、AudioProcessor、Slider、MidiMessage、MidiBuffer
3.4.1、入门
启动 Projucer 并创建一个名为TutorialPlugin的新音频插件项目。
3.4.2、方向
新创建的音频插件项目包含两个主要类:PluginProcessor
处理音频和 MIDI IO 和处理逻辑,以及PluginEditor
处理任何屏幕上的 GUI 控件或可视化。
在两者之间传递信息时,最好将处理器视为编辑器的父级。只有一个插件处理器,而您可以创建多个编辑器。每个编辑器都引用处理器,以便它可以编辑或访问音频线程中的信息和参数。编辑器的工作是设置和获取此处理器线程上的信息,而不是相反。
我们将在文件中编辑的主要函数PluginProcessor.cpp
是processBlock()
方法。该方法接收并生成音频和 MIDI 数据以输出到插件输出。我们将在PluginEditor.cpp
文件中更改的主要函数是构造函数,我们在其中初始化和设置窗口和 GUI 对象,以及paint()
我们可以绘制额外控件和自定义 GUI 组件的方法。
编辑器构造函数目前有一个方法调用——setSize (400, 300)
它设置了插件窗口的大小。让我们(200, 200)
为这个简单的应用程序制作一个较小的窗口。
//==============================================================================
TutorialPluginAudioProcessorEditor::TutorialPluginAudioProcessorEditor (TutorialPluginAudioProcessor& p)
: AudioProcessorEditor (&p), audioProcessor (p)
{
// Make sure that before the constructor has finished, you've set the
// editor's size to whatever you need it to be.
setSize (200, 200);
}
3.4.2.1、创建一个简单的GUI控件
我们将创建一个滑块对象来改变传入的 MIDI 消息的音量。
在 Editor 头文件中创建一个名为midiVolume
的新Slider对象:
class TutorialPluginAudioProcessorEditor : public juce::AudioProcessorEditor
{
public:
TutorialPluginAudioProcessorEditor (TutorialPluginAudioProcessor&);
~TutorialPluginAudioProcessorEditor() override;
//==============================================================================
void paint (juce::Graphics&) override;
void resized() override;
private:
// This reference is provided as a quick way for your editor to
// access the processor object that created it.
TutorialPluginAudioProcessor& audioProcessor;
// 创建一个滑块
juce::Slider midiVolume;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TutorialPluginAudioProcessorEditor)
};
注意:AudioProcessorEditor在音频插件中扮演的角色与主内容组件在独立应用中的角色相同。请参阅教程:主组件。
我们可以在编辑器构造函数中使用各种函数设置此滑块的属性。我们还必须调用addAndMakeVisible (&midiVolume)
将滑块附加到编辑器。在您自己的项目中,有许多不同的滑块样式和参数可供使用和试验。在本教程中,调整滑块参数,使您的编辑器构造函数如下所示:
TutorialPluginAudioProcessorEditor::TutorialPluginAudioProcessorEditor (TutorialPluginAudioProcessor& p)
: AudioProcessorEditor (&p), audioProcessor (p)
{
// Make sure that before the constructor has finished, you've set the
// editor's size to whatever you need it to be.
setSize (200, 200);
// 这些定义了滑块对象的参数
midiVolume.setSliderStyle(juce::Slider::LinearBarVertical);
midiVolume.setRange(0.0, 127.0, 1.0);
midiVolume.setTextBoxStyle(juce::Slider::NoTextBox, false, 90, 0);
midiVolume.setPopupDisplayEnabled(true, false, this);
midiVolume.setTextValueSuffix(" Volume");
midiVolume.setValue(1.0);
// 将滑块添加到编辑器
addAndMakeVisible(&midiVolume);
}
JUCE 窗口有一个名为resized()
的方法,该方法在窗口初始化时调用一次,并且每次用户调整窗口大小时(如果启用了调整大小功能)都会调用一次。这是一个设置滑块(和其他 GUI 组件)大小和位置的好地方,这样它们就可以相对于窗口边界进行定位。
void TutorialPluginAudioProcessorEditor::resized()
{
// This is generally where you'll want to lay out the positions of any
// subcomponents in your editor..
// 使用参数(x, y, width, height) 设置滑块的位置和大小
midiVolume.setBounds(40, 30, 20, getHeight() - 60);
}
我们还可以将paint()
函数中的"Hello World"
文本更改为"Midi Volume"
并将其移至顶部。此函数是将所有自定义形状和 GUI 元素绘制到窗口的地方。
void TutorialPluginAudioProcessorEditor::paint (juce::Graphics& g)
{
// (Our component is opaque, so we must completely fill the background with a solid colour)
g.fillAll (getLookAndFeel().findColour (juce::ResizableWindow::backgroundColourId));
g.setColour (juce::Colours::white);
g.setFont (juce::FontOptions (15.0f));
g.drawFittedText ("Midi Volume", getLocalBounds(), juce::Justification::centred, 1);
}
注意:您可以在教程:图形类和教程:父组件和子组件中了解有关组件及其paint()
、resized()
方法的更多信息。运行该程序应该会创建一个在主机编辑器中如下所示的插件:
3.4.2.2、将控制信息传递给处理器类
我们现在有一个可以调整的控件,但它实际上并不控制任何东西。我们需要拦截传入的 MIDI 数据,并用滑块的音量替换音量上的音符,这是在处理器中完成的。为了获取滑块值来控制处理器线程上的 MIDI 效果,我们需要在处理器线程上创建一个新变量,我们可以使用滑块来更改该变量。
在处理器类头中创建一个名为 的新public浮点变量noteOnVel
。这是我们将使用滑块设置的变量。
public:
float noteOnVel;
每当滑块发生变化时,我们都需要设置此值。为此,我们使用滑块侦听器回调函数。任何类都可以继承滑块侦听器功能,但出于本教程的目的,我们将此功能添加到编辑器类。
添加继承和默认回调函数,使得编辑器类如下所示:
class TutorialPluginAudioProcessorEditor : public juce::AudioProcessorEditor, private juce::Slider::Listener
{
public:
TutorialPluginAudioProcessorEditor (TutorialPluginAudioProcessor&);
~TutorialPluginAudioProcessorEditor() override;
private:
void sliderValueChanged(juce::Slider* slider) override;
//==============================================================================
// 这只是一种标准的Juce绘画方法
void paint (juce::Graphics&) override;
void resized() override;
private:
// This reference is provided as a quick way for your editor to
// access the processor object that created it.
TutorialPluginAudioProcessor& audioProcessor;
// 创建一个滑块
juce::Slider midiVolume;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TutorialPluginAudioProcessorEditor)
};
现在我们在编辑器构造函数中将滑块监听器添加到音量滑块中:
TutorialPluginAudioProcessorEditor::TutorialPluginAudioProcessorEditor (TutorialPluginAudioProcessor& p)
: AudioProcessorEditor (&p), audioProcessor (p)
{
...
// 将监听器添加到滑块
midiVolume.addListener(this);
}
...并插入设置公共处理器音量变量的监听器函数:
void TutorialPluginAudioProcessorEditor::sliderValueChanged(juce::Slider* slider) {
audioProcessor.noteOnVel = midiVolume.getValue();
}
现在,我们在处理器类中有一个滑块可以控制变量。现在我们需要使用这个处理器变量来更改 MIDI 数据。
3.4.2.3、修改 MIDI 音符
处理器类中的方法processBlock()
实时接收并生成 MIDI 和音频缓冲区。我们将遍历 midi 缓冲区以拦截noteOn
类型的信号并将其速度设置为滑块的值。
MIDI 消息全部通过此函数传递。为了在 MIDI 传递时对其进行更改,我们创建了一个名为的新MidiBuffer对象processedMidi
,并将修改后的 MIDI 信号附加到此新缓冲区,然后在最后将其与原始缓冲区交换(这避免了直接修改问题)。删除processBlock()
方法中的当前代码(这处理音频缓冲区,本教程不需要它)并将其替换为以下代码。
void TutorialPluginAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
buffer.clear();
juce::MidiBuffer handledMidiBuffer;
// 检查每个MIDI消息
for (const auto metadata : midiMessages) {
juce::MidiMessage message = metadata.getMessage();
// 时间戳
const auto time = metadata.samplePosition;
// 如果这个消息使一个音符开启消息(Note On),则设置其Velocity为noteOnVel值
if (message.isNoteOn()) {
// noteOn()函数为创建一个指定参数的MidiMessage
message = juce::MidiMessage::noteOn(message.getChannel(), message.getNoteNumber(), (juce::uint8)noteOnVel);
}
// 将修改后的消息添加到handledMidiBuffer中
handledMidiBuffer.addEvent(message, time);
}
// 与原buffer进行替换
midiMessages.swapWith(handledMidiBuffer);
}
在主机环境中运行插件,您将看到通过我们的插件发出的所有 MIDI 音符信号都具有使用滑块设置的值。if()
上述语句还可用于修改和应用各种转换和效果到其他类型的传入 MIDI 信号。使用这些方法,您可以构建更复杂的效果和 GUI。
4、为您的应用程序选择正确的Projucer模板
为您的应用程序选择正确的模板一开始可能是一项棘手的任务,而从一开始就从正确的类继承可以极大地提高生产力。在本教程中,我们将探讨 Projucer 提供的不同模板项目以及在构思应用程序时需要注意的主要类。
级别:初学者
平台: Windows、macOS、Linux、iOS、Android
类: JUCEApplication、组件、AudioAppComponent、AnimatedAppComponent、OpenGLAppComponent、AudioProcessor、AudioProcessorEditor
根据您正在开发的项目,您可能需要从 Projucer 向导中选择不同的模板项目。下图提供了一个直观的问卷,可帮助您为项目选择最佳模板:
4.1、GUI 项目
所有 GUI 项目模板都会为您提供源文件,帮助您开始开发。由于应用程序将显示图形用户界面,因此模板会为您提供一个 Main.cpp 文件,其中将创建一个从JUCEApplication派生的类。
JUCEApplication类是一个抽象基类,它为您的应用程序提供启动和关闭功能。Main.cpp 文件还会创建 GUI 将驻留在其中的应用程序窗口。
4.1.1、GUI 应用程序
GUI 应用程序项目是所有 GUI 项目中最通用的,除了 Main.cpp 文件之外,它还创建了一个从Component类派生的 MainComponent 类。
Main.cpp:
/*
==============================================================================
This file contains the basic startup code for a JUCE application.
==============================================================================
*/
#include <JuceHeader.h>
#include "MainComponent.h"
//==============================================================================
class TestGuiProjectApplication : public juce::JUCEApplication
{
public:
//==============================================================================
TestGuiProjectApplication() {}
const juce::String getApplicationName() override { return ProjectInfo::projectName; }
const juce::String getApplicationVersion() override { return ProjectInfo::versionString; }
bool moreThanOneInstanceAllowed() override { return true; }
//==============================================================================
void initialise (const juce::String& commandLine) override
{
// This method is where you should put your application's initialisation code..
mainWindow.reset (new MainWindow (getApplicationName()));
}
void shutdown() override
{
// Add your application's shutdown code here..
mainWindow = nullptr; // (deletes our window)
}
//==============================================================================
void systemRequestedQuit() override
{
// This is called when the app is being asked to quit: you can ignore this
// request and let the app carry on running, or call quit() to allow the app to close.
quit();
}
void anotherInstanceStarted (const juce::String& commandLine) override
{
// When another instance of the app is launched while this one is running,
// this method is invoked, and the commandLine parameter tells you what
// the other instance's command-line arguments were.
}
//==============================================================================
/*
This class implements the desktop window that contains an instance of
our MainComponent class.
*/
class MainWindow : public juce::DocumentWindow
{
public:
MainWindow (juce::String name)
: DocumentWindow (name,
juce::Desktop::getInstance().getDefaultLookAndFeel()
.findColour (juce::ResizableWindow::backgroundColourId),
DocumentWindow::allButtons)
{
setUsingNativeTitleBar (true);
setContentOwned (new MainComponent(), true);
#if JUCE_IOS || JUCE_ANDROID
setFullScreen (true);
#else
setResizable (true, true);
centreWithSize (getWidth(), getHeight());
#endif
setVisible (true);
}
void closeButtonPressed() override
{
// This is called when the user tries to close this window. Here, we'll just
// ask the app to quit when this happens, but you can change this to do
// whatever you need.
JUCEApplication::getInstance()->systemRequestedQuit();
}
/* Note: Be careful if you override any DocumentWindow methods - the base
class uses a lot of them, so by overriding you might break its functionality.
It's best to do all your work in your content component instead, but if
you really have to override any DocumentWindow methods, make sure your
subclass also calls the superclass's method.
*/
private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainWindow)
};
private:
std::unique_ptr<MainWindow> mainWindow;
};
//==============================================================================
// This macro generates the main() routine that launches the app.
START_JUCE_APPLICATION (TestGuiProjectApplication)
Component类是 JUCE 中所有用户界面对象的基类。所有 GUI 元素都应定义并放置在 MainComponent 类中。
创建 GUI 应用程序项目后,您将在源文件夹中找到以下文件:
- Main.cpp:源自JUCEApplication类,它为您的应用程序和窗口提供初始化代码。
- MainComponent.h:从Component类派生的 MainComponent 的头文件。
- MainComponent.cpp:从Component类派生的 MainComponent 的实现文件。
当您知道您的应用程序中需要 GUI 但不确定或需要应用程序功能的灵活性时,请使用此项目类型。
4.1.2、音频应用程序
音频应用程序与 GUI 应用程序类似,但它不是从Component类派生的 MainComponent,而是从AudioAppComponent类派生的。
AudioAppComponent类是一个抽象基类,它将Component的功能与AudioSource的功能结合起来,提供了一个处理音频输入/输出的便捷起点。
创建音频应用程序项目后,您将在源文件夹中找到以下文件:
- Main.cpp:源自JUCEApplication类,它为您的应用程序和窗口提供初始化代码。
- MainComponent.cpp:从AudioAppComponent类派生的 MainComponent 的头文件和实现文件。
当您希望应用程序中具有 GUI 的音频输入/输出功能时,请使用此项目类型。
4.1.3、动画应用程序
动画应用程序与 GUI 应用程序类似,但它不是从Component类派生的 MainComponent,而是从AnimatedAppComponent类派生的。
AnimatedAppComponent类是一个抽象基类,它将组件与计时器的功能结合起来,提供了一个显示动画的便捷起点。
创建动画应用程序项目后,您将在源文件夹中找到以下文件:
- Main.cpp:源自JUCEApplication类,它为您的应用程序和窗口提供初始化代码。
- MainComponent.cpp:从AnimatedAppComponent类派生的 MainComponent 的头文件和实现文件。
当您想在应用程序的 GUI 中创建简单的动画时,请使用此项目类型。
4.1.4、OpenGL 应用程序
OpenGL 应用程序与 GUI 应用程序类似,但它的 MainComponent 不是从Component类派生的,而是从OpenGLAppComponent类派生的。
OpenGLAppComponent类是一个抽象基类,它将Component和OpenGLRenderer的功能结合起来,为渲染复杂的图形提供了一个方便的起点。
创建 OpenGL 应用程序项目后,您将在源文件夹中找到以下文件:
- Main.cpp:源自JUCEApplication类,它为您的应用程序和窗口提供初始化代码。
- MainComponent.cpp:从OpenGLAppComponent类派生的 MainComponent 的头文件和实现文件。
当您想在应用程序的 GUI 中使用 OpenGL 渲染复杂的图形元素时,请使用此项目类型。
4.2、命令行项目
4.2.1、控制台应用程序
创建控制台应用程序项目后,您将在源文件夹中找到以下文件:
- Main.cpp:为您的应用程序提供 C 样式的 main() 函数,以便使用相应的命令行参数运行。
当在命令行中执行二进制文件时,将调用以下函数:
int main(int argc, char * argv[]) {
// 你的代码
...
return 0;
}
该项目类型不会在 Main.cpp 文件中创建任何类,也不会继承任何基类,但会创建一个 .jucer 文件和一个 JUCE 库代码文件夹以及您在创建项目时可能选择的任何导出器。
当您的应用程序不需要 GUI 并且想要在命令行控制台中运行该应用程序时,请使用此项目类型。
4.3、插件项目
与 Projucer 提供的其他模板项目相比,音频插件项目具有完全不同的项目结构,并创建了一个AudioProcessor和一个AudioProcessorEditor。
AudioProcessor类是一个抽象基类,用于处理音频插件的音频处理。它表示已加载插件的实例,并由不同的插件格式(如 VST、AU、RTAS 和 AAX)包装。
AudioProcessorEditor类是从Component类派生的基类,并拥有音频插件的 GUI 功能。
创建音频插件项目后,您将在源文件夹中找到以下文件:
- PluginProcessor.h:从AudioProcessor类派生的 PluginProcessor 的头文件。
- PluginProcessor.cpp:从AudioProcessor类派生的PluginProcessor的实现文件。
- PluginEditor.h:从AudioProcessorEditor类派生的 PluginEditor 的头文件。
- PluginEditor.cpp:从AudioProcessorEditor类派生的PluginEditor的实现文件。
当您想要创建一个可以托管在 DAW 中或作为具有 GUI 的独立应用程序的插件时,请使用此项目类型。
4.4、Library 项目
4.4.1、静态/动态库
如果您有兴趣创建一个库以用于其他项目,Projucer 提供了创建静态和动态库的选项。
该项目类型不会创建任何源文件,但会创建一个.jucer 文件和一个 JUCE 库代码文件夹以及您在创建项目时可能选择的任何导出器。
然后您可以随意添加文件,并随时方便地访问 JUCE 模块。