autd_wav_modulation/
wav_modulation.rs

1/*
2 * File: wav_modulation.rs
3 * Project: modulation
4 * Created Date: 03/12/2019
5 * Author: Shun Suzuki
6 * -----
7 * Last Modified: 31/12/2020
8 * Modified By: Shun Suzuki (suzuki@hapis.k.u-tokyo.ac.jp)
9 * -----
10 * Copyright (c) 2019 Hapis Lab. All rights reserved.
11 *
12 */
13
14use autd::modulation::Modulation;
15use autd::{consts::MOD_BUF_SIZE, Configuration};
16
17use hound::SampleFormat;
18use std::ffi::OsString;
19use std::{error::Error, vec};
20
21pub struct WavModulation {
22    raw_buf: Vec<u8>,
23    buffer: Vec<u8>,
24    sample_rate: u32,
25    sent: usize,
26}
27
28impl WavModulation {
29    pub fn create(
30        path: &OsString,
31        bits_per_sample: u16,
32        sample_format: SampleFormat,
33    ) -> Result<Self, Box<dyn Error>> {
34        let mut reader = hound::WavReader::open(path)?;
35        let sample_rate = reader.spec().sample_rate;
36        let sample_iter: Vec<u8> = match (sample_format, bits_per_sample) {
37            (SampleFormat::Int, 8) => reader
38                .samples::<i32>()
39                .map(|i| i.unwrap() as i32)
40                .map(|i| (i - std::i8::MIN as i32) as u8)
41                .collect(),
42            (SampleFormat::Int, 16) => reader
43                .samples::<i32>()
44                .map(|i| (i.unwrap() as i32) / (i32::pow(2, 8)))
45                .map(|i| (i - std::i8::MIN as i32) as u8)
46                .collect(),
47            (SampleFormat::Int, 24) => reader
48                .samples::<i32>()
49                .map(|i| (i.unwrap() as i32) / (i32::pow(2, 16)))
50                .map(|i| (i - std::i8::MIN as i32) as u8)
51                .collect(),
52            (SampleFormat::Int, 32) => reader
53                .samples::<i32>()
54                .map(|i| i.unwrap() / i32::pow(2, 24))
55                .map(|i| (i - std::i8::MIN as i32) as u8)
56                .collect(),
57            (SampleFormat::Float, 32) => reader
58                .samples::<f32>()
59                .map(|i| i.unwrap())
60                .map(|i| ((i + 1.0) / 2.0 * 255.0) as u8)
61                .collect(),
62            _ => return Err(From::from("Not supported format.")),
63        };
64        let size = std::cmp::min(MOD_BUF_SIZE as usize, sample_iter.len());
65        let mut buffer = Vec::with_capacity(size);
66        buffer.extend_from_slice(&sample_iter[0..size]);
67
68        Ok(Self {
69            raw_buf: buffer,
70            buffer: vec![],
71            sample_rate,
72            sent: 0,
73        })
74    }
75}
76
77impl Modulation for WavModulation {
78    fn build(&mut self, config: Configuration) {
79        let mod_sf = config.sampling_frequency() as usize;
80        let mod_buf_size = config.buf_size() as usize;
81
82        // down sampling
83        let freq_ratio = mod_sf as f64 / self.sample_rate as f64;
84        let mut buffer_size = (self.raw_buf.len() as f64 * freq_ratio) as usize;
85        if buffer_size > mod_buf_size {
86            buffer_size = mod_buf_size;
87        }
88
89        let mut sample_buf = Vec::with_capacity(buffer_size);
90        for i in 0..self.raw_buf.len() {
91            let idx = (i as f64 / freq_ratio) as usize;
92            sample_buf.push(self.raw_buf[idx]);
93        }
94
95        self.buffer = sample_buf;
96    }
97
98    fn buffer(&self) -> &[u8] {
99        &self.buffer
100    }
101
102    fn sent(&mut self) -> &mut usize {
103        &mut self.sent
104    }
105}