Documentation

LevelAPI2 & LevelShow2
Documentation

LevelAPI2 is a high-performance C dynamic library for loudness measurement and normalization to EBU R128 and ATSC A/85 (CALM Act) broadcast standards. This reference covers the full API, integration workflow, and all function signatures. LevelShow2, the bundled DirectShow filter for Windows pipelines, is documented in the second half.

01 Introduction

LevelAPI2 and LevelShow2 are built to support the transition from peak normalization to loudness normalization — one of the most significant changes in broadcast audio in decades. This shift began when the ITU published BS.1770 (LKFS/LUFS loudness metering) in 2006. The European Broadcast Union built on this foundation with EBU R128, released in 2010, which became the global broadcast loudness standard.

LevelAPI2 is the direct evolution of the software used by the EBU PLOUD working group during the creation of R128. It is maintained by tlemon.com.

The library interface consists entirely of C functions exposed through a dynamic library (.dll on Windows, .so on Linux). This makes it callable from any language with standard C FFI support — C, C++, Java, LUA, Python, Rust, Go, .NET, Delphi, and others.

02 System Requirements

  • Windows 7 or later (x86 / x64)
  • Linux — built on CentOS 7 (x64); custom builds available for other distributions
  • System memory: 512 MB minimum
  • Disk space: approximately 10 MB

The Linux .so build depends on standard shared libraries: libcurl.so.4, librt.so.1, libdl.so.2, libpthread.so.0, libm.so.6, libc.so.6. All are present in any standard CentOS 7 / RHEL / Fedora environment.

03 Upgrading from LevelAPI v1

If you are migrating from the original LevelAPI, note the following breaking changes:

Renamed functions

v1v2
Analyse()AnalyseInterleaved()
Adjust()AdjustInterleaved()
GetNeedLimiting()GetLimitingNeeded()
GetLimitThresholddB()GetLimiterThreshold()
SetNeedLimiting()SetLimiterEnable()
SetLimiterThresholdEffective()SetLimiterThresholdAdjust()
SetLimitThresholddB()SetLimiterThreshold()
IsAdjustLevelLowered()Removed — use GetLevel(AdjustLevel_NoPeak) vs GetLevel(AdjustLevel)

Renamed enum values

v1v2
Max_MLU_Max_M
Max_SLU_Max_S
Max_M_FSLUFS_Max_M
Max_S_FSLUFS_Max_S
LRA_LowLRA_Range_Low
LRA_HighLRA_Range_High
TruePeakHP / TruePeakLPTruePeak (high precision only)
PSR_MinPSR

Behaviour changes

  • All functions that return a boolean now return 1 (true) on success and 0 (false) on failure — previously inconsistent.
  • PPM and RMS meters are disabled by default. Enable with SetPPMEnable(true) and SetRMSEnable(true).
  • TruePeak HP and LP have been merged into a single high-precision TruePeak.

04 Usage Guide

