rescale_core/wav/
reader.rs1use super::header::{WavHeader, WavSampleFormat};
4use std::fs::File;
5use std::io::{self, BufReader, Read, Seek, SeekFrom};
6use std::path::Path;
7
8pub struct WavReader;
9
10impl WavReader {
11 pub fn read_from_file<P: AsRef<Path>>(path: P) -> io::Result<(WavHeader, Vec<Vec<f32>>)> {
13 let file = File::open(path)?;
14 let mut reader = BufReader::new(file);
15 Self::read_from_stream(&mut reader)
16 }
17
18 pub fn read_from_stream<R: Read + Seek>(
20 reader: &mut R,
21 ) -> io::Result<(WavHeader, Vec<Vec<f32>>)> {
22 let mut fourcc = [0u8; 4];
23
24 reader.read_exact(&mut fourcc)?;
26 if &fourcc != b"RIFF" {
27 return Err(io::Error::new(
28 io::ErrorKind::InvalidData,
29 "Not a valid RIFF file",
30 ));
31 }
32
33 let mut riff_size_bytes = [0u8; 4];
34 reader.read_exact(&mut riff_size_bytes)?;
35
36 reader.read_exact(&mut fourcc)?;
37 if &fourcc != b"WAVE" {
38 return Err(io::Error::new(
39 io::ErrorKind::InvalidData,
40 "Not a WAVE format",
41 ));
42 }
43
44 let mut audio_format: u16 = 0;
45 let mut num_channels: u16 = 0;
46 let mut sample_rate: u32 = 0;
47 let mut bits_per_sample: u16 = 0;
48 let mut data_chunk_size: u32 = 0;
49 let mut fmt_found = false;
50
51 loop {
53 if reader.read_exact(&mut fourcc).is_err() {
54 break;
55 }
56
57 let mut chunk_size_bytes = [0u8; 4];
58 reader.read_exact(&mut chunk_size_bytes)?;
59 let chunk_size = u32::from_le_bytes(chunk_size_bytes);
60
61 match &fourcc {
62 b"fmt " => {
63 let mut format_tag_bytes = [0u8; 2];
64 let mut channels_bytes = [0u8; 2];
65 let mut samplerate_bytes = [0u8; 4];
66 let mut byterate_bytes = [0u8; 4];
67 let mut blockalign_bytes = [0u8; 2];
68 let mut bitspersample_bytes = [0u8; 2];
69
70 reader.read_exact(&mut format_tag_bytes)?;
71 reader.read_exact(&mut channels_bytes)?;
72 reader.read_exact(&mut samplerate_bytes)?;
73 reader.read_exact(&mut byterate_bytes)?;
74 reader.read_exact(&mut blockalign_bytes)?;
75 reader.read_exact(&mut bitspersample_bytes)?;
76
77 audio_format = u16::from_le_bytes(format_tag_bytes);
78 num_channels = u16::from_le_bytes(channels_bytes);
79 sample_rate = u32::from_le_bytes(samplerate_bytes);
80 bits_per_sample = u16::from_le_bytes(bitspersample_bytes);
81
82 if chunk_size > 16 {
84 reader.seek(SeekFrom::Current((chunk_size - 16) as i64))?;
85 }
86 fmt_found = true;
87 }
88 b"data" => {
89 data_chunk_size = chunk_size;
90 break; }
92 _ => {
93 reader.seek(SeekFrom::Current(chunk_size as i64))?;
95 }
96 }
97 }
98
99 if !fmt_found {
100 return Err(io::Error::new(
101 io::ErrorKind::InvalidData,
102 "Missing 'fmt ' chunk in WAV file",
103 ));
104 }
105
106 let sample_format = match (audio_format, bits_per_sample) {
107 (1, 16) => WavSampleFormat::Pcm16Bit,
108 (1, 24) => WavSampleFormat::Pcm24Bit,
109 (3, 32) => WavSampleFormat::Pcm32BitFloat,
110 _ => {
111 return Err(io::Error::new(
112 io::ErrorKind::Unsupported,
113 format!(
114 "Unsupported WAV format: tag={}, bits={}",
115 audio_format, bits_per_sample
116 ),
117 ));
118 }
119 };
120
121 let bytes_per_sample = (bits_per_sample / 8) as usize;
122 let total_samples = (data_chunk_size as usize) / bytes_per_sample;
123 let samples_per_channel = total_samples / (num_channels as usize);
124
125 let mut channels: Vec<Vec<f32>> =
126 vec![Vec::with_capacity(samples_per_channel); num_channels as usize];
127
128 for _ in 0..samples_per_channel {
130 for channel in channels.iter_mut().take(num_channels as usize) {
131 let sample_val: f32 = match sample_format {
132 WavSampleFormat::Pcm16Bit => {
133 let mut b = [0u8; 2];
134 reader.read_exact(&mut b)?;
135 let i = i16::from_le_bytes(b);
136 if i < 0 {
137 i as f32 / 32768.0
138 } else {
139 i as f32 / 32767.0
140 }
141 }
142 WavSampleFormat::Pcm24Bit => {
143 let mut b = [0u8; 3];
144 reader.read_exact(&mut b)?;
145 let sign = if b[2] & 0x80 != 0 { 0xFF } else { 0x00 };
147 let i = i32::from_le_bytes([b[0], b[1], b[2], sign]);
148 if i < 0 {
149 i as f32 / 8388608.0
150 } else {
151 i as f32 / 8388607.0
152 }
153 }
154 WavSampleFormat::Pcm32BitFloat => {
155 let mut b = [0u8; 4];
156 reader.read_exact(&mut b)?;
157 f32::from_le_bytes(b)
158 }
159 };
160 channel.push(sample_val);
161 }
162 }
163
164 let header = WavHeader::new(
165 num_channels,
166 sample_rate,
167 sample_format,
168 samples_per_channel,
169 );
170 Ok((header, channels))
171 }
172}