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

# Audio System

> Overview of the LIV Camera Kit (LCK) modular audio capture system for Unreal Engine, including ILCKAudioSource interface, audio channel types, source discovery via modular features, and supported plugins (UnrealAudio, Oboe, Vivox, FMOD, Wwise).

<Info>
  **Module:** LCKAudio | **Version:** 1.0 | **Platforms:** All
</Info>

## Overview

The LCK SDK features a modular audio capture system that supports multiple audio sources including game audio, microphone input, and voice chat. Audio sources implement a common interface and register via Unreal's modular features system for automatic discovery.

## Audio Source Plugins

<CardGroup cols={2}>
  <Card title="LCKUnrealAudio" icon="gamepad" href="/unreal/audio/unreal-audio">
    Unreal Engine native audio capture for game audio and microphone
  </Card>

  <Card title="LCKOboe" icon="android" href="/unreal/audio/oboe-android">
    High-performance Android microphone capture via Google Oboe
  </Card>

  <Card title="LCKVivox" icon="headset" href="/unreal/audio/vivox">
    Vivox voice chat audio capture for multiplayer games
  </Card>

  <Card title="LCKFMOD" icon="music" href="/unreal/audio/fmod">
    FMOD Studio game audio integration
  </Card>

  <Card title="LCKWwise" icon="wave-square" href="/unreal/audio/wwise">
    Audiokinetic Wwise game audio integration
  </Card>
</CardGroup>

## Architecture

```
┌─────────────────────────────────────────────────────────────┐
│                    LCK Recording System                      │
├─────────────────────────────────────────────────────────────┤
│                     FLCKAudioMix                            │
│                    (Audio Mixer)                             │
├─────────────────────────────────────────────────────────────┤
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐      │
│  │ ILCKAudio    │  │ ILCKAudio    │  │ ILCKAudio    │      │
│  │   Source     │  │   Source     │  │   Source     │      │
│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘      │
│         │                 │                 │               │
└─────────┼─────────────────┼─────────────────┼───────────────┘
          │                 │                 │
┌─────────▼─────┐  ┌───────▼───────┐  ┌─────▼────────┐
│  LCKUnreal    │  │   LCKFMOD     │  │   LCKVivox   │
│    Audio      │  │   Source      │  │    Source     │
└───────────────┘  └───────────────┘  └──────────────┘
```

## Plugin Capabilities

| Source             | Game | Microphone | VoiceChat | Module         | Platform       |
| ------------------ | ---- | ---------- | --------- | -------------- | -------------- |
| **LCKUnrealAudio** | Yes  | Yes        | No        | LCKUnrealAudio | All            |
| **LCKFMOD**        | Yes  | No         | No        | LCKFMOD        | All            |
| **LCKWwise**       | Yes  | No         | No        | LCKWwise       | Win64, Android |
| **LCKOboe**        | No   | Yes        | No        | LCKOboe        | Android        |
| **LCKVivox**       | Yes  | Yes        | No        | LCKVivox       | All            |

## Audio Configuration Validation

Before recording starts, the audio system validates the configuration to ensure audio sources are properly set up. Use `FLCKAudioConfigValidation` to inspect the current state:

```cpp theme={null}
FLCKAudioConfigValidation Validation = AudioSystem->ValidateConfig();

if (!Validation.bIsValid)
{
    for (const FString& Warning : Validation.Warnings)
    {
        UE_LOG(LogLCKAudio, Warning, TEXT("%s"), *Warning);
    }
}

// Check microphone configuration
if (Validation.bHasMicrophoneSource)
{
    UE_LOG(LogLCKAudio, Log, TEXT("Mic sources: %d enabled, %d total"),
        Validation.EnabledMicrophoneSources.Num(),
        Validation.MicrophoneSourceCount);
}
```

