> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sammylabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Audio Stutter Prevention

> Understanding and preventing audio stuttering in SAMMY Three by managing main thread blocking

# Audio Stutter Prevention

> Learn how SAMMY Three's multi-layered buffering system protects against audio stuttering and how to avoid main thread blocking in your application

SAMMY Three uses a sophisticated audio buffering system to maintain smooth playback even when your application's main thread gets temporarily busy. However, extended main thread blocking can still cause audio stuttering. This guide explains how the system works and how to prevent audio issues.

## How the buffering system works

SAMMY Three implements a **three-layer buffering system** to protect against audio stuttering:

### Layer 1: JavaScript Audio Queue

The initial buffer that holds raw audio data waiting to be scheduled.

* **Buffer Size**: 7,680 samples per buffer
* **Duration**: 320ms per buffer at 24kHz sample rate
* **Queue Depth**: Typically holds 640ms to 1.6 seconds of audio

### Layer 2: Web Audio API Pre-scheduled Buffers

Audio buffers that are pre-scheduled in the Web Audio API's internal queue.

* **Schedule Window**: Maintains **400ms** of audio scheduled ahead of current playback
* **Key Benefit**: These buffers play automatically, even if JavaScript is blocked

### Layer 3: Initial Buffering Delay

A startup delay that ensures the system begins with adequate buffering.

* **Delay**: 300ms before first audio plays
* **Purpose**: Builds up initial buffer cushion

<Info>
  The Web Audio API continues playing pre-scheduled buffers independently of JavaScript execution, which is why brief main thread blocks don't cause stuttering.
</Info>

## The 400ms critical threshold

The most important number to remember is **400ms** - this is how far ahead the audio streamer schedules buffers.

```typescript theme={null}
const SCHEDULE_AHEAD_TIME = 0.4; // 400ms look-ahead window
```

### What happens during main thread blocking:

<Tabs>
  <Tab title="Safe (< 400ms)">
    **Scenario**: 200ms main thread block

    * ✅ Pre-scheduled buffers continue playing
    * ✅ No audible gaps or stuttering
    * ✅ System recovers seamlessly when thread unblocks

    ```
    Time 0ms:     Main thread blocks
    Time 0-200ms: Audio plays normally from buffer
    Time 200ms:   Main thread unblocks, scheduler resumes
    Result:       No user impact
    ```
  </Tab>

  <Tab title="Risky (≈ 400ms)">
    **Scenario**: 350-400ms main thread block

    * ⚠️ Buffer nearly depleted
    * ⚠️ Might experience brief glitches
    * 🔄 Recovery depends on timing

    ```
    Time 0ms:     Main thread blocks
    Time 0-350ms: Audio plays from buffer
    Time 350ms:   Buffer running low
    Time 351ms:   Thread unblocks just in time
    Result:       Possible brief glitch
    ```
  </Tab>

  <Tab title="Stuttering (> 400ms)">
    **Scenario**: 500ms main thread block

    * ❌ Buffer fully depleted at 400ms
    * ❌ 100ms of silence/stuttering
    * 🔄 Audio resumes after unblock

    ```
    Time 0ms:     Main thread blocks
    Time 0-400ms: Pre-scheduled buffers play
    Time 400ms:   Buffer exhausted
    Time 401-500ms: SILENCE (stuttering)
    Time 500ms:   Audio resumes
    Result:       Audible gap in playback
    ```
  </Tab>
</Tabs>

## Common causes of main thread blocking

Understanding what can block your main thread helps prevent audio issues:

### Safe operations (typically \< 100ms)

* DOM updates and style recalculations
* Moderate API calls with async/await
* Standard React re-renders
* Small array operations

### Risky operations (100-400ms)

<Warning>
  These operations are on the edge of causing stuttering. Consider optimizing or moving to web workers.
</Warning>

* Large DOM manipulations
* Complex calculations without chunking
* Processing moderate-sized images
* Multiple synchronous API calls
* Large state updates in React

