Naar inhoud
Inloggen

/docs · SignalLab · Practical

Streaming clippingdetectie op schaal

Clipping in audio detecteren tijdens het inladen, zonder het hele bestand te decoderen.


Als je een audioplatform draait (broadcasting, archivering, transcriptie) laad je veel bestanden in. Veel daarvan clippen. De meeste upstream-QA-tools merken het niet op, of pas bij een volledige decode, wat betekent dat je rekentijd verspilt aan elk slecht bestand voordat je weet dat het slecht is.

Er is een eenvoudigere aanpak: detecteer clipping tijdens de decode, op een streaming-manier. Dit is het patroon dat werkt.

De naïeve aanpak (en waarom die traag is)

samples = decode(audio_file)
clipping_count = sum(1 for s in samples if abs(s) > 0.99)

Hiervoor moet je het bestand volledig in het geheugen decoderen. Voor een podcast van meerdere uren is dat een merkbare kostenpost, en je weet pas nadat je het werk hebt gedaan of het bestand clipt.

Streamingdetectie

De streamingversie verwerkt blokken zodra ze uit de decoder komen:

def stream_clipping_check(decoder, threshold=0.99, run_length=3):
    """
    Decode in blocks and stop early if hopeless.
    Returns (total_clips, regions) or raises if catastrophic.
    """
    total = 0
    regions = []
    current_run = 0
    current_region_start = None
    sample_index = 0

    for block in decoder.blocks():  # generator yielding numpy arrays
        for v in block:
            if abs(v) > threshold:
                if current_run == 0:
                    current_region_start = sample_index
                current_run += 1
                if current_run == run_length:
                    total += 1
            else:
                if current_run >= run_length:
                    regions.append((current_region_start, sample_index))
                current_run = 0
                current_region_start = None
            sample_index += 1

        # Early-exit if catastrophic
        if total > 1000:
            raise CatastrophicClippingError(f"{total} clip events, abandoning analysis")

    return total, regions

Twee dingen om op te merken:

  1. Run-length-filtering: één enkele sample op -0.99 is geen clipping, dat is een piek. Echte clipping verschijnt als meerdere opeenvolgende samples die plat tegen het plafond aan liggen. Door run_length=3 te eisen (drie opeenvolgende samples boven de drempel) elimineer je 90% van de fout-positieven.
  2. Early-exit: als je meer dan een paar honderd clippinggebeurtenissen vindt, is het bestand kapot. Stop en sla de rest over. Het downstream-systeem kan het markeren en doorgaan.

Wat “clipping” eigenlijk betekent

Strikt genomen is clipping wanneer het analoge signaal meer was dan de ADC kon weergeven en werd afgekapt tot het plafond. In de praktijk, in het digitale domein:

  • Hard clipping: opeenvolgende samples op exact ±1.0 (in float) of het integer-maximum.
  • Soft clipping: opeenvolgende samples boven ~0.95 met een lage helling. Meestal een artefact van een compressor of limiter aan de bron.
  • Intersample clipping: pieken die tussen de samples 0 dBFS overschrijden na reconstructie. Onzichtbaar in metingen in het sampledomein; vereist oversampling om te detecteren.

Een robuuste detector verwerkt alle drie. Voor QA tijdens het inladen zijn de eerste twee essentieel. De derde is een geval van “behandel als waarschuwing, niet als fout”.

De drempels die werken

Na het draaien hiervan op een paar honderdduizend bestanden in productie:

  • Drempel 0.99: komt overeen met “echte” clipping bij 16-bit en 24-bit zonder fout-positieven door float-headroom.
  • run_length=3: vangt echte clipping op bij gangbare samplerates (44.1k/48k) zonder echte gebeurtenissen te missen.
  • total > 1000: een catastrofedrempel voor een typisch short-form-bestand (korter dan 30 minuten). Verhoog deze voor langere bestanden.
  • Region merging: gebieden binnen ~50 samples (~1 ms bij 48k) moeten worden samengevoegd tot één gebeurtenis. Anders wordt een aanhoudende clip gerapporteerd als honderden micro-gebeurtenissen.

Waarom dit belangrijk is

Een streaming clippingcontrole kost je een paar CPU-cycli per sample, loopt in de pas met de decode en laat je slechte bestanden afwijzen voordat een downstream-tool ze aanraakt. Op de schaal van een audioarchief is dat het verschil tussen een merkbare infrakost en een onopgemerkte.

Het is ook een goede herinnering dat “de analyse doen” en “het goedkope deel van de analyse doen” verschillende keuzes zijn. Veel audio-QA-problemen hebben een streamingvriendelijke goedkope vorm.

Gerelateerd