This is a relatively complex task for me and I am not fully able to sum it up in the title.
But the problem is this:
- I created a audio visualizer that converts raw audio data to a
Vec<f32>where the elements in the vector are ordered by ascending frequency starting with 0hz and ending with 20_000hz - But now I have to
normalizethe vector so that the frequencies are not spaced in a linear way but logarithmically, which is more like how the human hearing works. here is the function that does this:
fn normalize(buffer: Vec<f32>, volume: f32) -> Vec<f32> {
let mut output_buffer: Vec<f32> = vec![0.0; buffer.len()];
let mut start_pos: usize = 0;
let mut end_pos: usize = 0;
for i in 0..buffer.len() {
// FIRST HALF
let offset: f32 = (buffer.len() as f32 / (i + 1) as f32).sqrt();
if ((i as f32 * offset) as usize) < output_buffer.len() {
// normalized position
let pos: usize = (i as f32 * offset) as usize;
// stores positions needed for filling
start_pos = end_pos;
end_pos = pos;
let y = buffer[i];
// prevent volume loss, that could occur because of 'crunching' of higher freqs
// by only setting the value of buffer if y is bigger
if output_buffer[pos] < y {
output_buffer[pos] = y;
}
}
// SECOND HALF
// linear filling of the values between
if end_pos - start_pos > 1 && (end_pos - 1) < output_buffer.len() {
for s_p in (start_pos + 1)..end_pos {
let percentage: f32 = (s_p - start_pos) as f32 / ((end_pos - 1) - start_pos) as f32;
let mut y: f32 = 0.0;
//(output_buffer[s_p] * (1.0 - percentage) ) + (output_buffer[end_pos] * percentage);
y += output_buffer[start_pos] * (1.0 - percentage);
y += output_buffer[end_pos] * percentage;
output_buffer[s_p] = y;
}
}
}
output_buffer
}
In the first half I am reallocating the values of the buffer to be logarithmic, but with this method a lot of values especially in the low frequency range get skipped and then it looks like this: unfilled
|
| |
| |
| | | |
| | | |||
| | | | |||
+----+---+--+-+++
Because of that I found a way to fill in the the gaps in the second half. now it looks like this: filled
|
:|: |
::|:: :|:
:::|::: ::|:| |
::::|:::|::|:|||
|::::|:::|::|:|||
+----+---+--+-+++
I reduced the amount of bars for the sake of visualisation, the real implementation has about 10 time more 'bars' so the linearity is much more visible there.
So my final problem is that instead of straight lines in between the points I want to create curves, which represent sound much better.
I need to be able to access the 'y' coordinate value of any point of the curve.
Is there any way to do this, or am I doing this totally wrong?
I created audioviz that does all of this processing and where the code is from and audiolizer an application that makes use this libary combined with a GUI.