audio input and fft
All checks were successful
Build legacy Nix package on Ubuntu / build (push) Successful in 4m17s

This commit is contained in:
Max Känner 2025-01-12 17:52:47 +01:00
parent 33907234fd
commit 86dfbd21f4
6 changed files with 1336 additions and 12 deletions

2
.envrc
View File

@ -1 +1 @@
use flake export RUST_LOG=trace

1247
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -8,3 +8,9 @@ pedantic = "warn"
nursery = "warn" nursery = "warn"
[dependencies] [dependencies]
env_logger = "0.11"
log = "0.4"
color-eyre = "0.6"
cpal = { version = "0.15", features = ["jack"] }
rustfft = "6.2"

View File

@ -1,7 +1,10 @@
(import ( (import
fetchTarball { (
url = "https://github.com/edolstra/flake-compat/archive/99f1c2157fba4bfe6211a321fd0ee43199025dbf.tar.gz"; fetchTarball {
sha256 = "0x2jn3vrawwv9xp15674wjz9pixwjyj3j771izayl962zziivbx2"; } url = "https://github.com/edolstra/flake-compat/archive/99f1c2157fba4bfe6211a321fd0ee43199025dbf.tar.gz";
) { sha256 = "0x2jn3vrawwv9xp15674wjz9pixwjyj3j771izayl962zziivbx2";
src = ./.; }
}).defaultNix )
{
src = ./.;
}).defaultNix

View File

@ -12,9 +12,13 @@
naersk-lib = pkgs.callPackage naersk { }; naersk-lib = pkgs.callPackage naersk { };
in in
{ {
defaultPackage = naersk-lib.buildPackage ./.; defaultPackage = naersk-lib.buildPackage {
src = ./.;
buildInputs = with pkgs; [ alsa-lib libjack2 ];
nativeBuildInputs = with pkgs; [ pkg-config ];
};
devShell = with pkgs; mkShell { devShell = with pkgs; mkShell {
buildInputs = [ cargo rustc rustfmt pre-commit rustPackages.clippy ]; buildInputs = [ cargo rustc rustfmt pre-commit rustPackages.clippy alsa-lib pipewire ];
RUST_SRC_PATH = rustPlatform.rustLibSrc; RUST_SRC_PATH = rustPlatform.rustLibSrc;
}; };
} }

View File

@ -1,3 +1,67 @@
fn main() { use std::{thread::sleep, time::Duration};
println!("Hello, world!");
use color_eyre::eyre::bail;
use cpal::{
traits::{DeviceTrait, HostTrait, StreamTrait},
BufferSize, HostId, SupportedBufferSize,
};
use log::{debug, error, info, trace};
use rustfft::{num_complex::Complex, FftPlanner};
fn main() -> color_eyre::Result<()> {
env_logger::init();
debug!("Starting");
let mut hosts = cpal::platform::available_hosts();
hosts.sort_unstable_by_key(|host| match host {
HostId::Jack => 0,
HostId::Alsa => 1,
});
let host_id = hosts[0];
info!("Selected {host_id:?} audio backend");
let host = cpal::platform::host_from_id(host_id)?;
let Some(device) = host.default_input_device() else {
error!("Unable to get default input device for {host_id:?}");
bail!("Unable to get default input device")
};
debug!("Got default input device {:?}", device.name());
let default_config = device.default_input_config()?;
trace!("Default config {:?}", default_config);
let mut config = default_config.config();
let buffer_size =
if let SupportedBufferSize::Range { min, max: _ } = default_config.buffer_size() {
*min
} else {
1024
};
config.buffer_size = BufferSize::Fixed(buffer_size);
config.channels = 1;
debug!("Using config {config:?}");
let mut planner = FftPlanner::<f32>::new();
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_scratch = vec![Complex::new(0.0, 0.0); buffer_size as usize];
let stream = device.build_input_stream(
&config,
move |data: &[f32], _| {
for i in 0..data.len() {
fft_data[i] = Complex::new(data[i], 0.0);
}
fft.process_with_scratch(&mut fft_data[..], &mut fft_scratch[..]);
},
|err| {
error!("input stream error: {err}");
},
None,
)?;
stream.play()?;
loop {
sleep(Duration::from_secs(1));
}
} }