Implementing LevelAPI2 follows a consistent pattern regardless of language or platform. The steps below describe the complete workflow from loading the library to retrieving results.

  1. Load the dynamic library at runtime

    Use your platform's dynamic linking API (dlopen on Linux, LoadLibrary on Windows) to load the library file. A helper macro LevelAPI2_LoadDLL(path, &handles) is provided in the header to retrieve all function pointers in one call.

  2. Validate your certificate

    Call SetCertificate(cert_string, length) as the first call after loading. This validates your license. If it returns false, call GetErrorString() to retrieve the failure reason. The certificate string should be embedded or loaded from a secure location in your application.

  3. Create a handle

    Call Create_LevelAPI2(channels, samplerate, bitdepth) to create an instance. Every subsequent function call requires this handle as its first argument. You can create multiple handles to measure multiple sources simultaneously. Always call Destroy_LevelAPI2(handle) when done.

  4. Configure measurement standard

    For EBU R128 compliance, call SetPresetEBU_R128(handle). For ATSC A/85, call SetPresetATSC(handle). These convenience functions set calibration, gate, target type and level in one call. You can then override individual settings using the Advanced Settings functions if needed.

  5. Feed audio samples

    Call AnalyseInterleaved(handle, samples, numframes) with your interleaved float buffer. The numframes argument is in sample frames — for a stereo buffer of 512 samples, numframes = 256. For best performance, pass blocks of at least 256 frames. Maximum is 16 × 1024 = 16384 frames per call. For file-based workflows, use AnalyseFile(handle, filepath) directly.

  6. Read meter levels

    At any point after analysis, call GetLevel(handle, meterType, channel) using values from the MeterTypes enum. Pass -1 as channel to get the combined result across all channels. Key values: LU, LRA, TruePeak, LU_Max_M, LU_Max_S.

  7. Normalize the audio

    After analysis is complete, call AdjustInterleaved(handle, samples, numframes) to apply gain correction to your sample buffer. If using the same handle for both steps, the required adjustment level is already known. If using a separate handle for adjustment, first call SetAdjustLevel(handle, dB) with the value from GetAdjustLevel() or GetLevel(AdjustLevel). The built-in peak limiter activates automatically when needed.

Minimal C example

C
#include "LevelAPI2_dynlib.h"

// 1. Load library
struct LevelAPI2_FunctionHandles api;
void* lib = LevelAPI2_LoadDLL(library_path, &api);

// 2. Validate certificate
api.SetCertificate(cert_string, strlen(cert_string));

// 3. Create handle
LevelAPI2Ptr h = api.Create_LevelAPI2(channels, samplerate, bitdepth);

// 4. Configure for EBU R128
api.SetPresetEBU_R128(h);

// 5. Feed samples (interleaved float buffer)
//    numframes = total_samples / channels
api.AnalyseInterleaved(h, samples, numframes);

// 6. Read results
float lu       = api.GetLevel(h, LU,       -1);
float lra      = api.GetLevel(h, LRA,      -1);
float truepeak = api.GetLevel(h, TruePeak, -1);

// 7. Normalize
api.AdjustInterleaved(h, samples, numframes);

// Cleanup
api.Destroy_LevelAPI2(h);
LevelAPI2_UnloadDLL(lib);

05 Constants & Enums

DataRanges

ConstantValueDescription
max_channels16Maximum number of audio channels
max_frames16384Maximum sample frames per AnalyseInterleaved call (16 × 1024)

SurroundOrders

ValueChannel Order
SMTPE_ITU_AC3L — R — C — Lfe — Ls — Rs
FilmDolbyDigitalL — C — R — Ls — Rs — Lfe
DTS_ProControlL — R — Ls — Rs — C — Lfe

MeterTypes

Used as the meterType argument in GetLevel() and related functions. Values marked (*) are generally for testing only and not intended for display to end users.

ValueDescription
LUIntegrated loudness — calibrated LU (gated)
LUFSIntegrated loudness — uncalibrated LUFS (gated)
LU_UNGATEDCalibrated LU without gating (*)
LUFS_UNGATEDUncalibrated LUFS without gating (*)
LU_MinMinimum calibrated LU level (*)
LU_DialogCalibrated dialog LU level (*)
LUFS_DialogUncalibrated dialog LUFS level (*)
LU_Dialog_UNGATEDDialog LU without gating (*)
Dialog_percentagePercentage of dialog detected in the audio
LU_Max_MMaximum momentary level (calibrated LU)
LUFS_Max_MMaximum momentary level (uncalibrated LUFS)
LU_Max_SMaximum short-term level, 3 s window (calibrated LU)
LUFS_Max_SMaximum short-term level, 3 s window (uncalibrated LUFS)
LRALoudness range (LRA_High − LRA_Low)
LRA_Range_LowLow boundary of the LRA calculation (*)
LRA_Range_HighHigh boundary of the LRA calculation (*)
LU_BS1771Realtime calibrated LU (BS.1771) (*)
LU_BS1771_FilteredRealtime calibrated LU with meter filter
LU_BS1771_Shortterm3 s realtime calibrated LU
LUFS_BS1771_Shortterm3 s realtime uncalibrated LUFS (*)
PPMRealtime PPM level (must be enabled)
PPM_MaxMaximum PPM value
RMS_MaxMaximum RMS value
PeakMaximum sample peak (*)
TruePeakMaximum true inter-sample peak
PSRPeak-to-Short-term Ratio
PeakLoudnessPLR — Peak Loudness Range
Limited_dBAmount of limiting applied in dB (*)
AdjustLevelThe calculated normalization gain in dB
AdjustLevel_NoPeakNormalization gain ignoring peak limiting (*)

