ไลบรารีการแปลงอัตราเสียงตัวอย่างสำหรับการเกิดสนิม
ไลบรารีนี้ให้ผู้ทำการสุ่มตัวอย่างเพื่อประมวลผลเสียงเป็นชิ้น
อัตราส่วนระหว่างอัตราตัวอย่างอินพุตและเอาต์พุตนั้นฟรีอย่างสมบูรณ์ มีการใช้งานที่ยอมรับอินพุตความยาวคงที่ในขณะที่ส่งคืนเอาต์พุตความยาวตัวแปรและในทางกลับกัน
Rubato สามารถใช้ในแอปพลิเคชันเรียลไทม์โดยไม่ต้องจัดสรรระหว่างการประมวลผลโดย preallocating [resampler] และใช้วิธีการ input_buffer_allocate และ output_buffer_allocate ก่อนการประมวลผล คุณสมบัติการบันทึกควรปิดใช้งานเพื่อใช้เรียลไทม์ (ถูกปิดใช้งานโดยค่าเริ่มต้น)
ข้อมูลอินพุตและเอาท์พุทจะถูกเก็บไว้ในรูปแบบที่ไม่ถูกขัดจังหวะ
ข้อมูลอินพุตและเอาต์พุตถูกเก็บไว้เป็นชิ้นส่วนของการอ้างอิง &[AsRef<[f32]>]
หรือ &[AsRef<[f64]>]
การอ้างอิงภายใน ( AsRef<[f32]>
หรือ AsRef<[f64]>
) ถือค่าตัวอย่างสำหรับหนึ่งช่องแต่ละช่อง
เนื่องจากเวกเตอร์ปกติใช้คุณสมบัติ AsRef
, Vec<Vec<f32>>
และ Vec<Vec<f64>>
สามารถใช้สำหรับทั้งอินพุตและเอาต์พุต
Resamplers แบบอะซิงโครนัสมีให้บริการทั้งที่มีและไม่มีตัวกรองต่อต้านนามแฝง
การสุ่มตัวอย่างใหม่ด้วยการต่อต้านการเป็นนามธรรมขึ้นอยู่กับการแก้ไขแบบ จำกัด วงโดยใช้ตัวกรองการแก้ไข SINC การแก้ไข SINC upsamples โดยปัจจัยที่ปรับได้จากนั้นจุดตัวอย่างใหม่จะถูกคำนวณโดยการแก้ไขระหว่างจุดเหล่านี้ อัตราส่วนการสุ่มตัวอย่างสามารถอัปเดตได้ตลอดเวลา
การสุ่มตัวอย่างใหม่โดยไม่มีการต่อต้านการเป็นนามแฝงทำให้การแก้ไข SINC ของ CPU หนัก สิ่งนี้ทำงานได้เร็วขึ้นมาก แต่ให้ผลลัพธ์ที่มีคุณภาพต่ำกว่า
การสุ่มตัวอย่างแบบซิงโครนัสถูกนำมาใช้ผ่าน FFT ข้อมูลคือ FFT: ED, สเปกตรัมแก้ไขแล้วผกผัน FFT: ED เพื่อรับข้อมูลที่ถูกสุ่มตัวอย่าง resampler ประเภทนี้เร็วกว่ามาก แต่ไม่สนับสนุนการเปลี่ยนอัตราส่วนการสุ่มตัวอย่างใหม่
Resamplers ที่จัดทำโดยไลบรารีนี้มีวัตถุประสงค์เพื่อประมวลผลเสียงเป็นชิ้น ขนาดก้อนที่ดีที่สุดจะถูกกำหนดโดยแอปพลิเคชัน แต่น่าจะจบลงด้วยบางสิ่งที่อยู่ระหว่างสองสามร้อยถึงสองสามพันเฟรม สิ่งนี้ทำให้การประนีประนอมระหว่างประสิทธิภาพและการใช้หน่วยความจำที่ดี
Rubato เหมาะสำหรับการใช้งานแบบเรียลไทม์เมื่อใช้วิธี Resampler::process_into_buffer()
สิ่งนี้เก็บเอาต์พุตในบัฟเฟอร์เอาต์พุตที่จัดสรรไว้ล่วงหน้าและไม่มีการจัดสรรหรือการดำเนินการอื่น ๆ ที่อาจบล็อกเธรด
กระบวนการง่ายๆที่แนะนำสำหรับการสุ่มตัวอย่างคลิปเสียงที่มีความยาวที่รู้จักไปยังอัตราตัวอย่างใหม่มีดังนี้ ที่นี่สันนิษฐานว่าข้อมูลต้นฉบับจะถูกเก็บไว้ใน VEC หรือโครงสร้างอื่น ๆ ที่รองรับการอ่านจำนวนเฟรมตามอำเภอใจในแต่ละครั้ง เพื่อความเรียบง่ายเอาต์พุตจะถูกเก็บไว้ในบัฟเฟอร์ชั่วคราวระหว่างการสุ่มตัวอย่างใหม่และคัดลอกไปยังปลายทางหลังจากนั้น
การเตรียมการ:
Resampler::output_delay()
เพื่อทราบว่ามีกี่เฟรมที่ล่าช้า Resampler ให้ เก็บหมายเลขเป็น delay
new_length = original_length * new_rate / original_rate
ตอนนี้ถึงเวลาที่จะประมวลผลคลิปจำนวนมากโดยการโทรซ้ำหลายครั้ง ลูป:
Resampler::input_frames_next()
เพื่อเรียนรู้ว่าต้องการเฟรมที่ต้องการ resampler กี่เฟรมResampler::process()
หรือ Resampler::process_into_buffer()
ขั้นตอนต่อไปคือการประมวลผลเฟรมที่เหลืออยู่สุดท้าย
Resampler::process_partial()
หรือ Resampler::process_partial_into_buffer()
ณ จุดนี้เฟรมทั้งหมดถูกส่งไปยัง Resampler แต่เนื่องจากความล่าช้าผ่าน Resampler มันอาจยังคงมีเฟรมอยู่ในบัฟเฟอร์ภายใน เมื่อเฟรมที่ต้องการทั้งหมดได้รับการสร้างความยาวของบัฟเฟอร์เอาต์พุตชั่วคราวควรเป็นอย่างน้อย new_length + delay
หากไม่เป็นเช่นนั้นให้โทร Resampler::process_partial()
หรือ Resampler::process_partial_into_buffer()
โดย None
อินพุตและผนวกเอาต์พุตเข้ากับบัฟเฟอร์เอาต์พุตชั่วคราว หากจำเป็นให้ทำซ้ำจนกว่าความยาวจะเพียงพอ
สุดท้ายคัดลอกข้อมูลจากบัฟเฟอร์เอาต์พุตชั่วคราวไปยังปลายทางที่ต้องการ ข้ามเฟรม delay
เวลาแรกและคัดลอกเฟรม new_length
หากมีคลิปมากกว่าหนึ่งคลิปที่จะกลับมาใช้ใหม่จากและไปยังอัตราตัวอย่างเดียวกันควรนำกลับมาใช้ใหม่ซ้ำอีกครั้ง การสร้าง Resampler ใหม่เป็นงานที่มีราคาแพงและควรหลีกเลี่ยงหากเป็นไปได้ เริ่มต้น Procedire ตั้งแต่เริ่มต้น แต่แทนที่จะสร้าง Resampler ใหม่ให้โทร Resampler::reset()
บนอันที่มีอยู่เพื่อเตรียมงานใหม่
เมื่อทำการส่งกระแสข้อมูลใหม่กระบวนการจะดำเนินการตามเวลาจริงและอินพุตของเอาต์พุตเป็น API บางตัวที่ให้หรือใช้เฟรมในอัตราที่กำหนด
API เสียงเช่น CoreAudio บน MacOS หรือ Cross Cpal Crate มักใช้ฟังก์ชั่นการโทรกลับสำหรับการแลกเปลี่ยนข้อมูล
สมบูรณ์
เมื่อจับเสียงจากสิ่งเหล่านี้แอปพลิเคชันจะส่งผ่านฟังก์ชั่นไปยัง Audio API API จะเรียกฟังก์ชั่นนี้เป็นระยะโดยมีตัวชี้ไปยังบัฟเฟอร์ข้อมูลที่มีเฟรมเสียงใหม่ ขนาดบัฟเฟอร์ข้อมูลมักจะเหมือนกันในทุกการโทร แต่มันจะแตกต่างกันระหว่าง API เป็นสิ่งสำคัญที่ฟังก์ชั่นไม่ได้บล็อกเนื่องจากสิ่งนี้จะปิดกั้นลูปภายในของ API และทำให้สูญเสียข้อมูลเสียงบางอย่าง ขอแนะนำให้รักษาฟังก์ชั่นการโทรกลับ เป็นการดีที่ควรอ่านข้อมูลเสียงที่ให้มาจากบัฟเฟอร์ที่จัดทำโดย API และเลือกการประมวลผลแสงบางอย่างเช่นการแปลงรูปแบบตัวอย่าง ไม่ควรทำการประมวลผลอย่างหนักเช่นการสุ่มตัวอย่างที่นี่ จากนั้นควรจัดเก็บข้อมูลเสียงไปยังบัฟเฟอร์ที่ใช้ร่วมกัน บัฟเฟอร์อาจเป็น Arc<Mutex<VecDeque<T>>>
หรือสิ่งที่ก้าวหน้ากว่าเช่น ringbuf
ลูปแยกต่างหากที่ทำงานในหลักหรือเธรดแยกต่างหากควรอ่านจากบัฟเฟอร์, Resample และบันทึกเป็นไฟล์ หาก Audio API มีขนาดบัฟเฟอร์คงที่จำนวนเฟรมนี้เป็นตัวเลือกที่ดีสำหรับขนาดก้อนใหม่ หากขนาดแตกต่างกันไปบัฟเฟอร์ที่ใช้ร่วมกันสามารถใช้เพื่อปรับขนาดก้อนของ Audio API และ Resampler จุดเริ่มต้นที่ดีสำหรับขนาดก้อนที่ resampler คือการใช้ค่า "ง่าย" ใกล้ขนาดก้อนเฉลี่ยของ Audio API ตรวจสอบให้แน่ใจว่าบัฟเฟอร์ที่ใช้ร่วมกันมีขนาดใหญ่พอที่จะไม่ได้รับเต็มในกรณีที่ลูปถูกบล็อกรอตัวอย่างเช่นการเข้าถึงดิสก์
ลูปควรทำตามกระบวนการที่คล้ายกับการสุ่มตัวอย่างคลิป แต่อินพุตตอนนี้เป็นบัฟเฟอร์ที่ใช้ร่วมกัน ลูปจำเป็นต้องรอจำนวนเฟรมที่จำเป็นเพื่อให้พร้อมใช้งานในบัฟเฟอร์ก่อนที่จะอ่านและส่งผ่านไปยัง Resampler
นอกจากนี้ยังเหมาะสมที่จะละเว้นบัฟเฟอร์เอาต์พุตชั่วคราวและเขียนเอาต์พุตโดยตรงไปยังปลายทาง The Hound Crate เป็นตัวเลือกยอดนิยมสำหรับการอ่านและการเขียนรูปแบบเสียงที่ไม่บีบอัด
Resampler แบบอะซิงโครนัสรองรับ SIMD บน X86_64 และ AARCH64 ความสามารถของ SIMD ของ CPU ถูกกำหนดในเวลาทำงาน หากไม่มีชุดคำสั่ง SIMD ที่ได้รับการสนับสนุนมันจะกลับไปใช้งานสเกลาร์
บน X86_64 มันจะพยายามใช้ AVX หาก AVX ไม่พร้อมใช้งานมันจะลอง SSE3 แทน
บน Aarch64 (แขน 64 บิต) มันจะใช้นีออนถ้ามี
Resamplers แบบซิงโครนัสได้รับประโยชน์จากการสนับสนุน SIMD ของไลบรารี RustFFT
fft_resampler
: เปิดใช้งาน Resamplers แบบซิงโครนัสที่ใช้ FFTคุณสมบัตินี้เปิดใช้งานโดยค่าเริ่มต้น ปิดการใช้งานหากไม่จำเป็นต้องใช้ Resamplers FFT เพื่อประหยัดเวลาในการรวบรวมและลดขนาดไบนารีที่เกิดขึ้น
log
: เปิดใช้งานการบันทึก คุณสมบัตินี้ช่วยให้การบันทึกผ่านลัง log
สิ่งนี้มีไว้สำหรับวัตถุประสงค์ในการดีบัก โปรดทราบว่าการส่งออกบันทึกจัดสรร [std :: string :: string] และการใช้งานการบันทึกส่วนใหญ่เกี่ยวข้องกับการโทรระบบอื่น ๆ อีกมากมาย การโทรเหล่านี้อาจใช้เวลา (คาดเดาไม่ได้) ในการกลับมาในระหว่างที่แอปพลิเคชันถูกบล็อก ซึ่งหมายความว่าควรหลีกเลี่ยงการบันทึกหากใช้ไลบรารีนี้ในแอปพลิเคชันเรียลไทม์
คุณสมบัติ log
สามารถเปิดใช้งานได้เมื่อเรียกใช้การทดสอบซึ่งมีประโยชน์มากเมื่อทำการดีบัก ระดับการบันทึกสามารถตั้งค่าผ่านตัวแปรสภาพแวดล้อม RUST_LOG
ตัวอย่าง:
RUST_LOG=trace cargo test --features log
Resample ไฟล์เสียงหุ่นจำลองเดียวจาก 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 ใหม่ได้ ตัวอย่างนี้เปลี่ยนเป็น 16 บิตที่ 44.1 kHz:
sox -e floating-point -b 64 -r 44100 -c 2 resampler_output.raw -e signed-integer -b 16 some_file_resampled.wav
บรรณาธิการเสียงจำนวนมากเช่น Audacity สามารถนำเข้าและส่งออกตัวอย่างดิบได้โดยตรง
rubato
Crate ต้องการ RustC เวอร์ชัน 1.61 หรือใหม่กว่า
fft_resampler
log
input/output_buffer_allocate()
เลือกบัฟเฟอร์ก่อนเติมด้วยศูนย์ใบอนุญาต: MIT