### Dangerous operations (> 400ms)

<Danger>
  These will definitely cause audio stuttering. Always use web workers or async patterns for these operations.
</Danger>

* Synchronous file I/O operations
* Processing large datasets synchronously
* Complex image/video processing
* Blocking network requests
* Heavy cryptographic operations

## Best practices to prevent stuttering

### 1. Use Web Workers for heavy computation

Move CPU-intensive tasks off the main thread:

```javascript theme={null}
// ❌ Bad: Blocks main thread
function processLargeDataset(data) {
  const results = [];
  for (let i = 0; i < 1000000; i++) {
    results.push(complexCalculation(data[i]));
  }
  return results;
}

// ✅ Good: Runs in Web Worker
const worker = new Worker('processor.worker.js');
worker.postMessage({ data });
worker.onmessage = (e) => {
  const results = e.data;
  // Handle results without blocking
};
```

### 2. Chunk large operations

Break up large synchronous operations into smaller chunks:

```javascript theme={null}
// ❌ Bad: Processes everything at once
function processAllItems(items) {
  items.forEach(item => {
    expensiveOperation(item);
  });
}

// ✅ Good: Processes in chunks with breaks
async function processItemsChunked(items, chunkSize = 100) {
  for (let i = 0; i < items.length; i += chunkSize) {
    const chunk = items.slice(i, i + chunkSize);
    chunk.forEach(item => expensiveOperation(item));
    
    // Give the main thread a break
    await new Promise(resolve => setTimeout(resolve, 0));
  }
}
```

### 3. Use requestIdleCallback for non-critical work

Schedule non-critical work for when the browser is idle:

```javascript theme={null}
// ✅ Good: Runs when browser is idle
requestIdleCallback(() => {
  performNonCriticalWork();
}, { timeout: 200 }); // Fallback timeout
```

### 4. Optimize React renders

Prevent unnecessary re-renders that can block the thread:

```javascript theme={null}
// ✅ Use React.memo for expensive components
const ExpensiveComponent = React.memo(({ data }) => {
  // Component only re-renders when data changes
  return <ComplexVisualization data={data} />;
});

// ✅ Use useMemo for expensive calculations
const processedData = useMemo(() => {
  return expensiveDataProcessing(rawData);
}, [rawData]);
```

### 5. Monitor performance

Use the Performance API to identify blocking operations:

```javascript theme={null}
// Measure operation duration
performance.mark('operation-start');
performOperation();
performance.mark('operation-end');

performance.measure('operation', 'operation-start', 'operation-end');
const measure = performance.getEntriesByName('operation')[0];

if (measure.duration > 400) {
  console.warn('Operation took', measure.duration, 'ms - risk of audio stuttering!');
}
```

<Tip>
  Use Chrome DevTools Performance tab to profile your application and identify long tasks that might cause audio stuttering.
</Tip>

## Audio recording considerations

The audio recording system processes buffers approximately every **43ms** (2048 samples at 48kHz). While this is much shorter than the playback buffer, blocking the main thread can still affect recording quality by preventing timely processing of audio worklet messages.

<Note>
  Recording is generally more sensitive to main thread blocking than playback, but the 400ms playback buffer is the more critical threshold for user-noticeable stuttering.
</Note>

## Summary

To prevent audio stuttering in SAMMY Three:

1. **Remember the 400ms rule**: Keep main thread operations under 400ms
2. **Use Web Workers**: Move heavy computation off the main thread
3. **Chunk large operations**: Break up synchronous work
4. **Monitor performance**: Profile your app to identify blocking operations
5. **Optimize rendering**: Minimize unnecessary React re-renders

By following these guidelines, you can ensure smooth, uninterrupted audio playback in your SAMMY Three application, even when performing complex operations.

## Related resources

* [Audio Processing](/features/audio-processing)
* [Voice Activity Detection](/features/vad)
* [Performance Optimization](/guides/performance)