See [FLCKAudioConfigValidation](/api-reference/unreal/types#flckaudioconfigvalidation) in the types reference.

## Audio Plugin Discovery

Use `FLCKAudioPluginInfo` to query registered audio plugins at runtime:

```cpp theme={null}
TArray<FLCKAudioPluginInfo> Plugins = AudioSystem->GetPluginInfo();

for (const FLCKAudioPluginInfo& Plugin : Plugins)
{
    UE_LOG(LogLCKAudio, Log, TEXT("Plugin: %s (%s) - Loaded: %s, Game: %s, Mic: %s"),
        *Plugin.DisplayName,
        *Plugin.ModuleName,
        Plugin.bIsLoaded ? TEXT("Yes") : TEXT("No"),
        Plugin.bGameAudioEnabled ? TEXT("Yes") : TEXT("No"),
        Plugin.bMicrophoneEnabled ? TEXT("Yes") : TEXT("No"));
}
```

See [FLCKAudioPluginInfo](/api-reference/unreal/types#flckaudioplugininfo) in the types reference.

## Audio Channel System

### Channel Types

```cpp theme={null}
enum ELCKAudioChannel : uint64
{
    None       = 0,           // No audio channel
    Game       = 1,           // Game audio output
    Microphone = 1 << 1,      // Microphone input
    VoiceChat  = 1 << 2,      // Voice chat audio (reserved)
    Max        = 1 << 3       // Maximum value marker
};
```

| Channel      | Sources                                    |
| ------------ | ------------------------------------------ |
| `Game`       | UnrealAudio, FMOD, Wwise, Vivox (incoming) |
| `Microphone` | UnrealAudio, Oboe, Vivox (outgoing)        |
| `VoiceChat`  | Reserved for future use                    |

<Note>
  LCKVivox maps incoming voice chat to `Game` channel and outgoing microphone to `Microphone` channel for unified handling.
</Note>

### Channel Masks

```cpp theme={null}
// Create a channel mask for multiple channels
TLCKAudioChannelsMask Channels = ELCKAudioChannel::Game | ELCKAudioChannel::Microphone;

// Start capture with specific channels
AudioSource->StartCapture(Channels);

// Check if mask contains a channel
bool HasMicrophone = (Channels & ELCKAudioChannel::Microphone) != 0;
```

### Channel Source Configuration Types

The SDK provides helper structs for common channel configurations:

| Struct                     | Channels               | Use Case               |
| -------------------------- | ---------------------- | ---------------------- |
| `FLCKAudioSourceChannels`  | Game + Microphone      | Full audio capture     |
| `FLCKAudioSourceGameOnly`  | Game only              | Game audio without mic |
| `FLCKAudioSourceMicOnly`   | Microphone only        | Mic-only capture       |
| `FLCKAudioSourceVoiceChat` | Microphone + VoiceChat | Voice chat recording   |

See [Audio Source Channel Types](/api-reference/unreal/types#audio-source-channel-configuration) in the types reference.

## ILCKAudioSource Interface

All audio sources implement this interface:

```cpp theme={null}
class ILCKAudioSource : public IModularFeature, public TSharedFromThis<ILCKAudioSource>
{
public:
    static FName GetModularFeatureName() noexcept;

    // Audio data delegate (single delegate, NOT multicast)
    DECLARE_MULTICAST_DELEGATE_FourParams(FDelegateRenderAudio,
        TArrayView<const float>/*PCM-interleaved*/, int32/*Channels*/, int32/*SampleRate*/, ELCKAudioChannel/*SourceChannel*/);
    typedef FDelegateRenderAudio::FDelegate FOnRenderAudioDelegate;
    FOnRenderAudioDelegate OnAudioDataDelegate;

    // Control methods
    virtual bool StartCapture() noexcept = 0;
    virtual bool StartCapture(TLCKAudioChannelsMask Channels) noexcept = 0;
    virtual void StopCapture() noexcept = 0;

    // Query methods
    virtual float GetVolume() const noexcept = 0;
    virtual const FString& GetSourceName() const noexcept = 0;
    TLCKAudioChannelsMask GetSupportedChannels() const noexcept;

protected:
    TLCKAudioChannelsMask SupportedChannels;
};
```

<Warning>
  `OnAudioDataDelegate` is a **single delegate**, not multicast. Only one listener can be bound at a time using `BindLambda()`. The `FLCKAudioMix` class internally manages binding to multiple sources.
</Warning>

## Discovering Audio Sources

```cpp theme={null}
#include "Features/IModularFeatures.h"

// Find all registered audio sources
TArray<ILCKAudioSource*> AudioSources;
IModularFeatures::Get().GetModularFeatureImplementations<ILCKAudioSource>(
    ILCKAudioSource::GetModularFeatureName(),
    AudioSources
);

for (ILCKAudioSource* Source : AudioSources)
{
    UE_LOG(LogTemp, Log, TEXT("Found audio source: %s"), *Source->GetSourceName());

    // Check supported channels
    if (Source->GetSupportedChannels() & ELCKAudioChannel::Game)
    {
        UE_LOG(LogTemp, Log, TEXT("  - Supports game audio"));
    }
    if (Source->GetSupportedChannels() & ELCKAudioChannel::Microphone)
    {
        UE_LOG(LogTemp, Log, TEXT("  - Supports microphone"));
    }
}
```

## Listening to Audio Data

```cpp theme={null}
ILCKAudioSource* Source = /* obtained via modular features */;

// Use BindLambda for single delegate (replaces any existing binding)
Source->OnAudioDataDelegate.BindLambda([](
    TArrayView<const float> PCM,
    int32 Channels,
    int32 SampleRate,
    ELCKAudioChannel SourceChannel)
{
    // PCM: Interleaved float audio samples
    // Channels: Number of channels (typically 2 for stereo)
    // SampleRate: Audio sample rate in Hz (typically 48000)
    // SourceChannel: Which audio channel this data represents
});
```

## Audio Format

All audio sources provide audio in this format:

| Property      | Value                              |
| ------------- | ---------------------------------- |
| Sample Format | 32-bit float                       |
| Channels      | Stereo (2 channels)                |
| Layout        | Interleaved (L,R,L,R,...)          |
| Sample Rate   | Match encoder (typically 48000 Hz) |

## Thread Safety

* `OnAudioDataDelegate` may be called from any thread
* Implementers should use thread-safe data structures
* The encoder handles cross-thread data marshaling

## Log Category

```cpp theme={null}
DECLARE_LOG_CATEGORY_EXTERN(LogLCKAudio, Log, All);
```
