mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-09-13 19:14:24 +08:00
feat: 完善 OTG UAC 音频支持
This commit is contained in:
59
src/audio/uac/decoder.rs
Normal file
59
src/audio/uac/decoder.rs
Normal file
@@ -0,0 +1,59 @@
|
||||
use audiopus::coder::Decoder;
|
||||
use audiopus::{Channels, SampleRate};
|
||||
|
||||
use crate::error::{AppError, Result};
|
||||
|
||||
const CHANNELS: usize = 2;
|
||||
const MAX_PACKET_BYTES: usize = 1275;
|
||||
const MAX_SAMPLES_PER_CHANNEL: usize = 5760;
|
||||
|
||||
pub struct UacOpusDecoder {
|
||||
decoder: Decoder,
|
||||
buffer: Vec<i16>,
|
||||
}
|
||||
|
||||
impl UacOpusDecoder {
|
||||
pub fn new() -> Result<Self> {
|
||||
let decoder = Decoder::new(SampleRate::Hz48000, Channels::Stereo)
|
||||
.map_err(|error| AppError::AudioError(format!("Opus decoder init failed: {error}")))?;
|
||||
Ok(Self {
|
||||
decoder,
|
||||
buffer: vec![0; MAX_SAMPLES_PER_CHANNEL * CHANNELS],
|
||||
})
|
||||
}
|
||||
|
||||
pub fn decode(&mut self, packet: &[u8]) -> Result<&[i16]> {
|
||||
if packet.is_empty() || packet.len() > MAX_PACKET_BYTES {
|
||||
return Err(AppError::BadRequest(format!(
|
||||
"invalid Opus packet length {}",
|
||||
packet.len()
|
||||
)));
|
||||
}
|
||||
|
||||
let frames = self
|
||||
.decoder
|
||||
.decode(Some(packet), &mut self.buffer, false)
|
||||
.map_err(|error| AppError::AudioError(format!("Opus decode failed: {error}")))?;
|
||||
Ok(&self.buffer[..frames * CHANNELS])
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use audiopus::coder::Encoder;
|
||||
use audiopus::Application;
|
||||
|
||||
#[test]
|
||||
fn decode_preserves_all_stereo_samples() {
|
||||
let encoder =
|
||||
Encoder::new(SampleRate::Hz48000, Channels::Stereo, Application::Audio).unwrap();
|
||||
let pcm = vec![0i16; 960 * CHANNELS];
|
||||
let mut packet = vec![0u8; MAX_PACKET_BYTES];
|
||||
let packet_len = encoder.encode(&pcm, &mut packet).unwrap();
|
||||
|
||||
let mut decoder = UacOpusDecoder::new().unwrap();
|
||||
let decoded = decoder.decode(&packet[..packet_len]).unwrap();
|
||||
assert_eq!(decoded.len(), pcm.len());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user