noise suppression added via nnnoiseless + vad + gain-normalizer + few frontend changes

This commit is contained in:
Priler 2026-01-06 23:32:58 +05:00
parent bd8e2c989d
commit 88ecf21b2c
73 changed files with 1235 additions and 112 deletions

View file

@ -16,6 +16,7 @@ tauri-plugin-fs = "2"
peak_alloc = "0.3.0"
systemstat = "0.2"
lazy_static = "1.4"
sysinfo.workspace = true
once_cell.workspace = true
log.workspace = true

View file

@ -61,6 +61,9 @@ fn main() {
tauri_commands::get_peak_ram_usage,
tauri_commands::get_cpu_temp,
tauri_commands::get_cpu_usage,
tauri_commands::get_jarvis_app_stats,
tauri_commands::is_jarvis_app_running,
tauri_commands::run_jarvis_app,
// vosk
tauri_commands::list_vosk_models,

View file

@ -12,6 +12,9 @@ pub fn db_read(state: tauri::State<'_, AppState>, key: &str) -> String {
"selected_intent_recognition_engine" => format!("{:?}", settings.intent_recognition_engine),
"selected_vosk_model" => settings.vosk_model.clone(),
"speech_to_text_engine" => format!("{:?}", settings.speech_to_text_engine),
"noise_suppression" => format!("{:?}", settings.noise_suppression),
"vad" => format!("{:?}", settings.vad),
"gain_normalizer" => settings.gain_normalizer.to_string(),
"api_key__picovoice" => settings.api_keys.picovoice.clone(),
"api_key__openai" => settings.api_keys.openai.clone(),
_ => String::new(),
@ -53,6 +56,28 @@ pub fn db_write(state: tauri::State<'_, AppState>, key: &str, val: &str) -> bool
"selected_vosk_model" => {
settings.vosk_model = val.to_string();
}
"noise_suppression" => {
match val.to_lowercase().as_str() {
"none" => settings.noise_suppression = jarvis_core::config::structs::NoiseSuppressionBackend::None,
"nnnoiseless" => settings.noise_suppression = jarvis_core::config::structs::NoiseSuppressionBackend::Nnnoiseless,
_ => return false,
}
}
"vad" => {
match val.to_lowercase().as_str() {
"none" => settings.vad = jarvis_core::config::structs::VadBackend::None,
"energy" => settings.vad = jarvis_core::config::structs::VadBackend::Energy,
"nnnoiseless" => settings.vad = jarvis_core::config::structs::VadBackend::Nnnoiseless,
_ => return false,
}
}
"gain_normalizer" => {
match val.to_lowercase().as_str() {
"true" => settings.gain_normalizer = true,
"false" => settings.gain_normalizer = false,
_ => return false,
}
}
"api_key__picovoice" => {
settings.api_keys.picovoice = val.to_string();
}

View file

@ -1,49 +1,152 @@
use sysinfo::{System, Pid, ProcessRefreshKind, RefreshKind, CpuRefreshKind, Components};
use peak_alloc::PeakAlloc;
use std::sync::Mutex;
use once_cell::sync::Lazy;
use std::process::Command;
use std::env;
#[global_allocator]
static PEAK_ALLOC: PeakAlloc = PeakAlloc;
extern crate systemstat;
use std::thread;
use std::time::Duration;
use systemstat::{Platform, System};
use lazy_static::lazy_static;
static SYS: Lazy<Mutex<System>> = Lazy::new(|| {
Mutex::new(System::new_with_specifics(
RefreshKind::nothing()
.with_processes(ProcessRefreshKind::nothing().with_memory().with_cpu())
.with_cpu(CpuRefreshKind::everything())
))
});
lazy_static! {
static ref SYS: System = System::new();
static COMPONENTS: Lazy<Mutex<Components>> = Lazy::new(|| {
Mutex::new(Components::new_with_refreshed_list())
});
const JARVIS_APP_NAME: &str = "jarvis-app";
/// Find jarvis-app process and return its PID
fn find_jarvis_app_pid(sys: &System) -> Option<Pid> {
for (pid, process) in sys.processes() {
let name = process.name().to_string_lossy().to_lowercase();
if name.contains(JARVIS_APP_NAME) {
return Some(*pid);
}
}
None
}
#[derive(serde::Serialize)]
pub struct JarvisAppStats {
pub running: bool,
pub ram_mb: u64,
pub cpu_usage: f32,
}
#[tauri::command]
pub fn get_current_ram_usage() -> String {
let result = String::from(format!("{}", PEAK_ALLOC.current_usage_as_mb()));
result
pub fn get_jarvis_app_stats() -> JarvisAppStats {
let mut sys = SYS.lock().unwrap();
// refresh all processes to find jarvis-app
sys.refresh_processes(sysinfo::ProcessesToUpdate::All, true);
if let Some(pid) = find_jarvis_app_pid(&sys) {
if let Some(proc) = sys.process(pid) {
return JarvisAppStats {
running: true,
ram_mb: proc.memory() / 1024 / 1024,
cpu_usage: proc.cpu_usage(),
};
}
}
JarvisAppStats {
running: false,
ram_mb: 0,
cpu_usage: 0.0,
}
}
#[tauri::command]
pub fn get_peak_ram_usage() -> String {
let result = String::from(format!("{}", PEAK_ALLOC.peak_usage_as_gb()));
pub fn get_current_ram_usage() -> u64 {
let mut sys = SYS.lock().unwrap();
sys.refresh_processes(sysinfo::ProcessesToUpdate::All, true);
if let Some(pid) = find_jarvis_app_pid(&sys) {
if let Some(proc) = sys.process(pid) {
return proc.memory() / 1024 / 1024;
}
}
0
}
result
#[tauri::command]
pub fn is_jarvis_app_running() -> bool {
let mut sys = SYS.lock().unwrap();
sys.refresh_processes(sysinfo::ProcessesToUpdate::All, true);
find_jarvis_app_pid(&sys).is_some()
}
#[tauri::command]
pub fn get_cpu_temp() -> String {
if let Ok(cpu_temp) = SYS.cpu_temp() {
String::from(format!("{}", cpu_temp))
} else {
String::from("error")
let mut components = COMPONENTS.lock().unwrap();
components.refresh(true);
for component in components.iter() {
let label = component.label().to_lowercase();
if label.contains("cpu") || label.contains("core") || label.contains("package") {
if let Some(temp) = component.temperature() {
return format!("{:.1}", temp);
}
}
}
if let Some(component) = components.iter().next() {
if let Some(temp) = component.temperature() {
return format!("{:.1}", temp);
}
}
String::from("N/A")
}
// https://github.com/valpackett/systemstat/blob/trunk/examples/info.rs
#[tauri::command(async)]
pub async fn get_cpu_usage() -> String {
if let Ok(cpu) = SYS.cpu_load_aggregate() {
thread::sleep(Duration::from_secs(1));
let cpu = cpu.done().unwrap();
String::from(format!("{}", cpu.user * 100.0))
} else {
String::from("error")
}
#[tauri::command]
pub fn get_cpu_usage() -> f32 {
let mut sys = SYS.lock().unwrap();
sys.refresh_cpu_all();
std::thread::sleep(std::time::Duration::from_millis(200));
sys.refresh_cpu_all();
sys.global_cpu_usage()
}
#[tauri::command]
pub fn get_peak_ram_usage() -> String {
format!("{}", PEAK_ALLOC.peak_usage_as_gb())
}
#[tauri::command]
pub fn run_jarvis_app() -> Result<(), String> {
let exe_dir = std::env::current_exe()
.map_err(|e| format!("Failed to get exe path: {}", e))?
.parent()
.ok_or("Failed to get exe directory")?
.to_path_buf();
#[cfg(target_os = "windows")]
let jarvis_app_name = "jarvis-app.exe";
#[cfg(not(target_os = "windows"))]
let jarvis_app_name = "jarvis-app";
let jarvis_app_path = exe_dir.join(jarvis_app_name);
if !jarvis_app_path.exists() {
return Err(format!("jarvis-app not found at: {}", jarvis_app_path.display()));
}
std::process::Command::new(&jarvis_app_path)
.spawn()
.map_err(|e| format!("Failed to start jarvis-app: {}", e))?;
Ok(())
}