try to send exactly 10ms packets
This commit is contained in:
@@ -1,15 +1,12 @@
|
||||
const SAMPLE_RATE = 48000;
|
||||
const PACKET_MS = 10;
|
||||
const PACKET_FRAMES = PACKET_MS / 1000 * SAMPLE_RATE;
|
||||
//const PACKET_FRAMES = 2400;
|
||||
console.log("Frames per packet:", PACKET_FRAMES);
|
||||
const PACKET_SAMPLES = 480;
|
||||
|
||||
class RustWorklet extends AudioWorkletProcessor {
|
||||
constructor(options) {
|
||||
super();
|
||||
this.module = options.processorOptions;
|
||||
this.timestamp = null;
|
||||
this.buffer = new Float32Array(PACKET_FRAMES);
|
||||
this.buffer = new Float32Array(PACKET_SAMPLES * 2);
|
||||
this.buffer_offset = 0;
|
||||
if (sampleRate != SAMPLE_RATE) {
|
||||
throw Error(`sample rate ${sampleRate} should be ${SAMPLE_RATE}`);
|
||||
@@ -23,15 +20,16 @@ class RustWorklet extends AudioWorkletProcessor {
|
||||
const data = {
|
||||
format: 'f32',
|
||||
sampleRate: SAMPLE_RATE,
|
||||
//numberOfFrames: this.buffer_offset,
|
||||
numberOfFrames: this.buffer_offset,
|
||||
numberOfChannels: 1,
|
||||
timestamp: this.timestamp,
|
||||
//timestamp: null,
|
||||
data: this.buffer.slice(0, this.buffer_offset),
|
||||
data: this.buffer.slice(0, PACKET_SAMPLES),
|
||||
};
|
||||
this.port.postMessage(data);
|
||||
this.buffer_offset = 0;
|
||||
if (this.buffer_offset > PACKET_SAMPLES) {
|
||||
this.buffer.copyWithin(0, PACKET_SAMPLES, this.buffer_offset);
|
||||
}
|
||||
this.buffer_offset -= PACKET_SAMPLES;
|
||||
this.timestamp = null;
|
||||
}
|
||||
|
||||
@@ -52,18 +50,12 @@ class RustWorklet extends AudioWorkletProcessor {
|
||||
|
||||
const frames = input[0];
|
||||
|
||||
if (this.buffer_offset + frames.length > this.buffer.length) {
|
||||
// too full, send now
|
||||
this.do_send();
|
||||
}
|
||||
|
||||
this.buffer.set(frames, this.buffer_offset);
|
||||
this.buffer_offset += frames.length;
|
||||
|
||||
if (this.buffer_offset + 128 > this.buffer.length) {
|
||||
// full enough, send now
|
||||
if (this.buffer_offset >= PACKET_SAMPLES) {
|
||||
this.do_send();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
+13
-26
@@ -46,7 +46,6 @@ use web_sys::WorkletOptions;
|
||||
|
||||
mod ass {
|
||||
|
||||
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use ogg::PacketWriter;
|
||||
|
||||
@@ -60,11 +59,7 @@ const fn calc_sr_u64(val: u64, from: u32, to: u32) -> u64 {
|
||||
(val * to as u64) / from as u64
|
||||
}
|
||||
|
||||
pub fn encode(
|
||||
pre_encoded_frames: Vec<Vec<u8>>,
|
||||
frame_size: usize,
|
||||
skip: u16,
|
||||
) -> Vec<u8>{
|
||||
pub fn encode(pre_encoded_frames: Vec<Vec<u8>>, frame_size: usize, skip: u16) -> Vec<u8> {
|
||||
let mut buffer: Vec<u8> = Vec::new();
|
||||
let mut packet_writer = PacketWriter::new(&mut buffer);
|
||||
|
||||
@@ -92,21 +87,13 @@ pub fn encode(
|
||||
opus_tags.extend(&[0u8; 4]);
|
||||
|
||||
packet_writer.write_packet(&head, serial, ogg::PacketWriteEndInfo::EndPage, 0);
|
||||
packet_writer.write_packet(
|
||||
&opus_tags,
|
||||
serial,
|
||||
ogg::PacketWriteEndInfo::EndPage,
|
||||
0,
|
||||
);
|
||||
packet_writer.write_packet(&opus_tags, serial, ogg::PacketWriteEndInfo::EndPage, 0);
|
||||
|
||||
for (i, frame) in pre_encoded_frames.iter().enumerate() {
|
||||
let is_last = i == pre_encoded_frames.len() - 1;
|
||||
//let granule_pos = 0;
|
||||
let granule_pos = calc_sr_u64(
|
||||
(skip as usize + (i + 1) * frame_size) as u64,
|
||||
48000,
|
||||
48000,
|
||||
);
|
||||
let granule_pos =
|
||||
calc_sr_u64((skip as usize + (i + 1) * frame_size) as u64, 48000, 48000);
|
||||
|
||||
packet_writer.write_packet(
|
||||
frame.clone(),
|
||||
@@ -122,13 +109,12 @@ pub fn encode(
|
||||
|
||||
buffer
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Function to download data as a file
|
||||
pub fn download_data(data: Vec<u8>, filename: &str) -> Result<(), JsValue> {
|
||||
use wasm_bindgen::prelude::*;
|
||||
use web_sys::{Blob, Url, HtmlAnchorElement, window};
|
||||
use web_sys::{window, Blob, HtmlAnchorElement, Url};
|
||||
// Create a new Blob from the data
|
||||
let array = web_sys::js_sys::Uint8Array::from(&data[..]);
|
||||
let blob = Blob::new_with_u8_array_sequence(&vec![array].into())?;
|
||||
@@ -138,7 +124,9 @@ pub fn download_data(data: Vec<u8>, filename: &str) -> Result<(), JsValue> {
|
||||
|
||||
// Create an anchor element and set its href to the Blob URL
|
||||
let document = window().unwrap().document().unwrap();
|
||||
let a = document.create_element("a")?.dyn_into::<HtmlAnchorElement>()?;
|
||||
let a = document
|
||||
.create_element("a")?
|
||||
.dyn_into::<HtmlAnchorElement>()?;
|
||||
a.set_href(&url);
|
||||
a.set_download(filename);
|
||||
|
||||
@@ -153,7 +141,6 @@ pub fn download_data(data: Vec<u8>, filename: &str) -> Result<(), JsValue> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
// Borrowed from
|
||||
// https://github.com/security-union/videocall-rs/blob/main/videocall-client/src/decode/config.rs#L6
|
||||
fn configure_audio_context() -> AudioContext {
|
||||
@@ -207,10 +194,8 @@ async fn create_encoder_worklet(
|
||||
|
||||
let error: Closure<dyn FnMut(JsValue)> = Closure::new(|e| console::error_1(&e));
|
||||
|
||||
|
||||
let mut download_buffer = std::cell::RefCell::new(Vec::new());
|
||||
|
||||
|
||||
// This knows what MediaStreamTrackGenerator to use as it closes around it
|
||||
let mut sequence_num = 0;
|
||||
let output: Closure<dyn FnMut(EncodedAudioChunk)> =
|
||||
@@ -221,11 +206,13 @@ async fn create_encoder_worklet(
|
||||
download_buffer.borrow_mut().push(array.clone());
|
||||
if download_buffer.borrow().len() > 200 {
|
||||
//download_data(download_buffer.borrow().to_vec(), "download_buffer.opus");
|
||||
download_data(ass::encode(download_buffer.borrow().to_vec(), 960, 0), "download_buffer.opus");
|
||||
download_data(
|
||||
ass::encode(download_buffer.borrow().to_vec(), 960, 0),
|
||||
"download_buffer.opus",
|
||||
);
|
||||
download_buffer.borrow_mut().clear();
|
||||
}
|
||||
|
||||
|
||||
let _ = packets.try_send(ControlPacket::UDPTunnel(Box::new(VoicePacket::Audio {
|
||||
_dst: std::marker::PhantomData,
|
||||
target: 0,
|
||||
@@ -234,7 +221,7 @@ async fn create_encoder_worklet(
|
||||
payload: VoicePacketPayload::Opus(array.into(), false),
|
||||
position_info: None,
|
||||
})));
|
||||
sequence_num = sequence_num.wrapping_add(2);
|
||||
sequence_num = sequence_num.wrapping_add(1);
|
||||
});
|
||||
|
||||
let audio_encoder = AudioEncoder::new(&AudioEncoderInit::new(
|
||||
|
||||
Reference in New Issue
Block a user