use ringbuf to limit audio latency
Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
		
							parent
							
								
									bdc11eb035
								
							
						
					
					
						commit
						80b5033fb7
					
				
							
								
								
									
										62
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										62
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -4814,6 +4814,15 @@ dependencies = [
 | 
			
		||||
 "winapi 0.3.9",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "ringbuf"
 | 
			
		||||
version = "0.3.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "93ca10b9c9e53ac855a2d6953bce34cef6edbac32c4b13047a4d59d67299420a"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "crossbeam-utils",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "rpassword"
 | 
			
		||||
version = "2.1.0"
 | 
			
		||||
@ -4972,6 +4981,7 @@ dependencies = [
 | 
			
		||||
 "rdev",
 | 
			
		||||
 "repng",
 | 
			
		||||
 "reqwest",
 | 
			
		||||
 "ringbuf",
 | 
			
		||||
 "rpassword 7.2.0",
 | 
			
		||||
 "rubato",
 | 
			
		||||
 "runas",
 | 
			
		||||
@ -6773,12 +6783,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "windows_aarch64_gnullvm",
 | 
			
		||||
 "windows_aarch64_msvc 0.42.1",
 | 
			
		||||
 "windows_i686_gnu 0.42.1",
 | 
			
		||||
 "windows_i686_msvc 0.42.1",
 | 
			
		||||
 "windows_x86_64_gnu 0.42.1",
 | 
			
		||||
 "windows_aarch64_msvc 0.42.2",
 | 
			
		||||
 "windows_i686_gnu 0.42.2",
 | 
			
		||||
 "windows_i686_msvc 0.42.2",
 | 
			
		||||
 "windows_x86_64_gnu 0.42.2",
 | 
			
		||||
 "windows_x86_64_gnullvm",
 | 
			
		||||
 "windows_x86_64_msvc 0.42.1",
 | 
			
		||||
 "windows_x86_64_msvc 0.42.2",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
@ -6792,24 +6802,24 @@ dependencies = [
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows-targets"
 | 
			
		||||
version = "0.42.1"
 | 
			
		||||
version = "0.42.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
 | 
			
		||||
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "windows_aarch64_gnullvm",
 | 
			
		||||
 "windows_aarch64_msvc 0.42.1",
 | 
			
		||||
 "windows_i686_gnu 0.42.1",
 | 
			
		||||
 "windows_i686_msvc 0.42.1",
 | 
			
		||||
 "windows_x86_64_gnu 0.42.1",
 | 
			
		||||
 "windows_aarch64_msvc 0.42.2",
 | 
			
		||||
 "windows_i686_gnu 0.42.2",
 | 
			
		||||
 "windows_i686_msvc 0.42.2",
 | 
			
		||||
 "windows_x86_64_gnu 0.42.2",
 | 
			
		||||
 "windows_x86_64_gnullvm",
 | 
			
		||||
 "windows_x86_64_msvc 0.42.1",
 | 
			
		||||
 "windows_x86_64_msvc 0.42.2",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_aarch64_gnullvm"
 | 
			
		||||
version = "0.42.1"
 | 
			
		||||
version = "0.42.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
 | 
			
		||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_aarch64_msvc"
 | 
			
		||||
@ -6837,9 +6847,9 @@ checksum = "2623277cb2d1c216ba3b578c0f3cf9cdebeddb6e66b1b218bb33596ea7769c3a"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_aarch64_msvc"
 | 
			
		||||
version = "0.42.1"
 | 
			
		||||
version = "0.42.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
 | 
			
		||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_i686_gnu"
 | 
			
		||||
@ -6867,9 +6877,9 @@ checksum = "d3925fd0b0b804730d44d4b6278c50f9699703ec49bcd628020f46f4ba07d9e1"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_i686_gnu"
 | 
			
		||||
version = "0.42.1"
 | 
			
		||||
version = "0.42.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
 | 
			
		||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_i686_msvc"
 | 
			
		||||
@ -6897,9 +6907,9 @@ checksum = "ce907ac74fe331b524c1298683efbf598bb031bc84d5e274db2083696d07c57c"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_i686_msvc"
 | 
			
		||||
version = "0.42.1"
 | 
			
		||||
version = "0.42.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
 | 
			
		||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_x86_64_gnu"
 | 
			
		||||
@ -6927,15 +6937,15 @@ checksum = "2babfba0828f2e6b32457d5341427dcbb577ceef556273229959ac23a10af33d"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_x86_64_gnu"
 | 
			
		||||
version = "0.42.1"
 | 
			
		||||
version = "0.42.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
 | 
			
		||||
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_x86_64_gnullvm"
 | 
			
		||||
version = "0.42.1"
 | 
			
		||||
version = "0.42.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
 | 
			
		||||
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_x86_64_msvc"
 | 
			
		||||
@ -6963,9 +6973,9 @@ checksum = "f4dd6dc7df2d84cf7b33822ed5b86318fb1781948e9663bacd047fc9dd52259d"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "windows_x86_64_msvc"
 | 
			
		||||
version = "0.42.1"
 | 
			
		||||
version = "0.42.2"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
 | 
			
		||||
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "winit"
 | 
			
		||||
 | 
			
		||||
@ -72,6 +72,7 @@ cidr-utils = "0.5.9"
 | 
			
		||||
 | 
			
		||||
[target.'cfg(not(any(target_os = "android", target_os = "linux")))'.dependencies]
 | 
			
		||||
cpal = "0.14"
 | 
			
		||||
ringbuf = "0.3"
 | 
			
		||||
 | 
			
		||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
 | 
			
		||||
machine-uid = "0.2"
 | 
			
		||||
 | 
			
		||||
@ -14,6 +14,8 @@ use cpal::{
 | 
			
		||||
    Device, Host, StreamConfig,
 | 
			
		||||
};
 | 
			
		||||
use magnum_opus::{Channels::*, Decoder as AudioDecoder};
 | 
			
		||||
#[cfg(not(any(target_os = "android", target_os = "linux")))]
 | 
			
		||||
use ringbuf::{ring_buffer::RbBase, Rb};
 | 
			
		||||
use sha2::{Digest, Sha256};
 | 
			
		||||
use uuid::Uuid;
 | 
			
		||||
 | 
			
		||||
@ -701,7 +703,7 @@ pub struct AudioHandler {
 | 
			
		||||
    #[cfg(target_os = "linux")]
 | 
			
		||||
    simple: Option<psimple::Simple>,
 | 
			
		||||
    #[cfg(not(any(target_os = "android", target_os = "linux")))]
 | 
			
		||||
    audio_buffer: Arc<std::sync::Mutex<std::collections::vec_deque::VecDeque<f32>>>,
 | 
			
		||||
    audio_buffer: AudioBuffer,
 | 
			
		||||
    sample_rate: (u32, u32),
 | 
			
		||||
    #[cfg(not(any(target_os = "android", target_os = "linux")))]
 | 
			
		||||
    audio_stream: Option<Box<dyn StreamTrait>>,
 | 
			
		||||
@ -710,6 +712,18 @@ pub struct AudioHandler {
 | 
			
		||||
    ready: Arc<std::sync::Mutex<bool>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(not(any(target_os = "android", target_os = "linux")))]
 | 
			
		||||
struct AudioBuffer(pub Arc<std::sync::Mutex<ringbuf::HeapRb<f32>>>);
 | 
			
		||||
 | 
			
		||||
#[cfg(not(any(target_os = "android", target_os = "linux")))]
 | 
			
		||||
impl Default for AudioBuffer {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        Self(Arc::new(std::sync::Mutex::new(
 | 
			
		||||
            ringbuf::HeapRb::<f32>::new(48000 * 2), // 48000hz, 2 channel, 1 second
 | 
			
		||||
        )))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl AudioHandler {
 | 
			
		||||
    /// Start the audio playback.
 | 
			
		||||
    #[cfg(target_os = "linux")]
 | 
			
		||||
@ -816,11 +830,7 @@ impl AudioHandler {
 | 
			
		||||
                {
 | 
			
		||||
                    let sample_rate0 = self.sample_rate.0;
 | 
			
		||||
                    let sample_rate = self.sample_rate.1;
 | 
			
		||||
                    let audio_buffer = self.audio_buffer.clone();
 | 
			
		||||
                    // avoiding memory overflow if audio_buffer consumer side has problem
 | 
			
		||||
                    if audio_buffer.lock().unwrap().len() as u32 > sample_rate * 120 {
 | 
			
		||||
                        *audio_buffer.lock().unwrap() = Default::default();
 | 
			
		||||
                    }
 | 
			
		||||
                    let audio_buffer = self.audio_buffer.0.clone();
 | 
			
		||||
                    if sample_rate != sample_rate0 {
 | 
			
		||||
                        let buffer = crate::resample_channels(
 | 
			
		||||
                            &buffer[0..n],
 | 
			
		||||
@ -828,12 +838,12 @@ impl AudioHandler {
 | 
			
		||||
                            sample_rate,
 | 
			
		||||
                            channels,
 | 
			
		||||
                        );
 | 
			
		||||
                        audio_buffer.lock().unwrap().extend(buffer);
 | 
			
		||||
                        audio_buffer.lock().unwrap().push_slice_overwrite(&buffer);
 | 
			
		||||
                    } else {
 | 
			
		||||
                        audio_buffer
 | 
			
		||||
                            .lock()
 | 
			
		||||
                            .unwrap()
 | 
			
		||||
                            .extend(buffer[0..n].iter().cloned());
 | 
			
		||||
                            .push_slice_overwrite(&buffer[0..n]);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                #[cfg(target_os = "android")]
 | 
			
		||||
@ -861,7 +871,7 @@ impl AudioHandler {
 | 
			
		||||
            // too many errors, will improve later
 | 
			
		||||
            log::trace!("an error occurred on stream: {}", err);
 | 
			
		||||
        };
 | 
			
		||||
        let audio_buffer = self.audio_buffer.clone();
 | 
			
		||||
        let audio_buffer = self.audio_buffer.0.clone();
 | 
			
		||||
        let ready = self.ready.clone();
 | 
			
		||||
        let stream = device.build_output_stream(
 | 
			
		||||
            config,
 | 
			
		||||
@ -871,10 +881,13 @@ impl AudioHandler {
 | 
			
		||||
                }
 | 
			
		||||
                let mut lock = audio_buffer.lock().unwrap();
 | 
			
		||||
                let mut n = data.len();
 | 
			
		||||
                if lock.len() < n {
 | 
			
		||||
                    n = lock.len();
 | 
			
		||||
                if lock.occupied_len() < n {
 | 
			
		||||
                    n = lock.occupied_len();
 | 
			
		||||
                }
 | 
			
		||||
                let mut input = lock.drain(0..n);
 | 
			
		||||
                let mut elems = vec![0.0f32; n];
 | 
			
		||||
                lock.pop_slice(&mut elems);
 | 
			
		||||
                drop(lock);
 | 
			
		||||
                let mut input = elems.into_iter();
 | 
			
		||||
                for sample in data.iter_mut() {
 | 
			
		||||
                    *sample = match input.next() {
 | 
			
		||||
                        Some(x) => T::from(&x),
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user