use byteorder::{ByteOrder, LittleEndian, WriteBytesExt};
use serde::{Deserialize, Serialize};
use std::io::Write;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AudioFrameHeader {
pub seq: u64,
pub ts_unix_nanos: u64,
pub sample_rate: u32,
pub channels: u16,
pub format_tag: u16, }
pub const FORMAT_PCM16LE: u16 = 1;
pub const FORMAT_F32: u16 = 3;
pub fn pack_frame(h: &AudioFrameHeader, payload: &[u8]) -> Vec<u8> {
let mut out = vec![0u8; 8 + 8 + 4 + 2 + 2];
LittleEndian::write_u64(&mut out[0..8], h.seq);
LittleEndian::write_u64(&mut out[8..16], h.ts_unix_nanos);
LittleEndian::write_u32(&mut out[16..20], h.sample_rate);
LittleEndian::write_u16(&mut out[20..22], h.channels);
LittleEndian::write_u16(&mut out[22..24], h.format_tag);
out.extend_from_slice(payload);
out
}
pub fn unpack_frame(buf: &[u8]) -> Option<(AudioFrameHeader, &[u8])> {
if buf.len() < 24 {
return None;
}
let seq = LittleEndian::read_u64(&buf[0..8]);
let ts_unix_nanos = LittleEndian::read_u64(&buf[8..16]);
let sample_rate = LittleEndian::read_u32(&buf[16..20]);
let channels = LittleEndian::read_u16(&buf[20..22]);
let format_tag = LittleEndian::read_u16(&buf[22..24]);
Some((
AudioFrameHeader {
seq,
ts_unix_nanos,
sample_rate,
channels,
format_tag,
},
&buf[24..],
))
}
pub fn write_wav_pcm16_mono_24k(path: &str, samples: &[u8]) -> anyhow::Result<()> {
let mut f = std::fs::File::create(path)?;
let data_len = samples.len() as u32;
let byte_rate = 24_000u32 * 16 / 8; let block_align = 16 / 8; let subchunk2_size = data_len;
f.write_all(b"RIFF")?;
f.write_u32::<LittleEndian>(36 + subchunk2_size)?; f.write_all(b"WAVE")?;
f.write_all(b"fmt ")?;
f.write_u32::<LittleEndian>(16)?; f.write_u16::<LittleEndian>(1)?; f.write_u16::<LittleEndian>(1)?; f.write_u32::<LittleEndian>(24_000)?; f.write_u32::<LittleEndian>(byte_rate)?; f.write_u16::<LittleEndian>(block_align as u16)?; f.write_u16::<LittleEndian>(16)?;
f.write_all(b"data")?;
f.write_u32::<LittleEndian>(subchunk2_size)?;
f.write_all(samples)?;
Ok(())
}
pub fn pcm16_silence_24k(ms: u32) -> Vec<u8> {
let samples = (24_000u32 * ms / 1000) as usize;
let out = vec![0u8; samples * 2]; out
}