06 Dynlib Initialization

These functions are called immediately after loading the dynamic library, before creating any handles.

bool SetCertificate(const char *certificate_string, size_t bufferSize)

Must be the first call made to the loaded library. Validates your license certificate. Returns true on success.

  • arg 1Pointer to a char array containing the certificate text
  • arg 2Total byte length of the certificate text (max 10 × 1024)
bool GetErrorString(const char *error_string, size_t bufferSize)

Call only when SetCertificate() has returned false. Fills the provided buffer with the error description.

  • arg 1Pointer to an empty char array to receive the error text
  • arg 2Size of the buffer (max 10 × 1024)
LevelAPI2Ptr Create_LevelAPI2(const int channels, const unsigned int samplerate, const int bitdepth)

Creates and initializes a LevelAPI2 instance. Returns a valid handle, or NULL on failure. Every subsequent function call requires this handle as its first argument. Do not modify the returned value.

  • channelsNumber of audio channels, e.g. 2 for stereo
  • samplerateSample rate of the source material, e.g. 48000
  • bitdepthBit depth used for dithering during gain adjustment — 16, 24, or 32
void Destroy_LevelAPI2(LevelAPI2Ptr handle)

Releases all resources associated with the given handle. Must be called for every handle created with Create_LevelAPI2().

int GetRevision()

Returns the integer revision number of the loaded library binary. Useful for version checks at startup.

07 Library Initialization

bool SetPresetEBU_R128(LevelAPI2Ptr handle)

Convenience preset for full EBU R128 compliance. Equivalent to calling: SetRelativeGate(−10), SetCalibration(LU, −23), SetAdjustTargetType(LU), SetAdjustTargetLevel(0).

Returns true on success.
bool SetPresetATSC(LevelAPI2Ptr handle)

Convenience preset for full ATSC A/85 (CALM Act) compliance. Equivalent to: SetRelativeGate(0), SetCalibration(LU, −24), SetAdjustTargetType(LU), SetAdjustTargetLevel(0).

Returns true on success.

You can combine presets with manual overrides. For example: call SetPresetEBU_R128() then SetCalibration() to override only the calibration value.

The following functions return stream format properties set during initialization:

unsigned int GetChannels(LevelAPI2Ptr)

Returns the number of channels.

unsigned int GetSamplerate(LevelAPI2Ptr)

Returns the sample rate.

08 Processing

bool AnalyseInterleaved(LevelAPI2Ptr handle, float* samples, const unsigned int numframes)

Analyses a block of interleaved float samples. Call repeatedly to process a complete audio stream. For best performance, pass blocks of at least 256 frames.

  • samplesPointer to an interleaved float buffer
  • numframesNumber of sample frames (= total samples ÷ channels). Maximum: 16384
Returns true on success.
bool Analyse(LevelAPI2Ptr handle, float* samples, const unsigned int numframes)

Non-interleaved variant. Use when your audio data is in separate channel buffers rather than interleaved.

bool AdjustInterleaved(LevelAPI2Ptr handle, float* samples, const unsigned int numframes)

