audio input and fft
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Build legacy Nix package on Ubuntu / build (push) Successful in 4m17s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Build legacy Nix package on Ubuntu / build (push) Successful in 4m17s
				
			This commit is contained in:
		
							
								
								
									
										1247
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1247
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -8,3 +8,9 @@ pedantic = "warn" | ||||
| nursery = "warn" | ||||
|  | ||||
| [dependencies] | ||||
| env_logger = "0.11" | ||||
| log = "0.4" | ||||
| color-eyre = "0.6" | ||||
|  | ||||
| cpal = { version = "0.15", features = ["jack"] } | ||||
| rustfft = "6.2" | ||||
|   | ||||
							
								
								
									
										17
									
								
								default.nix
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								default.nix
									
									
									
									
									
								
							| @@ -1,7 +1,10 @@ | ||||
| (import ( | ||||
|   fetchTarball { | ||||
|     url = "https://github.com/edolstra/flake-compat/archive/99f1c2157fba4bfe6211a321fd0ee43199025dbf.tar.gz"; | ||||
|     sha256 = "0x2jn3vrawwv9xp15674wjz9pixwjyj3j771izayl962zziivbx2"; } | ||||
| ) { | ||||
|   src =  ./.; | ||||
| }).defaultNix | ||||
| (import | ||||
|   ( | ||||
|     fetchTarball { | ||||
|       url = "https://github.com/edolstra/flake-compat/archive/99f1c2157fba4bfe6211a321fd0ee43199025dbf.tar.gz"; | ||||
|       sha256 = "0x2jn3vrawwv9xp15674wjz9pixwjyj3j771izayl962zziivbx2"; | ||||
|     } | ||||
|   ) | ||||
|   { | ||||
|     src = ./.; | ||||
|   }).defaultNix | ||||
|   | ||||
| @@ -12,9 +12,13 @@ | ||||
|         naersk-lib = pkgs.callPackage naersk { }; | ||||
|       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 { | ||||
|           buildInputs = [ cargo rustc rustfmt pre-commit rustPackages.clippy ]; | ||||
|           buildInputs = [ cargo rustc rustfmt pre-commit rustPackages.clippy alsa-lib pipewire ]; | ||||
|           RUST_SRC_PATH = rustPlatform.rustLibSrc; | ||||
|         }; | ||||
|       } | ||||
|   | ||||
							
								
								
									
										68
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								src/main.rs
									
									
									
									
									
								
							| @@ -1,3 +1,67 @@ | ||||
| fn main() { | ||||
|     println!("Hello, world!"); | ||||
| use std::{thread::sleep, time::Duration}; | ||||
|  | ||||
| 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)); | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user