Rust 용 오디오 샘플 속도 변환 라이브러리.
이 라이브러리는 청크에서 오디오를 처리하기위한 리샘플러를 제공합니다.
입력과 출력 샘플 속도 사이의 비율은 완전히 자유 롭습니다. 가변 길이 출력을 반환하는 동안 고정 길이 입력을 허용하는 구현을 사용할 수 있으며 그 반대도 마찬가지입니다.
Rubato는 처리를 시작하기 전에 [resampler]를 Preallocated 및 input_buffer_allogey 및 output_buffer_allocate 방법을 사용하여 처리하는 동안 할당하지 않고 실시간 응용 프로그램에 사용할 수 있습니다. 실시간 사용을 위해 로그 기능을 비활성화해야합니다 (기본적으로 비활성화).
입력 및 출력 데이터는 무관심한 형식으로 저장됩니다.
입력 및 출력 데이터는 참조 조각 &[AsRef<[f64]>]
저장됩니다 &[AsRef<[f32]>]
내부 참조 ( 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
이어야합니다. 그렇지 않은 경우, 입력과 같이 None
Resampler::process_partial()
또는 Resampler::process_partial_into_buffer()
를 호출하고 임시 출력 버퍼에 출력을 추가하십시오. 필요한 경우 길이가 충분할 때까지 반복하십시오.
마지막으로 임시 출력 버퍼에서 원하는 대상으로 데이터를 복사하십시오. 첫 번째 delay
프레임을 건너 뛰고 new_length
프레임을 복사하십시오.
동일한 샘플 속도에서 및 동일한 샘플 속도로 다시 샘플링 할 클립이 둘 이상인 경우 동일한 리샘플러를 재사용해야합니다. 새 리샘플러를 만드는 것은 비싼 작업이며 가능한 경우 피해야합니다. 처음부터 프로 시저를 시작하지만 새 리샘플러를 만드는 대신 기존의 Resampler::reset()
호출하여 새 작업을 준비하십시오.
스트림을 재조정 할 때 프로세스는 일반적으로 실시간으로 수행되며 출력의 입력은 주어진 속도로 프레임을 제공하거나 소비하는 일부 API입니다.
MacOS의 Coreaudio 또는 Cross Platform CPAL Crate와 같은 오디오 API는 종종 데이터 교환에 콜백 기능을 사용합니다.
완전한
이들로부터 오디오를 캡처 할 때 응용 프로그램은 기능을 오디오 API로 전달합니다. 그런 다음 API는 새로운 오디오 프레임이 포함 된 데이터 버퍼에 대한 포인터와 함께이 기능을 주기적으로 호출합니다. 데이터 버퍼 크기는 일반적으로 모든 호출에서 동일하지만 API에 따라 다릅니다. 이 기능은 API의 내부 루프를 차단하고 일부 오디오 데이터가 손실되기 때문에 함수가 차단되지 않는 것이 중요합니다. 콜백 함수를 밝게 유지하는 것이 좋습니다. 이상적으로는 API가 제공 한 버퍼에서 제공된 오디오 데이터를 읽고 샘플 형식 변환과 같은 일부 가벼운 처리를 수행해야합니다. 리샘플링과 같은 무거운 처리는 여기에서 수행되어서는 안됩니다. 그런 다음 오디오 데이터를 공유 버퍼에 저장해야합니다. 버퍼는 Arc<Mutex<VecDeque<T>>>
이거나 Ringbuf와 같이 더 발전된 것일 수 있습니다.
메인 또는 별도의 스레드에서 실행되는 별도의 루프는 해당 버퍼에서 읽고 재판매 및 파일에 저장해야합니다. 오디오 API가 고정 버퍼 크기를 제공하는 경우이 프레임 수는 리샘플러 청크 크기에 적합한 선택입니다. 크기가 다르면 공유 버퍼를 사용하여 오디오 API 및 리샘플러의 청크 크기를 조정할 수 있습니다. 리샘플러 청크 크기의 좋은 출발점은 오디오 API의 평균 청크 크기 근처에서 "쉬운"값을 사용하는 것입니다. 루프가 예를 들어 디스크 액세스를 위해 대기 대기가 막히면 공유 버퍼가 가득 차지 않을 정도로 충분히 크지 않도록하십시오.
루프는 클립을 리샘플링하는 것과 유사한 프로세스를 따라야하지만 입력은 이제 공유 버퍼입니다. 루프는 리샘플러에 읽고 전달하기 전에 필요한 수의 프레임이 버퍼에서 사용할 수있을 때까지 기다려야합니다.
임시 출력 버퍼를 생략하고 출력을 대상에 직접 작성하는 것이 적절합니다. Hound Crate는 압축되지 않은 오디오 형식을 읽고 쓰는 데 인기있는 선택입니다.
비동기 리 샘플러는 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
디렉토리에는 리샘플러 테스트를위한 몇 가지 샘플 응용 프로그램이 포함되어 있습니다. 간단한 테스트 신호를 생성하고 리 샘플링 된 결과를 분석하기위한 파이썬 스크립트도 있습니다.
예제는 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()
0으로 제로로 전제 버퍼를 선택하십시오.라이센스 : MIT