Applies loudness normalization gain to the sample buffer in-place. Uses the AdjustLevel calculated by AnalyseInterleaved() (same handle), or the value set manually with SetAdjustLevel(). The peak limiter activates automatically when required.

  • samplesPointer to the float buffer to be modified in-place
  • numframesNumber of sample frames
bool Adjust(LevelAPI2Ptr handle, float* samples, const unsigned int numframes)

Non-interleaved variant. Use when your audio data is in separate channel buffers rather than interleaved.

bool AnalyseFile(LevelAPI2Ptr handle, const char* filepath)

Analyses an audio file directly. Supported formats: WAV, AIFF, FLAC.

bool AdjustFile(LevelAPI2Ptr handle, const char* infile, const char* outfile)

Normalizes an audio file and writes the result to a new file. The output path must not already exist.

  • infilePath to the source audio file (WAV / AIFF / FLAC)
  • outfilePath for the normalized output file (must not exist)

09 Results

float GetLevel(LevelAPI2Ptr handle, enum MeterTypes meterType, const int channel)

Returns a meter value in dB for the given meter type and channel.

  • meterTypeA value from the MeterTypes enum — e.g. LU, LRA, TruePeak
  • channelChannel index (0-based), or -1 for the combined result across all channels
float GetAdjustLevel(LevelAPI2Ptr handle, const bool ignore_peak_limit)

Returns the calculated normalization gain in dB. Use this to apply the gain manually, or save it for later use with a separate handle. Pass false (default) to include peak limiting in the calculation.

bool SetAdjustLevel(LevelAPI2Ptr handle, const float adjustLevel)

Manually sets the normalization gain in dB. Not needed when using the same handle for both analysis and adjustment. Use this when separating the analyse and adjust passes — for example, to analyse multiple files first, then adjust them in a second pass.

unsigned int GetAdjustLatency(LevelAPI2Ptr handle)

Returns the latency in samples introduced by the peak limiter during adjustment (approximately 20 ms). Account for this when synchronizing audio streams.

10 Advanced Settings

These functions modify measurement behaviour beyond the standard presets. For straightforward EBU R128 or ATSC A/85 compliance, the preset functions are sufficient. All Set functions return true on success.

Adjust Target

int GetAdjustTargetType(LevelAPI2Ptr)

Returns the current target meter type used for normalization.

bool SetAdjustTargetType(LevelAPI2Ptr, enum MeterTypes)

Sets the target meter type. Options: LU (default for R128/ATSC), PPM, or TruePeak.

float GetAdjustTargetLevel(LevelAPI2Ptr)

Returns the target loudness level in dB.

bool SetAdjustTargetLevel(LevelAPI2Ptr, const float targetLevel)

Sets the normalization target level in dB. Default is 0 (0 LU = −23 LUFS for EBU, −24 LKFS for ATSC).

Channels

enum SurroundOrders GetSurroundOrder(LevelAPI2Ptr)

Returns the current surround channel order.

bool SetSurroundOrder(LevelAPI2Ptr, enum SurroundOrders)

Sets the channel order for surround sources. Also automatically configures dialog channel detection. Use SMTPE_ITU_AC3, FilmDolbyDigital, or DTS_ProControl.

bool SetChannelWeight(LevelAPI2Ptr, const int channel, const float weight)

Overrides the per-channel weighting used for loudness measurement. Only relevant for surround configurations. SetSurroundOrder() handles this automatically for standard layouts.

  • channelChannel index, 0 to max_channels
  • weightWeight in dB

Gates

float GetRelativeGate(LevelAPI2Ptr)

Returns the relative gate threshold in dB.

bool SetRelativeGate(LevelAPI2Ptr, const float threshold)

Sets the relative gate threshold. Default: −10 dB (EBU R128), 0 (ATSC — no gating).

bool GetDialogGate(LevelAPI2Ptr)

