1use anyhow::{Result, anyhow};
8use std::io::{Read, Seek};
9
10#[derive(Debug, Clone)]
11pub struct Pcm16 {
12 pub channels: u16,
14 pub sample_rate: u32,
16 pub samples: Vec<i16>,
18}
19
20pub fn decode_ogg_vorbis_reader<T: Read + Seek>(rdr: T) -> Result<Pcm16> {
26 use lewton::inside_ogg::OggStreamReader;
27
28 let mut r = OggStreamReader::new(rdr)
29 .map_err(|e| anyhow!("ogg/vorbis: failed to parse headers: {e}"))?;
30
31 let channels = r.ident_hdr.audio_channels as u16;
32 let sample_rate = r.ident_hdr.audio_sample_rate;
33
34 let mut samples = Vec::<i16>::new();
35 while let Some(pkt) = r
36 .read_dec_packet_itl()
37 .map_err(|e| anyhow!("ogg/vorbis: decode error: {e}"))?
38 {
39 samples.extend_from_slice(&pkt);
40 }
41
42 Ok(Pcm16 {
43 channels,
44 sample_rate,
45 samples,
46 })
47}
48
49pub fn ogg_vorbis_decoded_len<T: Read + Seek>(rdr: T) -> Result<(u16, u32, u64)> {
53 use lewton::inside_ogg::OggStreamReader;
54
55 let mut r = OggStreamReader::new(rdr)
56 .map_err(|e| anyhow!("ogg/vorbis: failed to parse headers: {e}"))?;
57 let channels = r.ident_hdr.audio_channels as u16;
58 let sample_rate = r.ident_hdr.audio_sample_rate;
59 let mut samples = 0u64;
60 while let Some(pkt) = r
61 .read_dec_packet_itl()
62 .map_err(|e| anyhow!("ogg/vorbis: decode error: {e}"))?
63 {
64 samples += pkt.len() as u64;
65 }
66 Ok((channels, sample_rate, samples))
67}
68
69pub fn decode_ogg_vorbis_bytes(data: &[u8]) -> Result<Pcm16> {
71 decode_ogg_vorbis_reader(std::io::Cursor::new(data))
72}
73
74pub fn pcm16_to_wav_bytes(pcm: &Pcm16) -> Vec<u8> {
78 let num_channels = pcm.channels;
80 let sample_rate = pcm.sample_rate;
81 let bits_per_sample: u16 = 16;
82 let block_align: u16 = num_channels.saturating_mul(bits_per_sample / 8);
83 let byte_rate: u32 = sample_rate.saturating_mul(block_align as u32);
84
85 let data_bytes_len: u32 = (pcm.samples.len() * 2) as u32;
86 let riff_size: u32 = 36u32.saturating_add(data_bytes_len);
87
88 let mut out = Vec::with_capacity(44 + data_bytes_len as usize);
89
90 out.extend_from_slice(b"RIFF");
92 out.extend_from_slice(&riff_size.to_le_bytes());
93 out.extend_from_slice(b"WAVE");
94
95 out.extend_from_slice(b"fmt ");
97 out.extend_from_slice(&16u32.to_le_bytes()); out.extend_from_slice(&1u16.to_le_bytes()); out.extend_from_slice(&num_channels.to_le_bytes());
100 out.extend_from_slice(&sample_rate.to_le_bytes());
101 out.extend_from_slice(&byte_rate.to_le_bytes());
102 out.extend_from_slice(&block_align.to_le_bytes());
103 out.extend_from_slice(&bits_per_sample.to_le_bytes());
104
105 out.extend_from_slice(b"data");
107 out.extend_from_slice(&data_bytes_len.to_le_bytes());
108
109 for s in &pcm.samples {
111 out.extend_from_slice(&s.to_le_bytes());
112 }
113
114 out
115}
116
117pub fn decode_ogg_vorbis_bytes_to_wav(data: &[u8]) -> Result<Vec<u8>> {
119 let pcm = decode_ogg_vorbis_bytes(data)?;
120 Ok(pcm16_to_wav_bytes(&pcm))
121}
122
123pub fn decode_ogg_vorbis_reader_to_wav<T: Read + Seek>(rdr: T) -> Result<Vec<u8>> {
125 let pcm = decode_ogg_vorbis_reader(rdr)?;
126 Ok(pcm16_to_wav_bytes(&pcm))
127}