sapi_lite/
lib.rs

1#![warn(missing_docs)]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3
4//! A simplified wrapper around Microsoft's Speech API (SAPI) library.
5//!
6//! # Features
7//!
8//! The goal of this crate is to expose a subset of SAPI features in a way that is easy to use in
9//! Rust. It does not aim to provide the full set of features SAPI offers. Since the focus is on
10//! relative ease of use (compared to dealing with COM directly) and simplicity of API, many
11//! SAPI features are missing in this crate.
12//!
13//! ## Text-to-speech
14//!
15//! The [tts] module provides the API to render text as a speech using one or more SAPI voices
16//! installed on the system.
17//!
18//! To generate speech, you first need to create an instance of one of the
19//! available synthesizer types. Which synthesizer you choose will depend on whether you want to
20//! block the execution while the speech is synthesized or not.
21//!
22//! You can configure the synthesizer to output to the default audio device, to a file, or to a
23//! memory buffer. You can control the synthesizer's default speaking voice, rate of speech, and
24//! volume.
25//!
26//! The speech you synthesize can be a simple string, or it can be a series of instructions
27//! controlling various aspects of the speech synthesis, such as voice, rate, volume, pitch, or
28//! pronunciation.
29//!
30//! You can enumerate the installed voices and filter them by one or more of their characteristics
31//! (e.g. age or gender).
32//!
33//! ## Speech recognition
34//!
35//! The [stt] module provides the API to recognize speech, convert it to text, and annotate it with
36//! semantic tags.
37//!
38//! The first thing you need is an instance of the recognition engine. Once created, you can
39//! configure it to listen to the default recording device, to read a file, or to read from a
40//! memory buffer. You can stop and resume recognition by disabling and enabling the recognizer.
41//!
42//! To configure which spoken phrases the engine can recognize, you need to define one or more
43//! grammars. A grammar is a set of rules that define what word structures form recognizable
44//! phrases.
45//!
46//! A grammar must be loaded into a recognition context before the engine can recognize the phrases
47//! in it. Which context type you choose will depend on whether you want to block the execution
48//! while waiting for a phrase to be recognized or not.
49//!
50//! # COM and Lifetime of SAPI Types
51//!
52//! Microsoft SAPI is a COM library. All COM objects and interfaces use reference counting to
53//! control their lifetime. Many types in this crate wrap these COM objects. As such, when you drop
54//! an instance of one of these types, it doesn't mean that the underlying COM object will be
55//! destroyed.
56//!
57//! For example, if you have a [`Recognizer`](stt::Recognizer), a [`SyncContext`](stt::SyncContext),
58//! and a [`Grammar`](stt::Grammar), dropping the `Recognizer` while the `SyncContext` or the
59//! `Grammar` are still alive will *not* destroy the underlying recognition engine with its
60//! associated contexts and rules.
61//!
62//! This crate does not currently represent these COM references using Rust lifetimes. This was a
63//! deliberate design decision to keep the API and the code as simple as possible.
64
65use std::ptr::null;
66
67use windows::Win32::System::Com::{CoInitialize, CoUninitialize};
68
69pub mod audio;
70mod com_util;
71mod event;
72pub mod stt;
73mod token;
74pub mod tts;
75
76#[cfg(feature = "tokio")]
77pub mod tokio;
78
79/// The error type returned by SAPI functions and methods.
80pub type Error = windows::core::Error;
81
82/// The type returned by SAPI functions and methods.
83pub type Result<T> = windows::core::Result<T>;
84
85/// Initializes SAPI on the current thread. This function must be called for every thread that
86/// intends to use SAPI.
87pub fn initialize() -> Result<()> {
88    unsafe { CoInitialize(null()) }
89}
90
91/// Deinitializes SAPI for the current thread. This function must be called for every thread that
92/// called `initialize()`, the same number of times.
93pub fn finalize() {
94    unsafe { CoUninitialize() }
95}