symphonia_format_riff/wave/
mod.rs1use std::io::{Seek, SeekFrom};
9
10use symphonia_core::codecs::CodecParameters;
11use symphonia_core::errors::{seek_error, unsupported_error};
12use symphonia_core::errors::{Result, SeekErrorKind};
13use symphonia_core::formats::prelude::*;
14use symphonia_core::io::*;
15use symphonia_core::meta::{Metadata, MetadataLog};
16use symphonia_core::probe::{Descriptor, Instantiate, QueryDescriptor};
17use symphonia_core::support_format;
18
19use log::{debug, error};
20
21use crate::common::{
22 append_data_params, append_format_params, next_packet, ByteOrder, ChunksReader, PacketInfo,
23};
24mod chunks;
25use chunks::*;
26
27const WAVE_STREAM_MARKER: [u8; 4] = *b"RIFF";
29const WAVE_RIFF_FORM: [u8; 4] = *b"WAVE";
31
32pub struct WavReader {
36 reader: MediaSourceStream,
37 tracks: Vec<Track>,
38 cues: Vec<Cue>,
39 metadata: MetadataLog,
40 packet_info: PacketInfo,
41 data_start_pos: u64,
42 data_end_pos: u64,
43}
44
45impl QueryDescriptor for WavReader {
46 fn query() -> &'static [Descriptor] {
47 &[
48 support_format!(
50 "wave",
51 "Waveform Audio File Format",
52 &["wav", "wave"],
53 &["audio/vnd.wave", "audio/x-wav", "audio/wav", "audio/wave"],
54 &[b"RIFF"]
55 ),
56 ]
57 }
58
59 fn score(_context: &[u8]) -> u8 {
60 255
61 }
62}
63
64impl FormatReader for WavReader {
65 fn try_new(mut source: MediaSourceStream, _options: &FormatOptions) -> Result<Self> {
66 let marker = source.read_quad_bytes()?;
68
69 if marker != WAVE_STREAM_MARKER {
70 return unsupported_error("wav: missing riff stream marker");
71 }
72
73 let riff_len = source.read_u32()?;
77 let riff_form = source.read_quad_bytes()?;
78
79 if riff_form != WAVE_RIFF_FORM {
81 error!("riff form is not wave ({})", String::from_utf8_lossy(&riff_form));
82
83 return unsupported_error("wav: riff form is not wave");
84 }
85
86 let mut riff_chunks =
87 ChunksReader::<RiffWaveChunks>::new(riff_len, ByteOrder::LittleEndian);
88
89 let mut codec_params = CodecParameters::new();
90 let mut metadata: MetadataLog = Default::default();
91 let mut packet_info = PacketInfo::without_blocks(0);
92
93 loop {
94 let chunk = riff_chunks.next(&mut source)?;
95
96 if chunk.is_none() {
99 return unsupported_error("wav: missing data chunk");
100 }
101
102 match chunk.unwrap() {
103 RiffWaveChunks::Format(fmt) => {
104 let format = fmt.parse(&mut source)?;
105
106 packet_info = format.packet_info()?;
109 codec_params
110 .with_max_frames_per_packet(packet_info.get_max_frames_per_packet())
111 .with_frames_per_block(packet_info.frames_per_block);
112
113 append_format_params(
115 &mut codec_params,
116 &format.format_data,
117 format.sample_rate,
118 );
119 }
120 RiffWaveChunks::Fact(fct) => {
121 let fact = fct.parse(&mut source)?;
122
123 append_fact_params(&mut codec_params, &fact);
125 }
126 RiffWaveChunks::List(lst) => {
127 let list = lst.parse(&mut source)?;
128
129 match &list.form {
132 b"INFO" => metadata.push(read_info_chunk(&mut source, list.len)?),
133 _ => list.skip(&mut source)?,
134 }
135 }
136 RiffWaveChunks::Data(dat) => {
137 let data = dat.parse(&mut source)?;
138
139 let data_start_pos = source.pos();
141 let data_end_pos = data_start_pos + u64::from(data.len);
142
143 append_data_params(&mut codec_params, data.len as u64, &packet_info);
145
146 return Ok(WavReader {
148 reader: source,
149 tracks: vec![Track::new(0, codec_params)],
150 cues: Vec::new(),
151 metadata,
152 packet_info,
153 data_start_pos,
154 data_end_pos,
155 });
156 }
157 }
158 }
159 }
160
161 fn next_packet(&mut self) -> Result<Packet> {
162 next_packet(
163 &mut self.reader,
164 &self.packet_info,
165 &self.tracks,
166 self.data_start_pos,
167 self.data_end_pos,
168 )
169 }
170
171 fn metadata(&mut self) -> Metadata<'_> {
172 self.metadata.metadata()
173 }
174
175 fn cues(&self) -> &[Cue] {
176 &self.cues
177 }
178
179 fn tracks(&self) -> &[Track] {
180 &self.tracks
181 }
182
183 fn seek(&mut self, _mode: SeekMode, to: SeekTo) -> Result<SeekedTo> {
184 if self.tracks.is_empty() || self.packet_info.is_empty() {
185 return seek_error(SeekErrorKind::Unseekable);
186 }
187
188 let params = &self.tracks[0].codec_params;
189
190 let ts = match to {
191 SeekTo::TimeStamp { ts, .. } => ts,
193 SeekTo::Time { time, .. } => {
195 if let Some(sample_rate) = params.sample_rate {
198 TimeBase::new(1, sample_rate).calc_timestamp(time)
199 }
200 else {
201 return seek_error(SeekErrorKind::Unseekable);
202 }
203 }
204 };
205
206 if let Some(n_frames) = params.n_frames {
209 if ts > n_frames {
210 return seek_error(SeekErrorKind::OutOfRange);
211 }
212 }
213
214 debug!("seeking to frame_ts={}", ts);
215
216 let actual_ts = self.packet_info.get_actual_ts(ts);
223
224 let seek_pos = self.data_start_pos + (actual_ts * self.packet_info.block_size);
226
227 if self.reader.is_seekable() {
230 self.reader.seek(SeekFrom::Start(seek_pos))?;
231 }
232 else {
235 let current_pos = self.reader.pos();
236 if seek_pos >= current_pos {
237 self.reader.ignore_bytes(seek_pos - current_pos)?;
238 }
239 else {
240 return seek_error(SeekErrorKind::ForwardOnly);
241 }
242 }
243
244 debug!("seeked to packet_ts={} (delta={})", actual_ts, actual_ts as i64 - ts as i64);
245
246 Ok(SeekedTo { track_id: 0, actual_ts, required_ts: ts })
247 }
248
249 fn into_inner(self: Box<Self>) -> MediaSourceStream {
250 self.reader
251 }
252}