{"id":20217,"date":"2026-09-23T20:43:07","date_gmt":"2026-09-23T18:43:07","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/narzedzia\/click-splice-finder-hard-cuts-slope-breaks\/"},"modified":"2026-09-23T21:54:57","modified_gmt":"2026-09-23T19:54:57","slug":"click-splice-finder-hard-cuts-slope-breaks","status":"publish","type":"page","link":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/click-splice-finder-hard-cuts-slope-breaks\/","title":{"rendered":"Wykrywacz trzask\u00f3w i ci\u0119\u0107: trzaski, twarde ci\u0119cia i za\u0142amania w pliku audio"},"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;\">Przeszukuje plik audio pod k\u0105tem trzask\u00f3w: twardych ci\u0119\u0107, pojedynczych odstaj\u0105cych pr\u00f3bek i miejsc, w kt\u00f3rych przebieg nagle zmienia kierunek. Przy ka\u017cdym miejscu podaje czas, o ile odstaje od otoczenia, poziom powy\u017cej 5\u00a0kHz i d\u0142ugo\u015b\u0107 przenikania, kt\u00f3ra zakrywa trzask tej wielko\u015bci. Plik jest odczytywany w przegl\u0105darce i nie trafia na serwer.<\/p>\n<div id=\"kf-zone\" class=\"kf-zone\">\n<p style=\"margin: 0 0 12px; color: var(--text-primary, #e8e8ee); font-weight: 700;\">Wyb\u00f3r pliku audio<\/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;\">Wyb\u00f3r pliku<\/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 i AIFF s\u0105 odczytywane pr\u00f3bka po pr\u00f3bce; FLAC, MP3, M4A, Ogg i Opus przechodz\u0105 przez dekoder przegl\u0105darki.<\/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\">Miejsca<\/div>\n<div class=\"kf-tabelle\">\n<table class=\"kf-karten\">\n<thead>\n<tr>\n<th>Czas<\/th>\n<th>Rodzaj<\/th>\n<th>Kana\u0142<\/th>\n<th>Odstaje o<\/th>\n<th>Trzask powy\u017cej 5\u00a0kHz<\/th>\n<th>Przenikanie, kt\u00f3re go zakrywa<\/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\">Kopiowanie wyniku<\/button><br \/>\n        <span id=\"kf-kopiert\" class=\"kf-klein\" style=\"margin-left: 10px;\"><\/span>\n    <\/div>\n<div class=\"kf-h\">Jak przebiega wyszukiwanie<\/div>\n<p class=\"kf-klein\" style=\"margin: 0 0 6px;\">Predyktor liniowy rz\u0119du 16, dopasowywany na nowo co 2048 pr\u00f3bek, przewiduje ka\u017cd\u0105 pr\u00f3bk\u0119 z poprzednich. Materia\u0142 tonalny znika w b\u0142\u0119dzie predykcji, skok zostaje. Miejsce jest zg\u0142aszane, gdy b\u0142\u0105d w jego bloku 1\u00a0ms le\u017cy co najmniej 12\u00a0dB ponad g\u0142o\u015bniejszym z dw\u00f3ch otocze\u0144 po 20\u00a0ms i jest co najmniej 18\u00a0dB ostrzejszy ni\u017c b\u0142\u0105d wok\u00f3\u0142 w granicach 1\u00a0ms. Druga regu\u0142a oddziela pojedynczy wyj\u0105tek od uderzenia perkusyjnego, kt\u00f3re rozk\u0142ada si\u0119 na wiele pr\u00f3bek.<\/p>\n<p class=\"kf-klein\" style=\"margin: 0 0 6px;\">Skok to nag\u0142a zmiana warto\u015bci, jak przy ci\u0119ciu w \u015brodku drgania. Za\u0142amanie zachowuje warto\u015b\u0107, ale odwraca kierunek: w pomiarze do artyku\u0142u o przenikaniach ci\u0119cie dok\u0142adnie w opadaj\u0105cym przej\u015bciu przez zero i tak dawa\u0142o trzask \u221237,44\u00a0dBFS. Poziom powy\u017cej 5\u00a0kHz to ta sama miara co w tym artykule.<\/p>\n<p class=\"kf-klein\" style=\"margin: 0 0 6px;\">D\u0142ugo\u015b\u0107 przenikania pochodzi z tego samego pomiaru: przenikanie 1\u00a0ms obni\u017ca\u0142o trzask o 33,08\u00a0dB, powy\u017cej ka\u017cde podwojenie dawa\u0142o kolejne 6\u00a0dB, a\u017c do 59,35\u00a0dB przy 20\u00a0ms, niezale\u017cnie od wysoko\u015bci materia\u0142u. Narz\u0119dzie wybiera najkr\u00f3tsz\u0105 d\u0142ugo\u015b\u0107, kt\u00f3ra obni\u017ca trzask o jego nadwy\u017ck\u0119 nad otoczeniem plus 6\u00a0dB.<\/p>\n<p class=\"kf-klein\" style=\"margin: 0 0 6px;\">adeclick z ffmpeg dzia\u0142a na tej samej zasadzie i zast\u0119puje wyj\u0105tki interpolacj\u0105. W ustawieniach domy\u015blnych zmieni\u0142 w g\u0119stym miksie testowym bez ani jednego trzasku mimo to 10,6\u00a0% wszystkich pr\u00f3bek, a to wyszukiwanie znalaz\u0142o tam potem 18 miejsc zamiast jednego; w plamie usun\u0105\u0142 15 z 20 ci\u0119\u0107 i zmieni\u0142 1,4\u00a0% pr\u00f3bek.<\/p>\n<p style=\"font-weight: 700; color: var(--text-primary, #e8e8ee); font-size: 0.95rem; margin: 24px 0 8px;\">Artyku\u0142y na ten temat<\/p>\n<p class=\"kf-klein\" style=\"margin: 0 0 6px;\">Jak g\u0142o\u015bny jest trzask na styku i jaka d\u0142ugo\u015b\u0107 przenikania go zakrywa, mierzy artyku\u0142 \u201e<span class=\"lw-artikel-geplant\">Przenikania i ci\u0119cia<\/span>\u201d.<\/p>\n<p class=\"kf-klein\" style=\"margin: 20px 0 0;\">\u0179r\u00f3d\u0142a:<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;\">W g\u0119stym miksie testowym z hi-hatami w szesnastkach odstawa\u0142o i zosta\u0142o zg\u0142oszonych 7 z 20 twardych ci\u0119\u0107; pozosta\u0142e gin\u0119\u0142y w g\u00f3rze pasma hi-hat\u00f3w. Zg\u0142aszane mog\u0105 by\u0107 tak\u017ce bardzo twarde, zamierzone ataki, jak syntetyczna stopa zaczynaj\u0105ca si\u0119 skokiem.<\/p>\n<\/div>\n<p><script>\n(function () {\n    'use strict';\n    const T = {\"dezimal\":\",\",\"einleitung\":\"Przeszukuje plik audio pod k\u0105tem trzask\u00f3w: twardych ci\u0119\u0107, pojedynczych odstaj\u0105cych pr\u00f3bek i miejsc, w kt\u00f3rych przebieg nagle zmienia kierunek. Przy ka\u017cdym miejscu podaje czas, o ile odstaje od otoczenia, poziom powy\u017cej 5\u00a0kHz i d\u0142ugo\u015b\u0107 przenikania, kt\u00f3ra zakrywa trzask tej wielko\u015bci. Plik jest odczytywany w przegl\u0105darce i nie trafia na serwer.\",\"zone_titel\":\"Wyb\u00f3r pliku audio\",\"knopf_datei\":\"Wyb\u00f3r pliku\",\"zone_hinweis\":\"WAV i AIFF s\u0105 odczytywane pr\u00f3bka po pr\u00f3bce; FLAC, MP3, M4A, Ogg i Opus przechodz\u0105 przez dekoder przegl\u0105darki.\",\"status_lesen\":\"Odczyt pliku \u2026\",\"status_dekodieren\":\"Dekodowanie \u2026\",\"status_suchen\":\"Wyszukiwanie \u2026\",\"k_stellen\":\"Znalezione miejsca\",\"k_arten\":\"Skoki \\\/ za\u0142amania\",\"k_max\":\"Odstaje najwy\u017cej o\",\"k_rand\":\"Twardy pocz\u0105tek lub koniec\",\"wert_weich\":\"brak\",\"urteil_sauber\":\"Brak trzask\u00f3w\",\"urteil_stellen\":\"Znalezione miejsca: {n}\",\"urteil_text_sauber\":\"\u017badne miejsce nie odstaje od otoczenia jako pojedynczy wyj\u0105tek. Skok, kt\u00f3ry ginie w g\u00f3rze pasma otaczaj\u0105cego materia\u0142u, nie jest zg\u0142aszany; zob. ograniczenia poni\u017cej.\",\"urteil_text_stellen\":\"Ka\u017cde miejsce poni\u017cej to pojedynczy wyj\u0105tek, kt\u00f3rego nie przewiduj\u0105 wcze\u015bniejsze pr\u00f3bki. Przy ci\u0119ciu podana d\u0142ugo\u015b\u0107 przenikania wciska trzask tej wielko\u015bci w otoczenie; trzask w \u015brodku nagrania wymaga filtra usuwaj\u0105cego trzaski albo r\u0119cznej naprawy.\",\"h_liste\":\"Miejsca\",\"sp_zeit\":\"Czas\",\"sp_art\":\"Rodzaj\",\"sp_kanal\":\"Kana\u0142\",\"sp_ueber\":\"Odstaje o\",\"sp_klick\":\"Trzask powy\u017cej 5\u00a0kHz\",\"sp_blende\":\"Przenikanie, kt\u00f3re go zakrywa\",\"art_sprung\":\"skok\",\"art_knick\":\"za\u0142amanie\",\"art_anfang\":\"twardy pocz\u0105tek\",\"art_ende\":\"twardy koniec\",\"blende_mehr\":\"ponad 20\u00a0ms\",\"mehr\":\"Lista pokazuje {n} z {gesamt} miejsc; skopiowany wynik zawiera ten sam wyb\u00f3r.\",\"knopf_kopieren\":\"Kopiowanie wyniku\",\"kopiert\":\"skopiowano\",\"kopieren_fehler\":\"kopiowanie niemo\u017cliwe\",\"bericht_kopf\":\"Wyszukiwanie trzask\u00f3w\",\"fehler_format\":\"Ten plik nie nale\u017cy do odczytywanych tu format\u00f3w: WAV, AIFF, FLAC, MP3, M4A, Ogg i Opus.\",\"fehler_lesen\":\"Odczyt lub dekodowanie pliku zako\u0144czy\u0142o si\u0119 b\u0142\u0119dem.\",\"fehler_kurz\":\"Plik jest za kr\u00f3tki do przeszukania.\",\"h_erklaerung\":\"Jak przebiega wyszukiwanie\",\"erkl_verfahren\":\"Predyktor liniowy rz\u0119du 16, dopasowywany na nowo co 2048 pr\u00f3bek, przewiduje ka\u017cd\u0105 pr\u00f3bk\u0119 z poprzednich. Materia\u0142 tonalny znika w b\u0142\u0119dzie predykcji, skok zostaje. Miejsce jest zg\u0142aszane, gdy b\u0142\u0105d w jego bloku 1\u00a0ms le\u017cy co najmniej 12\u00a0dB ponad g\u0142o\u015bniejszym z dw\u00f3ch otocze\u0144 po 20\u00a0ms i jest co najmniej 18\u00a0dB ostrzejszy ni\u017c b\u0142\u0105d wok\u00f3\u0142 w granicach 1\u00a0ms. Druga regu\u0142a oddziela pojedynczy wyj\u0105tek od uderzenia perkusyjnego, kt\u00f3re rozk\u0142ada si\u0119 na wiele pr\u00f3bek.\",\"erkl_art\":\"Skok to nag\u0142a zmiana warto\u015bci, jak przy ci\u0119ciu w \u015brodku drgania. Za\u0142amanie zachowuje warto\u015b\u0107, ale odwraca kierunek: w pomiarze do artyku\u0142u o przenikaniach ci\u0119cie dok\u0142adnie w opadaj\u0105cym przej\u015bciu przez zero i tak dawa\u0142o trzask \u221237,44\u00a0dBFS. Poziom powy\u017cej 5\u00a0kHz to ta sama miara co w tym artykule.\",\"erkl_blende\":\"D\u0142ugo\u015b\u0107 przenikania pochodzi z tego samego pomiaru: przenikanie 1\u00a0ms obni\u017ca\u0142o trzask o 33,08\u00a0dB, powy\u017cej ka\u017cde podwojenie dawa\u0142o kolejne 6\u00a0dB, a\u017c do 59,35\u00a0dB przy 20\u00a0ms, niezale\u017cnie od wysoko\u015bci materia\u0142u. Narz\u0119dzie wybiera najkr\u00f3tsz\u0105 d\u0142ugo\u015b\u0107, kt\u00f3ra obni\u017ca trzask o jego nadwy\u017ck\u0119 nad otoczeniem plus 6\u00a0dB.\",\"erkl_adeclick\":\"adeclick z ffmpeg dzia\u0142a na tej samej zasadzie i zast\u0119puje wyj\u0105tki interpolacj\u0105. W ustawieniach domy\u015blnych zmieni\u0142 w g\u0119stym miksie testowym bez ani jednego trzasku mimo to 10,6\u00a0% wszystkich pr\u00f3bek, a to wyszukiwanie znalaz\u0142o tam potem 18 miejsc zamiast jednego; w plamie usun\u0105\u0142 15 z 20 ci\u0119\u0107 i zmieni\u0142 1,4\u00a0% pr\u00f3bek.\",\"quellen_titel\":\"\u0179r\u00f3d\u0142a\",\"grenze\":\"W g\u0119stym miksie testowym z hi-hatami w szesnastkach odstawa\u0142o i zosta\u0142o zg\u0142oszonych 7 z 20 twardych ci\u0119\u0107; pozosta\u0142e gin\u0119\u0142y w g\u00f3rze pasma hi-hat\u00f3w. Zg\u0142aszane mog\u0105 by\u0107 tak\u017ce bardzo twarde, zamierzone ataki, jak syntetyczna stopa zaczynaj\u0105ca si\u0119 skokiem.\",\"lesen_h\":\"Artyku\u0142y na ten temat\",\"lesen_1_vor\":\"Jak g\u0142o\u015bny jest trzask na styku i jaka d\u0142ugo\u015b\u0107 przenikania go zakrywa, mierzy artyku\u0142 \u201e\",\"lesen_1_titel\":\"Przenikania i ci\u0119cia\",\"lesen_1_nach\":\"\u201d.\"};<\/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>Przeszukuje plik audio pod k\u0105tem trzask\u00f3w, twardych ci\u0119\u0107 i miejsc, w kt\u00f3rych przebieg nagle si\u0119 odwraca, na podstawie b\u0142\u0119du predykcji liniowej. Przy ka\u017cdym miejscu podaje czas, nadwy\u017ck\u0119 nad otoczeniem, poziom powy\u017cej 5\u00a0kHz i d\u0142ugo\u015b\u0107 przenikania, kt\u00f3ra je zakrywa, na podstawie pomiaru przenika\u0144.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":9284,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template-tool-base.php","meta":{"footnotes":""},"tags":[92906],"class_list":["post-20217","page","type-page","status-publish","hentry","tag-music-production-pl"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Wykrywacz trzask\u00f3w i ci\u0119\u0107: trzaski, twarde ci\u0119cia i za\u0142amania w pliku audio - 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\/pl\/narzedzia\/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=\"Wykrywacz trzask\u00f3w i ci\u0119\u0107: trzaski, twarde ci\u0119cia i za\u0142amania w pliku audio - Lukas Wojcik - Blog\" \/>\n<meta property=\"og:description\" content=\"Przeszukuje plik audio pod k\u0105tem trzask\u00f3w, twardych ci\u0119\u0107 i miejsc, w kt\u00f3rych przebieg nagle si\u0119 odwraca, na podstawie b\u0142\u0119du predykcji liniowej. Przy ka\u017cdym miejscu podaje czas, nadwy\u017ck\u0119 nad otoczeniem, poziom powy\u017cej 5\u00a0kHz i d\u0142ugo\u015b\u0107 przenikania, kt\u00f3ra je zakrywa, na podstawie pomiaru przenika\u0144.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/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:57+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\\\/pl\\\/narzedzia\\\/click-splice-finder-hard-cuts-slope-breaks\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/click-splice-finder-hard-cuts-slope-breaks\\\/\",\"name\":\"Wykrywacz trzask\u00f3w i ci\u0119\u0107: trzaski, twarde ci\u0119cia i za\u0142amania w pliku audio - Lukas Wojcik - Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-09-23T18:43:07+00:00\",\"dateModified\":\"2026-09-23T19:54:57+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/click-splice-finder-hard-cuts-slope-breaks\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/click-splice-finder-hard-cuts-slope-breaks\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/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-3\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Wykrywacz trzask\u00f3w i ci\u0119\u0107: trzaski, twarde ci\u0119cia i za\u0142amania w pliku audio\"}]},{\"@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":"Wykrywacz trzask\u00f3w i ci\u0119\u0107: trzaski, twarde ci\u0119cia i za\u0142amania w pliku audio - 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\/pl\/narzedzia\/click-splice-finder-hard-cuts-slope-breaks\/","og_locale":"en_US","og_type":"article","og_title":"Wykrywacz trzask\u00f3w i ci\u0119\u0107: trzaski, twarde ci\u0119cia i za\u0142amania w pliku audio - Lukas Wojcik - Blog","og_description":"Przeszukuje plik audio pod k\u0105tem trzask\u00f3w, twardych ci\u0119\u0107 i miejsc, w kt\u00f3rych przebieg nagle si\u0119 odwraca, na podstawie b\u0142\u0119du predykcji liniowej. Przy ka\u017cdym miejscu podaje czas, nadwy\u017ck\u0119 nad otoczeniem, poziom powy\u017cej 5\u00a0kHz i d\u0142ugo\u015b\u0107 przenikania, kt\u00f3ra je zakrywa, na podstawie pomiaru przenika\u0144.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/click-splice-finder-hard-cuts-slope-breaks\/","og_site_name":"Lukas Wojcik - Blog","article_modified_time":"2026-09-23T19:54:57+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\/pl\/narzedzia\/click-splice-finder-hard-cuts-slope-breaks\/","url":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/click-splice-finder-hard-cuts-slope-breaks\/","name":"Wykrywacz trzask\u00f3w i ci\u0119\u0107: trzaski, twarde ci\u0119cia i za\u0142amania w pliku audio - Lukas Wojcik - Blog","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"datePublished":"2026-09-23T18:43:07+00:00","dateModified":"2026-09-23T19:54:57+00:00","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/click-splice-finder-hard-cuts-slope-breaks\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/click-splice-finder-hard-cuts-slope-breaks\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/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-3\/"},{"@type":"ListItem","position":3,"name":"Wykrywacz trzask\u00f3w i ci\u0119\u0107: trzaski, twarde ci\u0119cia i za\u0142amania w pliku audio"}]},{"@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\/20217","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=20217"}],"version-history":[{"count":3,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/20217\/revisions"}],"predecessor-version":[{"id":20303,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/20217\/revisions\/20303"}],"up":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/9284"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=20217"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=20217"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}