最近,我对音乐制作和音频设备的创造产生了浓厚的兴趣。学生时代在Nordic工作时,我了解到了通过蓝牙传输音频的知识,这让我很感兴趣。尤其是令人兴奋的蓝牙 LE 音频,据说它能以更低的比特率和更少的延迟获得更好的音频质量。在演奏乐器时,你希望自己的动作和声音响应之间的延迟很小。我想测试一下是否可以利用 nRF5340 通过一个简单的键盘接口控制产生悦耳的声音,并看看延迟是否足以不影响我的演奏。
该应用程序由发声装置、合成器和接收耳机组成。LE Audio 可以同步发送与耳机左右部分相对应的两个音频流。
该应用程序基于 Nordic nrf5340_audio 演示应用程序,但针对合成器用例进行了精简和专门化。应用程序的主要关注点是合成器和键盘输入部分。
系统设计
该合成器的结构高度模块化,可以轻松加入或排除不同的模块,并测试不同的音频合成拓扑结构。所提供的设置演示了合成器的不同方面,如复调振荡器、效果和音频同步时间相关性。
合成器模块从按钮模块接收关于播放和停止播放哪个音符的信息。这些音符可以转换成音序器,或者在本例中转换成琶音器。琶音器与时间相关,因此需要一个时间源。我们必须使用与处理后音频的时间感同步的时间源。这就是 tick_provider 的功能,它为处理的每个音频块增加时间。tick 提供者向订阅模块发送 tick。这与 MIDI 同步不同音频源的方法相同,因此可以实现 MIDI 同步。
对于复调合成,我们需要多个振荡器,其数量与一次可以演奏的音符数量相等。 key_assign 会跟踪当前激活的振荡器,并以先激活(激活时间最长的振荡器)的方式将音符分配给振荡器。如果没有不活动的振荡器,它将把新音符分配给第一个活动的(活动时间最长的振荡器)振荡器。默认情况下,应用程序配置有五个振荡器。即使播放的琶音器超过 5 个音符,也很难注意到最后一个处于活动状态的音符被切断。
在 audio_process_start 中,应用程序被配置为单声道音频编码。所有模块也都以单声道构建。修改应用程序以处理立体声音频并不难。例如,可以将回声效果转换为立体声乒乓延时效果。在使用回声效果之前,先将单声道声音分成左右两个声道。然后将这些通道输入回声效果。确保在 sw_codec_encode 中正确设置 pcm_size,以便进行立体声编码。
信号处理
音频以 N 个采样块为单位进行处理,在 audio_process 中启动。定时器确保新块的处理间隔与音频采样率相匹配。这或许应直接与蓝牙连接间隔同步,以便进一步开发。
使用 16 位位深度。DSP 主要使用定点格式的整数。因此,在 interger_math 中定义了fixed16类型和相关操作。由于该应用程序专门针对 nRF5340,因此在某些情况下使用了 SoC 中包含的 DSP 指令,并通过 dsp_instruction 进行了抽象。
下面的代码块(来自 oscillator.c)是一个产生频率由 phase_increment 决定的正弦波的示例。phase_accumulate[24:31] 的高 8 位用于选择要使用的存储样本,而 phase_increment[8:23] 则用于确定这两个样本之间的插值。然后是信号的应用幅度。
for (uint32_t i = 0; i < block_size; i++) {
uint32_t wave_index = osc->phase_accumulate >> 24;
uint32_t interpolate_pos = (osc->phase_accumulate >> 8) & UINT16_MAX;
block[i] = FIXED_INTERPOLATE_AND_SCALE(sinus_samples[wave_index], sinus_samples[wave_index + 1], interpolate_pos, osc->magnitude);
osc->phase_accumulate += osc->phase_increment;
}
在 integer_math 中提供了 FIXED_INTERPOLATE_AND_SCALE,以便使用 CPU 上的 DSP 指令高效地执行这一计算。
在当前的应用配置下,当所有振荡器都处于激活状态时,nRF5340 应用内核的使用率约为 80%。当连接两个耳机设备时,约有 40% 的应用内核被使用。其中很大一部分可能是 LC3 编码器。
延迟
低功耗蓝牙的最小连接间隔为 7.5 毫秒。音频处理每 7.5 毫秒启动一次,以匹配连接间隔。因此,处理过程不会增加延迟。LE 音频中的新 LC3 编解码器取代了 SBC 编解码器,应该会大大减少延迟。但在此特定应用中尚未进行测试。输入按钮的消抖时间为 50 毫秒。不过,这并不会造成延迟。这是因为在实现过程中,每当有新的中断触发时,按钮状态就会发生变化。消抖时间结束后,通过读取引脚值来测试这一假设。这将导致偶尔出现错误的按钮状态,但在消抖时间后会再次纠正。这并没有导致测试中出现任何听觉假象。
结果
由此产生的应用程序演示了使用 BLE LE 音频传输合成器音频的功能系统。有关如何测试应用程序的说明,请查看 Github repo。下面是使用的设置图片: 2 个nRF5340 Audio DK 作为耳机,1 个 nRF5340 DK 作为合成器:
虽然没有进行定量分析以确定总延迟,但我认为在弹奏键盘并聆听所产生的声音时,延迟并不明显。我相信 nRF5340 上的 LE Audio 能带来许多令人兴奋的新应用。
如需完整指南,请查看项目 README 文件。