# AudioMixerRingBuffer Window Size Configuration: Why Meetily Uses a 600ms Mixing Window

> Discover why Meetily uses a 600ms AudioMixerRingBuffer window for glitch-free audio mixing. Learn how it aligns streams and prevents under-runs for clear sound.

- Repository: [Zackriya Solutions/meetily](https://github.com/Zackriya-Solutions/meetily)
- Tags: deep-dive
- Published: 2026-07-26

---

**The `AudioMixerRingBuffer` in Meetily is configured with a fixed 600ms window size to align dual audio streams, prevent buffer under-runs, and ensure glitch-free mixing across microphone and system audio sources.**

The audio pipeline in **Zackriya-Solutions/meetily** relies on a precise **AudioMixerRingBuffer window size** configuration to synchronize independent capture streams. Written in Rust as part of the Tauri-based frontend, the ring buffer implementation found in [`frontend/src-tauri/src/audio/pipeline.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/pipeline.rs) calculates a fixed-duration mixing window that balances latency tolerance with mixing stability according to the sample rate of the audio stream.

## How the 600ms Window is Calculated

Inside [`frontend/src-tauri/src/audio/pipeline.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/pipeline.rs) (lines 27–30), the `AudioMixerRingBuffer` struct initializes its mixing window using a hardcoded millisecond value converted to samples:

```rust
let window_ms = 600.0;
let window_size_samples = (sample_rate as f32 * window_ms / 1000.0) as usize;

```

This calculation ensures the buffer holds exactly 600 milliseconds of audio data regardless of the stream's sample rate. For a standard 48 kHz stream, this results in a window of 28,800 samples, while a 44.1 kHz stream yields 26,460 samples. By deriving the window size dynamically from the sample rate, the implementation maintains consistent temporal behavior across different hardware configurations.

## Why Meetily Uses a 600ms Mixing Window

The 600ms duration was selected after evaluating four critical requirements for dual-source audio mixing in a meeting recording context.

### Alignment of Mic and System Streams

The ring buffer aggregates audio from two asynchronous sources: the **microphone** (`DeviceType::Microphone`) and **system playback** (`DeviceType::System`). Because these streams operate on independent capture pipelines with separate clock domains, they experience variable jitter and drift. A 600ms window provides sufficient temporal breadth for both streams to deliver coherent chunks, allowing the buffer to align their timelines before mixing occurs.

### Stability for the ProfessionalAudioMixer

Once the ring buffer accumulates enough data, the `extract_window()` method yields paired slices for microphone and system audio. These slices feed directly into the `ProfessionalAudioMixer::mix_window()` function. The 600ms chunk size guarantees that the mixer operates on a fully saturated buffer, eliminating the risk of under-run (processing empty buffers) or overflow (data loss due to excessive accumulation). This full-window approach ensures the mixer produces artifact-free output on every invocation.

### Latency vs. Quality Trade-off

While a smaller window—such as 50ms—would reduce end-to-end latency, it significantly increases the probability of buffer starvation. Temporary stalls in system audio capture, common on slower hardware or under heavy system load, would cause the mixer to process incomplete windows, resulting in audible clicks or dropouts. The 600ms **AudioMixerRingBuffer window size** represents a deliberate compromise: it remains responsive enough for real-time meeting recording while providing a robust buffer against transient capture delays.

### Safety Margin for Buffer Overflow

The implementation enforces a maximum capacity of eight windows to prevent unbounded memory growth. This safety limit works in conjunction with the 600ms window to ensure the ring buffer never exceeds its allocated capacity, even when one stream temporarily outpaces the other. By capping the buffer at eight windows, Meetily protects against runaway memory usage during extended recording sessions.

## Implementation Example

The following Rust snippet demonstrates the complete workflow: initializing the ring buffer, adding samples from both devices, extracting the 600ms window, and mixing:

```rust
use crate::audio::pipeline::{AudioMixerRingBuffer, ProfessionalAudioMixer};
use crate::audio::recording_state::DeviceType;

// Initialize the ring buffer for a 48kHz stream
let mut ring = AudioMixerRingBuffer::new(48_000);

// Add microphone samples captured from the hardware
ring.add_samples(DeviceType::Microphone, mic_samples);

// Add system audio samples from the playback loopback
ring.add_samples(DeviceType::System, sys_samples);

// Once ≥600ms of data is available, extract the aligned windows
if let Some((mic_win, sys_win)) = ring.extract_window() {
    let mut mixer = ProfessionalAudioMixer::new(48_000);
    
    // Mix the two 600ms windows into a single output chunk
    let mixed = mixer.mix_window(&mic_win, &sys_win);
    
    // `mixed` contains a 600ms audio chunk ready for encoding or transcription
}

```

This pattern appears throughout the audio pipeline in [`frontend/src-tauri/src/audio/pipeline.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/pipeline.rs), where the `ProfessionalAudioMixer` (defined around lines 45–90) consumes the extracted windows to produce the final mixed output.

## Summary

- **Dynamic calculation**: The `AudioMixerRingBuffer` computes its capacity as `(sample_rate * 600.0 / 1000.0)` samples, translating the fixed 600ms window into platform-independent sample counts.
- **Dual-stream alignment**: The 600ms duration accommodates clock drift between microphone and system audio capture paths.
- **Mixer stability**: `ProfessionalAudioMixer` requires full 600ms windows to avoid processing glitches and under-runs.
- **Latency balance**: 600ms provides responsiveness for meeting recording while preventing starvation on slower hardware.
- **Overflow protection**: An eight-window maximum capacity guards against memory exhaustion during extended captures.

## Frequently Asked Questions

### What file contains the AudioMixerRingBuffer window size calculation?

The calculation appears in [`frontend/src-tauri/src/audio/pipeline.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/pipeline.rs) at lines 27–30, where the `window_ms` constant is defined as `600.0` and converted to samples based on the stream's sample rate.

### How does the 600ms window prevent audio glitches?

By requiring a full 600ms of data from both the microphone and system streams before mixing, the `ProfessionalAudioMixer` avoids processing partial buffers. This eliminates under-run artifacts (silent gaps) and ensures synchronized mixing that accounts for jitter between the two independent capture sources.

### Can the AudioMixerRingBuffer window size be adjusted?

The current implementation in Meetily hardcodes the window at 600ms. While the `new()` function accepts a sample rate to scale the buffer capacity, the `window_ms` variable is fixed at 600.0 in the source. Modifying this value would require changing the constant in [`pipeline.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/pipeline.rs) and recompiling the Tauri application.

### Where is the ProfessionalAudioMixer struct defined?

The `ProfessionalAudioMixer` struct and its `mix_window()` method are defined in the same file, [`frontend/src-tauri/src/audio/pipeline.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/pipeline.rs), approximately between lines 45 and 90, according to the source code analysis.