pub struct MicrophoneStream { /* private fields */ }Expand description
An open capture stream you pull AudioChunks from.
Obtained from Microphone::start. Read audio with
next_chunk (blocking, with a timeout) or
try_next_chunk (non-blocking). Call
stop to end capture and release the device; dropping the
handle also releases it. The type is Send + Sync.
Implementations§
Source§impl MicrophoneStream
impl MicrophoneStream
Sourcepub fn receiver(&self) -> &Receiver<AudioChunk>
pub fn receiver(&self) -> &Receiver<AudioChunk>
Direct access to the underlying crossbeam_channel::Receiver.
Intended for in-process Rust consumers and for bindings (like the decibri Node.js addon) that integrate the channel into their own drain pump or event loop.
FFI bindings targeting languages without native crossbeam_channel
support, such as Python and the eventual mobile platforms, should
prefer try_next_chunk and
next_chunk: they expose the same data with a
three-state return (Some / None / Err(MicrophoneStreamClosed))
that maps cleanly across a language boundary.
Sourcepub fn try_next_chunk(
&self,
samples: usize,
) -> Result<Option<AudioChunk>, DecibriError>
pub fn try_next_chunk( &self, samples: usize, ) -> Result<Option<AudioChunk>, DecibriError>
Attempt to read exactly samples interleaved samples without blocking.
samples is the requested block size in interleaved f32 samples
(frames times channels). The device’s native capture buffers are
re-blocked on the consumer side, so every returned chunk holds exactly
samples samples. samples should be non-zero and, for frame
alignment, a multiple of the channel count.
§Returns
Ok(Some(chunk)): a full block of exactlysamplessamples was available and has been dequeued.Ok(None): the stream is open and running, but fewer thansamplessamples are buffered. Try again shortly, or callnext_chunkto block until a full block arrives.Err(DecibriError::MicrophoneStreamClosed): the stream is closed (either by explicitstopor by an audio-driver error reported via the cpal error callback) and the buffer is now empty (any final tail was already delivered as a short chunk). No further chunks will ever be available.
Buffered samples that form one or more full blocks are delivered first.
Once the stream closes with fewer than samples remaining, the final
partial block (1..samples samples) is delivered as one short chunk, and
the closed signal is returned on the next call once the buffer is empty.
No captured sample is dropped: every chunk is exactly samples long
except the final chunk at close, which carries the remaining tail.
§Thread safety
May be called from any thread. Takes the re-block buffer mutex, so
concurrent callers serialize on it; a non-blocking
crossbeam_channel::try_recv drains the native buffers into it.
§Stability
Part of decibri’s stable FFI-consumer API surface, alongside
next_chunk.
Sourcepub fn next_chunk(
&self,
samples: usize,
timeout: Option<Duration>,
) -> Result<Option<AudioChunk>, DecibriError>
pub fn next_chunk( &self, samples: usize, timeout: Option<Duration>, ) -> Result<Option<AudioChunk>, DecibriError>
Read exactly samples interleaved samples, blocking the calling thread
until a full block arrives, the stream closes, or timeout elapses.
samples is the requested block size in interleaved f32 samples
(frames times channels). The device’s native capture buffers are
re-blocked on the consumer side, so a returned chunk holds exactly
samples samples. samples should be non-zero and, for frame
alignment, a multiple of the channel count.
§Arguments
timeout = None: block indefinitely until a full block arrives or the stream closes.timeout = Some(dur): block at mostdur; returnOk(None)if the deadline passes before a full block accumulates. The partial block is retained for the next call.
§Returns
Ok(Some(chunk)): a full block of exactlysamplessamples was received within the deadline.Ok(None):timeoutelapsed before a full block accumulated. The stream is still open and the partial stays buffered.Err(DecibriError::MicrophoneStreamClosed): the stream closed and the buffer is now empty. Any full blocks buffered at the time of close are delivered first, then the final partial block (1..samplessamples) as one short chunk; this error is only returned once the buffer is empty. No captured sample is dropped.
§Thread safety
May be called from any thread. Blocks only the calling thread; other
threads can call stop concurrently to unblock this call
within approximately 20 ms. Holds the re-block buffer mutex for the
duration of the call, so concurrent reads serialize.
Implementation note: this method polls both the channel and
is_open at a short interval. An explicit
stop disconnects the channel (it drops the cpal Stream,
and with it the sender), which wakes a blocked wait promptly; the poll
additionally covers a driver-error stop, which flips
is_open without dropping the stream.
§Stability
Part of decibri’s stable FFI-consumer API surface.
Sourcepub fn sample_rate(&self) -> u32
pub fn sample_rate(&self) -> u32
The sample rate (Hz) this stream was opened with.
Sourcepub fn vad_input(&self, samples: usize) -> Option<Vec<f32>>
pub fn vad_input(&self, samples: usize) -> Option<Vec<f32>>
The pre-transform (post-normalize) samples for the VAD feed, drained as
next_chunk delivers blocks.
Binding-internal plumbing: a binding that runs voice-activity detection
calls this right after a next_chunk / try_next_chunk delivery, passing
the delivered chunk’s length, and feeds the returned samples to the
detector instead of the delivered chunk. This makes the detector read the
signal BEFORE the opt-in enhancement step, so enabling enhancement does not
change detection. Not part of the stable FFI-consumer surface.
§Returns
Some(v): the chain has an enhancement step, so the delivered output is the post-enhancement signal;vholds up tosamplespost-normalize samples from the front of the tap, the pre-enhancement signal a detector should read. With only a length-preserving transform (DC removal) those are the exact pre-transform twin of the just-delivered block. With a length-changing, latency-introducing transform (denoise), the tap is the real-time pre-enhancement signal and LEADS the delivered enhanced block by the chain’s latency, sovis a bounded amount ahead rather than sample- aligned. That lead is intended (the detector reads audio sooner, never later) and invisible to consumers, which keep only a rolling probability and never pair a score to specific returned samples.None: the chain has no enhancement step, so the delivered chunk already is the post-normalize signal; feed the detector the delivered chunk exactly as before, with no allocation or copy.
§Thread safety
Takes only the tap mutex (never the reblock or chain locks), so it composes
with a concurrent next_chunk. The lead stays bounded
as long as the same consumer calls this once per delivered block, as the
binding pump does.
Sourcepub fn take_last_error(&self) -> Option<DecibriError>
pub fn take_last_error(&self) -> Option<DecibriError>
Take the last device/driver error reported while streaming, if any.
When the cpal error callback fires (device unplug, driver failure) it
records a typed DecibriError::DeviceFailed and closes the stream.
Reading it here drains it (returns None afterwards), letting a
consumer that observes a closed stream tell a driver failure apart from
an explicit stop.
Sourcepub fn overrun_count(&self) -> u64
pub fn overrun_count(&self) -> u64
Total number of capture buffers dropped because the channel was full (a consumer that could not keep up). Stays 0 while the consumer keeps pace; a rising count means audio is being dropped to bound memory.
Sourcepub fn stop(&self)
pub fn stop(&self)
Stop capturing audio and release the device.
Flips the running flag, then drops the held stream, so the OS releases
the input device (and the mic-in-use indicator clears) at once rather
than only when this handle is dropped. Dropping the stream also
disconnects the capture channel; chunks already buffered remain readable
via try_next_chunk or
next_chunk until the buffer is drained, after which
those methods return Err(MicrophoneStreamClosed).
May be called from any thread; wakes a concurrent
next_chunk waiter promptly (the channel disconnect
unblocks it). Releasing the device blocks briefly while the audio thread
tears down.