RUST的音频样本率转换库。
该库提供了重新采样器来处理块中的音频。
输入和输出样本速率之间的比率是完全免费的。实现可用,可以在返回可变长度输出时接受固定的长度输入,反之亦然。
Rubato可在实时应用程序中使用,而无需在处理过程中进行处理,而无需进行任何分配,并在开始处理之前使用其Input_Buffer_Allocate和output_buffer_allocate和output_buffer_allocate方法。日志功能应禁用实时使用(默认情况下是禁用的)。
输入和输出数据以非相互交流的格式存储。
输入和输出数据存储为参考的切片, &[AsRef<[f32]>]
或&[AsRef<[f64]>]
。内部引用( AsRef<[f32]>
或AsRef<[f64]>
)每个通道的样品值。
由于普通向量实现了AsRef
性状,因此Vec<Vec<f32>>
和Vec<Vec<f64>>
可用于输入和输出。
异步重采样器可提供有或没有抗稳定过滤器的情况。
用抗氧化剂重新采样是基于使用SINC插值过滤器的带限制插值。 SINC插值通过可调节因子进行了调整,然后通过在这些点之间插值来计算新的样品点。可以随时更新重新采样率。
反采样而无需抗异化会省略CPU重型的SINC插值。这速度更快,但产生质量较低的结果。
同步重采样是通过FFT实现的。数据是FFT:ED,修改了频谱,然后逆FFT:ED获取重新采样的数据。这种类型的重采样器要快得多,但不支持更改重采样比。
该库提供的重采样器旨在在块中处理音频。最佳块尺寸由应用程序确定,但最终可能会在几百到几千帧之间。这使效率和内存使用情况之间有很好的损害。
Rubato使用Resampler::process_into_buffer()
方法时适用于实时应用程序。这将输出存储在预先分配的输出缓冲区中,并且不执行可能阻止线程的分配或其他操作。
建议将已知长度的音频夹重新采样到新的采样率的简单过程如下。在这里,假定源数据存储在VEC中,或者一次支持一次读取任意数量的帧数的其他结构。为简单起见,输出在重采样过程中存储在临时缓冲区中,然后复制到目的地。
准备:
Resampler::output_delay()
以了解重新采样器给出多少帧的延迟帧。将数字存储为delay
。new_length = original_length * new_rate / original_rate
。现在是时候通过重复进行通话来处理大部分剪辑的时间了。环形:
Resampler::input_frames_next()
了解重新采样器需求的框架。Resampler::process()
或Resampler::process_into_buffer()
。下一步是处理最后剩余的帧。
Resampler::process_partial()
或Resampler::process_partial_into_buffer()
。在这一点上,所有帧都已发送到重新采样器,但是由于通过重新采样器的延迟,它的内部缓冲区中仍然可能有一些框架。生成所有想要的帧时,临时输出缓冲区的长度至少应为new_length + delay
。如果不是这种情况,请致电Resampler::process_partial()
或Resampler::process_partial_into_buffer()
以None
作为输入,并将输出附加到临时输出缓冲区。如果需要,请重复直到足够的长度为止。
最后,将数据从临时输出缓冲区复制到所需的目的地。跳过第一个delay
帧,然后复制new_length
框架。
如果有多个以上的剪辑可以从相同的样本速率进行重新采样,则应重复使用相同的重采样器。创建新的重采样器是一项昂贵的任务,应尽可能避免。从一开始就启动该过程,但是与其创建新的重新采样器,不如在现有的一个过程中调用Resampler::reset()
以准备新工作。
在重新启动流时,该过程通常是实时执行的,并且输出的输入是某些API,以给定速率提供或消耗帧。
音频API,例如MACOS上的CoreAudio或Cross Platform Cpal Crate,通常使用回调功能进行数据交换。
完整
从这些捕获音频时,应用程序将功能传递到音频API。然后,API定期调用此功能,并用指向包含新音频帧的数据缓冲区的指针。数据缓冲区大小通常在每个呼叫上都相同,但是在API之间有所不同。重要的是该函数不会阻止,因为这会阻止API的某些内部环路并导致某些音频数据的丢失。建议保持回调功能的光线。理想情况下,它应该从API提供的缓冲区中读取所提供的音频数据,并选择执行一些光处理,例如样品格式转换。不应在此处执行诸如重采样之类的重型处理。然后,它应该将音频数据存储到共享的缓冲区中。缓冲液可以是Arc<Mutex<VecDeque<T>>>
,也可以是诸如ringbuf之类的更先进的东西。
然后,在主或单独的线程中运行的单独循环应从该缓冲区中读取,重新采样并保存到文件。如果音频API提供了固定的缓冲尺寸,则此数量的帧是重采样器块尺寸的一个不错的选择。如果大小有所不同,则可以使用共享缓冲区来调整音频API和重新采样器的块大小。重新采样器块尺寸的一个很好的起点是,使用音频API的平均块大小的“简单”值。确保共享的缓冲区足够大,以至于在循环被阻止的情况下,等待磁盘访问。
循环应遵循类似于重新采样夹的过程,但是输入现在是共享缓冲区。循环需要等待所需数量的框架在缓冲区中可用,然后再阅读并将其传递到重采样器。
省略临时输出缓冲区并将输出直接写入目的地也是适当的。猎犬板条箱是阅读和编写未压缩音频格式的流行选择。
异步重采样器在X86_64和AARCH64上支持SIMD。 CPU的SIMD功能在运行时确定。如果没有支持的SIMD指令集可用,则将返回标量实现。
在X86_64上,它将尝试使用AVX。如果没有AVX,它将尝试使用SSE3。
在AARCH64(64位臂)上,如果可用,它将使用霓虹灯。
同步重采样器受益于Rustfft库的SIMD支持。
fft_resampler
:启用基于FFT的同步重新采样器默认情况下启用了此功能。如果不需要FFT重新采样器,则将其禁用,以节省编译时间并减少所得的二进制尺寸。
log
:启用记录此功能可以通过log
板板进行记录。这旨在调试目的。请注意,输出日志分配了[STD :: String :: String],并且大多数日志记录实现都涉及其他各种系统调用。这些呼叫可能需要一些(不可预测的)时间来返回,在此期间申请被阻止。这意味着如果在实时应用程序中使用此库,则应避免记录。
运行测试时可以启用log
功能,在调试时,这可能非常有用。可以通过RUST_LOG
环境变量设置记录级别。
例子:
RUST_LOG=trace cargo test --features log
将一个虚拟音频文件的单个块从44100重新采样至48000 Hz。另请参见可用于从磁盘处理文件的“ Process_F64”示例。
use rubato :: { Resampler , SincFixedIn , SincInterpolationType , SincInterpolationParameters , WindowFunction } ;
let params = SincInterpolationParameters {
sinc_len : 256 ,
f_cutoff : 0.95 ,
interpolation : SincInterpolationType :: Linear ,
oversampling_factor : 256 ,
window : WindowFunction :: BlackmanHarris2 ,
} ;
let mut resampler = SincFixedIn :: < f64 > :: new (
48000 as f64 / 44100 as f64 ,
2.0 ,
params ,
1024 ,
2 ,
) . unwrap ( ) ;
let waves_in = vec ! [ vec! [ 0.0f64 ; 1024 ] ; 2 ] ;
let waves_out = resampler . process ( & waves_in , None ) . unwrap ( ) ;
examples
目录包含一些用于测试重采样器的示例应用程序。还有Python脚本来生成简单的测试信号以及分析重采样结果。
这些示例以64位浮点格式读写原始音频数据。如果文件首先转换为正确的格式,则可以用于处理.wav文件。使用sox
将.WAV转换为原始样本:
sox some_file.wav -e floating-point -b 64 some_file_f64.raw
处理后,可以将结果转换回新.WAV。这个示例以44.1 kHz的形式转换为16位:
sox -e floating-point -b 64 -r 44100 -c 2 resampler_output.raw -e signed-integer -b 16 some_file_resampled.wav
许多音频编辑器(例如Audacity)也能够直接导入和导出原始样本。
rubato
板条箱需要Rustc 1.61版或更新。
fft_resampler
功能使FFT重新采样器可选。log
功能修复建筑物。input/output_buffer_allocate()
带有零的填充缓冲区。许可证:麻省理工学院