Skip to main content
Module: LCKAudio | Version: 0.9.2 | Platforms: All

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

Architecture

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

Audio Channel System

Channel Types

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
};
ChannelSources
GameUnrealAudio, FMOD, Wwise, Vivox (incoming)
MicrophoneUnrealAudio, Oboe, Vivox (outgoing)
VoiceChatReserved for future use
LCKVivox maps incoming voice chat to Game channel and outgoing microphone to Microphone channel for unified handling.

Channel Masks

// 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;

ILCKAudioSource Interface

All audio sources implement this interface:
class ILCKAudioSource : public IModularFeature, public TSharedFromThis<ILCKAudioSource>
{
public:
    static FName GetModularFeatureName() noexcept;

    // Audio data delegate (single delegate, NOT multicast)
    DECLARE_MULTICAST_DELEGATE_ThreeParams(FDelegateRenderAudio,
        TArrayView<const float>/*PCM*/, int32/*Channels*/, ELCKAudioChannel/*Source*/);
    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;
};
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.

Discovering Audio Sources

#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

ILCKAudioSource* Source = /* obtained via modular features */;

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

Audio Format

All audio sources provide audio in this format:
PropertyValue
Sample Format32-bit float
ChannelsStereo (2 channels)
LayoutInterleaved (L,R,L,R,…)
Sample RateMatch 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

DECLARE_LOG_CATEGORY_EXTERN(LogLCKAudio, Log, All);