## States

| State | Meaning |
| --- | --- |
| `kInitializing` | Connecting to the server — do not send audio yet. |
| `kReady` | Connected and ready — safe to call `ProcessSamples`. |
| `kFailed` | Connection or processing error. Destroy and recreate the processor. |
| `kDisconnected` | Was connected; the connection dropped. Destroy and recreate if needed. |
| `kUnknown` | Initial state before connection begins. |

## Option A — State callback (recommended)

Pass a `ProcessorStateCallback` when creating the processor. It fires on a background thread — keep it fast and thread-safe.

```
std::atomic<bool> ready{false}, failed{false};

auto onState = [&](ProcessorState s, std::string reason) {
    if (s == ProcessorState::kReady)          ready  = true;
    else if (s == ProcessorState::kFailed ||
             s == ProcessorState::kDisconnected) failed = true;
};

auto p = sdk->CreateAudioProcessor(params, rc, onState);
while (!ready && !failed)
    std::this_thread::sleep_for(std::chrono::milliseconds(50));
```

## Option B — Polling

Useful if you prefer not to use callbacks.

```cpp
// Instant check
if (processor->GetState() == ProcessorState::kReady) { /* ... */ }

// Drain all queued state changes (non-blocking)
ProcessorStateChange change;
while (processor->GetNextStateChange(change))
    handle(change.state, change.reason);

// Block until the next change (use a dedicated monitor thread)
if (processor->WaitForStateChange(change, /*timeoutMs=*/5000)) { /* ... */ }
```

Do not call `WaitForStateChange` from your audio thread. Use a dedicated monitor thread or the callback approach instead.