Returns whether the dialog gate is enabled.

bool SetDialogGate(LevelAPI2Ptr, const bool on)

Enables or disables the dialog gate. Required for ATSC CALM Act compliance. The ATSC preset enables this automatically.

Calibration

float GetCalibration(LevelAPI2Ptr, enum MeterTypes)

Returns the calibration offset in dB for a given meter type.

bool SetCalibration(LevelAPI2Ptr, enum MeterTypes, const float calibration)

Sets calibration offset. Defaults: −23 dB for EBU LU, −24 dB for ATSC. Meter type: LU, PPM, or TruePeak.

Limiter

bool GetLimiterEnable(LevelAPI2Ptr)

Returns whether the limiter is active.

bool SetLimiterEnable(LevelAPI2Ptr, const bool on)

Forces the limiter on or off. By default it activates automatically when needed.

float GetLimiterThreshold(LevelAPI2Ptr)

Returns the limiter analysis threshold in dBFS.

bool SetLimiterThreshold(LevelAPI2Ptr, const float dB)

Sets the limiter threshold used during analysis. Default: −1.0 dBFS (prevents TruePeak clipping).

float GetLimiterThresholdAdjust(LevelAPI2Ptr)

Returns the limiter threshold used during the adjustment pass.

bool SetLimiterThresholdAdjust(LevelAPI2Ptr, const float dB)

Sets the limiter threshold for the adjustment pass. May differ from the analysis threshold because TruePeak and sample peak are not identical.

Time Window

int GetTimeWindow(LevelAPI2Ptr)

Returns the current measurement window in seconds.

bool SetTimeWindow(LevelAPI2Ptr, const unsigned int seconds)

Limits the measurement to a rolling time window. Useful for continuous realtime metering. Each additional hour of window increases memory use by ~1.44 MB.

Legacy Meters (PPM / RMS)

PPM and RMS are legacy meters, disabled by default. Enable them only if your integration specifically requires them.

bool SetPPMEnable(LevelAPI2Ptr, const bool)

Enables or disables PPM measurement. Default: off.

bool SetRMSEnable(LevelAPI2Ptr, const bool)

Enables or disables RMS measurement. Default: off.

Histogram Access

Thread safety: Histogram functions are not thread-safe. Complete your read or copy before calling any other function on the same handle.

Raw histogram data is available for detailed loudness distribution analysis:

FunctionReturns
GetHistogramLUFS(handle, &size)Integrated loudness histogram
GetHistogramLUFS_Dialog(handle, &size)Dialog loudness histogram
GetHistogramLUFS_S(handle, &size)Short-term loudness and LRA histogram
GetHistogramPSR(handle, &size)Peak-to-Short-term Ratio histogram

Conversion helpers between histogram positions and dB values:

int LUFS2tablePos(LevelAPI2Ptr, float lufs)

Converts a LUFS value to a histogram array index.

float tablePos2LUFS(LevelAPI2Ptr, int pos)

Converts a histogram array index to a LUFS value.

float dB2float(LevelAPI2Ptr, float dB)

Converts a dB value to a linear float.

float float2dB(LevelAPI2Ptr, float flt)

Converts a linear float to dB.

11 Technical Specifications

EBU R128

MeasurementITU BS.1770-2
Relative gate−10 LU
0 LU equals−23 LUFS
Target tolerance0 LU ± 6 LU

ATSC A/85

MeasurementITU BS.1770-1
Relative gateNone
0 LU equals−24 LKFS
Target tolerance0 LU ± 6 LU

Surround channel orders

ModeChannel order
SMPTE / ITUL — R — C — Lfe — Ls — Rs
Film / DolbyL — C — R — Ls — Rs — Lfe
DTSL — R — Ls — Rs — C — Lfe

12 LevelShow2 — Overview

LevelShow2 is a Windows DirectShow filter that wraps LevelAPI2 for use in Windows media pipeline applications. It is included with every LevelAPI2 license.

