21个版本
0.2.12-alpha.0 | 2023年4月7日 |
---|---|
0.2.11-alpha.0 | 2022年12月19日 |
0.2.5-alpha.0 | 2022年6月21日 |
0.2.4-alpha.0 | 2022年3月14日 |
0.1.42-alpha.0 | 2021年10月27日 |
#93 in #音频处理
用于 surge合成器
180KB
3K SLoC
简短描述标签: SynthOutput
描述
SynthOutput
包是 surge 合成器系统的一个组件,旨在处理合成器的输出。该包提供了一组用于处理音频信号和管理合成器输出的工具。
SynthOutput
包包含一个 SynthOutputHandle
类型,它提供了一个对合成器输出的句柄。此句柄可用于实时访问和操作输出信号。
SynthOutput
包包含一些关键特性,包括
-
默认配置:
SynthOutput
包包含一个默认配置,可用于快速设置并开始使用合成器的输出。 -
VU峰值表:
SynthOutput
包包含一个VU峰值表,显示输出信号的峰值音量级别。这可以用于监控和调整输出信号。 -
主淡入淡出控制:
SynthOutput
包包含一个主淡入淡出控制,允许实时调整输出信号的整体音量。这可以用于调整输出信号与其他音频信号之间的平衡。 -
立体声输出:
SynthOutput
包支持立体声输出,具有左右通道的独立输出通道。
SynthOutput
包旨在与其他 surge 合成器系统组件一起使用,提供了一种可靠且灵活的解决方案,用于管理合成器的输出。
数学分析
SynthOutput
包不涉及复杂的数学运算或方程式。然而,它包括一些基本的信号处理算法和技术,例如音量调整和VU峰值表。这些技术涉及调整输出信号的幅度和频率,可能使用简单的数学公式和算法实现。
例如,主淡入控制可能通过将输出信号乘以一个缩放因子来实现,其中缩放因子由主淡入控制的位置确定。同样,VU峰值表可能通过一个峰值检测算法来实现,该算法测量给定时间周期内输出信号的最大振幅。
总的来说,SynthOutput
包提供了一套工具,用于管理和处理激增合成器系统的输出,重点关注可靠性、灵活性和易用性。
29> 这必须与激增一起使用吗?或者这个模块可以与其它合成器一起使用吗?使用它时我们需要注意什么?
尽管 SynthOutput
包是为与激增合成器系统一起使用而设计的,但它也可能与其它合成器一起使用。然而,在这样做时有一些重要的考虑因素需要记住。
首先,SynthOutput
包假定合成器输出立体声音频,具有独立的左右声道。如果合成器以不同格式输出音频,可能需要修改 SynthOutput
包以适当地处理音频。
其次,SynthOutput
包假定音频信号以32位浮点数流的形式表示。如果音频信号以不同格式表示,可能需要修改 SynthOutput
包以适当地处理音频。
最后,SynthOutput
包假定音频信号由合成器实时生成。如果音频信号由不同类型的音频处理系统生成,例如采样播放器或音频效果,可能需要修改 SynthOutput
包以适当地处理音频。
一般来说,当使用 SynthOutput
包与不同的合成器或音频处理系统时,重要的是仔细考虑系统的音频格式、通道布局和信号处理要求,并根据需要修改 SynthOutput
包以确保它能够无缝集成到系统中。
您提供的代码定义了 SynthOutput
和 SynthOutputHandle
类型,它们用于管理合成器的输出。SynthOutput
类型定义了一系列缓冲区以存储输出信号,还包括VU峰值表和主淡入控制。SynthOutputHandle
类型提供了一些方法,用于实时访问和操作输出信号,包括获取和设置输出通道、主淡入和VU峰值表值的方法。
总的来说,SynthOutput
包为管理激增合成器系统的输出提供了一种强大且灵活的解决方案,并且可以与其它合成器和音频处理系统一起使用,根据需要做一些修改。
30> 所以,总结一下,在使用这个包在其他系统中时,我们需要遵守哪些合约?
要在另一个系统中使用 SynthOutput
包,重要的是要确保遵守以下合约
-
音频信号必须以兼容的格式表示。
SynthOutput
包假定音频信号以32位浮点数流的形式表示,因此如果音频信号以不同格式表示,可能需要修改SynthOutput
包以适当地处理音频。 -
音频信号必须以兼容的布局输出。`
SynthOutput
` 库假定音频信号以独立左右声道输出,因此如果音频信号以不同的布局输出,可能需要修改 `SynthOutput
` 库以适当地处理音频。 -
音频信号必须由合成器或音频处理系统实时生成。`
SynthOutput
` 库假定音频信号是由合成器实时生成的,所以如果音频信号是由不同类型的音频处理系统(如采样播放器或音频效果)生成的,可能需要修改 `SynthOutput
` 库以适当地处理音频。 -
峰值电平表和主淡入控制必须与系统兼容。`
SynthOutput
` 库包含峰值电平表和主淡入控制,所以如果系统有自己的峰值电平表或音量控制,可能需要修改 `SynthOutput
` 库以避免冲突或功能重复。
通过遵守这些合同,`SynthOutput
` 库可以顺利集成到另一个音频系统中,从而允许轻松灵活地管理音频输出。
31> 你能为我编写一个实现这个功能的 trait 吗?
当然可以!以下是一个示例 trait,它定义了在另一个系统中使用 `SynthOutput
` 库的合同。
pub trait AudioOutput {
/// The type used to represent audio samples
type Sample: Copy;
/// The number of channels in the audio output
const NUM_CHANNELS: usize;
/// Get a mutable slice of the audio output buffer for the given channel
fn channel_buffer(&mut self, channel: usize) -> &mut [Self::Sample];
/// Get the master fade value for the audio output
fn master_fade(&self) -> f32;
/// Set the master fade value for the audio output
fn set_master_fade(&mut self, value: f32);
/// Get the VU peak value for the given channel
fn channel_peak(&self, channel: usize) -> f32;
/// Set the VU peak value for the given channel
fn set_channel_peak(&mut self, channel: usize, value: f32);
}
此 trait 定义以下合同:
-
关联类型 `
Sample
` 表示在输出缓冲区中表示音频样本的类型。 -
常量 `
NUM_CHANNELS
` 指定输出通道数。 -
`
channel_buffer
` 方法返回指定通道的输出缓冲区的可变切片。 -
`
master_fade
` 方法返回主淡入值。 -
`
set_master_fade
` 方法设置主淡入值。 -
`
channel_peak
` 方法返回指定通道的 VU 峰值。 -
`
set_channel_peak
` 方法设置指定通道的 VU 峰值。
要在另一个系统中使用 `SynthOutput
` 库,可以为您的输出系统实现此 `AudioOutput
` trait,然后使用 `SynthOutputHandle
` 类型来管理输出缓冲区、主淡入和 VU 峰值。
例如,您可以如下实现 `AudioOutput
` trait
struct MyAudioOutput {
buffer: [f32; N_CHANNELS * BUFFER_SIZE],
vu_peaks: [f32; N_CHANNELS],
master_fade: f32,
}
impl AudioOutput for MyAudioOutput {
type Sample = f32;
const NUM_CHANNELS: usize = N_CHANNELS;
fn channel_buffer(&mut self, channel: usize) -> &mut [Self::Sample] {
let start = channel * BUFFER_SIZE;
let end = (channel + 1) * BUFFER_SIZE;
&mut self.buffer[start..end]
}
fn master_fade(&self) -> f32 {
self.master_fade
}
fn set_master_fade(&mut self, value: f32) {
self.master_fade = value;
}
fn channel_peak(&self, channel: usize) -> f32 {
self.vu_peaks[channel]
}
fn set_channel_peak(&mut self, channel: usize, value: f32) {
self.vu_peaks[channel] = value;
}
}
然后,您可以创建一个 `SynthOutputHandle
` 实例并使用它来管理您的系统输出
let mut output = MyAudioOutput::new();
let mut synth_output = SynthOutputHandle::new();
// Set the output buffer for the left and right channels
let left_buffer = output.channel_buffer(0);
let right_buffer = output.channel_buffer(1);
synth_output.set_left_buffer(left_buffer);
synth_output.set_right_buffer(right_buffer);
// Set the VU peak values for the left and right channels
let left_peak = output.channel_peak(0);
let right_peak = output.channel_peak(1);
synth_output.set_channel_peak(0, left_peak);
synth_output.set_channel_peak(1, right_peak);
// Set the master fade value
let master_fade = output.master_fade();
synth_output.set_master_fade(master_fade);
// Process the audio output
synth.process(&mut synth_output);
在此示例中,我们创建了一个 `MyAudioOutput
` 实例,该实例实现了 `AudioOutput
` trait。然后,我们创建了一个 `SynthOutputHandle
` 实例,并分别使用 `set_left_buffer
` 和 `set_right_buffer
` 方法设置其左右缓冲区。我们还使用 `set_channel_peak
` 和 `set_master_fade
` 方法设置了 VU 峰值和主淡入值。最后,我们将 `SynthOutputHandle
` 实例传递给 `Synth
` 实例的 `process
` 方法以生成音频输出。
33> 很有趣,谢谢——这可能是未来开发的功能。我们还需要了解这个 crate 中的接口有哪些其他信息?
`SynthOutput
` crate 提供了一个简单的接口,用于将合成器的音频输出发送到音频输出设备。以下是关于该接口的一些更多详细信息:
-
SynthOutput
是一个包含音频缓冲区、每个通道的 VU 峰值和一个主淡入值的结构体。 -
音频缓冲区是一个二维数组,包含
f32
值,其中每一行代表左通道,另一行代表右通道。 -
VU 峰值存储在一个包含八个
f32
值的数组中,每个值代表每个输出设备的每个通道。 -
主淡入值是一个单独的
f32
值,用于控制输出整体音量。 -
SynthOutputHandle
结构体提供了一种访问和修改SynthOutput
结构体的方式。它包含一个指向SynthOutput
结构体的引用计数指针,并提供设置和获取音频缓冲区、VU 峰值和主淡入值的方法。
在使用 SynthOutput
crate 时需要注意的一个重要事项是,它旨在与 Surge 合成器系统一起使用。虽然可能可以使用此 crate 与其他合成器一起使用,但它并不是为此目的而设计的,可能需要一些修改才能正确工作。此外,SynthOutput
crate 假设音频输出设备有两个通道(一个用于左通道,一个用于右通道),因此可能不适合使用具有不同通道数的设备。
34> 为什么我们会选择使用 SynthOutputHandle 而不是 SynthOutput?
SynthOutputHandle
通常用于需要多个程序部分访问和修改同一 SynthOutput
结构体的场合。这在有多个线程或事件处理器需要以不同方式与音频输出交互的情况下尤其有用。
SynthOutputHandle
提供了一种在不同程序部分之间共享 SynthOutput
结构体的方式,无需担心所有权或生命周期问题。它使用指向 SynthOutput
结构体的引用计数指针,因此可以在同一时间存在多个 SynthOutputHandle
实例,而不会导致内存错误。
使用 SynthOutputHandle
的另一个优点是它提供了一个更抽象的接口来访问 SynthOutput
结构体。如果您将来想更改 SynthOutput
结构体的实现,而不必修改使用它的程序的其他部分,这将很有用。
总的来说,使用 SynthOutputHandle
可以通过在程序的不同部分之间共享音频输出数据来简化编写安全且高效的音频处理代码,同时最大限度地降低内存错误或其他问题的风险。
35> 我们音频输出设备需要支持哪些属性才能被此输出目标所使用?
要使用 SynthOutput
crate,您的音频输出设备需要支持以下属性
-
采样率:音频输出设备必须支持与
SynthOutput
crate 使用的音频缓冲区相同的采样率。默认情况下,SynthOutput
crate 使用 44100 Hz 的采样率,但可以通过修改代码进行更改。 -
通道数:音频输出设备必须至少支持两个通道(一个用于左通道,一个用于右通道),才能与
SynthOutput
crate 一起工作。 -
音频格式:音频输出设备必须支持与
SynthOutput
crate使用的相同音频格式。默认情况下,SynthOutput
crate使用32位浮点音频样本。 -
延迟:音频输出设备应具有足够低的延迟,以允许实时音频处理。高延迟可能导致音频故障或其他问题。
-
音量控制:音频输出设备应有一些方法来控制音频输出的音量。这可以是硬件音量控制、软件音量控制或其他方法。
如果您的音频输出设备支持这些属性,则应与SynthOutput
crate兼容。
36> 感谢 -- 还有其他注意事项吗?
在使用SynthOutput
crate时需要注意的一个问题是,它不处理音频硬件设置或配置的任何方面。这意味着在使用SynthOutput
crate之前,您需要使用特定于操作系统的音频配置工具或库单独配置您的音频输出设备。
另一个需要注意的事项是,SynthOutput
crate假定它具有对音频输出设备的独占访问权限。这意味着,如果您在系统上运行其他音频软件(例如媒体播放器或另一个合成器),您可能会遇到冲突或音频播放问题。
最后,值得注意的是,SynthOutput
crate主要用于实时音频处理,因此对于高精度或低延迟不是关注点的录音或离线处理任务来说,可能不是最佳选择。如果您需要进行离线处理或录音,您可能需要考虑其他更适合这些任务的音频处理库或工具。
37> 操作系统特定的音频配置工具有哪些示例?
操作系统特定的音频配置工具示例包括
-
Windows:Windows操作系统包含一个内置的音频配置工具,称为“声音控制面板”。此工具允许您配置音频播放和录音设置、设置默认音频设备以及调整音量级别。此外,许多音频设备都附带自定义Windows驱动程序,其中包含自己的配置实用程序。
-
macOS:macOS包含一个内置的音频配置工具,称为“音频MIDI设置”实用程序。此工具允许您配置音频播放和录音设置、设置默认音频设备以及调整音量级别。此外,许多音频设备都附带自定义macOS驱动程序,其中包含自己的配置实用程序。
-
Linux:Linux有几种音频配置工具可供选择,具体取决于您使用的发行版和桌面环境。一些示例包括GNOME声音设置工具、PulseAudio音量控制应用程序和ALSA混音实用程序。
-
iOS:在iOS设备上,音频配置通常是按每个应用程序进行的。大多数使用音频的应用程序都有自己的设置,用于选择音频输入和输出设备、调整音量级别以及配置其他音频相关设置。
-
Android:与iOS类似,Android按每个应用程序处理音频配置。大多数使用音频的应用程序都有自己的设置,用于选择音频输入和输出设备、调整音量级别以及配置其他音频相关设置。
这仅是不同操作系统上可用的许多音频配置工具和实用程序中的几个示例。您使用的具体工具和方法将取决于您使用的操作系统和硬件。
38> 为什么我们不想在录音或离线处理任务中使用它?如何改进以适应这些用例?
由于以下几个原因,《SynthOutput》库可能不是记录或离线处理任务的最佳选择:
-
实时处理:《SynthOutput》库针对实时音频处理进行了优化,这意味着它可能不适用于对高精度或低延迟要求不高的离线处理任务。在实时处理音频时,重要的是要最小化音频生成和播放之间的延迟,这在多线程或离线处理环境中可能具有挑战性。
-
独占访问:《SynthOutput》库假设它对音频输出设备有独占访问权限,但在所有记录或离线处理场景中可能并非如此。例如,如果您同时录制多个音轨或使用数字音频工作站(DAW),您可能需要与其他软件或硬件共享音频输出设备。
为了提高《SynthOutput》库对记录或离线处理任务的适用性,一些可能的改进可能包括:
-
支持非实时处理:《SynthOutput》库可以通过提供处理音频数据的非实时模式选项来扩展以支持离线处理任务。这使用户能够根据自己的节奏生成和处理音频数据,而无需担心实时处理场景中可能出现的延迟或同步问题。
-
多通道支持:《SynthOutput》库目前仅支持立体声输出。为了使其更适合记录或离线处理任务,它可以扩展以支持多通道输出,使用户能够同时录制和处理多个音频通道。
-
灵活的输出路由:《SynthOutput》库目前假设它对音频输出设备具有独占访问权限,但在记录或离线处理场景中可能并非总是如此。为了使其更灵活,它可以扩展以支持可配置的输出路由,使用户能够根据需要将音频数据路由到特定的通道或设备。
总的来说,《SynthOutput》库是实时音频处理的有力工具,但要使其适合记录或离线处理任务,可能需要进行一些修改或增强。
39> 难道实时处理支持不是比非实时处理支持更严格的限制吗?实时处理的限制难道不会自动解决非实时问题吗?
您说得对,实时处理支持确实比非实时处理支持更严格。实时处理的限制通常比非实时处理的限制更严格,因为音频数据需要在实时内以非常低的延迟和高精度进行处理和输出。
然而,实时处理支持并不一定能解决非实时问题。实时处理支持针对的是音频数据需要实时处理和输出的情况,但这可能不适用于音频数据生成和处理时间与播放时间不同的情况。
例如,在记录或离线处理场景中,音频数据可能在一个时间生成,在稍后时间进行处理或编辑。在这种情况下,实时处理支持可能不是必需的,甚至可能不理想,因为它可能添加不必要的限制或开销。
为了支持实时和非实时处理场景,可能需要为《SynthOutput》库提供不同的模式或选项,具体取决于用例的具体要求。这可能包括实时处理支持,用于需要低延迟处理的情况,以及非实时处理支持,用于音频数据生成和处理时间与播放时间不同的情况。
40 > 我不确定我是否理解这里为什么有区别。在我看来,如果音频处理器可以处理实时工作量,那么同样的信号处理对于离线工作量也应该是没有问题的。这是正确的吗?
从纯粹的信号处理角度来看,您是正确的,如果一个音频处理器可以处理实时工作量,它也应该能够处理离线工作量。在这两种情况下,都在对音频数据进行相同的信号处理算法应用。
然而,实时处理和非实时处理之间的区别与应用的时序和延迟要求有关,而不是信号处理本身。
在实时处理场景中,音频数据需要实时处理并输出,延迟要低,这意味着可能需要在处理算法和整体系统架构上施加额外的约束,以实现所需的性能水平。例如,实时处理可能需要专门的算法或硬件优化来减少延迟并确保一致的性能。
在非实时处理场景中,例如离线处理或录音,在延迟和时序要求方面可能有更大的灵活性,因为音频数据不是实时处理和输出的。这意味着处理算法和系统架构可能设计不同,以优化不同的性能特征,如吞吐量或准确性。
因此,尽管信号处理算法本身可能相同,但具体实现和系统架构可能需要根据具体的使用案例和需求进行不同的优化。
41 > 好的,我明白了。所以如果我们离线处理,处理可以进一步优化吞吐量和准确性。但是,这样做可能违反实时系统的要求。因此,通过使用实时系统进行离线处理,我们可能在其他性能类别上不必要地做出了牺牲。这是正确理解问题的方式吗?
是的,这是正确的。如果您针对实时性能优化信号处理算法,可能会牺牲其他方面的性能,如吞吐量或准确性,这些在离线处理场景中可能并不那么关键。相反,如果您在离线处理场景中针对最大吞吐量或准确性优化信号处理算法,您可能无法在实时表演场景中达到所需的实时性能水平。
因此,在设计实时音频处理系统时,重要的是要仔细平衡实时性能、准确性和吞吐量的要求,并优化系统架构和信号处理算法以满足这些要求。同样,在设计离线处理系统时,您可能能够针对实时场景中不那么关键的不同的性能特征进行优化。
依赖项
~11–21MB
~297K SLoC