show fft in terminal
All checks were successful
Build legacy Nix package on Ubuntu / build (push) Successful in 4m25s

This commit is contained in:
Max Känner 2025-01-12 18:21:15 +01:00
parent 86dfbd21f4
commit d4bfd03c02
3 changed files with 79 additions and 4 deletions

52
Cargo.lock generated
View File

@ -106,6 +106,7 @@ dependencies = [
"env_logger", "env_logger",
"log", "log",
"rustfft", "rustfft",
"textplots",
] ]
[[package]] [[package]]
@ -165,6 +166,12 @@ version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "bytemuck"
version = "1.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.9.0" version = "1.9.0"
@ -247,6 +254,16 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
[[package]]
name = "colored"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
dependencies = [
"lazy_static",
"windows-sys 0.59.0",
]
[[package]] [[package]]
name = "combine" name = "combine"
version = "4.6.7" version = "4.6.7"
@ -313,6 +330,16 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f"
[[package]]
name = "drawille"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e64e461c3f1e69d99372620640b3fd5f0309eeda2e26e4af69f6760c0e1df845"
dependencies = [
"colored",
"fnv",
]
[[package]] [[package]]
name = "either" name = "either"
version = "1.13.0" version = "1.13.0"
@ -358,6 +385,12 @@ dependencies = [
"once_cell", "once_cell",
] ]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]] [[package]]
name = "gimli" name = "gimli"
version = "0.28.1" version = "0.28.1"
@ -768,6 +801,15 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "rgb"
version = "0.8.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a"
dependencies = [
"bytemuck",
]
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.24" version = "0.1.24"
@ -836,6 +878,16 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "textplots"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f59b64803118dbff62f92842b3154a2c802dfd8e18660132bbcbfb141c637ae3"
dependencies = [
"drawille",
"rgb",
]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.69" version = "1.0.69"

View File

@ -14,3 +14,5 @@ color-eyre = "0.6"
cpal = { version = "0.15", features = ["jack"] } cpal = { version = "0.15", features = ["jack"] }
rustfft = "6.2" rustfft = "6.2"
textplots = "0.8"

View File

@ -1,4 +1,4 @@
use std::{thread::sleep, time::Duration}; use std::{sync::mpsc, thread::sleep, time::Duration};
use color_eyre::eyre::bail; use color_eyre::eyre::bail;
use cpal::{ use cpal::{
@ -6,7 +6,11 @@ use cpal::{
BufferSize, HostId, SupportedBufferSize, BufferSize, HostId, SupportedBufferSize,
}; };
use log::{debug, error, info, trace}; use log::{debug, error, info, trace};
use rustfft::{num_complex::Complex, FftPlanner}; use rustfft::{
num_complex::{Complex, ComplexFloat},
FftPlanner,
};
use textplots::{Chart, Plot, Shape};
fn main() -> color_eyre::Result<()> { fn main() -> color_eyre::Result<()> {
env_logger::init(); env_logger::init();
@ -44,6 +48,7 @@ fn main() -> color_eyre::Result<()> {
let fft = planner.plan_fft_forward(buffer_size as usize); let fft = planner.plan_fft_forward(buffer_size as usize);
let mut fft_data = vec![Complex::new(0.0, 0.0); buffer_size as usize]; let mut fft_data = vec![Complex::new(0.0, 0.0); buffer_size as usize];
let mut fft_scratch = vec![Complex::new(0.0, 0.0); buffer_size as usize]; let mut fft_scratch = vec![Complex::new(0.0, 0.0); buffer_size as usize];
let (sender, receiver) = mpsc::channel();
let stream = device.build_input_stream( let stream = device.build_input_stream(
&config, &config,
@ -51,7 +56,15 @@ fn main() -> color_eyre::Result<()> {
for i in 0..data.len() { for i in 0..data.len() {
fft_data[i] = Complex::new(data[i], 0.0); fft_data[i] = Complex::new(data[i], 0.0);
} }
fft.process_with_scratch(&mut fft_data[..], &mut fft_scratch[..]); let mut fft_output = vec![Complex::new(0.0, 0.0); data.len()];
fft.process_outofplace_with_scratch(
&mut fft_data[..],
&mut fft_output[..],
&mut fft_scratch[..],
);
if let Err(e) = sender.send(fft_output) {
error!("Unable to send fft output: {e}");
}
}, },
|err| { |err| {
error!("input stream error: {err}"); error!("input stream error: {err}");
@ -62,6 +75,14 @@ fn main() -> color_eyre::Result<()> {
stream.play()?; stream.play()?;
loop { loop {
sleep(Duration::from_secs(1)); let data = receiver.recv()?;
let plot_data: Vec<_> = data
.into_iter()
.enumerate()
.map(|(i, datum)| ((i as f32).log10(), datum.abs() / 1024.0.sqrt()))
.collect();
Chart::new_with_y_range(200, 50, 0.0, 1024.0.log10(), 0.0, 2.0)
.lineplot(&Shape::Bars(&plot_data[..]))
.display();
} }
} }