wav2json/
lib.rs

1use std::{
2    collections::HashMap,
3    fs::File,
4    io::{BufReader, Read},
5};
6
7use reqwest::blocking::Response;
8
9/// Bytes used by the wav file header.
10const LEN_CHUNK_DESCRIPTOR: usize = 4;
11const LEN_WAVE_FLAG: usize = 4;
12const LEN_FMT_SUB_CHUNK: usize = 4;
13const LEN_DATA_SUB_CHUNK: usize = 4;
14
15/// Wav file header information.
16const RIFF: &str = "RIFF";
17const WAVE: &str = "WAVE";
18const FMT_: &str = "fmt ";
19const DATA: &str = "data";
20
21#[derive(Debug)]
22enum WavReader {
23    FileReader(BufReader<File>),
24    ResponseReader(BufReader<Response>),
25}
26
27#[derive(Debug, Default)]
28pub struct Wav {
29    chunk_descriptor: String,
30    chunk_size: u64,
31    wave_flag: String,
32    fmt_sub_chunk: String,
33    sub_chunk1_size: u64,
34    audio_format: i32,
35    num_channels: u32,
36    sample_rate: u64,
37    byte_rate: u64,
38    block_align: i32,
39    bits_per_sample: u32,
40    sub_chunk2_size: u32,
41    data: String,
42    length: u32,
43    reader: Option<WavReader>,
44    sample_data: HashMap<u32, Vec<f64>>,
45    json_width: u32,
46}
47
48impl Wav {
49    /// Get the final `Url` of this `Response`.
50    ///
51    /// # Example
52    ///
53    /// ```no_run
54    /// fn main() {
55    ///     // Support for local and network files.
56    ///     // let mut wav = Wav::new("http://[host]/sample-15s.wav").set_json_width(1920);
57    ///     let mut wav = Wav::new("examples/sample-15s.wav").set_json_width(1920);
58    ///
59    ///     println!("duration: {}", Instant::now().elapsed().as_millis());
60    ///
61    ///     // Generate json data files that can be rendered.
62    ///     let mut json_file = File::create("examples/data.json").expect("create failed");
63    ///     json_file.write(b"[").unwrap();
64    ///     for v in result_data.iter() {
65    ///         json_file.write(v.to_string().as_bytes()).unwrap();
66    ///         json_file.write(b",").unwrap();
67    ///     }
68    ///     json_file.write(b"]").unwrap();
69    /// }
70    /// ```
71    pub fn new(path: &str) -> Self {
72        let reader;
73        if path.starts_with("http") {
74            let resp = reqwest::blocking::get(path).unwrap();
75            reader = Some(WavReader::ResponseReader(BufReader::new(resp)));
76        } else {
77            let file = File::open(path).unwrap();
78            reader = Some(WavReader::FileReader(BufReader::new(file)));
79        }
80
81        Self {
82            reader,
83            ..Default::default()
84        }
85    }
86
87    /// Sets the number of json points generated by decoding.
88    pub fn set_json_width(mut self, width: u32) -> Self {
89        self.json_width = width;
90
91        self
92    }
93
94    /// Start decoding.
95    pub fn decode(&mut self) -> Vec<f64> {
96        let mut buf = vec![0u8; 2];
97        self.chunk_descriptor = self.read_string(LEN_CHUNK_DESCRIPTOR);
98        if !self.chunk_descriptor.eq(RIFF) {
99            println!("Not standard format!")
100        }
101        self.chunk_size = self.read_long();
102        self.wave_flag = self.read_string(LEN_WAVE_FLAG);
103        if !self.wave_flag.eq(WAVE) {
104            println!("Not standard format!")
105        }
106        self.fmt_sub_chunk = self.read_string(LEN_FMT_SUB_CHUNK);
107        if !self.fmt_sub_chunk.eq(FMT_) {
108            println!("Not standard format!")
109        }
110        self.sub_chunk1_size = self.read_long();
111        self.audio_format = self.read_int(&mut buf);
112        self.num_channels = self.read_int(&mut buf) as u32;
113        self.sample_rate = self.read_long();
114        self.byte_rate = self.read_long();
115        self.block_align = self.read_int(&mut buf);
116        self.bits_per_sample = self.read_int(&mut buf) as u32;
117
118        self.data = self.read_string(LEN_DATA_SUB_CHUNK);
119        if !self.data.eq(DATA) {
120            println!("Not standard format!")
121        }
122        self.sub_chunk2_size = self.read_long() as u32;
123        self.length =
124            (self.sub_chunk2_size / (self.bits_per_sample / 8) / self.num_channels) as u32;
125
126        self.read_data(self.length);
127
128        let mut result_data: Vec<f64> = Vec::new();
129
130        let len = self.sample_data.len() as u32;
131        match len {
132            1 => {
133                result_data = self.sample_data.get(&0).unwrap().to_vec();
134            }
135            _ => {
136                let mut max4 = 0;
137                for i in 0..len {
138                    if i <= len - 2 {
139                        max4 = self
140                            .sample_data
141                            .get(&i)
142                            .unwrap()
143                            .len()
144                            .max(self.sample_data.get(&(i + 1)).unwrap().len())
145                    }
146                }
147                for i in 0..max4 {
148                    for j in 0..len {
149                        if self.sample_data.get(&j).unwrap().len() >= i {
150                            let val = self.sample_data.get(&j).unwrap().get(i).unwrap();
151                            result_data.push((*val * 100.0).round() / 100.0);
152                        }
153                    }
154                }
155            }
156        }
157
158        result_data
159    }
160
161    /// Parsing audio data.
162    fn read_data(&mut self, length: u32) {
163        let size;
164        if length <= self.json_width {
165            size = 1;
166        } else {
167            size = length / self.json_width;
168        }
169
170        for i in 0..self.num_channels {
171            self.sample_data.insert(i, Vec::new());
172        }
173
174        let buf: &mut Vec<u8> = &mut vec![0u8; 2];
175
176        let mut sample_sum: i64 = 0;
177        let mut i = 0;
178        while i < length {
179            let mut n = 0;
180            while n < self.num_channels {
181                match self.bits_per_sample {
182                    8 => {
183                        if i == length - 1 {
184                            self.handle8bit(n, sample_sum, size);
185                        } else {
186                            let mut buf = vec![0u8; 1];
187                            if let Some(wav_reader) = self.reader.as_mut() {
188                                let mut handle_reader = |reader: &mut dyn Read| {
189                                    reader.read(&mut buf).unwrap();
190                                };
191                                match wav_reader {
192                                    WavReader::FileReader(reader) => handle_reader(reader),
193                                    WavReader::ResponseReader(reader) => handle_reader(reader),
194                                }
195                            }
196                            if i != 0 && (i % size) == 0 {
197                                self.handle8bit(n, sample_sum, size);
198                                sample_sum = 0;
199                            } else {
200                                sample_sum += (buf[0] as i64).pow(2);
201                            }
202                        }
203                    }
204                    16 => {
205                        if i == length - 1 {
206                            self.handle16bit(n, sample_sum, size);
207                        } else {
208                            let val = self.read_int(buf) as i64;
209                            if i != 0 && (i % size) == 0 {
210                                self.handle16bit(n, sample_sum, size);
211                                sample_sum = 0;
212                            } else {
213                                sample_sum += val.pow(2);
214                            }
215                        }
216                    }
217                    _ => {}
218                }
219
220                n += 1;
221            }
222            i += 1;
223        }
224    }
225
226    fn handle8bit(&mut self, key: u32, sample_sum: i64, size: u32) {
227        self.handle_bit(key, sample_sum, size, 128f32);
228    }
229
230    fn handle16bit(&mut self, key: u32, sample_sum: i64, size: u32) {
231        self.handle_bit(key, sample_sum, size, 32768f32);
232    }
233
234    // fn handle24bit(&mut self, key: u32, sample_sum: i64, size: u32) {
235    //     self.handle_bit(key, sample_sum, size, 8388608f32);
236    // }
237
238    // fn handle32bit(&mut self, key: u32, sample_sum: i64, size: u32) {
239    //     self.handle_bit(key, sample_sum, size, 2147483648f32);
240    // }
241
242    fn handle_bit(&mut self, key: u32, sample_sum: i64, size: u32, scope: f32) {
243        let sample_arr = self.sample_data.get_mut(&key).unwrap();
244        let data = cal_rms(sample_sum as f32 / scope, size);
245        sample_arr.push(data);
246    }
247
248    fn read_string(&mut self, len: usize) -> String {
249        let mut buf = vec![0u8; len];
250        if let Some(wav_reader) = self.reader.as_mut() {
251            let mut handle_reader = |reader: &mut dyn Read| {
252                reader.read(&mut buf).unwrap();
253            };
254            match wav_reader {
255                WavReader::FileReader(reader) => handle_reader(reader),
256                WavReader::ResponseReader(reader) => handle_reader(reader),
257            }
258        }
259        String::from_utf8(buf).unwrap()
260    }
261
262    fn read_long(&mut self) -> u64 {
263        let mut buffer = [0u64; 4];
264        let mut i = 0;
265        while i < 4 {
266            let mut buf = vec![0u8; 1];
267            if let Some(wav_reader) = self.reader.as_mut() {
268                let mut handle_reader = |reader: &mut dyn Read| {
269                    reader.read(&mut buf).unwrap();
270                };
271                match wav_reader {
272                    WavReader::FileReader(reader) => handle_reader(reader),
273                    WavReader::ResponseReader(reader) => handle_reader(reader),
274                }
275            }
276            buffer[i] = buf[0] as u64;
277            i += 1;
278        }
279        buffer[0] | (buffer[1] << 8) | (buffer[2] << 16) | (buffer[3] << 24)
280    }
281
282    fn read_int(&mut self, buf: &mut Vec<u8>) -> i32 {
283        if let Some(reader_type) = self.reader.as_mut() {
284            let mut handle_reader = |reader: &mut dyn Read| {
285                reader.read(buf).unwrap();
286            };
287            match reader_type {
288                WavReader::FileReader(reader) => handle_reader(reader),
289                WavReader::ResponseReader(reader) => handle_reader(reader),
290            }
291        }
292        buf[0] as i32 | ((buf[1] as i8) as i32) << 8
293    }
294}
295
296/// rms algorithm.
297fn cal_rms(sample_sum: f32, size: u32) -> f64 {
298    (sample_sum / size as f32).sqrt() as f64
299}
300
301#[cfg(test)]
302mod tests {
303    use super::*;
304
305    #[test]
306    fn decode() {
307        let mut wav = Wav::new("examples/sample-15s.wav").set_json_width(3000);
308        let result_data = wav.decode();
309        println!("{:?}", result_data)
310    }
311}