Files
voice_linux/src/config.c
T

275 lines
12 KiB
C

#include "config.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void trim(char *s) {
size_t len = strlen(s);
while (len > 0 && isspace((unsigned char)s[len - 1])) {
s[--len] = '\0';
}
char *p = s;
while (*p && isspace((unsigned char)*p)) {
p++;
}
if (p != s) {
memmove(s, p, strlen(p) + 1);
}
}
void config_set_defaults(voice_config_t *cfg) {
if (!cfg) return;
snprintf(cfg->model_path, sizeof(cfg->model_path), "./models/ggml-base.en.bin");
snprintf(cfg->audio_device, sizeof(cfg->audio_device), "qubes-source");
snprintf(cfg->language, sizeof(cfg->language), "en");
snprintf(cfg->hotkey, sizeof(cfg->hotkey), "Ctrl+Alt+V");
cfg->use_gpu = 1;
cfg->sample_rate = 16000;
cfg->type_delay_us = 8000;
cfg->max_record_seconds = 30;
cfg->always_on = 1;
cfg->always_on_window_ms = 1400;
cfg->vad_peak_threshold = 0.006f;
cfg->vad_trigger_ms = 100;
cfg->vad_release_ms = 300;
cfg->vad_preroll_ms = 500;
cfg->vad_min_speech_ms = 250;
cfg->vad_max_speech_ms = 15000;
cfg->autotype_enabled = 1;
cfg->filter_bracketed_tags = 1;
cfg->whisper_sampling_strategy = 0;
cfg->whisper_n_max_text_ctx = 16384;
cfg->whisper_offset_ms = 0;
cfg->whisper_duration_ms = 0;
cfg->whisper_translate = 0;
cfg->whisper_detect_language = 0;
cfg->whisper_no_context = 0;
cfg->whisper_no_timestamps = 1;
cfg->whisper_single_segment = 0;
cfg->whisper_token_timestamps = 0;
cfg->whisper_thold_pt = 0.01f;
cfg->whisper_thold_ptsum = 0.01f;
cfg->whisper_max_len = 0;
cfg->whisper_split_on_word = 0;
cfg->whisper_max_tokens = 0;
cfg->whisper_audio_ctx = 0;
cfg->whisper_tdrz_enable = 0;
cfg->whisper_suppress_blank = 1;
cfg->whisper_suppress_nst = 0;
cfg->whisper_temperature = 0.0f;
cfg->whisper_max_initial_ts = 1.0f;
cfg->whisper_length_penalty = -1.0f;
cfg->whisper_temperature_inc = 0.2f;
cfg->whisper_entropy_thold = 2.4f;
cfg->whisper_logprob_thold = -1.0f;
cfg->whisper_no_speech_thold = 0.6f;
cfg->whisper_greedy_best_of = 1;
cfg->whisper_beam_size = 5;
cfg->whisper_beam_patience = -1.0f;
}
int config_load_file(const char *path, voice_config_t *cfg) {
if (!path || !cfg) return -1;
FILE *f = fopen(path, "r");
if (!f) return -2;
char line[1024];
while (fgets(line, sizeof(line), f)) {
trim(line);
if (line[0] == '\0' || line[0] == '#') continue;
char *eq = strchr(line, '=');
if (!eq) continue;
*eq = '\0';
char *key = line;
char *value = eq + 1;
trim(key);
trim(value);
if (strcmp(key, "model_path") == 0) {
snprintf(cfg->model_path, sizeof(cfg->model_path), "%s", value);
} else if (strcmp(key, "audio_device") == 0) {
snprintf(cfg->audio_device, sizeof(cfg->audio_device), "%s", value);
} else if (strcmp(key, "language") == 0) {
snprintf(cfg->language, sizeof(cfg->language), "%s", value);
} else if (strcmp(key, "hotkey") == 0) {
snprintf(cfg->hotkey, sizeof(cfg->hotkey), "%s", value);
} else if (strcmp(key, "use_gpu") == 0) {
cfg->use_gpu = atoi(value);
} else if (strcmp(key, "sample_rate") == 0) {
cfg->sample_rate = atoi(value);
} else if (strcmp(key, "type_delay_us") == 0) {
cfg->type_delay_us = atoi(value);
} else if (strcmp(key, "max_record_seconds") == 0) {
cfg->max_record_seconds = atoi(value);
} else if (strcmp(key, "always_on") == 0) {
cfg->always_on = atoi(value);
} else if (strcmp(key, "always_on_window_ms") == 0) {
cfg->always_on_window_ms = atoi(value);
} else if (strcmp(key, "vad_peak_threshold") == 0) {
cfg->vad_peak_threshold = (float)atof(value);
} else if (strcmp(key, "vad_trigger_ms") == 0) {
cfg->vad_trigger_ms = atoi(value);
} else if (strcmp(key, "vad_release_ms") == 0) {
cfg->vad_release_ms = atoi(value);
} else if (strcmp(key, "vad_preroll_ms") == 0) {
cfg->vad_preroll_ms = atoi(value);
} else if (strcmp(key, "vad_min_speech_ms") == 0) {
cfg->vad_min_speech_ms = atoi(value);
} else if (strcmp(key, "vad_max_speech_ms") == 0) {
cfg->vad_max_speech_ms = atoi(value);
} else if (strcmp(key, "autotype_enabled") == 0) {
cfg->autotype_enabled = atoi(value);
} else if (strcmp(key, "filter_bracketed_tags") == 0) {
cfg->filter_bracketed_tags = atoi(value);
} else if (strcmp(key, "whisper_sampling_strategy") == 0) {
cfg->whisper_sampling_strategy = atoi(value);
} else if (strcmp(key, "whisper_n_max_text_ctx") == 0) {
cfg->whisper_n_max_text_ctx = atoi(value);
} else if (strcmp(key, "whisper_offset_ms") == 0) {
cfg->whisper_offset_ms = atoi(value);
} else if (strcmp(key, "whisper_duration_ms") == 0) {
cfg->whisper_duration_ms = atoi(value);
} else if (strcmp(key, "whisper_translate") == 0) {
cfg->whisper_translate = atoi(value);
} else if (strcmp(key, "whisper_detect_language") == 0) {
cfg->whisper_detect_language = atoi(value);
} else if (strcmp(key, "whisper_no_context") == 0) {
cfg->whisper_no_context = atoi(value);
} else if (strcmp(key, "whisper_no_timestamps") == 0) {
cfg->whisper_no_timestamps = atoi(value);
} else if (strcmp(key, "whisper_single_segment") == 0) {
cfg->whisper_single_segment = atoi(value);
} else if (strcmp(key, "whisper_token_timestamps") == 0) {
cfg->whisper_token_timestamps = atoi(value);
} else if (strcmp(key, "whisper_thold_pt") == 0) {
cfg->whisper_thold_pt = (float)atof(value);
} else if (strcmp(key, "whisper_thold_ptsum") == 0) {
cfg->whisper_thold_ptsum = (float)atof(value);
} else if (strcmp(key, "whisper_max_len") == 0) {
cfg->whisper_max_len = atoi(value);
} else if (strcmp(key, "whisper_split_on_word") == 0) {
cfg->whisper_split_on_word = atoi(value);
} else if (strcmp(key, "whisper_max_tokens") == 0) {
cfg->whisper_max_tokens = atoi(value);
} else if (strcmp(key, "whisper_audio_ctx") == 0) {
cfg->whisper_audio_ctx = atoi(value);
} else if (strcmp(key, "whisper_tdrz_enable") == 0) {
cfg->whisper_tdrz_enable = atoi(value);
} else if (strcmp(key, "whisper_suppress_blank") == 0) {
cfg->whisper_suppress_blank = atoi(value);
} else if (strcmp(key, "whisper_suppress_nst") == 0) {
cfg->whisper_suppress_nst = atoi(value);
} else if (strcmp(key, "whisper_temperature") == 0) {
cfg->whisper_temperature = (float)atof(value);
} else if (strcmp(key, "whisper_max_initial_ts") == 0) {
cfg->whisper_max_initial_ts = (float)atof(value);
} else if (strcmp(key, "whisper_length_penalty") == 0) {
cfg->whisper_length_penalty = (float)atof(value);
} else if (strcmp(key, "whisper_temperature_inc") == 0) {
cfg->whisper_temperature_inc = (float)atof(value);
} else if (strcmp(key, "whisper_entropy_thold") == 0) {
cfg->whisper_entropy_thold = (float)atof(value);
} else if (strcmp(key, "whisper_logprob_thold") == 0) {
cfg->whisper_logprob_thold = (float)atof(value);
} else if (strcmp(key, "whisper_no_speech_thold") == 0) {
cfg->whisper_no_speech_thold = (float)atof(value);
} else if (strcmp(key, "whisper_greedy_best_of") == 0) {
cfg->whisper_greedy_best_of = atoi(value);
} else if (strcmp(key, "whisper_beam_size") == 0) {
cfg->whisper_beam_size = atoi(value);
} else if (strcmp(key, "whisper_beam_patience") == 0) {
cfg->whisper_beam_patience = (float)atof(value);
}
}
fclose(f);
return 0;
}
int config_save_file(const char *path, const voice_config_t *cfg) {
if (!path || !cfg) return -1;
FILE *f = fopen(path, "w");
if (!f) return -2;
fprintf(f, "# voice_linux runtime configuration\n");
fprintf(f, "# Hotkey format supports Ctrl, Alt, Shift, Super + final key symbol\n");
fprintf(f, "# Example: Ctrl+Alt+V\n\n");
fprintf(f, "model_path=%s\n", cfg->model_path);
fprintf(f, "use_gpu=%d\n", cfg->use_gpu ? 1 : 0);
fprintf(f, "audio_device=%s\n", cfg->audio_device);
fprintf(f, "sample_rate=%d\n", cfg->sample_rate);
fprintf(f, "language=%s\n", cfg->language);
fprintf(f, "hotkey=%s\n", cfg->hotkey);
fprintf(f, "type_delay_us=%d\n", cfg->type_delay_us);
fprintf(f, "max_record_seconds=%d\n", cfg->max_record_seconds);
fprintf(f, "# always-on VAD controls\n");
fprintf(f, "always_on=%d\n", cfg->always_on ? 1 : 0);
fprintf(f, "# legacy window size (unused by new VAD pipeline, kept for compatibility)\n");
fprintf(f, "always_on_window_ms=%d\n\n", cfg->always_on_window_ms);
fprintf(f, "# live level threshold (0.0 - 1.0)\n");
fprintf(f, "vad_peak_threshold=%.4f\n", cfg->vad_peak_threshold);
fprintf(f, "# level must stay above threshold this long before speech starts\n");
fprintf(f, "vad_trigger_ms=%d\n", cfg->vad_trigger_ms);
fprintf(f, "# level must stay below threshold this long before speech ends\n");
fprintf(f, "vad_release_ms=%d\n", cfg->vad_release_ms);
fprintf(f, "# include this much pre-trigger audio in transcript segment\n");
fprintf(f, "vad_preroll_ms=%d\n", cfg->vad_preroll_ms);
fprintf(f, "# discard segments shorter than this\n");
fprintf(f, "vad_min_speech_ms=%d\n", cfg->vad_min_speech_ms);
fprintf(f, "# hard cap for one speech segment\n");
fprintf(f, "vad_max_speech_ms=%d\n\n", cfg->vad_max_speech_ms);
fprintf(f, "autotype_enabled=%d\n", cfg->autotype_enabled ? 1 : 0);
fprintf(f, "filter_bracketed_tags=%d\n\n", cfg->filter_bracketed_tags ? 1 : 0);
fprintf(f, "# whisper decode controls\n");
fprintf(f, "whisper_sampling_strategy=%d\n", cfg->whisper_sampling_strategy);
fprintf(f, "whisper_n_max_text_ctx=%d\n", cfg->whisper_n_max_text_ctx);
fprintf(f, "whisper_offset_ms=%d\n", cfg->whisper_offset_ms);
fprintf(f, "whisper_duration_ms=%d\n", cfg->whisper_duration_ms);
fprintf(f, "whisper_translate=%d\n", cfg->whisper_translate ? 1 : 0);
fprintf(f, "whisper_detect_language=%d\n", cfg->whisper_detect_language ? 1 : 0);
fprintf(f, "whisper_no_context=%d\n", cfg->whisper_no_context ? 1 : 0);
fprintf(f, "whisper_no_timestamps=%d\n", cfg->whisper_no_timestamps ? 1 : 0);
fprintf(f, "whisper_single_segment=%d\n", cfg->whisper_single_segment ? 1 : 0);
fprintf(f, "whisper_token_timestamps=%d\n", cfg->whisper_token_timestamps ? 1 : 0);
fprintf(f, "whisper_thold_pt=%.4f\n", cfg->whisper_thold_pt);
fprintf(f, "whisper_thold_ptsum=%.4f\n", cfg->whisper_thold_ptsum);
fprintf(f, "whisper_max_len=%d\n", cfg->whisper_max_len);
fprintf(f, "whisper_split_on_word=%d\n", cfg->whisper_split_on_word ? 1 : 0);
fprintf(f, "whisper_max_tokens=%d\n", cfg->whisper_max_tokens);
fprintf(f, "whisper_audio_ctx=%d\n", cfg->whisper_audio_ctx);
fprintf(f, "whisper_tdrz_enable=%d\n", cfg->whisper_tdrz_enable ? 1 : 0);
fprintf(f, "whisper_suppress_blank=%d\n", cfg->whisper_suppress_blank ? 1 : 0);
fprintf(f, "whisper_suppress_nst=%d\n", cfg->whisper_suppress_nst ? 1 : 0);
fprintf(f, "whisper_temperature=%.4f\n", cfg->whisper_temperature);
fprintf(f, "whisper_max_initial_ts=%.4f\n", cfg->whisper_max_initial_ts);
fprintf(f, "whisper_length_penalty=%.4f\n", cfg->whisper_length_penalty);
fprintf(f, "whisper_temperature_inc=%.4f\n", cfg->whisper_temperature_inc);
fprintf(f, "whisper_entropy_thold=%.4f\n", cfg->whisper_entropy_thold);
fprintf(f, "whisper_logprob_thold=%.4f\n", cfg->whisper_logprob_thold);
fprintf(f, "whisper_no_speech_thold=%.4f\n", cfg->whisper_no_speech_thold);
fprintf(f, "whisper_greedy_best_of=%d\n", cfg->whisper_greedy_best_of);
fprintf(f, "whisper_beam_size=%d\n", cfg->whisper_beam_size);
fprintf(f, "whisper_beam_patience=%.4f\n", cfg->whisper_beam_patience);
fclose(f);
return 0;
}