1 use nihav_core::frame::*;
2 use nihav_core::demuxers::*;
4 const SAMPLE_RATES: [u32; 15] = [
5 6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000,
6 32000, 44100, 48000, 64000, 88200, 96000, 192000
8 const WV_FLAG_MONO: u32 = 1 << 2;
9 //const WV_FLAG_HYBRID: u32 = 1 << 3;
10 //const WV_FLAG_JSTEREO: u32 = 1 << 4;
11 //const WV_FLAG_CH_DECORR: u32 = 1 << 5;
12 //const WV_FLAG_HYB_NOISE_SHAPING: u32 = 1 << 6;
13 const WV_FLAG_FLOATS: u32 = 1 << 7;
14 //const WV_FLAG_EXT_INTEGERS: u32 = 1 << 8;
15 //const WV_FLAG_HYB_BITRATE: u32 = 1 << 9;
16 //const WV_FLAG_HYB_BALANCED_NOISE: u32 = 1 << 10;
17 const WV_FLAG_START_BLOCK: u32 = 1 << 11;
18 const WV_FLAG_END_BLOCK: u32 = 1 << 12;
19 //const WV_FLAG_HAS_CRC: u32 = 1 << 28;
20 const WV_FLAG_FALSE_STEREO: u32 = 1 << 30;
21 //const WV_FLAG_DSD_AUDIO: u32 = 1 << 31;
23 const WV_STREAM_FLAGS: u32 = 0x8000008B;
25 #[derive(Clone,Copy,Default)]
36 const WV_HEADER_SIZE: usize = 32;
39 fn parse(src: &[u8]) -> DemuxerResult<Self> {
40 let mut mr = MemoryReader::new_read(src);
41 let mut br = ByteReader::new(&mut mr);
42 let tag = br.read_tag()?;
43 validate!(&tag == b"wvpk");
44 let mut hdr = Self::default();
45 hdr.size = br.read_u32le()? as usize;
46 validate!(hdr.size >= 24);
47 hdr.ver = br.read_u16le()?;
48 validate!(hdr.ver >= 0x402 || hdr.ver <= 0x410);
49 let top_idx = br.read_byte()?;
50 let top_samps = br.read_byte()?;
51 hdr.tot_samples = u64::from(br.read_u32le()?) | (u64::from(top_samps) << 32);
52 hdr.block_index = u64::from(br.read_u32le()?) | (u64::from(top_idx) << 32);
53 hdr.block_samples = br.read_u32le()?;
54 hdr.flags = br.read_u32le()?;
55 hdr.crc = br.read_u32le()?;
58 fn stream_eq(&self, rval: &Self) -> bool {
59 self.ver == rval.ver &&
60 (self.flags & WV_STREAM_FLAGS) == (rval.flags & WV_STREAM_FLAGS)
62 fn block_eq(&self, rval: &Self) -> bool {
63 self.stream_eq(rval) && self.tot_samples == rval.tot_samples &&
64 self.block_index == rval.block_index &&
65 self.block_samples == rval.block_samples
67 fn is_start_block(&self) -> bool {
68 (self.flags & WV_FLAG_START_BLOCK) != 0
70 fn is_end_block(&self) -> bool {
71 (self.flags & WV_FLAG_END_BLOCK) != 0
73 fn get_num_channels(&self) -> u8 {
74 if (self.flags & WV_FLAG_MONO) != 0 && (self.flags & WV_FLAG_FALSE_STEREO) == 0 { 1 } else { 2 }
76 fn get_sample_rate(&self) -> u32 {
77 let idx = ((self.flags >> 23) & 0xF) as usize;
84 fn get_size(&self) -> usize {
85 self.size - (WV_HEADER_SIZE - 8)
89 #[derive(Clone,Copy,Default)]
90 struct FrameSeekInfo {
95 struct WavPackDemuxer<'a> {
96 src: &'a mut ByteReader<'a>,
99 first_blocks: Option<(WVHeader, Vec<u8>)>,
101 known_frames: Vec<FrameSeekInfo>,
104 impl<'a> WavPackDemuxer<'a> {
105 fn new(io: &'a mut ByteReader<'a>) -> Self {
112 known_frames: Vec::new(),
115 fn read_blocks(&mut self) -> DemuxerResult<(WVHeader, Vec<u8>)> {
116 let mut hdrbuf = [0u8; WV_HEADER_SIZE];
117 let mut buf: Vec<u8> = Vec::new();
118 let mut first = true;
119 let mut refhdr = WVHeader::default();
121 self.src.read_buf(&mut hdrbuf)?;
122 let hdr = WVHeader::parse(&hdrbuf)?;
124 validate!(hdr.is_start_block());
128 validate!(refhdr.block_eq(&hdr));
130 buf.extend_from_slice(&hdrbuf);
132 buf.resize(pos + hdr.get_size(), 0);
133 self.src.read_buf(&mut buf[pos..])?;
135 if hdr.is_end_block() {
143 impl<'a> DemuxCore<'a> for WavPackDemuxer<'a> {
144 fn open(&mut self, strmgr: &mut StreamManager, seek_index: &mut SeekIndex) -> DemuxerResult<()> {
146 let (hdr, buf) = self.read_blocks()?;
148 let srate = hdr.get_sample_rate();
149 validate!(srate != 0);
150 let channels = if !hdr.is_end_block() {
151 let mut ch_count = 0;
154 let hdr = WVHeader::parse(&buf[off..]).unwrap();
155 off += WV_HEADER_SIZE + hdr.get_size();
156 ch_count += hdr.get_num_channels();
157 if hdr.is_end_block() {
163 hdr.get_num_channels()
166 self.nsamples = hdr.tot_samples;
168 let mut fmt = SND_S16P_FORMAT;
169 if (hdr.flags & WV_FLAG_FLOATS) != 0 {
172 fmt.bits = (((hdr.flags & 3) + 1) * 8) as u8;
175 let ahdr = NAAudioInfo::new(srate, channels, SND_S16P_FORMAT, 1);
176 let ainfo = NACodecInfo::new("wavpack", NACodecTypeInfo::Audio(ahdr), Some(buf.clone()));
177 strmgr.add_stream(NAStream::new(StreamType::Audio, 0, ainfo, 1, srate, hdr.tot_samples)).unwrap();
178 seek_index.mode = SeekIndexMode::Automatic;
180 self.known_frames = Vec::with_capacity(((self.nsamples + u64::from(srate) - 1) / u64::from(srate)) as usize);
181 self.known_frames.push(FrameSeekInfo { off: 0, samplepos: hdr.block_index });
183 self.first_blocks = Some((hdr, buf));
186 fn get_frame(&mut self, strmgr: &mut StreamManager) -> DemuxerResult<NAPacket> {
187 if self.first_blocks.is_some() {
189 std::mem::swap(&mut fb, &mut self.first_blocks);
190 let (refhdr, buf) = fb.unwrap();
191 let stream = strmgr.get_stream(0).unwrap();
192 let (tb_num, tb_den) = stream.get_timebase();
193 let ts = NATimeInfo::new(Some(self.samplepos), None, None, tb_num, tb_den);
194 let pkt = NAPacket::new(stream, ts, true, buf);
196 self.samplepos += u64::from(refhdr.block_samples);
200 if self.samplepos == self.nsamples {
201 return Err(DemuxerError::EOF);
203 let cur_off = self.src.tell();
204 let cur_spos = self.samplepos;
205 let (refhdr, buf) = self.read_blocks()?;
207 let stream = strmgr.get_stream(0).unwrap();
208 let (tb_num, tb_den) = stream.get_timebase();
209 let ts = NATimeInfo::new(Some(self.samplepos), None, None, tb_num, tb_den);
210 let pkt = NAPacket::new(stream, ts, true, buf);
212 self.samplepos += u64::from(refhdr.block_samples);
213 if self.known_frames.last().unwrap_or(&FrameSeekInfo::default()).samplepos < cur_spos {
214 self.known_frames.push(FrameSeekInfo{off: cur_off, samplepos: cur_spos });
219 fn seek(&mut self, time: NATimePoint, _seek_index: &SeekIndex) -> DemuxerResult<()> {
220 self.first_blocks = None;
221 if let NATimePoint::Milliseconds(ms) = time {
222 let samppos = ms * u64::from(self.srate) / 1000;
223 if self.known_frames.last().unwrap_or(&FrameSeekInfo::default()).samplepos >= samppos {
224 for point in self.known_frames.iter().rev() {
225 if point.samplepos <= samppos {
226 self.src.seek(SeekFrom::Start(point.off))?;
227 self.samplepos = point.samplepos;
232 let mut hdrbuf = [0u8; WV_HEADER_SIZE];
233 let lastoff = self.known_frames.last().unwrap_or(&FrameSeekInfo::default()).off;
234 self.src.seek(SeekFrom::Start(lastoff))?;
236 self.src.peek_buf(&mut hdrbuf)?;
237 let hdr = WVHeader::parse(&hdrbuf)?;
238 if hdr.is_start_block() {
239 self.known_frames.push(FrameSeekInfo{off: self.src.tell(), samplepos: hdr.block_index });
240 if hdr.block_index <= samppos && hdr.block_index + u64::from(hdr.block_samples) > samppos {
241 self.samplepos = hdr.block_index;
244 if hdr.block_index > samppos {
248 self.src.read_skip(WV_HEADER_SIZE + hdr.get_size())?
251 Err(DemuxerError::SeekError)
253 Err(DemuxerError::NotPossible)
256 fn get_duration(&self) -> u64 { 0 }
259 impl<'a> NAOptionHandler for WavPackDemuxer<'a> {
260 fn get_supported_options(&self) -> &[NAOptionDefinition] { &[] }
261 fn set_options(&mut self, _options: &[NAOption]) { }
262 fn query_option_value(&self, _name: &str) -> Option<NAValue> { None }
266 pub struct WavPackDemuxerCreator { }
268 impl DemuxerCreator for WavPackDemuxerCreator {
269 fn new_demuxer<'a>(&self, br: &'a mut ByteReader<'a>) -> Box<dyn DemuxCore<'a> + 'a> {
270 Box::new(WavPackDemuxer::new(br))
272 fn get_name(&self) -> &'static str { "wavpack" }
281 fn test_wavpack_demux() {
282 let mut file = File::open("assets/LLaudio/wv/false_stereo.wv").unwrap();
283 let mut fr = FileReader::new_read(&mut file);
284 let mut br = ByteReader::new(&mut fr);
285 let mut dmx = WavPackDemuxer::new(&mut br);
286 let mut sm = StreamManager::new();
287 let mut si = SeekIndex::new();
288 dmx.open(&mut sm, &mut si).unwrap();
290 let pktres = dmx.get_frame(&mut sm);
291 if let Err(e) = pktres {
292 if (e as i32) == (DemuxerError::EOF as i32) { break; }
295 let pkt = pktres.unwrap();
296 println!("Got {}", pkt);