-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathmanual_audio_resampler.rs
More file actions
75 lines (63 loc) · 2.64 KB
/
Copy pathmanual_audio_resampler.rs
File metadata and controls
75 lines (63 loc) · 2.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use alloc::vec::Vec;
use magenboy_core::apu::audio_device::{BUFFER_SIZE, StereoSample};
use super::audio_resampler::AudioResampler;
pub struct ManualAudioResampler{
to_skip:u32,
sampling_buffer:Vec<StereoSample>,
sampling_counter:u32,
reminder_steps:f32,
reminder_counter:f32,
alternate_to_skip:u32,
skip_to_use:u32,
}
impl AudioResampler for ManualAudioResampler{
fn new(original_frequency:u32, target_frequency:u32)->Self{
// Calling round in order to get the nearest integer and resample as precise as possible
let div = original_frequency as f32 / target_frequency as f32;
// Sicne we dont have many f32 methods without std we are implementing them ourself
let lower_to_skip = div as u32; // Acts as f32::floor (since inputs are unsigned)
let upper_to_skip = ((original_frequency as f32 + target_frequency as f32 - 1.0) / target_frequency as f32) as u32; // Acts as f32::ceil
let mut reminder = div - (div as u32 as f32); // Acts as f32::fracts (since inputs are unsigned)
let (to_skip, alt_to_skip) = if reminder < 0.5{
(lower_to_skip, upper_to_skip)
}
else{
reminder = 1.0 - reminder;
(upper_to_skip, lower_to_skip)
};
if lower_to_skip == 0{
core::panic!("target freqency is too high: {}", target_frequency);
}
ManualAudioResampler{
to_skip:to_skip,
sampling_buffer:Vec::with_capacity(upper_to_skip as usize),
sampling_counter: 0,
reminder_steps:reminder,
reminder_counter:0.0,
alternate_to_skip: alt_to_skip,
skip_to_use:to_skip
}
}
fn resample(&mut self, buffer:&[StereoSample; BUFFER_SIZE])->Vec<StereoSample>{
let mut output = Vec::new();
for sample in buffer.into_iter(){
self.sampling_buffer.push(sample.clone());
self.sampling_counter += 1;
if self.sampling_counter == self.skip_to_use {
let interpolated_sample = StereoSample::interpolate(&self.sampling_buffer);
self.sampling_counter = 0;
self.sampling_buffer.clear();
output.push(interpolated_sample);
if self.reminder_counter >= 1.0{
self.skip_to_use = self.alternate_to_skip;
self.reminder_counter -= 1.0;
}
else{
self.skip_to_use = self.to_skip;
self.reminder_counter += self.reminder_steps;
}
}
}
return output;
}
}