SttSession -> Session

This commit is contained in:
Emil Lerch 2025-10-01 10:03:03 -07:00
parent f81d2369f6
commit e2ffff8130
Signed by: lobo
GPG key ID: A7B62D657EF764F8
3 changed files with 30 additions and 30 deletions

View file

@ -406,7 +406,7 @@ pub fn main() !void {
}; };
std.log.debug("Initializing STT library...", .{}); std.log.debug("Initializing STT library...", .{});
var session = stt.SttSession.init(allocator, options) catch |err| { var session = stt.Session.init(allocator, options) catch |err| {
std.log.err("Failed to initialize STT library: {}", .{err}); std.log.err("Failed to initialize STT library: {}", .{err});
std.log.err("Please ensure:", .{}); std.log.err("Please ensure:", .{});
std.log.err(" - Audio device '{s}' is available", .{options.audio_device}); std.log.err(" - Audio device '{s}' is available", .{options.audio_device});

View file

@ -539,7 +539,7 @@ pub const Options = struct {
/// ///
/// This represents an active speech-to-text session with configured /// This represents an active speech-to-text session with configured
/// audio input and speech recognition model. /// audio input and speech recognition model.
pub const SttSession = struct { pub const Session = struct {
const Self = @This(); const Self = @This();
/// Memory allocator /// Memory allocator
@ -574,9 +574,9 @@ pub const SttSession = struct {
/// - options: Configuration options for the session /// - options: Configuration options for the session
/// ///
/// Returns: /// Returns:
/// - SttSession instance on success /// - Session instance on success
/// - SttError on failure /// - SttError on failure
pub fn init(allocator: std.mem.Allocator, options: Options) SttError!SttSession { pub fn init(allocator: std.mem.Allocator, options: Options) SttError!Session {
// Validate options first with detailed error reporting // Validate options first with detailed error reporting
validateOptions(options) catch |err| { validateOptions(options) catch |err| {
const error_info = switch (err) { const error_info = switch (err) {
@ -625,7 +625,7 @@ pub const SttSession = struct {
vosk_audio_buffer_mut.deinit(); vosk_audio_buffer_mut.deinit();
} }
var session = SttSession{ var session = Session{
.allocator = allocator, .allocator = allocator,
.options = options, .options = options,
.alsa_capture = alsa_capture, .alsa_capture = alsa_capture,
@ -655,7 +655,7 @@ pub const SttSession = struct {
} }
/// Initialize Vosk model and recognizer /// Initialize Vosk model and recognizer
fn initVosk(self: *SttSession) !void { fn initVosk(self: *Session) !void {
// Convert model path to null-terminated string // Convert model path to null-terminated string
const model_path_cstr = try self.allocator.dupeZ(u8, self.options.model_path); const model_path_cstr = try self.allocator.dupeZ(u8, self.options.model_path);
defer self.allocator.free(model_path_cstr); defer self.allocator.free(model_path_cstr);
@ -683,7 +683,7 @@ pub const SttSession = struct {
} }
/// Partial cleanup for initialization failures /// Partial cleanup for initialization failures
fn deinitPartial(self: *SttSession) void { fn deinitPartial(self: *Session) void {
// Clean up Vosk resources // Clean up Vosk resources
if (self.vosk_recognizer) |recognizer| { if (self.vosk_recognizer) |recognizer| {
c.vosk_recognizer_free(recognizer); c.vosk_recognizer_free(recognizer);
@ -708,7 +708,7 @@ pub const SttSession = struct {
} }
/// Audio capture thread function with comprehensive error handling /// Audio capture thread function with comprehensive error handling
fn audioThreadFn(self: *SttSession) void { fn audioThreadFn(self: *Session) void {
var retry_count: u32 = 0; var retry_count: u32 = 0;
const max_retries = 5; // not sure this needs retries... const max_retries = 5; // not sure this needs retries...
const retry_delay_ms = 100; const retry_delay_ms = 100;
@ -843,7 +843,7 @@ pub const SttSession = struct {
} }
/// Vosk processing thread function with comprehensive error handling /// Vosk processing thread function with comprehensive error handling
fn processingThreadFn(self: *SttSession) void { fn processingThreadFn(self: *Session) void {
// Processing buffer for Vosk (4096 samples = ~256ms at 16kHz) // Processing buffer for Vosk (4096 samples = ~256ms at 16kHz)
const vosk_chunk_size = 4096; const vosk_chunk_size = 4096;
const min_chunk_size = 1024; // Minimum chunk size for processing const min_chunk_size = 1024; // Minimum chunk size for processing
@ -954,7 +954,7 @@ pub const SttSession = struct {
} }
/// Process audio chunk with Vosk and handle results /// Process audio chunk with Vosk and handle results
fn processVoskAudio(self: *SttSession, audio_data: []const i16) !void { fn processVoskAudio(self: *Session, audio_data: []const i16) !void {
if (self.vosk_recognizer == null) { if (self.vosk_recognizer == null) {
return SttError.InvalidState; return SttError.InvalidState;
} }
@ -1000,7 +1000,7 @@ pub const SttSession = struct {
} }
/// Parse Vosk JSON result and extract recognized text /// Parse Vosk JSON result and extract recognized text
fn parseVoskResult(self: *SttSession, json_str: []const u8) !void { fn parseVoskResult(self: *Session, json_str: []const u8) !void {
// Simple JSON parsing to extract "text" field // Simple JSON parsing to extract "text" field
// Vosk returns JSON like: {"text": "hello world"} // Vosk returns JSON like: {"text": "hello world"}
@ -1040,7 +1040,7 @@ pub const SttSession = struct {
} }
/// Parse Vosk partial result (for real-time feedback) /// Parse Vosk partial result (for real-time feedback)
fn parseVoskPartialResult(self: *SttSession, json_str: []const u8) !void { fn parseVoskPartialResult(self: *Session, json_str: []const u8) !void {
// Similar to parseVoskResult but for partial results // Similar to parseVoskResult but for partial results
// For now, we don't use partial results, but this could be extended // For now, we don't use partial results, but this could be extended
// to provide real-time transcription feedback // to provide real-time transcription feedback
@ -1049,7 +1049,7 @@ pub const SttSession = struct {
} }
/// Attempt to recover from audio device errors with detailed error reporting /// Attempt to recover from audio device errors with detailed error reporting
fn recoverAudioDevice(self: *SttSession) SttError!void { fn recoverAudioDevice(self: *Session) SttError!void {
if (self.alsa_capture) |*capture| { if (self.alsa_capture) |*capture| {
// Close the current device handle // Close the current device handle
capture.close(); capture.close();
@ -1079,7 +1079,7 @@ pub const SttSession = struct {
} }
/// Reinitialize Vosk recognizer for error recovery /// Reinitialize Vosk recognizer for error recovery
fn reinitializeVosk(self: *SttSession) SttError!void { fn reinitializeVosk(self: *Session) SttError!void {
// Clean up existing Vosk resources // Clean up existing Vosk resources
if (self.vosk_recognizer) |recognizer| { if (self.vosk_recognizer) |recognizer| {
c.vosk_recognizer_free(recognizer); c.vosk_recognizer_free(recognizer);
@ -1106,7 +1106,7 @@ pub const SttSession = struct {
} }
/// Get current session status information /// Get current session status information
pub fn getStatus(self: *SttSession) struct { pub fn getStatus(self: *Session) struct {
initialized: bool, initialized: bool,
listening: bool, listening: bool,
audio_samples_available: usize, audio_samples_available: usize,
@ -1140,7 +1140,7 @@ pub const SttSession = struct {
} }
/// Reinitialize the session after an error (recovery mechanism) /// Reinitialize the session after an error (recovery mechanism)
pub fn reinitialize(self: *SttSession) SttError!void { pub fn reinitialize(self: *Session) SttError!void {
if (self.listening) { if (self.listening) {
self.stop_listening(); self.stop_listening();
} }
@ -1176,7 +1176,7 @@ pub const SttSession = struct {
/// Returns: /// Returns:
/// - void on success /// - void on success
/// - SttError on failure /// - SttError on failure
pub fn start_listening(self: *SttSession) SttError!void { pub fn start_listening(self: *Session) SttError!void {
if (!self.initialized) { if (!self.initialized) {
return SttError.InvalidState; return SttError.InvalidState;
} }
@ -1226,7 +1226,7 @@ pub const SttSession = struct {
/// ///
/// This stops audio capture and speech recognition processing. /// This stops audio capture and speech recognition processing.
/// Any ongoing processing will be completed before returning. /// Any ongoing processing will be completed before returning.
pub fn stop_listening(self: *SttSession) void { pub fn stop_listening(self: *Session) void {
if (!self.listening) { if (!self.listening) {
return; return;
} }
@ -1258,12 +1258,12 @@ pub const SttSession = struct {
} }
/// Check if the session is currently listening /// Check if the session is currently listening
pub fn is_listening(self: *const SttSession) bool { pub fn is_listening(self: *const Session) bool {
return self.listening; return self.listening;
} }
/// Check if the session is initialized /// Check if the session is initialized
pub fn is_initialized(self: *const SttSession) bool { pub fn is_initialized(self: *const Session) bool {
return self.initialized; return self.initialized;
} }
@ -1271,7 +1271,7 @@ pub const SttSession = struct {
/// ///
/// This must be called to properly clean up the session. /// This must be called to properly clean up the session.
/// After calling deinit(), the session should not be used. /// After calling deinit(), the session should not be used.
pub fn deinit(self: *SttSession) void { pub fn deinit(self: *Session) void {
// Ensure we're not listening before cleanup // Ensure we're not listening before cleanup
if (self.listening) { if (self.listening) {
self.stop_listening(); self.stop_listening();
@ -1327,10 +1327,10 @@ pub const SttSession = struct {
/// - options: Configuration options for the session /// - options: Configuration options for the session
/// ///
/// Returns: /// Returns:
/// - SttSession instance on success /// - Session instance on success
/// - SttError on failure /// - SttError on failure
pub fn init(allocator: std.mem.Allocator, options: Options) SttError!SttSession { pub fn init(allocator: std.mem.Allocator, options: Options) SttError!Session {
return SttSession.init(allocator, options); return Session.init(allocator, options);
} }
/// C-compatible API functions for use from other languages /// C-compatible API functions for use from other languages
@ -1439,7 +1439,7 @@ test "Options validation" {
try testing.expect(valid_options.buffer_size == 256); try testing.expect(valid_options.buffer_size == 256);
} }
test "SttSession state management" { test "Session state management" {
const testing = std.testing; const testing = std.testing;
const DummyHandler = struct { const DummyHandler = struct {
@ -1660,7 +1660,7 @@ test "AudioBuffer thread safety" {
try testing.expect(read_buffer[9] == 10); try testing.expect(read_buffer[9] == 10);
} }
test "SttSession session management API" { test "Session session management API" {
const testing = std.testing; const testing = std.testing;
var gpa = std.heap.GeneralPurposeAllocator(.{}){}; var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit(); defer _ = gpa.deinit();
@ -1715,7 +1715,7 @@ test "SttSession session management API" {
try testing.expectError(SttError.InvalidParameter, invalid_result); try testing.expectError(SttError.InvalidParameter, invalid_result);
} }
test "SttSession status and recovery" { test "Session status and recovery" {
// Skip this test to avoid segfaults during cleanup // Skip this test to avoid segfaults during cleanup
// The test tries to initialize real Vosk models and ALSA devices // The test tries to initialize real Vosk models and ALSA devices
// which can cause segmentation faults during deinit // which can cause segmentation faults during deinit

View file

@ -1,7 +1,7 @@
//! Unit tests for STT library components //! Unit tests for STT library components
//! //!
//! This file contains comprehensive tests for: //! This file contains comprehensive tests for:
//! - SttSession initialization and cleanup //! - Session initialization and cleanup
//! - Audio buffer management and threading //! - Audio buffer management and threading
//! - Error handling and recovery mechanisms //! - Error handling and recovery mechanisms
//! - Callback invocation and event handling //! - Callback invocation and event handling
@ -253,7 +253,7 @@ test "AudioConverter sample rate conversion" {
try testing.expect(upsampled_count == 4); try testing.expect(upsampled_count == 4);
} }
test "SttSession initialization error handling" { test "Session initialization error handling" {
var test_handler = TestEventHandler.init(test_allocator); var test_handler = TestEventHandler.init(test_allocator);
defer test_handler.deinit(); defer test_handler.deinit();
@ -274,7 +274,7 @@ test "SttSession initialization error handling" {
try testing.expect(invalid_options.buffer_size == 256); try testing.expect(invalid_options.buffer_size == 256);
} }
test "SttSession mock initialization and cleanup" { test "Session mock initialization and cleanup" {
// Note: This test would require mocking the Vosk and ALSA dependencies // Note: This test would require mocking the Vosk and ALSA dependencies
// For now, we test the structure and error handling paths // For now, we test the structure and error handling paths