tidy up
All checks were successful
Build legacy Nix package on Ubuntu / build (push) Successful in 4m37s
All checks were successful
Build legacy Nix package on Ubuntu / build (push) Successful in 4m37s
This commit is contained in:
50
src/main.rs
50
src/main.rs
@ -1,5 +1,6 @@
|
||||
use std::{cmp::Ordering, net::UdpSocket, sync::mpsc, thread::sleep, time::Duration};
|
||||
use std::{cmp::Ordering, net::UdpSocket, sync::mpsc};
|
||||
|
||||
use az::{Az, SaturatingAs};
|
||||
use bytemuck::{Pod, Zeroable};
|
||||
use color_eyre::eyre::{bail, Result};
|
||||
use cpal::{
|
||||
@ -8,10 +9,11 @@ use cpal::{
|
||||
};
|
||||
use log::{debug, error, info, trace};
|
||||
use realfft::{
|
||||
num_complex::{Complex, Complex32, ComplexFloat},
|
||||
num_complex::{Complex32, ComplexFloat},
|
||||
RealFftPlanner, RealToComplex,
|
||||
};
|
||||
use textplots::{Chart, LabelBuilder, LabelFormat, Plot, Shape};
|
||||
#[cfg(feature = "plot")]
|
||||
use textplots::{Chart, Plot, Shape};
|
||||
|
||||
fn main() -> color_eyre::Result<()> {
|
||||
env_logger::init();
|
||||
@ -87,15 +89,18 @@ fn main() -> color_eyre::Result<()> {
|
||||
error!("Unable to send packet over multicast: {e}");
|
||||
}
|
||||
|
||||
// let plot_data: Vec<_> = data
|
||||
// .fft_result
|
||||
// .iter()
|
||||
// .enumerate()
|
||||
// .map(|(i, datum)| (i as f32, f32::from(*datum)))
|
||||
// .collect();
|
||||
// Chart::new_with_y_range(250, 50, 0.0, 16.0, 0.0, 255.0)
|
||||
// .lineplot(&Shape::Bars(&plot_data[..]))
|
||||
// .display();
|
||||
#[cfg(feature = "plot")]
|
||||
{
|
||||
let plot_data: Vec<_> = data
|
||||
.fft_result
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, datum)| (i.az(), f32::from(*datum)))
|
||||
.collect();
|
||||
Chart::new_with_y_range(250, 50, 0.0, 16.0, 0.0, 255.0)
|
||||
.lineplot(&Shape::Bars(&plot_data[..]))
|
||||
.display();
|
||||
}
|
||||
let magnitude = data.fft_magnitude;
|
||||
let sample_raw = data.sample_raw;
|
||||
let sample_smth = data.sample_smth;
|
||||
@ -113,9 +118,9 @@ struct AudioSyncPacket {
|
||||
header: [u8; 6],
|
||||
/// Optional sound pressure as fixed point (8bit integer, 8bit fractional)
|
||||
preasure: [u8; 2],
|
||||
/// either "sample_raw" or "raw_sample_agc" depending on sound_agc setting
|
||||
/// either `sample_raw` or `raw_sample_agc` depending on `sound_agc` setting
|
||||
sample_raw: f32,
|
||||
/// either "sample_avg" or "sample_agc" depending on sound_agc setting
|
||||
/// either `sample_avg` or `sample_agc` depending on `sound_agc` setting
|
||||
sample_smth: f32,
|
||||
/// 0 = no peak, >= 1 = peak detected, In future, this will also provide peak Magnitude
|
||||
sample_peak: u8,
|
||||
@ -168,14 +173,14 @@ impl AudioSyncPacket {
|
||||
let abs_data: Vec<_> = data.iter().map(|sample| sample.abs()).collect();
|
||||
|
||||
// calculate peak (raw level and peak level)
|
||||
let raw_level = abs_data.iter().sum::<f32>() / data.len() as f32 * 256.0;
|
||||
let raw_level = abs_data.iter().sum::<f32>() / data.len().az::<f32>() * 512.0;
|
||||
let peak_level = abs_data
|
||||
.iter()
|
||||
.max_by(|lhs, rhs| lhs.partial_cmp(rhs).unwrap_or(Ordering::Equal))
|
||||
.copied()
|
||||
.unwrap_or(0.0);
|
||||
// scale peak level to u8
|
||||
let peak_level = (peak_level * f32::from(u8::MAX)) as u8;
|
||||
let peak_level = (peak_level * f32::from(u8::MAX)).saturating_as();
|
||||
|
||||
// calculate fft
|
||||
fft_input[..].copy_from_slice(data);
|
||||
@ -183,13 +188,14 @@ impl AudioSyncPacket {
|
||||
let real_fft_output: Vec<_> = fft_output.iter().map(|value| value.abs()).collect();
|
||||
|
||||
// find dominant frequency
|
||||
let (peak_index, peak) = real_fft_output
|
||||
let peak_index = real_fft_output
|
||||
.iter()
|
||||
.enumerate()
|
||||
.max_by(|(_, lhs), (_, rhs)| lhs.partial_cmp(rhs).unwrap_or(Ordering::Equal))
|
||||
.map(|(i, value)| (i, *value))
|
||||
.map(|(i, _)| i)
|
||||
.unwrap_or_default();
|
||||
let peak_frequency = (peak_index * sample_rate as usize) as f32 / data.len() as f32;
|
||||
let peak_frequency =
|
||||
(peak_index * sample_rate.az::<usize>()).az::<f32>() / data.len().az::<f32>();
|
||||
|
||||
// select 16 [frequency bins](https://github.com/MoonModules/WLED/blob/fc173b3bc00694e59b653ca230133052b5476c05/usermods/audioreactive/audio_reactive.h#L733-L760)
|
||||
let bins = [
|
||||
@ -197,12 +203,12 @@ impl AudioSyncPacket {
|
||||
]
|
||||
.map(|frequency| frequency * data.len() / sample_rate as usize);
|
||||
let mut fft_values = [0.0; 16];
|
||||
fft_values[0] = real_fft_output[1..=bins[0]].iter().sum::<f32>() / (bins[0]) as f32;
|
||||
fft_values[0] = real_fft_output[1..=bins[0]].iter().sum::<f32>() / (bins[0]).az::<f32>();
|
||||
for i in 1..fft_values.len() {
|
||||
fft_values[i] = real_fft_output[bins[i - 1] + 1..=bins[i]]
|
||||
.iter()
|
||||
.sum::<f32>()
|
||||
/ (bins[i] - bins[i - 1] + 1) as f32;
|
||||
/ (bins[i] - bins[i - 1] + 1).az::<f32>();
|
||||
}
|
||||
fft_values[14] *= 0.88;
|
||||
fft_values[15] *= 0.7;
|
||||
@ -218,7 +224,7 @@ impl AudioSyncPacket {
|
||||
fft_max = 1.0;
|
||||
}
|
||||
for i in 0..fft_values.len() {
|
||||
fft_values_u8[i] = (fft_values[i] * f32::from(u8::MAX) / fft_max) as u8;
|
||||
fft_values_u8[i] = (fft_values[i] * f32::from(u8::MAX) / fft_max).saturating_as();
|
||||
}
|
||||
|
||||
// calculate fft magnitude sum
|
||||
|
Reference in New Issue
Block a user