It exposes the same measurement and normalization capabilities as LevelAPI2 through two interfaces: a graphical properties page for manual operation, and the ILevelShow2 COM interface for programmatic control.

LevelShow2 is primarily relevant for Windows-based broadcast automation pipelines. For cross-platform or non-DirectShow use, LevelAPI2 directly is the correct integration path.

13 LevelShow2 — Usage

LevelShow2 can be implemented in two ways:

  • Single instance — One filter handles both analysis and adjustment in sequence. Simpler workflow, suitable for most use cases.
  • Two instances — One filter analyses, a second applies the adjustment. Allows analysing multiple files first, then normalizing them in a separate pass.

Basic workflow

  1. 1

    Build your DirectShow graph

    Connect your audio source to the LevelShow2 input pin and connect the output pin downstream.

  2. 2

    Configure analysis settings

    Enter your certificate, set Mode to Analyse, select your standard (EBU R128 or ATSC), and if using surround, select the correct channel order.

  3. 3

    Stream the audio

    Run the graph to pass all audio through the filter. LevelShow2 accumulates measurement data throughout the stream.

  4. 4

    Switch to Adjust mode

    Set Mode to Adjust. The filter automatically configures itself with the calculated normalization gain. To reset for a new stream, set Mode to −1.

  5. 5

    Re-stream to apply normalization

    Pass the audio through the filter again. The output is now level-normalized. Alternatively, pass the AdjustLevel value to a second instance set to Adjust mode.

14 LevelShow2 — Programmatic Interface

Query the ILevelShow2 interface via IUnknown::QueryInterface to control the filter programmatically. The interface mirrors the graphical controls exactly.

License

MethodDescription
put_Certificate(char*)Supply your license certificate string
get_CertificateError(char*)Retrieve error text if certificate is invalid
get_License(bool*)Returns true if the current certificate is valid

Mode

ValueMeaning
0Analyse mode
1Adjust mode
−1Reset — clears measurement history and returns to Analyse

Analyse settings

MethodValues / DefaultDescription
put/get_MeasureType0=EBU R128, 1=ATSC, 2=CustomConvenience preset — sets all related parameters
put/get_LURelativeGatebool (true=on)Enable/disable the −10 LU relative gate
put/get_DialogGatebool (true=on)Enable/disable dialog gate (ATSC CALM)
put/get_SurroundOrder0=SMPTE, 1=Film, 2=DTSSurround channel order
put/get_CalibrationLUfloat, default −23.00LU calibration offset in dB
put/get_CalibrationPPMfloat, default −9.00PPM calibration offset in dB
put/get_MeterType0=LU, 1=PPM, 2=PeakTarget meter type for normalization
put/get_TargetLevelfloat, default 0.00Target level in dB

Results

MethodDescription
get_LULevel(float*)Integrated loudness in LU
get_PPMLevel(float*)PPM level
get_PeakLevel(float*)True peak level
get_MaxMLevel(float*)Maximum momentary level
get_MaxSLevel(float*)Maximum short-term level
get_LRALevel(float*)Loudness range
get_AdjustLevel(float*)Calculated normalization gain in dB — use with put_AdjustLevel on a second instance
put_AdjustLevel(float)Manually sets the adjustment gain — bypasses analysis
get_MLevel(float*)Current momentary level (call per processed block for realtime metering)
get_SLevel(float*)Current short-term level (call per processed block)
get_Warning(char*)Returns a warning string if the adjust level is abnormal, NULL if none

15 References

  • tech.ebu.ch/loudness — EBU R128 recommendation, official documents, guidelines, and introduction videos
  • ATSC A/85 Recommendation — available from the ATSC website
  • ITU-R BS.1770 — the foundational loudness metering standard

A complete trial certificate and the header file (LevelAPI2_dynlib.h) are available on request. Contact us for licensing →