{"id":20216,"date":"2026-09-23T20:43:04","date_gmt":"2026-09-23T18:43:04","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/werkzeuge\/click-splice-finder-hard-cuts-slope-breaks\/"},"modified":"2026-09-23T21:54:53","modified_gmt":"2026-09-23T19:54:53","slug":"click-splice-finder-hard-cuts-slope-breaks","status":"publish","type":"page","link":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/click-splice-finder-hard-cuts-slope-breaks\/","title":{"rendered":"Knack- und Schnittstellen-Finder: Knackser, harte Schnitte und Knicke in einer Audiodatei finden"},"content":{"rendered":"<div class=\"lw-kf\" id=\"kf-wurzel\" style=\"background: var(--bg-panel, #1e1e24); padding: 25px; border-radius: 8px; border: 1px solid var(--border, #2a2a35);\">\n<style>\n.lw-kf { --kf-warn: #e8a33d; }\n:root[data-theme=\"light\"] .lw-kf { --kf-warn: #8f5300; }\n.lw-kf .kf-zone { border: 2px dashed var(--border, #2a2a35); border-radius: 8px; padding: 22px; text-align: center; }\n.lw-kf .kf-zone.kf-ueber { border-color: var(--accent, #2ba6df); }\n.lw-kf .kf-kacheln { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin: 4px 0; }\n.lw-kf .kf-kachel { background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-radius: 8px; padding: 11px 14px; min-width: 0; }\n.lw-kf .kf-kachel-name { font-size: 0.74rem; color: var(--text-secondary, #a0a0b0); text-transform: uppercase; letter-spacing: 0.4px; }\n.lw-kf .kf-kachel-wert { font-family: monospace; font-size: 1.4rem; font-weight: 700; color: var(--text-primary, #e8e8ee); line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.lw-kf .kf-urteil { border-radius: 8px; padding: 12px 15px; margin-top: 14px; border: 1px solid var(--border, #2a2a35); background: var(--bg-body, #14141a); }\n.lw-kf .kf-urteil-kopf { font-weight: 700; color: var(--text-primary, #e8e8ee); margin-bottom: 4px; }\n.lw-kf .kf-u-sauber .kf-urteil-kopf { color: var(--ok, #7ee787); }\n.lw-kf .kf-u-stellen .kf-urteil-kopf { color: var(--kf-warn); }\n.lw-kf .kf-tabelle { overflow-x: auto; margin-top: 6px; }\n.lw-kf table { border-collapse: collapse; width: 100%; font-size: 0.86rem; }\n.lw-kf th, .lw-kf td { text-align: left; padding: 6px 10px; border-bottom: 1px solid var(--border, #2a2a35); vertical-align: top; }\n.lw-kf th { color: var(--text-primary, #e8e8ee); white-space: nowrap; }\n.lw-kf td { color: var(--text-primary, #e8e8ee); }\n.lw-kf td.kf-wert { font-family: monospace; color: var(--text-secondary, #a0a0b0); white-space: nowrap; }\n.lw-kf .kf-h { font-weight: 700; color: var(--text-primary, #e8e8ee); font-size: 0.95rem; margin: 24px 0 8px; }\n.lw-kf .kf-klein { font-size: 0.84rem; color: var(--text-secondary, #a0a0b0); line-height: 1.55; }\n.lw-kf .kf-knopf { background: transparent; color: var(--text-secondary, #a0a0b0); border: 1px solid var(--border, #2a2a35); padding: 9px 14px; border-radius: 6px; cursor: pointer; font-size: 0.9rem; margin-top: 12px; }\n.lw-kf .kf-fehler { color: var(--fehler, #f0857a); font-size: 0.88rem; margin-top: 12px; }\n.lw-kf a { color: var(--accent, #2ba6df); }\n@media (max-width: 480px) {\n    .lw-kf .kf-kacheln { grid-template-columns: 1fr 1fr; gap: 8px; }\n    .lw-kf .kf-kachel-wert { font-size: 1.15rem; }\n}\n\/* Schmal: die Liste als gestapelte Karten *\/\n@media (max-width: 600px) {\n    .lw-kf table.kf-karten thead { display: none; }\n    .lw-kf table.kf-karten tr { display: block; padding: 8px 0; border-bottom: 1px solid var(--border, #2a2a35); }\n    .lw-kf table.kf-karten td { display: inline-block; border: none; padding: 1px 10px 1px 0; }\n    .lw-kf table.kf-karten td:first-child { display: block; font-weight: 700; }\n    .lw-kf table.kf-karten td[data-name]::before { content: attr(data-name) \": \"; color: var(--text-secondary, #a0a0b0); font-family: inherit; }\n}\n<\/style>\n<p style=\"color: var(--text-secondary, #a0a0b0); margin-bottom: 18px;\">Durchsucht eine Audiodatei nach Knacksern: harten Schnitten, einzelnen Ausrei\u00dfern und Stellen, an denen die Wellenform pl\u00f6tzlich die Richtung wechselt. Zu jeder Stelle stehen Zeit, wie weit sie aus ihrer Umgebung herausragt, ihr Pegel oberhalb von 5\u00a0kHz und die Blendenl\u00e4nge, die einen Klick dieser Gr\u00f6\u00dfe zudeckt. Die Datei wird im Browser gelesen und nicht hochgeladen.<\/p>\n<div id=\"kf-zone\" class=\"kf-zone\">\n<p style=\"margin: 0 0 12px; color: var(--text-primary, #e8e8ee); font-weight: 700;\">Audiodatei ausw\u00e4hlen<\/p>\n<p>        <button id=\"kf-knopf\" type=\"button\" class=\"button\" style=\"background: var(--accent, #7ee787); color: var(--on-accent, #0b1114); border: none; padding: 11px 22px; border-radius: 6px; font-weight: 700; cursor: pointer;\">Datei w\u00e4hlen<\/button><br \/>\n        <input id=\"kf-datei\" type=\"file\" accept=\"audio\/*,.wav,.wave,.aif,.aiff,.aifc,.flac,.mp3,.m4a,.ogg,.opus\" hidden><\/p>\n<p class=\"kf-klein\" style=\"margin: 12px 0 0;\">WAV und AIFF werden Wert f\u00fcr Wert gelesen; FLAC, MP3, M4A, Ogg und Opus laufen \u00fcber den Decoder des Browsers.<\/p>\n<\/p><\/div>\n<div id=\"kf-status\" class=\"kf-klein\" data-mp-mask style=\"margin-top: 12px;\" aria-live=\"polite\"><\/div>\n<div id=\"kf-fehler\" class=\"kf-fehler\" data-mp-mask hidden><\/div>\n<div id=\"kf-ausgabe\" data-mp-mask style=\"margin-top: 18px;\" aria-live=\"polite\" hidden>\n<div id=\"kf-kacheln\" class=\"kf-kacheln\"><\/div>\n<div id=\"kf-urteil\" class=\"kf-urteil\"><\/div>\n<div class=\"kf-h\">Stellen<\/div>\n<div class=\"kf-tabelle\">\n<table class=\"kf-karten\">\n<thead>\n<tr>\n<th>Zeit<\/th>\n<th>Art<\/th>\n<th>Kanal<\/th>\n<th>Ragt heraus um<\/th>\n<th>Klick oberhalb 5\u00a0kHz<\/th>\n<th>Blende, die ihn zudeckt<\/th>\n<\/tr>\n<\/thead>\n<tbody id=\"kf-liste\"><\/tbody>\n<\/table><\/div>\n<p id=\"kf-mehr\" class=\"kf-klein\" style=\"margin: 8px 0 0;\">\n<p>        <button id=\"kf-kopieren\" type=\"button\" class=\"kf-knopf\">Ergebnis kopieren<\/button><br \/>\n        <span id=\"kf-kopiert\" class=\"kf-klein\" style=\"margin-left: 10px;\"><\/span>\n    <\/div>\n<div class=\"kf-h\">Wie gesucht wird<\/div>\n<p class=\"kf-klein\" style=\"margin: 0 0 6px;\">Ein linearer Pr\u00e4diktor 16. Ordnung, f\u00fcr jeweils 2048 Werte neu angepasst, sagt jeden Wert aus den vorigen voraus. Tonales Material verschwindet im Vorhersagefehler, ein Sprung bleibt stehen. Gemeldet wird eine Stelle, wenn der Fehler in ihrem 1-ms-Block mindestens 12\u00a0dB \u00fcber dem lauteren der beiden Umfelder von je 20\u00a0ms liegt und mindestens 18\u00a0dB sch\u00e4rfer ist als der Fehler rundherum innerhalb von 1\u00a0ms. Die zweite Regel trennt einen einzelnen Ausrei\u00dfer von einem Schlagzeugeinsatz, der sich \u00fcber viele Werte verteilt.<\/p>\n<p class=\"kf-klein\" style=\"margin: 0 0 6px;\">Ein Sprung ist ein pl\u00f6tzlicher Wertewechsel, wie bei einem Schnitt mitten in einer Schwingung. Ein Knick beh\u00e4lt den Wert, kehrt aber die Richtung um: In der Messung zum Artikel \u00fcber Crossfades klickte ein Schnitt genau im fallenden Nulldurchgang trotzdem mit \u221237,44\u00a0dBFS. Der Pegel oberhalb von 5\u00a0kHz ist dasselbe Ma\u00df wie in diesem Artikel.<\/p>\n<p class=\"kf-klein\" style=\"margin: 0 0 6px;\">Die Blendenl\u00e4nge stammt aus derselben Messung: Eine Blende von 1\u00a0ms senkte den Klick um 33,08\u00a0dB, dar\u00fcber brachte jede Verdopplung weitere 6\u00a0dB, bis 59,35\u00a0dB bei 20\u00a0ms, unabh\u00e4ngig von der Tonh\u00f6he des Materials. Das Werkzeug w\u00e4hlt die k\u00fcrzeste L\u00e4nge, die den Klick um seine \u00dcberh\u00f6hung plus 6\u00a0dB senkt.<\/p>\n<p class=\"kf-klein\" style=\"margin: 0 0 6px;\">adeclick aus ffmpeg arbeitet nach demselben Prinzip und ersetzt Ausrei\u00dfer durch Interpolation. In der Vorgabe ver\u00e4nderte es in einem dichten Testmix ohne einen einzigen Knackser trotzdem 10,6\u00a0% aller Werte, und diese Suche fand dort danach 18 Stellen statt einer; in einer Fl\u00e4che beseitigte es 15 von 20 Schnitten und ver\u00e4nderte 1,4\u00a0% der Werte.<\/p>\n<p style=\"font-weight: 700; color: var(--text-primary, #e8e8ee); font-size: 0.95rem; margin: 24px 0 8px;\">Artikel dazu<\/p>\n<p class=\"kf-klein\" style=\"margin: 0 0 6px;\">Wie laut der Klick am Sto\u00df ist und welche Blendenl\u00e4nge ihn zudeckt, misst der Artikel \u201e<span class=\"lw-artikel-geplant\">Crossfades und Schnitte<\/span>\u201c.<\/p>\n<p class=\"kf-klein\" style=\"margin: 20px 0 0;\">Quellen:<br \/>\n        <a href=\"https:\/\/www.image-line.com\/fl-studio-learning\/fl-studio-online-manual\/html\/chansettings_sampler.htm\" rel=\"noopener\">Image-Line: Sampler Channel Settings (Declicking)<\/a> \u00b7<br \/>\n        <a href=\"https:\/\/ffmpeg.org\/ffmpeg-filters.html\" rel=\"noopener\">ffmpeg Filters Documentation (adeclick, acrossfade)<\/a>\n    <\/p>\n<p class=\"kf-klein\" style=\"font-size: 0.8rem; margin: 14px 0 0;\">In einem dichten Testmix mit Sechzehntel-Hi-Hats ragten 7 von 20 harten Schnitten heraus und wurden gemeldet; die \u00fcbrigen gingen im Hochton der Hats unter. Auch sehr harte, gewollte Eins\u00e4tze wie ein synthetischer Kick, der mit einem Sprung beginnt, k\u00f6nnen gemeldet werden.<\/p>\n<\/div>\n<p><script>\n(function () {\n    'use strict';\n    const T = {\"dezimal\":\",\",\"einleitung\":\"Durchsucht eine Audiodatei nach Knacksern: harten Schnitten, einzelnen Ausrei\u00dfern und Stellen, an denen die Wellenform pl\u00f6tzlich die Richtung wechselt. Zu jeder Stelle stehen Zeit, wie weit sie aus ihrer Umgebung herausragt, ihr Pegel oberhalb von 5\u00a0kHz und die Blendenl\u00e4nge, die einen Klick dieser Gr\u00f6\u00dfe zudeckt. Die Datei wird im Browser gelesen und nicht hochgeladen.\",\"zone_titel\":\"Audiodatei ausw\u00e4hlen\",\"knopf_datei\":\"Datei w\u00e4hlen\",\"zone_hinweis\":\"WAV und AIFF werden Wert f\u00fcr Wert gelesen; FLAC, MP3, M4A, Ogg und Opus laufen \u00fcber den Decoder des Browsers.\",\"status_lesen\":\"Datei wird gelesen \u2026\",\"status_dekodieren\":\"Wird dekodiert \u2026\",\"status_suchen\":\"Suche l\u00e4uft \u2026\",\"k_stellen\":\"Gefundene Stellen\",\"k_arten\":\"Spr\u00fcnge \\\/ Knicke\",\"k_max\":\"Ragt heraus bis\",\"k_rand\":\"Harter Anfang oder Ende\",\"wert_weich\":\"keiner\",\"urteil_sauber\":\"Keine Knackser gefunden\",\"urteil_stellen\":\"Gefundene Stellen: {n}\",\"urteil_text_sauber\":\"Keine Stelle ragt als einzelner Ausrei\u00dfer aus ihrer Umgebung heraus. Ein Sprung, der im Hochton des umgebenden Materials untergeht, wird nicht gemeldet; siehe die Grenzen unten.\",\"urteil_text_stellen\":\"Jede Stelle unten ist ein einzelner Ausrei\u00dfer, den die vorangehenden Werte nicht vorhersagen. Bei einem Schnitt dr\u00fcckt die genannte Blendenl\u00e4nge einen Klick dieser Gr\u00f6\u00dfe in die Umgebung; ein Knackser mitten in einer Aufnahme braucht einen Entknackser oder eine Reparatur von Hand.\",\"h_liste\":\"Stellen\",\"sp_zeit\":\"Zeit\",\"sp_art\":\"Art\",\"sp_kanal\":\"Kanal\",\"sp_ueber\":\"Ragt heraus um\",\"sp_klick\":\"Klick oberhalb 5\u00a0kHz\",\"sp_blende\":\"Blende, die ihn zudeckt\",\"art_sprung\":\"Sprung\",\"art_knick\":\"Knick\",\"art_anfang\":\"harter Anfang\",\"art_ende\":\"hartes Ende\",\"blende_mehr\":\"mehr als 20\u00a0ms\",\"mehr\":\"Die Liste zeigt {n} von {gesamt} Stellen; das kopierte Ergebnis enth\u00e4lt dieselbe Auswahl.\",\"knopf_kopieren\":\"Ergebnis kopieren\",\"kopiert\":\"kopiert\",\"kopieren_fehler\":\"Kopieren nicht m\u00f6glich\",\"bericht_kopf\":\"Knacksersuche\",\"fehler_format\":\"Diese Datei geh\u00f6rt zu keinem der hier gelesenen Formate: WAV, AIFF, FLAC, MP3, M4A, Ogg oder Opus.\",\"fehler_lesen\":\"Die Datei lie\u00df sich nicht lesen oder dekodieren.\",\"fehler_kurz\":\"Die Datei ist zu kurz f\u00fcr eine Suche.\",\"h_erklaerung\":\"Wie gesucht wird\",\"erkl_verfahren\":\"Ein linearer Pr\u00e4diktor 16. Ordnung, f\u00fcr jeweils 2048 Werte neu angepasst, sagt jeden Wert aus den vorigen voraus. Tonales Material verschwindet im Vorhersagefehler, ein Sprung bleibt stehen. Gemeldet wird eine Stelle, wenn der Fehler in ihrem 1-ms-Block mindestens 12\u00a0dB \u00fcber dem lauteren der beiden Umfelder von je 20\u00a0ms liegt und mindestens 18\u00a0dB sch\u00e4rfer ist als der Fehler rundherum innerhalb von 1\u00a0ms. Die zweite Regel trennt einen einzelnen Ausrei\u00dfer von einem Schlagzeugeinsatz, der sich \u00fcber viele Werte verteilt.\",\"erkl_art\":\"Ein Sprung ist ein pl\u00f6tzlicher Wertewechsel, wie bei einem Schnitt mitten in einer Schwingung. Ein Knick beh\u00e4lt den Wert, kehrt aber die Richtung um: In der Messung zum Artikel \u00fcber Crossfades klickte ein Schnitt genau im fallenden Nulldurchgang trotzdem mit \u221237,44\u00a0dBFS. Der Pegel oberhalb von 5\u00a0kHz ist dasselbe Ma\u00df wie in diesem Artikel.\",\"erkl_blende\":\"Die Blendenl\u00e4nge stammt aus derselben Messung: Eine Blende von 1\u00a0ms senkte den Klick um 33,08\u00a0dB, dar\u00fcber brachte jede Verdopplung weitere 6\u00a0dB, bis 59,35\u00a0dB bei 20\u00a0ms, unabh\u00e4ngig von der Tonh\u00f6he des Materials. Das Werkzeug w\u00e4hlt die k\u00fcrzeste L\u00e4nge, die den Klick um seine \u00dcberh\u00f6hung plus 6\u00a0dB senkt.\",\"erkl_adeclick\":\"adeclick aus ffmpeg arbeitet nach demselben Prinzip und ersetzt Ausrei\u00dfer durch Interpolation. In der Vorgabe ver\u00e4nderte es in einem dichten Testmix ohne einen einzigen Knackser trotzdem 10,6\u00a0% aller Werte, und diese Suche fand dort danach 18 Stellen statt einer; in einer Fl\u00e4che beseitigte es 15 von 20 Schnitten und ver\u00e4nderte 1,4\u00a0% der Werte.\",\"quellen_titel\":\"Quellen\",\"grenze\":\"In einem dichten Testmix mit Sechzehntel-Hi-Hats ragten 7 von 20 harten Schnitten heraus und wurden gemeldet; die \u00fcbrigen gingen im Hochton der Hats unter. Auch sehr harte, gewollte Eins\u00e4tze wie ein synthetischer Kick, der mit einem Sprung beginnt, k\u00f6nnen gemeldet werden.\",\"lesen_h\":\"Artikel dazu\",\"lesen_1_vor\":\"Wie laut der Klick am Sto\u00df ist und welche Blendenl\u00e4nge ihn zudeckt, misst der Artikel \u201e\",\"lesen_1_titel\":\"Crossfades und Schnitte\",\"lesen_1_nach\":\"\u201c.\"};<\/p>\n<p>    \/\/ KERN-ANFANG ------------------------------------------------------------\n    \/\/ Knack- und Schnittstellen-Finder. Mass wie im Artikel \"Crossfades und Schnitte\":\n    \/\/ die Spitze oberhalb von 5 kHz, wo tiefe Toene nichts beitragen.\n    var HP_HZ = 5000;\n    var BLOCK_S = 0.001;           \/\/ 1-ms-Bloecke fuer Spitze und Umfeld\n    var UMFELD_S = 0.02;           \/\/ je 20 ms vor und nach der Stelle\n    var LUECKE_S = 0.002;          \/\/ die 2 ms um die Stelle zaehlen nicht zum Umfeld\n    var SCHWELLE_DB = 12;          \/\/ Ueberhoehung des Restfehlers ueber das lautere der beiden Umfelder\n    var SCHAERFE_DB = 18;          \/\/ Spitze gegen den RMS des Restfehlers in +-1 ms ohne die Spitze\n    \/\/ Kalibriert an Testdateien: Schnitte in einer Flaeche 18 bis 51 dB Ueberhoehung und 20 bis\n    \/\/ 29 dB Schaerfe; Hi-Hat- und Kick-Einsaetze erreichen Ueberhoehung, aber nur 8 bis 17,5 dB\n    \/\/ Schaerfe, weil sie Rauschstoesse ueber viele Werte sind und kein einzelner Ausreisser.\n    var BODEN_DBFS = -90;          \/\/ darunter wird nichts gemeldet\n    var ZUSAMMEN_S = 0.005;        \/\/ Treffer innerhalb 5 ms sind eine Stelle\n    var HOECHSTENS = 500;\n    \/\/ Blendenlaenge -> Senkung des Klicks gegen den harten Schnitt, gemessen im Artikel\n    \/\/ (220 Hz, Spitze oberhalb 5 kHz): -14,24 dBFS ohne Blende.\n    var BLENDE = [[0.1, 8.85], [0.25, 21.07], [0.5, 26.80], [1, 33.08], [2, 39.28], [5, 47.24], [10, 53.30], [20, 59.35]];<\/p>\n<p>    \/\/ Butterworth-Hochpass 4. Ordnung als zwei Biquads (RBJ), Q 0,5412 und 1,3066\n    function hochpass(fs, f0) {\n        return [0.5411961, 1.3065630].map(function (q) {\n            var w = 2 * Math.PI * f0 \/ fs, c = Math.cos(w), a = Math.sin(w) \/ (2 * q), a0 = 1 + a;\n            return { b0: (1 + c) \/ 2 \/ a0, b1: -(1 + c) \/ a0, b2: (1 + c) \/ 2 \/ a0, a1: -2 * c \/ a0, a2: (1 - a) \/ a0 };\n        });\n    }\n    function filtern(x, stufen) {\n        var y = new Float32Array(x.length), i, s;\n        for (i = 0; i < x.length; i++) { y[i] = x[i]; }\n        for (s = 0; s < stufen.length; s++) {\n            var k = stufen[s], z1 = 0, z2 = 0;\n            for (i = 0; i < y.length; i++) {\n                var v = y[i], o = k.b0 * v + z1;\n                z1 = k.b1 * v - k.a1 * o + z2;\n                z2 = k.b2 * v - k.a2 * o;\n                y[i] = o;\n            }\n        }\n        return y;\n    }\n    function median(werte) {\n        var a = Array.prototype.slice.call(werte).sort(function (x, y) { return x - y; });\n        return a.length ? a[Math.floor(a.length \/ 2)] : 0;\n    }\n    function db(v) { return v > 0 ? 20 * Math.log10(v) : -Infinity; }<\/p>\n<p>    \/\/ Lineare Praediktion: je Block von 2048 Werten ein Praediktor der Ordnung 16\n    \/\/ (Autokorrelation mit Hann-Fenster, Levinson-Durbin). Der Restfehler enthaelt, was\n    \/\/ sich aus den vorigen Werten nicht vorhersagen laesst - tonales Material faellt\n    \/\/ weg, ein Sprung bleibt stehen.\n    var LPC_ORDNUNG = 16, LPC_BLOCK = 2048;\n    function levinson(r, p) {\n        var a = new Float64Array(p + 1), e = r[0], i, j;\n        a[0] = 1;\n        if (e <= 0) { return a; }\n        for (i = 1; i <= p; i++) {\n            var acc = r[i];\n            for (j = 1; j < i; j++) { acc += a[j] * r[i - j]; }\n            var k = -acc \/ e, neu = new Float64Array(a);\n            for (j = 1; j < i; j++) { neu[j] = a[j] + k * a[i - j]; }\n            neu[i] = k;\n            a = neu;\n            e *= (1 - k * k);\n            if (e <= 0) { break; }\n        }\n        return a;\n    }\n    function restfehler(x) {\n        var n = x.length, e = new Float32Array(n), p = LPC_ORDNUNG, B = LPC_BLOCK, w = new Float64Array(B), start, i, j;\n        for (i = 0; i < B; i++) { w[i] = 0.5 - 0.5 * Math.cos(2 * Math.PI * i \/ (B - 1)); }\n        for (start = 0; start < n; start += B) {\n            var ende = Math.min(n, start + B), m = ende - start, r = new Float64Array(p + 1), g = new Float64Array(m);\n            for (i = 0; i < m; i++) { g[i] = x[start + i] * w[i]; }\n            for (j = 0; j <= p; j++) { var s = 0; for (i = j; i < m; i++) { s += g[i] * g[i - j]; } r[j] = s; }\n            r[0] *= 1.000001;   \/\/ leichte Daempfung gegen schlecht bedingte Bloecke\n            var a = levinson(r, p);\n            for (i = start; i < ende; i++) {\n                var v = x[i];\n                for (j = 1; j <= p &#038;&#038; i - j >= 0; j++) { v += a[j] * x[i - j]; }\n                e[i] = v;\n            }\n        }\n        return e;\n    }<\/p>\n<p>    function blendeFuer(senkung) {\n        for (var i = 0; i < BLENDE.length; i++) { if (BLENDE[i][1] >= senkung) { return BLENDE[i][0]; } }\n        return null;   \/\/ mehr als 20 ms\n    }<\/p>\n<p>    \/\/ Sucht Stellen in einem Kanal auf dem Restfehler der Praediktion. Gibt [{i, spitze, umfeld,\n    \/\/ ueber, sprung, knick}] zurueck; spitze ist die Spitze oberhalb 5 kHz wie im Artikel.\n    function kanalSuchen(x, fs, stufen) {\n        var h = restfehler(x), hp = filtern(x, stufen), bl = Math.max(1, Math.round(BLOCK_S * fs)), nb = Math.floor(h.length \/ bl);\n        var spitze = new Float32Array(nb), ort = new Int32Array(nb), b, i;\n        for (b = 0; b < nb; b++) {\n            var m = 0, mi = b * bl;\n            for (i = b * bl; i < (b + 1) * bl; i++) { var a = h[i] < 0 ? -h[i] : h[i]; if (a > m) { m = a; mi = i; } }\n            spitze[b] = m; ort[b] = mi;\n        }\n        var um = Math.round(UMFELD_S \/ BLOCK_S), lu = Math.round(LUECKE_S \/ BLOCK_S), treffer = [];\n        var grenze = Math.pow(10, SCHWELLE_DB \/ 20), boden = Math.pow(10, BODEN_DBFS \/ 20);\n        for (b = um + lu; b < nb - um - lu; b++) {\n            var s = spitze[b];\n            if (s < boden) { continue; }\n            \/\/ nur lokale Maxima pruefen\n            if (s < spitze[b - 1] || s < spitze[b + 1]) { continue; }\n            var vor = median(spitze.subarray(b - lu - um, b - lu)), nach = median(spitze.subarray(b + lu + 1, b + lu + 1 + um));\n            var bezug = Math.max(vor, nach, 1e-9);\n            if (s < grenze * bezug) { continue; }\n            var kk = ort[b], e2 = 0, ne = 0;\n            for (i = kk - bl; i <= kk + bl; i++) {\n                if (i < 0 || i >= h.length || Math.abs(i - kk) <= 2) { continue; }\n                e2 += h[i] * h[i]; ne++;\n            }\n            var schaerfe = db(s \/ Math.sqrt(e2 \/ Math.max(1, ne) + 1e-30));\n            if (schaerfe < SCHAERFE_DB) { continue; }\n            \/\/ Sprung und Knick im Original um die Stelle (+-3 Werte um die Hochpass-Spitze)\n            var k = ort[b], sprung = 0, knick = 0, d1typ = [];\n            for (i = Math.max(2, k - 3); i <= Math.min(x.length - 1, k + 3); i++) {\n                sprung = Math.max(sprung, Math.abs(x[i] - x[i - 1]));\n                knick = Math.max(knick, Math.abs(x[i] - 2 * x[i - 1] + x[i - 2]));\n            }\n            for (i = Math.max(1, k - Math.round(0.005 * fs)); i < Math.min(x.length, k + Math.round(0.005 * fs)); i++) {\n                if (Math.abs(i - k) > 4) { d1typ.push(Math.abs(x[i] - x[i - 1])); }\n            }\n            var d1med = median(d1typ), hpSpitze = 0;\n            for (i = Math.max(0, k - bl); i < Math.min(hp.length, k + bl); i++) { hpSpitze = Math.max(hpSpitze, Math.abs(hp[i])); }\n            treffer.push({ i: k, spitze: hpSpitze, umfeld: bezug, ueber: db(s \/ bezug), schaerfe: schaerfe, sprung: sprung, knick: knick,\n                           art: sprung > 4 * d1med + 1e-7 ? 'sprung' : 'knick' });\n        }\n        return treffer;\n    }<\/p>\n<p>    \/\/ Sucht in allen Kanaelen, fasst Stellen innerhalb von 5 ms zusammen.\n    function suchen(kanaele, fs) {\n        var stufen = hochpass(fs, Math.min(HP_HZ, fs * 0.45)), alle = [];\n        kanaele.forEach(function (x, c) { kanalSuchen(x, fs, stufen).forEach(function (t) { t.kanal = c + 1; alle.push(t); }); });\n        alle.sort(function (a, b) { return a.i - b.i; });\n        var stellen = [], zs = Math.round(ZUSAMMEN_S * fs);\n        alle.forEach(function (t) {\n            var letzte = stellen[stellen.length - 1];\n            if (letzte && t.i - letzte.i <= zs) {\n                if (letzte.kanaele.indexOf(t.kanal) === -1) { letzte.kanaele.push(t.kanal); }\n                if (t.ueber > letzte.ueber) { var kn = letzte.kanaele; Object.keys(t).forEach(function (k) { letzte[k] = t[k]; }); letzte.kanaele = kn; }\n                return;\n            }\n            t.kanaele = [t.kanal];\n            stellen.push(t);\n        });\n        stellen.forEach(function (s) {\n            s.zeit_s = s.i \/ fs;\n            s.spitze_dbfs = db(s.spitze);\n            s.sprung_dbfs = db(s.sprung);\n            \/\/ Blende, die den Klick in der Messung um die Ueberhoehung plus 6 dB senkt\n            s.blende_ms = blendeFuer(s.ueber + 6);\n        });\n        \/\/ Anfang und Ende: Sprung aus der Stille bzw. in die Stille\n        var rand = [];\n        var n = kanaele[0].length, a0 = 0, e0 = 0;\n        kanaele.forEach(function (x) { a0 = Math.max(a0, Math.abs(x[0])); e0 = Math.max(e0, Math.abs(x[n - 1])); });\n        if (a0 >= 0.01) { rand.push({ art: 'anfang', zeit_s: 0, sprung_dbfs: db(a0) }); }\n        if (e0 >= 0.01) { rand.push({ art: 'ende', zeit_s: (n - 1) \/ fs, sprung_dbfs: db(e0) }); }\n        var gesamt = stellen.length;\n        stellen.sort(function (a, b) { return b.ueber - a.ueber; });\n        var gezeigt = stellen.slice(0, HOECHSTENS).sort(function (a, b) { return a.i - b.i; });\n        return { stellen: gezeigt, gesamt: gesamt, rand: rand, dauer_s: n \/ fs, fs: fs, kanaele: kanaele.length };\n    }\n    function str(u8, o, l) { var s = ''; for (var i = 0; i < l &#038;&#038; o + i < u8.length; i++) { s += String.fromCharCode(u8[o + i]); } return s; }\n    function le16(u8, o) { return u8[o] | (u8[o + 1] << 8); }\n    function le32(u8, o) { return (u8[o] | (u8[o + 1] << 8) | (u8[o + 2] << 16)) + ((u8[o + 3] << 24) >>> 0); }\n    function be16(u8, o) { return (u8[o] << 8) | u8[o + 1]; }\n    function be32(u8, o) { return ((u8[o] << 24) >>> 0) + (u8[o + 1] << 16) + (u8[o + 2] << 8) + u8[o + 3]; }\n\n    function pcm(puffer, start, laenge, anzahl, bytes, gleit, klein) {\n        var rahmen = Math.floor(laenge \/ (bytes * anzahl)), raus = [], c, i;\n        for (c = 0; c < anzahl; c++) { raus.push(new Float32Array(rahmen)); }\n        var dv = new DataView(puffer, start, rahmen * bytes * anzahl), u8 = new Uint8Array(puffer, start, rahmen * bytes * anzahl);\n        var teiler = Math.pow(2, bytes * 8 - 1), o = 0, v;\n        for (i = 0; i < rahmen; i++) {\n            for (c = 0; c < anzahl; c++) {\n                if (gleit) { v = bytes === 4 ? dv.getFloat32(o, klein) : dv.getFloat64(o, klein); }\n                else if (bytes === 1) { v = (klein ? u8[o] - 128 : dv.getInt8(o)) \/ teiler; }\n                else if (bytes === 2) { v = dv.getInt16(o, klein) \/ teiler; }\n                else if (bytes === 3) {\n                    var w = klein ? (u8[o] | (u8[o + 1] << 8) | (u8[o + 2] << 16)) : ((u8[o] << 16) | (u8[o + 1] << 8) | u8[o + 2]);\n                    if (w &#038; 0x800000) { w -= 0x1000000; }\n                    v = w \/ teiler;\n                } else { v = dv.getInt32(o, klein) \/ teiler; }\n                raus[c][i] = v;\n                o += bytes;\n            }\n        }\n        return raus;\n    }\n\n    function wavLesen(puffer) {\n        var u8 = new Uint8Array(puffer), p = 12, fmt = null, ds64 = null;\n        while (p + 8 <= u8.length) {\n            var id = str(u8, p, 4), l = le32(u8, p + 4);\n            if (id === 'ds64' &#038;&#038; l >= 16) { ds64 = le32(u8, p + 16) + le32(u8, p + 20) * 4294967296; }\n            if (id === 'fmt ') {\n                var tag = le16(u8, p + 8);\n                if (tag === 0xFFFE && l >= 26) { tag = le16(u8, p + 32); }\n                fmt = { tag: tag, anzahl: le16(u8, p + 10), rate: le32(u8, p + 12), bits: le16(u8, p + 22) };\n            } else if (id === 'data') {\n                if (l === 0xFFFFFFFF && ds64 !== null) { l = ds64; }\n                if (!fmt || (fmt.tag !== 1 && fmt.tag !== 3)) { return null; }\n                var bytes = fmt.bits \/ 8;\n                if ([1, 2, 3, 4, 8].indexOf(bytes) === -1 || !fmt.anzahl) { return null; }\n                return { format: 'WAV', rate: fmt.rate, kanaele: pcm(puffer, p + 8, Math.min(l, u8.length - p - 8), fmt.anzahl, bytes, fmt.tag === 3, true) };\n            }\n            if (l === 0xFFFFFFFF) { break; }\n            p += 8 + l + (l & 1);\n        }\n        return null;\n    }<\/p>\n<p>    function aiffLesen(puffer, aifc) {\n        var u8 = new Uint8Array(puffer), p = 12, comm = null;\n        while (p + 8 <= u8.length) {\n            var id = str(u8, p, 4), l = be32(u8, p + 4);\n            if (id === 'COMM') {\n                var exp = be16(u8, p + 16) &#038; 0x7FFF, hi = be32(u8, p + 18), lo = be32(u8, p + 22);\n                comm = { anzahl: be16(u8, p + 8), bits: be16(u8, p + 14), rate: Math.round((hi * 4294967296 + lo) * Math.pow(2, exp - 16383 - 63)),\n                         art: aifc &#038;&#038; l >= 22 ? str(u8, p + 26, 4) : 'NONE' };\n            } else if (id === 'SSND' && comm) {\n                var versatz = be32(u8, p + 8), start = p + 16 + versatz, laenge = Math.min(l - 8 - versatz, u8.length - start);\n                var gleit = \/^(fl32|FL32|fl64|FL64)$\/.test(comm.art);\n                if (!gleit && ['NONE', 'twos', 'sowt'].indexOf(comm.art) === -1) { return null; }\n                var bytes = gleit ? (comm.art.slice(2) === '32' ? 4 : 8) : Math.ceil(comm.bits \/ 8);\n                return { format: 'AIFF', rate: comm.rate, kanaele: pcm(puffer, start, laenge, comm.anzahl, bytes, gleit, comm.art === 'sowt') };\n            }\n            p += 8 + l + (l & 1);\n        }\n        return null;\n    }<\/p>\n<p>    \/\/ Abtastrate komprimierter Formate aus dem Kopf, damit der Decoder nicht umrechnet.\n    \/\/ Rate aus dem ersten Eintrag der Box stsd (AudioSampleEntry, 16.16 bei +32 ab Eintrag). Der Kopf kann am\n    \/\/ Dateiende stehen, deshalb wird die ganze Datei durchsucht. Raten ueber 65535 Hz passen nicht in das Feld.\n    function mp4Rate(puffer) {\n        var u = new Uint8Array(puffer), i;\n        for (i = 4; i + 46 < u.length; i++) {\n            if (u[i] === 0x73 &#038;&#038; u[i + 1] === 0x74 &#038;&#038; u[i + 2] === 0x73 &#038;&#038; u[i + 3] === 0x64) {\n                var r = (u[i + 44] << 8) | u[i + 45];\n                return r >= 3000 ? r : null;\n            }\n        }\n        return null;\n    }<\/p>\n<p>    function kopfRate(puffer) {\n        var u8 = new Uint8Array(puffer, 0, Math.min(puffer.byteLength, 1 << 20)), k = str(u8, 0, 4), p = 0;\n        if (k === 'ID3' &#038;&#038; u8.length > 10) {\n            p = 10 + ((u8[6] & 0x7f) << 21 | (u8[7] &#038; 0x7f) << 14 | (u8[8] &#038; 0x7f) << 7 | (u8[9] &#038; 0x7f));\n            if (str(u8, p, 4) === 'fLaC') { k = 'fLaC'; }\n        }\n        if (k === 'fLaC') { var s = p + 8; return { format: 'FLAC', rate: (u8[s + 10] << 12) | (u8[s + 11] << 4) | (u8[s + 12] >> 4) }; }\n        if (k === 'OggS' && u8.length > 64) {\n            var d = 27 + u8[26];\n            if (str(u8, d + 1, 6) === 'vorbis') { return { format: 'Ogg Vorbis', rate: le32(u8, d + 12) }; }\n            if (str(u8, d, 8) === 'OpusHead') { return { format: 'Opus', rate: 48000 }; }\n            return { format: 'Ogg', rate: null };\n        }\n        if (str(u8, 4, 4) === 'ftyp') { return { format: 'MP4', rate: mp4Rate(puffer) }; }\n        for (var j = p; j < Math.min(u8.length - 4, p + 65536); j++) {\n            if (u8[j] !== 0xFF || (u8[j + 1] &#038; 0xE0) !== 0xE0) { continue; }\n            var version = (u8[j + 1] >> 3) & 3, schicht = (u8[j + 1] >> 1) & 3, ri = (u8[j + 2] >> 2) & 3, bri = u8[j + 2] >> 4;\n            if (version === 1 || schicht === 0 || ri === 3 || bri === 15 || bri === 0) { continue; }\n            var basis = [44100, 48000, 32000][ri];\n            return { format: 'MP3', rate: version === 3 ? basis : (version === 2 ? basis \/ 2 : basis \/ 4) };\n        }\n        return { format: null, rate: null };\n    }<\/p>\n<p>    \/\/ WAV und AIFF selbst lesen; null heisst: den Decoder des Browsers fragen.\n    function direktLesen(puffer) {\n        var u8 = new Uint8Array(puffer);\n        if (u8.length < 16) { return null; }\n        var k = str(u8, 0, 4), a = str(u8, 8, 4);\n        if ((k === 'RIFF' || k === 'RF64' || k === 'BW64') &#038;&#038; a === 'WAVE') { return wavLesen(puffer); }\n        if (k === 'FORM' &#038;&#038; (a === 'AIFF' || a === 'AIFC')) { return aiffLesen(puffer, a === 'AIFC'); }\n        return null;\n    }\n\n    \/\/ KERN-ENDE --------------------------------------------------------------\n\n\n    function el(id) { return document.getElementById(id); }\n    var NB = '\u00a0', ZEILEN = 100;\n    function satz(k, w) { return (T[k] || '').replace(\/\\{(\\w+)\\}\/g, function (_, x) { return w &#038;&#038; w[x] !== undefined ? w[x] : ''; }); }\n    function zahl(v, st) {\n        if (v === -Infinity) { return '\u2212\u221e'; }\n        if (v === null || v === undefined || !isFinite(v)) { return '\u2013'; }\n        var s = Number(v).toFixed(st === undefined ? 1 : st);\n        if (\/^-0(\\.0+)?$\/.test(s)) { s = s.slice(1); }\n        s = s.replace('-', '\u2212');\n        return T.dezimal === ',' ? s.replace('.', ',') : s;\n    }\n    function zeit(s) {\n        var m = Math.floor(s \/ 60), r = s - 60 * m;\n        return m + ':' + (r < 10 ? '0' : '') + zahl(r, 3);\n    }\n    function blendeText(ms) { return ms === null || ms === undefined ? T.blende_mehr : zahl(ms, ms < 1 ? 2 : 0) + NB + 'ms'; }\n\n    function zeilenDaten(r) {\n        var z = [];\n        r.rand.forEach(function (x) {\n            \/\/ Der Wert ist der erste bzw. letzte Abtastwert, kein Klick oberhalb 5 kHz: er gehoert zur Art.\n            z.push({ zeit: x.zeit_s, werte: [zeit(x.zeit_s), T['art_' + x.art] + ' (' + zahl(x.sprung_dbfs, 1) + NB + 'dBFS)', '\u2013', '\u2013', '\u2013', '\u2013'] });\n        });\n        r.stellen.forEach(function (s) {\n            z.push({ zeit: s.zeit_s, werte: [zeit(s.zeit_s), T['art_' + s.art], s.kanaele.join(', '), zahl(s.ueber, 1) + NB + 'dB',\n                zahl(s.spitze_dbfs, 1) + NB + 'dBFS', blendeText(s.blende_ms)] });\n        });\n        z.sort(function (a, b) { return a.zeit - b.zeit; });\n        return z;\n    }\n\n    function bericht(e) {\n        var r = e.r, z = [T.bericht_kopf + ': ' + (e.name || '')];\n        z.push(satz(r.gesamt + r.rand.length ? 'urteil_stellen' : 'urteil_sauber', { n: r.gesamt }));\n        zeilenDaten(r).forEach(function (x) { z.push(x.werte.join(' | ')); });\n        return z.join('\\n');\n    }\n\n    function kachel(name, wert) {\n        var d = document.createElement('div'); d.className = 'kf-kachel';\n        var a = document.createElement('div'); a.className = 'kf-kachel-name'; a.textContent = name;\n        var b = document.createElement('div'); b.className = 'kf-kachel-wert'; b.textContent = wert;\n        d.appendChild(a); d.appendChild(b);\n        return d;\n    }\n\n    function darstellen(e) {\n        var r = e.r;\n        if (!el('kf-kacheln')) { return e; }\n        var k = el('kf-kacheln'), spr = 0, kn = 0, max = null;\n        r.stellen.forEach(function (s) { if (s.art === 'sprung') { spr++; } else { kn++; } if (max === null || s.ueber > max) { max = s.ueber; } });\n        k.textContent = '';\n        k.appendChild(kachel(T.k_stellen, String(r.gesamt)));\n        k.appendChild(kachel(T.k_arten, spr + ' \/ ' + kn));\n        k.appendChild(kachel(T.k_max, max === null ? '\u2013' : zahl(max, 1) + NB + 'dB'));\n        k.appendChild(kachel(T.k_rand, r.rand.length ? String(r.rand.length) : T.wert_weich));\n        var u = el('kf-urteil'), stufe = r.gesamt + r.rand.length ? 'stellen' : 'sauber';\n        u.className = 'kf-urteil kf-u-' + stufe;\n        u.textContent = '';\n        var kopf = document.createElement('div'); kopf.className = 'kf-urteil-kopf';\n        kopf.textContent = satz('urteil_' + stufe, { n: r.gesamt });\n        var txt = document.createElement('div'); txt.className = 'kf-klein';\n        txt.textContent = T['urteil_text_' + stufe];\n        u.appendChild(kopf); u.appendChild(txt);\n        var t = el('kf-liste'), namen = [T.sp_zeit, T.sp_art, T.sp_kanal, T.sp_ueber, T.sp_klick, T.sp_blende], alle = zeilenDaten(r);\n        t.textContent = '';\n        alle.slice(0, ZEILEN).forEach(function (zeile) {\n            var tr = document.createElement('tr');\n            zeile.werte.forEach(function (w, i) {\n                var td = document.createElement('td');\n                if (i > 1) { td.className = 'kf-wert'; td.setAttribute('data-name', namen[i]); }\n                td.textContent = w; tr.appendChild(td);\n            });\n            t.appendChild(tr);\n        });\n        el('kf-mehr').textContent = alle.length > ZEILEN ? satz('mehr', { n: ZEILEN, gesamt: alle.length }) : (r.gesamt > r.stellen.length ? satz('mehr', { n: r.stellen.length, gesamt: r.gesamt }) : '');\n        el('kf-ausgabe').hidden = false;\n        el('kf-fehler').hidden = true;\n        return e;\n    }<\/p>\n<p>    function fehlerZeigen(s) {\n        var f = el('kf-fehler');\n        if (!f) { return; }\n        f.textContent = s; f.hidden = false;\n        el('kf-ausgabe').hidden = true;\n        el('kf-status').textContent = '';\n    }<\/p>\n<p>    function dekodieren(puffer, rate) {\n        return new Promise(function (ok, schlecht) {\n            var Ctx = window.OfflineAudioContext || window.webkitOfflineAudioContext;\n            if (!Ctx) { schlecht(new Error('webaudio')); return; }\n            var ctx, fertig = false;\n            try { ctx = new Ctx(1, 1, rate); } catch (x) { ctx = new Ctx(1, 1, 48000); }\n            function gut(b) { if (!fertig) { fertig = true; ok(b); } }\n            function nein(x) { if (!fertig) { fertig = true; schlecht(x || new Error('dekodieren')); } }\n            setTimeout(function () { nein(new Error('zeit')); }, 60000);\n            try { var p = ctx.decodeAudioData(puffer, gut, nein); if (p && p.then) { p.then(gut, nein); } } catch (x) { nein(x); }\n        });\n    }<\/p>\n<p>    var tick = typeof MessageChannel !== 'undefined' ? new MessageChannel() : null, schlange = [];\n    if (tick) { tick.port1.onmessage = function () { var f = schlange.shift(); if (f) { f(); } }; }\n    function spaeter(f) { if (tick) { schlange.push(f); tick.port2.postMessage(0); } else { setTimeout(f, 0); } }<\/p>\n<p>    var letztes = null;\n    function verarbeiten(puffer, name) {\n        var info = null;\n        try { info = direktLesen(puffer); } catch (x) { info = null; }\n        var weg;\n        if (info) { weg = Promise.resolve(info); }\n        else {\n            var kopf = kopfRate(puffer);\n            if (!kopf.format) { fehlerZeigen(T.fehler_format); return Promise.resolve(null); }\n            if (el('kf-status')) { el('kf-status').textContent = T.status_dekodieren; }\n            var rate = kopf.rate && kopf.rate >= 3000 && kopf.rate <= 768000 ? kopf.rate : 48000;\n            weg = dekodieren(puffer.slice(0), rate).then(function (b) {\n                var k = [];\n                for (var c = 0; c < b.numberOfChannels; c++) { k.push(b.getChannelData(c)); }\n                return { format: kopf.format, rate: b.sampleRate, kanaele: k };\n            });\n        }\n        return weg.then(function (inf) {\n            if (!inf.kanaele.length || inf.kanaele[0].length < inf.rate * 0.05) { fehlerZeigen(T.fehler_kurz); return null; }\n            if (el('kf-status')) { el('kf-status').textContent = T.status_suchen; }\n            return new Promise(function (ok) {\n                spaeter(function () {\n                    var r = suchen(inf.kanaele, inf.rate);\n                    if (el('kf-status')) { el('kf-status').textContent = ''; }\n                    letztes = { name: name || '', r: r };\n                    ok(darstellen(letztes));\n                });\n            });\n        }, function () { fehlerZeigen(T.fehler_lesen); return null; });\n    }\n\n    function dateiNehmen(datei) {\n        if (!datei) { return; }\n        var leser = new FileReader();\n        el('kf-status').textContent = T.status_lesen;\n        leser.onload = function () { verarbeiten(leser.result, datei.name); };\n        leser.onerror = function () { fehlerZeigen(T.fehler_lesen); };\n        try { leser.readAsArrayBuffer(datei); } catch (x) { fehlerZeigen(T.fehler_lesen); }\n    }\n\n    window.LW_TEST = window.LW_TEST || {};\n    window.LW_TEST.KF = { T: T, suchen: suchen, direktLesen: direktLesen, blendeFuer: blendeFuer, verarbeiten: verarbeiten,\n        bericht: bericht, zeilenDaten: zeilenDaten, letztes: function () { return letztes; } };\n\n    var zone = el('kf-zone'), eingabe = el('kf-datei'), knopf = el('kf-knopf');\n    if (!zone || !eingabe || !knopf) { return; }\n    knopf.addEventListener('click', function () { eingabe.click(); });\n    eingabe.addEventListener('change', function () { dateiNehmen(eingabe.files &#038;&#038; eingabe.files[0]); eingabe.value = ''; });\n    ['dragenter', 'dragover'].forEach(function (t) { zone.addEventListener(t, function (ev) { ev.preventDefault(); zone.classList.add('kf-ueber'); }); });\n    ['dragleave', 'drop'].forEach(function (t) { zone.addEventListener(t, function (ev) { ev.preventDefault(); zone.classList.remove('kf-ueber'); }); });\n    zone.addEventListener('drop', function (ev) { ev.preventDefault(); dateiNehmen(ev.dataTransfer &#038;&#038; ev.dataTransfer.files &#038;&#038; ev.dataTransfer.files[0]); });\n    var kop = el('kf-kopieren'), kopiert = el('kf-kopiert');\n    if (kop) {\n        kop.addEventListener('click', function () {\n            if (!letztes) { return; }\n            var t = bericht(letztes);\n            if (navigator.clipboard &#038;&#038; navigator.clipboard.writeText) {\n                navigator.clipboard.writeText(t).then(function () { kopiert.textContent = T.kopiert; }, function () { kopiert.textContent = T.kopieren_fehler; });\n            } else { kopiert.textContent = T.kopieren_fehler; }\n        });\n    }\n})();\n<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Durchsucht eine Audiodatei \u00fcber den Vorhersagefehler einer linearen Pr\u00e4diktion nach Knacksern, harten Schnitten und Stellen, an denen die Wellenform pl\u00f6tzlich umkehrt. Nennt je Stelle Zeit, \u00dcberh\u00f6hung, Pegel oberhalb von 5\u00a0kHz und die Blendenl\u00e4nge, die sie zudeckt, gest\u00fctzt auf eine Messung zu Crossfades.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":9283,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template-tool-base.php","meta":{"footnotes":""},"tags":[92903],"class_list":["post-20216","page","type-page","status-publish","hentry","tag-music-production-de"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Knack- und Schnittstellen-Finder: Knackser, harte Schnitte und Knicke in einer Audiodatei finden - Lukas Wojcik - Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/click-splice-finder-hard-cuts-slope-breaks\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Knack- und Schnittstellen-Finder: Knackser, harte Schnitte und Knicke in einer Audiodatei finden - Lukas Wojcik - Blog\" \/>\n<meta property=\"og:description\" content=\"Durchsucht eine Audiodatei \u00fcber den Vorhersagefehler einer linearen Pr\u00e4diktion nach Knacksern, harten Schnitten und Stellen, an denen die Wellenform pl\u00f6tzlich umkehrt. Nennt je Stelle Zeit, \u00dcberh\u00f6hung, Pegel oberhalb von 5\u00a0kHz und die Blendenl\u00e4nge, die sie zudeckt, gest\u00fctzt auf eine Messung zu Crossfades.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/click-splice-finder-hard-cuts-slope-breaks\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-23T19:54:53+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"2 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/click-splice-finder-hard-cuts-slope-breaks\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/click-splice-finder-hard-cuts-slope-breaks\\\/\",\"name\":\"Knack- und Schnittstellen-Finder: Knackser, harte Schnitte und Knicke in einer Audiodatei finden - Lukas Wojcik - Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-09-23T18:43:04+00:00\",\"dateModified\":\"2026-09-23T19:54:53+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/click-splice-finder-hard-cuts-slope-breaks\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/click-splice-finder-hard-cuts-slope-breaks\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/click-splice-finder-hard-cuts-slope-breaks\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Toolbox\",\"item\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/toolbox-2\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Knack- und Schnittstellen-Finder: Knackser, harte Schnitte und Knicke in einer Audiodatei finden\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/\",\"name\":\"Lukas Wojcik - Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#\\\/schema\\\/person\\\/895f7604f9b6b71aad9bba33af28d0f9\",\"name\":\"Lukas Wojcik\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"contentUrl\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\",\"width\":424,\"height\":636,\"caption\":\"Lukas Wojcik\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/wp-content\\\/uploads\\\/2026\\\/07\\\/lw-x2.jpg\"},\"sameAs\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Knack- und Schnittstellen-Finder: Knackser, harte Schnitte und Knicke in einer Audiodatei finden - Lukas Wojcik - Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/click-splice-finder-hard-cuts-slope-breaks\/","og_locale":"en_US","og_type":"article","og_title":"Knack- und Schnittstellen-Finder: Knackser, harte Schnitte und Knicke in einer Audiodatei finden - Lukas Wojcik - Blog","og_description":"Durchsucht eine Audiodatei \u00fcber den Vorhersagefehler einer linearen Pr\u00e4diktion nach Knacksern, harten Schnitten und Stellen, an denen die Wellenform pl\u00f6tzlich umkehrt. Nennt je Stelle Zeit, \u00dcberh\u00f6hung, Pegel oberhalb von 5\u00a0kHz und die Blendenl\u00e4nge, die sie zudeckt, gest\u00fctzt auf eine Messung zu Crossfades.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/click-splice-finder-hard-cuts-slope-breaks\/","og_site_name":"Lukas Wojcik - Blog","article_modified_time":"2026-09-23T19:54:53+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"2 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/click-splice-finder-hard-cuts-slope-breaks\/","url":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/click-splice-finder-hard-cuts-slope-breaks\/","name":"Knack- und Schnittstellen-Finder: Knackser, harte Schnitte und Knicke in einer Audiodatei finden - Lukas Wojcik - Blog","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"datePublished":"2026-09-23T18:43:04+00:00","dateModified":"2026-09-23T19:54:53+00:00","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/click-splice-finder-hard-cuts-slope-breaks\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/click-splice-finder-hard-cuts-slope-breaks\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/click-splice-finder-hard-cuts-slope-breaks\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.lukaswojcik.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Toolbox","item":"https:\/\/www.lukaswojcik.com\/blog\/toolbox-2\/"},{"@type":"ListItem","position":3,"name":"Knack- und Schnittstellen-Finder: Knackser, harte Schnitte und Knicke in einer Audiodatei finden"}]},{"@type":"WebSite","@id":"https:\/\/www.lukaswojcik.com\/blog\/#website","url":"https:\/\/www.lukaswojcik.com\/blog\/","name":"Lukas Wojcik - Blog","description":"","publisher":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.lukaswojcik.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.lukaswojcik.com\/blog\/#\/schema\/person\/895f7604f9b6b71aad9bba33af28d0f9","name":"Lukas Wojcik","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","contentUrl":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg","width":424,"height":636,"caption":"Lukas Wojcik"},"logo":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/07\/lw-x2.jpg"},"sameAs":["https:\/\/www.lukaswojcik.com\/blog"]}]}},"_links":{"self":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/20216","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/comments?post=20216"}],"version-history":[{"count":3,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/20216\/revisions"}],"predecessor-version":[{"id":20302,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/20216\/revisions\/20302"}],"up":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/9283"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=20216"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=20216"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}