{"id":19926,"date":"2026-09-17T20:06:56","date_gmt":"2026-09-17T18:06:56","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/narzedzia\/stereo-correlation-mid-side-meter\/"},"modified":"2026-09-17T20:06:56","modified_gmt":"2026-09-17T18:06:56","slug":"stereo-correlation-mid-side-meter","status":"publish","type":"page","link":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/stereo-correlation-mid-side-meter\/","title":{"rendered":"Miernik korelacji stereo i mid\/side: korelacja w pasmach, udzia\u0142 sygna\u0142u bocznego, zgodno\u015b\u0107 mono i balans kana\u0142\u00f3w z pliku audio"},"content":{"rendered":"<div class=\"lw-sk\" id=\"sk-wurzel\" style=\"background: var(--bg-panel, #1e1e24); padding: 25px; border-radius: 8px; border: 1px solid var(--border, #2a2a35);\">\n<style>\n.lw-sk .sk-zone { border: 2px dashed var(--border, #2a2a35); border-radius: 8px; padding: 24px 16px; text-align: center; transition: border-color 0.15s, background 0.15s; }\n.lw-sk .sk-zone.sk-ueber { border-color: var(--accent, #2ba6df); background: var(--bg-body, #14141a); }\n.lw-sk .sk-kacheln { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 10px; margin: 14px 0 4px; }\n.lw-sk .sk-kachel { background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-radius: 8px; padding: 11px 14px; min-width: 0; }\n.lw-sk .sk-kachel-name { font-size: 0.74rem; color: var(--text-secondary, #a0a0b0); text-transform: uppercase; letter-spacing: 0.4px; }\n.lw-sk .sk-kachel-wert { font-family: monospace; font-size: 1.4rem; font-weight: 700; color: var(--text-primary, #e8e8ee); line-height: 1.25; white-space: nowrap; }\n.lw-sk .sk-einheit { font-size: 0.8rem; font-weight: 400; color: var(--text-secondary, #a0a0b0); margin-left: 4px; }\n.lw-sk .sk-tabelle { overflow-x: auto; }\n.lw-sk table { border-collapse: collapse; width: 100%; font-size: 0.86rem; }\n.lw-sk th, .lw-sk td { text-align: right; padding: 6px 10px; border-bottom: 1px solid var(--border, #2a2a35); white-space: nowrap; }\n.lw-sk th:first-child, .lw-sk td:first-child { text-align: left; }\n.lw-sk th { color: var(--text-primary, #e8e8ee); }\n.lw-sk td { color: var(--text-primary, #e8e8ee); font-family: monospace; }\n.lw-sk td.sk-name { font-family: inherit; color: var(--text-secondary, #a0a0b0); }\n.lw-sk .sk-ok { color: var(--ok, #7ee787) !important; }\n.lw-sk .sk-warn { color: var(--sk-warn); }\n.lw-sk .sk-fail { color: var(--fail, #ff7b72) !important; }\n.lw-sk { --sk-warn: #e8a33d; }\n:root[data-theme=\"light\"] .lw-sk { --sk-warn: #8f5300; }\n.lw-sk .sk-befund { background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-left-width: 3px; border-radius: 8px; padding: 11px 14px; margin: 0 0 8px; }\n.lw-sk .sk-befund.sk-b-ok { border-left-color: var(--ok, #7ee787); }\n.lw-sk .sk-befund.sk-b-warn { border-left-color: var(--sk-warn); }\n.lw-sk .sk-befund.sk-b-fail { border-left-color: var(--fail, #ff7b72); }\n.lw-sk .sk-befund b { color: var(--text-primary, #e8e8ee); }\n.lw-sk .sk-balken { height: 8px; background: var(--bg-body, #14141a); border: 1px solid var(--border, #2a2a35); border-radius: 4px; overflow: hidden; }\n.lw-sk .sk-balken > div { height: 100%; width: 0; background: var(--accent, #2ba6df); }\n.lw-sk .sk-h { font-weight: 700; color: var(--text-primary, #e8e8ee); font-size: 0.95rem; margin: 24px 0 8px; }\n.lw-sk .sk-klein { font-size: 0.84rem; color: var(--text-secondary, #a0a0b0); line-height: 1.55; }\n.lw-sk canvas { display: block; width: 100%; max-width: 100%; }\n.lw-sk a { color: var(--accent, #2ba6df); }\n@media (max-width: 480px) {\n    .lw-sk .sk-kacheln { grid-template-columns: 1fr 1fr; gap: 8px; }\n    .lw-sk .sk-kachel { padding: 10px 11px; }\n    .lw-sk .sk-kachel-wert { font-size: 1.15rem; }\n    .lw-sk th, .lw-sk td { padding: 6px 6px; }\n}\n<\/style>\n<p style=\"color: var(--text-secondary, #a0a0b0); margin-bottom: 18px;\">Miks mo\u017ce brzmie\u0107 szeroko w s\u0142uchawkach i rozpa\u015b\u0107 si\u0119 w mono. Miernik odczytuje plik audio w przegl\u0105darce i wyznacza korelacj\u0119 mi\u0119dzy kana\u0142em lewym i prawym, udzia\u0142 sygna\u0142u bocznego, strat\u0119 poziomu sumy mono oraz balans kana\u0142\u00f3w, \u0142\u0105cznie i w trzech pasmach cz\u0119stotliwo\u015bci, a do tego przebieg w czasie.<\/p>\n<div id=\"sk-zone\" class=\"sk-zone\">\n<p style=\"margin: 0 0 12px; color: var(--text-primary, #e8e8ee); font-weight: 700;\">Przeci\u0105gnij tutaj plik audio<\/p>\n<p>        <button id=\"sk-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=\"sk-datei\" type=\"file\" accept=\"audio\/*,.wav,.wave,.aif,.aiff,.flac,.mp3,.m4a,.mp4,.aac,.ogg,.oga,.opus\" hidden><\/p>\n<p class=\"sk-klein\" style=\"margin: 12px 0 0;\">Plik pozostaje w przegl\u0105darce, nic nie jest wysy\u0142ane. WAV, FLAC, MP3, M4A, OGG i Opus, o ile przegl\u0105darka je odtwarza.<\/p>\n<\/p><\/div>\n<div id=\"sk-status\" style=\"margin-top: 16px;\" hidden>\n<div id=\"sk-status-text\" data-mp-mask class=\"sk-klein\" style=\"margin-bottom: 6px;\"><\/div>\n<div class=\"sk-balken\">\n<div id=\"sk-fortschritt\"><\/div>\n<\/div><\/div>\n<div id=\"sk-ausgabe\" data-mp-mask style=\"margin-top: 18px;\" aria-live=\"polite\"><\/div>\n<div class=\"sk-h\">Co oznaczaj\u0105 liczby<\/div>\n<p class=\"sk-klein\" style=\"margin: 0 0 6px;\">Korelacja por\u00f3wnuje kana\u0142 lewy i prawy: +1 oznacza ten sam sygna\u0142 (w mono bez zmian), 0 oznacza niezale\u017cno\u015b\u0107, \u22121 oznacza przeciwn\u0105 faz\u0119, wtedy suma mono wygasza sygna\u0142. W wektoroskopie FL Studio wy\u015brodkowany sygna\u0142 mono pojawia si\u0119 jako linia pionowa, a linia pozioma oznacza przesuni\u0119cie faz o 180 stopni.<\/p>\n<p class=\"sk-klein\" style=\"margin: 0 0 6px;\">\u015arodek to (L + R) \u00f7 2, bok to (L \u2212 R) \u00f7 2. Podana warto\u015b\u0107 to odst\u0119p obu warto\u015bci skutecznych: \u22126 dB oznacza w\u0105sko, 0 dB oznacza, \u017ce bok i \u015brodek s\u0105 tak samo g\u0142o\u015bne. Narz\u0119dzia stereo wed\u0142ug podr\u0119cznika FL Studio dzia\u0142aj\u0105 w\u0142a\u015bnie na tej r\u00f3\u017cnicy mi\u0119dzy kana\u0142ami.<\/p>\n<p class=\"sk-klein\" style=\"margin: 0 0 6px;\">Suma mono to poziom (L + R) \u00f7 2 wobec warto\u015bci skutecznej sygna\u0142u stereo. 0 dB oznacza brak strat; kana\u0142y niezale\u017cne trac\u0105 oko\u0142o 3 dB, sk\u0142adowe w przeciwfazie wi\u0119cej.<\/p>\n<p class=\"sk-klein\" style=\"margin: 0 0 6px;\">Pasma powstaj\u0105 z filtr\u00f3w g\u00f3rno- i dolnoprzepustowych drugiego rz\u0119du, jednakowych dla obu kana\u0142\u00f3w. Wida\u0107 dzi\u0119ki temu, czy szerokie s\u0105 tylko wysokie tony, czy rozje\u017cd\u017ca si\u0119 tak\u017ce bas.<\/p>\n<p class=\"sk-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\/plugins\/Wave%20Candy.htm\" rel=\"noopener\">Wave Candy<\/a> \u00b7<br \/>\n        <a href=\"https:\/\/www.image-line.com\/fl-studio-learning\/fl-studio-online-manual\/html\/plugins\/Fruity%20Stereo%20Enhancer.htm\" rel=\"noopener\">Fruity Stereo Enhancer<\/a>\n    <\/p>\n<p class=\"sk-klein\" style=\"font-size: 0.8rem; margin: 14px 0 0;\">Wszystkie obliczenia odbywaj\u0105 si\u0119 w przegl\u0105darce, plik nie opuszcza komputera. Mierzony jest ca\u0142y plik, wi\u0119c kr\u00f3tkie fragmenty w przeciwfazie prawie nie wida\u0107 w warto\u015bci \u0142\u0105cznej i pojawiaj\u0105 si\u0119 w przebiegu. Kana\u0142y poza dwoma pierwszymi pozostaj\u0105 pomini\u0119te.<\/p>\n<\/div>\n<p><script>\n(function () {\n    'use strict';<\/p>\n<p>    const T = {\"einleitung\":\"Miks mo\u017ce brzmie\u0107 szeroko w s\u0142uchawkach i rozpa\u015b\u0107 si\u0119 w mono. Miernik odczytuje plik audio w przegl\u0105darce i wyznacza korelacj\u0119 mi\u0119dzy kana\u0142em lewym i prawym, udzia\u0142 sygna\u0142u bocznego, strat\u0119 poziomu sumy mono oraz balans kana\u0142\u00f3w, \u0142\u0105cznie i w trzech pasmach cz\u0119stotliwo\u015bci, a do tego przebieg w czasie.\",\"zone_titel\":\"Przeci\u0105gnij tutaj plik audio\",\"knopf_datei\":\"Wyb\u00f3r pliku\",\"zone_hinweis\":\"Plik pozostaje w przegl\u0105darce, nic nie jest wysy\u0142ane. WAV, FLAC, MP3, M4A, OGG i Opus, o ile przegl\u0105darka je odtwarza.\",\"status_lesen\":\"Trwa odczyt pliku \u2026\",\"status_dekodieren\":\"Trwa dekodowanie \u2026\",\"status_messen\":\"Trwa pomiar \u2026\",\"fehler_dekodieren\":\"Nie uda\u0142o si\u0119 zdekodowa\u0107 pliku. Przegl\u0105darka musi umie\u0107 odtworzy\u0107 ten format.\",\"fehler_webaudio\":\"Ta przegl\u0105darka nie oferuje dekodowania Web Audio.\",\"fehler_speicher\":\"Plik jest za du\u017cy dla pami\u0119ci przegl\u0105darki.\",\"fehler_leer\":\"Plik nie zawiera pr\u00f3bek.\",\"fehler_format\":\"Ten format nie jest tutaj czytelny: {detail}.\",\"datei_satz\":\"{name} \u00b7 {dauer} \u00b7 {rate} kHz \u00b7 {kanaele}\",\"kanal_mono\":\"1 kana\u0142\",\"kanal_stereo\":\"2 kana\u0142y\",\"kanal_mehr\":\"{n} kana\u0142\u00f3w (mierzone s\u0105 dwa pierwsze)\",\"k_korrelation\":\"Korelacja\",\"k_seite\":\"Bok wobec \u015brodka\",\"k_mono\":\"Suma mono\",\"k_balance\":\"Balans L wobec R\",\"h_befunde\":\"Wyniki\",\"h_baender\":\"Pasma\",\"sp_band\":\"Pasmo\",\"sp_korrelation\":\"Korelacja\",\"sp_seite\":\"Bok wobec \u015brodka (dB)\",\"sp_mono\":\"Suma mono (dB)\",\"sp_anteil\":\"Udzia\u0142 w energii (%)\",\"band_tief\":\"Niskie ({von}\u2013{bis} Hz)\",\"band_mitten\":\"\u015arednie ({von}\u2013{bis} Hz)\",\"band_hoehen\":\"Wysokie ({von}\u2013{bis} Hz)\",\"h_verlauf\":\"Przebieg korelacji\",\"verlauf_hinweis\":\"Jeden s\u0142upek na {fenster} s. Poni\u017cej zera le\u017cy {unter} % okien, najmniejsza warto\u015b\u0107 to {kleinste}.\",\"h_erklaerung\":\"Co oznaczaj\u0105 liczby\",\"erkl_korrelation\":\"Korelacja por\u00f3wnuje kana\u0142 lewy i prawy: +1 oznacza ten sam sygna\u0142 (w mono bez zmian), 0 oznacza niezale\u017cno\u015b\u0107, \u22121 oznacza przeciwn\u0105 faz\u0119, wtedy suma mono wygasza sygna\u0142. W wektoroskopie FL Studio wy\u015brodkowany sygna\u0142 mono pojawia si\u0119 jako linia pionowa, a linia pozioma oznacza przesuni\u0119cie faz o 180 stopni.\",\"erkl_seite\":\"\u015arodek to (L + R) \u00f7 2, bok to (L \u2212 R) \u00f7 2. Podana warto\u015b\u0107 to odst\u0119p obu warto\u015bci skutecznych: \u22126 dB oznacza w\u0105sko, 0 dB oznacza, \u017ce bok i \u015brodek s\u0105 tak samo g\u0142o\u015bne. Narz\u0119dzia stereo wed\u0142ug podr\u0119cznika FL Studio dzia\u0142aj\u0105 w\u0142a\u015bnie na tej r\u00f3\u017cnicy mi\u0119dzy kana\u0142ami.\",\"erkl_mono\":\"Suma mono to poziom (L + R) \u00f7 2 wobec warto\u015bci skutecznej sygna\u0142u stereo. 0 dB oznacza brak strat; kana\u0142y niezale\u017cne trac\u0105 oko\u0142o 3 dB, sk\u0142adowe w przeciwfazie wi\u0119cej.\",\"erkl_baender\":\"Pasma powstaj\u0105 z filtr\u00f3w g\u00f3rno- i dolnoprzepustowych drugiego rz\u0119du, jednakowych dla obu kana\u0142\u00f3w. Wida\u0107 dzi\u0119ki temu, czy szerokie s\u0105 tylko wysokie tony, czy rozje\u017cd\u017ca si\u0119 tak\u017ce bas.\",\"quellen_titel\":\"\u0179r\u00f3d\u0142a\",\"grenze\":\"Wszystkie obliczenia odbywaj\u0105 si\u0119 w przegl\u0105darce, plik nie opuszcza komputera. Mierzony jest ca\u0142y plik, wi\u0119c kr\u00f3tkie fragmenty w przeciwfazie prawie nie wida\u0107 w warto\u015bci \u0142\u0105cznej i pojawiaj\u0105 si\u0119 w przebiegu. Kana\u0142y poza dwoma pierwszymi pozostaj\u0105 pomini\u0119te.\",\"befund_mono\":\"Plik jest monofoniczny || Oba kana\u0142y s\u0105 takie same; korelacja, udzia\u0142 boku i suma mono nic tu nie m\u00f3wi\u0105.\",\"befund_gegenphase\":\"Kana\u0142y pracuj\u0105 przeciwko sobie || Korelacja wynosi {k}. W mono plik traci {mono} dB, du\u017ce cz\u0119\u015bci wygaszaj\u0105 si\u0119.\",\"befund_mono_verlust\":\"Suma mono traci {mono} dB || Przy korelacji {k} w mono s\u0142yszalnie ubywa poziomu. Dotyczy to system\u00f3w klubowych, telefon\u00f3w i wielu g\u0142o\u015bnik\u00f3w w sklepach.\",\"befund_bass_breit\":\"Bas nie stoi w \u015brodku || Do {hz} Hz korelacja wynosi {k}. Niskie sk\u0142adowe w boku trac\u0105 w mono najwi\u0119cej poziomu.\",\"befund_sehr_breit\":\"Bok g\u0142o\u015bniejszy ni\u017c \u015brodek || Sygna\u0142 boczny le\u017cy {seite} dB powy\u017cej \u015brodka. W s\u0142uchawkach brzmi to szeroko, w mono zostaje niewiele.\",\"befund_balance_links\":\"Lewy kana\u0142 jest g\u0142o\u015bniejszy || Lewy kana\u0142 le\u017cy {db} dB powy\u017cej prawego.\",\"befund_balance_rechts\":\"Prawy kana\u0142 jest g\u0142o\u015bniejszy || Prawy kana\u0142 le\u017cy {db} dB powy\u017cej lewego.\",\"befund_kurz\":\"Kr\u00f3tki fragment || Plik trwa {s} s. To ma\u0142o jak na wiarygodn\u0105 warto\u015b\u0107 \u0142\u0105czn\u0105.\",\"befund_gut\":\"Bez zastrze\u017ce\u0144 || Korelacja {k}, bok {seite} dB wobec \u015brodka. Suma mono pozostaje prawie w ca\u0142o\u015bci.\",\"dezimal\":\",\"};<\/p>\n<p>    \/\/ KERN-ANFANG ------------------------------------------------------------\n    \/\/ Korrelation, Mitte\/Seite und Mono-Summe, gesamt und in drei Baendern.\n    \/\/ Rein rechnend, ohne Dokument: derselbe Text laeuft im Browser und im Test.<\/p>\n<p>    var FENSTER_S = 0.4;        \/\/ Fensterlaenge des Verlaufs\n    var STUECK = 1 << 18;       \/\/ Abtastwerte je Rechenschritt\n    var BAENDER = [\n        { id: 'tief', von: 20, bis: 120 },\n        { id: 'mitten', von: 120, bis: 2000 },\n        { id: 'hoehen', von: 2000, bis: 20000 }\n    ];\n\n    function db(x) { return x > 0 ? 20 * Math.log(x) \/ Math.LN10 : -Infinity; }<\/p>\n<p>    \/\/ Biquad nach der Kochbuch-Formel (Butterworth, Q = 1\/sqrt(2)).\n    function biquad(art, f0, fs) {\n        var grenze = Math.min(Math.max(f0, 1), fs * 0.45);\n        var w0 = 2 * Math.PI * grenze \/ fs, c = Math.cos(w0), s = Math.sin(w0);\n        var alpha = s \/ (2 * Math.SQRT1_2);\n        var a0 = 1 + alpha, a1 = -2 * c, a2 = 1 - alpha, b0, b1, b2;\n        if (art === 'hp') {\n            b0 = (1 + c) \/ 2; b1 = -(1 + c); b2 = (1 + c) \/ 2;\n        } else {\n            b0 = (1 - c) \/ 2; b1 = 1 - c; b2 = (1 - c) \/ 2;\n        }\n        return { b0: b0 \/ a0, b1: b1 \/ a0, b2: b2 \/ a0, a1: a1 \/ a0, a2: a2 \/ a0 };\n    }\n    function zustand() { return { x1: 0, x2: 0, y1: 0, y2: 0 }; }\n    function schritt(k, z, x) {\n        var y = k.b0 * x + k.b1 * z.x1 + k.b2 * z.x2 - k.a1 * z.y1 - k.a2 * z.y2;\n        z.x2 = z.x1; z.x1 = x; z.y2 = z.y1; z.y1 = y;\n        return y;\n    }\n    \/\/ Ein Band: Hochpass und Tiefpass hintereinander, je zweiter Ordnung.\n    function bandFiltern(daten, fs, von, bis) {\n        var hp = biquad('hp', von, fs), lp = biquad('lp', bis, fs);\n        var zh = zustand(), zl = zustand(), aus = new Float32Array(daten.length);\n        for (var i = 0; i < daten.length; i++) { aus[i] = schritt(lp, zl, schritt(hp, zh, daten[i])); }\n        return aus;\n    }\n\n    function summenAnlegen() { return { ll: 0, rr: 0, lr: 0, mm: 0, ss: 0, n: 0 }; }\n    function summenNehmen(s, l, r) {\n        s.ll += l * l; s.rr += r * r; s.lr += l * r;\n        var m = (l + r) \/ 2, seite = (l - r) \/ 2;\n        s.mm += m * m; s.ss += seite * seite; s.n++;\n    }\n    function auswerten(s) {\n        var nenner = Math.sqrt(s.ll * s.rr);\n        var rmsL = Math.sqrt(s.ll \/ (s.n || 1)), rmsR = Math.sqrt(s.rr \/ (s.n || 1));\n        var rmsM = Math.sqrt(s.mm \/ (s.n || 1)), rmsS = Math.sqrt(s.ss \/ (s.n || 1));\n        var rmsStereo = Math.sqrt((s.ll + s.rr) \/ (2 * (s.n || 1)));\n        return {\n            korrelation: nenner > 0 ? s.lr \/ nenner : 0,\n            seite_db: db(rmsS) - db(rmsM),\n            mono_db: db(rmsM) - db(rmsStereo),\n            balance_db: db(rmsL) - db(rmsR),\n            rms_l_db: db(rmsL), rms_r_db: db(rmsR), rms_m_db: db(rmsM), rms_s_db: db(rmsS),\n            energie: s.ll + s.rr\n        };\n    }<\/p>\n<p>    \/\/ Messung in Stuecken, damit lange Dateien die Oberflaeche nicht anhalten.\n    function messungAnlegen(kanaele, fs) {\n        var l = kanaele[0], r = kanaele.length > 1 ? kanaele[1] : kanaele[0];\n        var n = Math.min(l.length, r.length);\n        var filter = BAENDER.map(function (b) {\n            return {\n                hpL: biquad('hp', b.von, fs), lpL: biquad('lp', b.bis, fs),\n                hpR: biquad('hp', b.von, fs), lpR: biquad('lp', b.bis, fs),\n                zhl: zustand(), zll: zustand(), zhr: zustand(), zlr: zustand(),\n                summen: summenAnlegen()\n            };\n        });\n        return {\n            l: l, r: r, n: n, fs: fs, pos: 0, kanaeleAnzahl: kanaele.length,\n            gesamt: summenAnlegen(), filter: filter, spitzeL: 0, spitzeR: 0,\n            fensterLaenge: Math.max(1, Math.round(FENSTER_S * fs)), fenster: summenAnlegen(), verlauf: []\n        };\n    }\n    function messungSchritt(m, wieviel) {\n        var ende = Math.min(m.n, m.pos + wieviel);\n        for (var i = m.pos; i < ende; i++) {\n            var l = m.l[i], r = m.r[i];\n            summenNehmen(m.gesamt, l, r);\n            summenNehmen(m.fenster, l, r);\n            if (Math.abs(l) > m.spitzeL) { m.spitzeL = Math.abs(l); }\n            if (Math.abs(r) > m.spitzeR) { m.spitzeR = Math.abs(r); }\n            for (var b = 0; b < m.filter.length; b++) {\n                var f = m.filter[b];\n                summenNehmen(f.summen, schritt(f.lpL, f.zll, schritt(f.hpL, f.zhl, l)), schritt(f.lpR, f.zlr, schritt(f.hpR, f.zhr, r)));\n            }\n            if (m.fenster.n >= m.fensterLaenge) {\n                m.verlauf.push(auswerten(m.fenster).korrelation);\n                m.fenster = summenAnlegen();\n            }\n        }\n        m.pos = ende;\n        return m.pos >= m.n;\n    }\n    function messungAuswerten(m) {\n        if (m.fenster.n > m.fensterLaenge \/ 4) { m.verlauf.push(auswerten(m.fenster).korrelation); }\n        var gesamt = auswerten(m.gesamt);\n        var energie = gesamt.energie || 1;\n        var baender = BAENDER.map(function (b, i) {\n            var e = auswerten(m.filter[i].summen);\n            e.id = b.id; e.von = b.von; e.bis = Math.min(b.bis, Math.round(m.fs * 0.45));\n            e.anteil = 100 * e.energie \/ energie;\n            return e;\n        });\n        var unter = m.verlauf.filter(function (k) { return k < 0; }).length;\n        var mono = m.kanaeleAnzahl < 2 || gesamt.korrelation > 0.99999 && gesamt.seite_db < -60;\n        return {\n            fs: m.fs, dauer: m.n \/ m.fs, kanaele: m.kanaeleAnzahl, mono: mono,\n            korrelation: gesamt.korrelation, seite_db: gesamt.seite_db, mono_db: gesamt.mono_db,\n            balance_db: gesamt.balance_db, rms_l_db: gesamt.rms_l_db, rms_r_db: gesamt.rms_r_db,\n            spitze_l_db: db(m.spitzeL), spitze_r_db: db(m.spitzeR),\n            baender: baender, verlauf: m.verlauf, fenster_s: FENSTER_S,\n            unter_null: m.verlauf.length ? 100 * unter \/ m.verlauf.length : 0,\n            kleinste: m.verlauf.length ? Math.min.apply(null, m.verlauf) : gesamt.korrelation\n        };\n    }\n    function analysiere(kanaele, fs) {\n        var m = messungAnlegen(kanaele, fs);\n        while (!messungSchritt(m, 1 << 20)) { \/* alles auf einmal *\/ }\n        return messungAuswerten(m);\n    }\n\n    \/\/ Befunde: Titel || Erklaerung, Art bestimmt die Farbe der Kante.\n    function befunde(e) {\n        var aus = [];\n        function nimm(schluessel, art, werte) {\n            var roh = String(T['befund_' + schluessel] || ''), teil = roh.split(' || ');\n            aus.push({ id: schluessel, art: art, titel: text0(teil[0], werte), text: text0(teil[1] || '', werte) });\n        }\n        if (e.mono) { nimm('mono', 'ok', {}); return aus; }\n        if (e.korrelation < -0.05) {\n            nimm('gegenphase', 'fail', { k: zahl(e.korrelation, 2), mono: zahl(e.mono_db, 1) });\n        } else if (e.mono_db < -3) {\n            nimm('mono_verlust', 'warn', { mono: zahl(e.mono_db, 1), k: zahl(e.korrelation, 2) });\n        }\n        var tief = e.baender[0];\n        if (tief.anteil > 1 && tief.korrelation < 0.5) {\n            nimm('bass_breit', 'warn', { k: zahl(tief.korrelation, 2), hz: zahl(tief.bis, 0) });\n        }\n        if (e.seite_db > 0.5) {\n            nimm('sehr_breit', 'warn', { seite: zahl(e.seite_db, 1) });\n        }\n        if (Math.abs(e.balance_db) > 1) {\n            nimm(e.balance_db > 0 ? 'balance_links' : 'balance_rechts', 'warn', { db: zahl(Math.abs(e.balance_db), 1) });\n        }\n        if (e.dauer < 5) { nimm('kurz', 'warn', { s: zahl(e.dauer, 1) }); }\n        if (!aus.length) { nimm('gut', 'ok', { k: zahl(e.korrelation, 2), seite: zahl(e.seite_db, 1) }); }\n        return aus;\n    }\n    \/\/ KERN-ENDE --------------------------------------------------------------\n\n    function text0(vorlage, werte) {\n        return String(vorlage).replace(\/\\{(\\w+)\\}\/g, function (m, k) { return werte &#038;&#038; werte[k] !== undefined ? werte[k] : m; });\n    }\n    function text(schluessel, werte) { return text0(T[schluessel], werte); }\n    function zahl(x, stellen, plus) {\n        if (typeof x !== 'number' || isNaN(x)) { return '\u2013'; }\n        if (!isFinite(x)) { return x > 0 ? '\u221e' : '\u2212\u221e'; }\n        var s = x.toFixed(stellen);\n        if (parseFloat(s) === 0) { s = Math.abs(parseFloat(s)).toFixed(stellen); }\n        else if (s.charAt(0) === '-') { s = '\u2212' + s.slice(1); }\n        else if (plus) { s = '+' + s; }\n        return s.replace('.', T.dezimal);\n    }\n    function dauerText(sek) {\n        var m = Math.floor(sek \/ 60), s = sek - 60 * m;\n        return m + ':' + (s < 10 ? '0' : '') + zahl(s, 1);\n    }\n    function el(id) { return document.getElementById(id); }\n\n    var ausgabe = el('sk-ausgabe'), status = el('sk-status'), statusText = el('sk-status-text'), fortschritt = el('sk-fortschritt');\n    var letztes = null;\n\n    function zeigeStatus(t, anteil) {\n        if (!status) { return; }\n        status.hidden = false;\n        statusText.textContent = t;\n        fortschritt.style.width = Math.round(100 * (anteil || 0)) + '%';\n    }\n    function fehlerZeigen(t) {\n        if (status) { status.hidden = true; }\n        ausgabe.textContent = '';\n        var p = document.createElement('p');\n        p.className = 'sk-befund sk-b-fail';\n        p.textContent = t;\n        ausgabe.appendChild(p);\n    }\n\n    function kachel(name, wert, einheit, klasse) {\n        var d = document.createElement('div'), n = document.createElement('div'), w = document.createElement('div');\n        d.className = 'sk-kachel'; n.className = 'sk-kachel-name'; w.className = 'sk-kachel-wert';\n        n.textContent = name;\n        w.textContent = wert;\n        w.setAttribute('data-kachel', klasse || name);\n        if (einheit) {\n            var e = document.createElement('span');\n            e.className = 'sk-einheit';\n            e.textContent = einheit;\n            w.appendChild(e);\n        }\n        d.appendChild(n); d.appendChild(w);\n        return d;\n    }\n\n    function verlaufZeichnen(e) {\n        var c = el('sk-verlauf');\n        if (!c || !e || !e.verlauf.length) { return; }\n        var breite = Math.max(320, c.clientWidth || 640), hoehe = 120, dpr = window.devicePixelRatio || 1;\n        c.width = Math.round(breite * dpr); c.height = Math.round(hoehe * dpr);\n        c.style.height = hoehe + 'px';\n        var g = c.getContext('2d');\n        if (!g) { return; }\n        g.setTransform(dpr, 0, 0, dpr, 0, 0);\n        var stil = window.getComputedStyle(document.documentElement);\n        var linie = (stil.getPropertyValue('--border') || '#2a2a35').trim() || '#2a2a35';\n        var akzent = (stil.getPropertyValue('--accent') || '#2ba6df').trim() || '#2ba6df';\n        var schlecht = (stil.getPropertyValue('--fail') || '#ff7b72').trim() || '#ff7b72';\n        g.clearRect(0, 0, breite, hoehe);\n        function y(k) { return hoehe \/ 2 - k * (hoehe \/ 2 - 6); }\n        g.strokeStyle = linie; g.lineWidth = 1;\n        [1, 0.5, 0, -0.5, -1].forEach(function (k) {\n            g.beginPath(); g.moveTo(0, y(k) + 0.5); g.lineTo(breite, y(k) + 0.5); g.stroke();\n        });\n        var n = e.verlauf.length;\n        for (var i = 0; i < n; i++) {\n            var x0 = breite * i \/ n, x1 = breite * (i + 1) \/ n, k = e.verlauf[i];\n            g.fillStyle = k < 0 ? schlecht : akzent;\n            var oben = Math.min(y(k), y(0)), hoch = Math.max(1, Math.abs(y(k) - y(0)));\n            g.fillRect(x0, oben, Math.max(1, x1 - x0), hoch);\n        }\n        g.strokeStyle = linie; g.beginPath(); g.moveTo(0, y(0) + 0.5); g.lineTo(breite, y(0) + 0.5); g.stroke();\n    }\n\n    function darstellen(e, info) {\n        letztes = { e: e, info: info };\n        ausgabe.textContent = '';\n\n        var kopf = document.createElement('p');\n        kopf.className = 'sk-klein';\n        kopf.style.margin = '0 0 10px';\n        kopf.textContent = text('datei_satz', {\n            name: info.name || '', dauer: dauerText(e.dauer), rate: zahl(e.fs \/ 1000, 1),\n            kanaele: e.kanaele === 1 ? T.kanal_mono : (e.kanaele === 2 ? T.kanal_stereo : text('kanal_mehr', { n: e.kanaele }))\n        });\n        ausgabe.appendChild(kopf);\n\n        var k = document.createElement('div');\n        k.className = 'sk-kacheln';\n        k.appendChild(kachel(T.k_korrelation, zahl(e.korrelation, 2, true), '', 'k_korrelation'));\n        k.appendChild(kachel(T.k_seite, zahl(e.seite_db, 1, true), 'dB', 'k_seite'));\n        k.appendChild(kachel(T.k_mono, zahl(e.mono_db, 1, true), 'dB', 'k_mono'));\n        k.appendChild(kachel(T.k_balance, zahl(e.balance_db, 1, true), 'dB', 'k_balance'));\n        ausgabe.appendChild(k);\n\n        var hb = document.createElement('div');\n        hb.className = 'sk-h';\n        hb.textContent = T.h_befunde;\n        ausgabe.appendChild(hb);\n        befunde(e).forEach(function (b) {\n            var d = document.createElement('div');\n            d.className = 'sk-befund sk-b-' + b.art;\n            var t = document.createElement('b');\n            t.textContent = b.titel;\n            d.appendChild(t);\n            if (b.text) {\n                var p = document.createElement('div');\n                p.className = 'sk-klein';\n                p.style.marginTop = '4px';\n                p.textContent = b.text;\n                d.appendChild(p);\n            }\n            ausgabe.appendChild(d);\n        });\n\n        var ht = document.createElement('div');\n        ht.className = 'sk-h';\n        ht.textContent = T.h_baender;\n        ausgabe.appendChild(ht);\n        var wrap = document.createElement('div');\n        wrap.className = 'sk-tabelle';\n        var tab = document.createElement('table');\n        var thead = document.createElement('thead'), tr = document.createElement('tr');\n        [T.sp_band, T.sp_korrelation, T.sp_seite, T.sp_mono, T.sp_anteil].forEach(function (s) {\n            var th = document.createElement('th');\n            th.textContent = s;\n            tr.appendChild(th);\n        });\n        thead.appendChild(tr);\n        tab.appendChild(thead);\n        var tbody = document.createElement('tbody');\n        tbody.id = 'sk-baender';\n        e.baender.forEach(function (b) {\n            var z = document.createElement('tr');\n            [[text('band_' + b.id, { von: zahl(b.von, 0), bis: zahl(b.bis, 0) }), true], [zahl(b.korrelation, 2, true)],\n             [zahl(b.seite_db, 1, true)], [zahl(b.mono_db, 1, true)], [zahl(b.anteil, 1)]].forEach(function (w) {\n                var td = document.createElement('td');\n                td.textContent = w[0];\n                if (w[1]) { td.className = 'sk-name'; }\n                z.appendChild(td);\n            });\n            tbody.appendChild(z);\n        });\n        tab.appendChild(tbody);\n        wrap.appendChild(tab);\n        ausgabe.appendChild(wrap);\n\n        var hv = document.createElement('div');\n        hv.className = 'sk-h';\n        hv.textContent = T.h_verlauf;\n        ausgabe.appendChild(hv);\n        var c = document.createElement('canvas');\n        c.id = 'sk-verlauf';\n        c.setAttribute('data-mp-mask', '');\n        ausgabe.appendChild(c);\n        var hinweis = document.createElement('p');\n        hinweis.className = 'sk-klein';\n        hinweis.style.margin = '8px 0 0';\n        hinweis.textContent = text('verlauf_hinweis', {\n            fenster: zahl(e.fenster_s, 1), unter: zahl(e.unter_null, 0), kleinste: zahl(e.kleinste, 2, true)\n        });\n        ausgabe.appendChild(hinweis);\n        verlaufZeichnen(e);\n        return e;\n    }\n\n    \/\/ --- Datei lesen ---------------------------------------------------------\n    \/\/ --- Dateien lesen -------------------------------------------------------\n    \/\/ WAV und AIFF werden selbst gelesen: so bleibt jeder Abtastwert, wie er in\n    \/\/ der Datei steht, und der Browser rechnet nicht auf seine eigene Rate um.\n    function ascii(dv, o, l) {\n        var s = '';\n        for (var i = 0; i < l &#038;&#038; o + i < dv.byteLength; i++) { s += String.fromCharCode(dv.getUint8(o + i)); }\n        return s;\n    }\n\n    function pcmZuKanaele(puffer, start, laenge, kanaele, bytes, art, kleinEndian) {\n        var rahmen = Math.floor(laenge \/ (bytes * kanaele));\n        var raus = [], c, i;\n        for (c = 0; c < kanaele; c++) { raus.push(new Float32Array(rahmen)); }\n        var ausgerichtet = kleinEndian &#038;&#038; (art === 'int' &#038;&#038; (bytes === 2 || bytes === 4) || art === 'float');\n        if (ausgerichtet) {\n            var stueck = puffer.slice(start, start + rahmen * bytes * kanaele);\n            var ansicht = art === 'float' ? (bytes === 4 ? new Float32Array(stueck) : new Float64Array(stueck))\n                : (bytes === 2 ? new Int16Array(stueck) : new Int32Array(stueck));\n            var teiler = art === 'float' ? 1 : (bytes === 2 ? 32768 : 2147483648);\n            for (c = 0; c < kanaele; c++) {\n                var ziel = raus[c];\n                for (i = 0; i < rahmen; i++) { ziel[i] = ansicht[i * kanaele + c] \/ teiler; }\n            }\n            return raus;\n        }\n        var dv = new DataView(puffer, start, rahmen * bytes * kanaele);\n        var u8 = new Uint8Array(puffer, start, rahmen * bytes * kanaele);\n        var o = 0;\n        for (i = 0; i < rahmen; i++) {\n            for (c = 0; c < kanaele; c++) {\n                var v;\n                if (art === 'float') { v = bytes === 4 ? dv.getFloat32(o, kleinEndian) : dv.getFloat64(o, kleinEndian); }\n                else if (bytes === 1) { v = kleinEndian ? (u8[o] - 128) \/ 128 : dv.getInt8(o) \/ 128; }\n                else if (bytes === 2) { v = dv.getInt16(o, kleinEndian) \/ 32768; }\n                else if (bytes === 3) {\n                    var w = kleinEndian ? (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 \/ 8388608;\n                } else { v = dv.getInt32(o, kleinEndian) \/ 2147483648; }\n                raus[c][i] = v;\n                o += bytes;\n            }\n        }\n        return raus;\n    }\n\n    function wavLesen(puffer) {\n        var dv = new DataView(puffer), n = puffer.byteLength, o = 12, fmt = null, ds64 = null;\n        while (o + 8 <= n) {\n            var id = ascii(dv, o, 4), groesse = dv.getUint32(o + 4, true);\n            if (id === 'ds64' &#038;&#038; groesse >= 16) {\n                ds64 = dv.getUint32(o + 16, true) + dv.getUint32(o + 20, true) * 4294967296;\n            } else if (id === 'fmt ') {\n                var tag = dv.getUint16(o + 8, true);\n                if (tag === 0xFFFE && groesse >= 26) { tag = dv.getUint16(o + 32, true); }\n                fmt = { tag: tag, kanaele: dv.getUint16(o + 10, true), rate: dv.getUint32(o + 12, true), bits: dv.getUint16(o + 22, true) };\n            } else if (id === 'data') {\n                if (!fmt) { return { fehler: 'fmt' }; }\n                var laenge = (groesse === 0xFFFFFFFF && ds64 !== null) ? ds64 : groesse;\n                laenge = Math.min(laenge, n - o - 8);\n                var bytes = fmt.bits \/ 8;\n                var art = fmt.tag === 1 ? 'int' : (fmt.tag === 3 ? 'float' : null);\n                if (!art || (art === 'int' && [1, 2, 3, 4].indexOf(bytes) === -1) || (art === 'float' && bytes !== 4 && bytes !== 8) || !fmt.kanaele) {\n                    return { fehler: 'tag ' + fmt.tag + ', ' + fmt.bits + ' bit' };\n                }\n                return { format: 'WAV', rate: fmt.rate, bits: fmt.bits, gleitkomma: art === 'float',\n                    kanaele: pcmZuKanaele(puffer, o + 8, laenge, fmt.kanaele, bytes, art, true) };\n            }\n            if (groesse === 0xFFFFFFFF) { break; }\n            o += 8 + groesse + (groesse % 2);\n        }\n        return { fehler: 'data' };\n    }<\/p>\n<p>    function erweitert80(dv, o) {\n        var exp = dv.getUint16(o, false) & 0x7FFF, hi = dv.getUint32(o + 2, false), lo = dv.getUint32(o + 6, false);\n        if (!exp && !hi && !lo) { return 0; }\n        return (hi * 4294967296 + lo) * Math.pow(2, exp - 16383 - 63);\n    }<\/p>\n<p>    function aiffLesen(puffer, aifc) {\n        var dv = new DataView(puffer), n = puffer.byteLength, o = 12, comm = null;\n        while (o + 8 <= n) {\n            var id = ascii(dv, o, 4), groesse = dv.getUint32(o + 4, false);\n            if (id === 'COMM') {\n                comm = { kanaele: dv.getUint16(o + 8, false), bits: dv.getUint16(o + 14, false), rate: Math.round(erweitert80(dv, o + 16)), art: 'NONE' };\n                if (aifc &#038;&#038; groesse >= 22) { comm.art = ascii(dv, o + 26, 4); }\n            } else if (id === 'SSND') {\n                if (!comm) { return { fehler: 'COMM' }; }\n                var versatz = dv.getUint32(o + 8, false), start = o + 16 + versatz;\n                var laenge = Math.min(groesse - 8 - versatz, n - start);\n                var art = comm.art, bytes = Math.ceil(comm.bits \/ 8);\n                if (art === 'NONE' || art === 'twos') {\n                    return { format: 'AIFF', rate: comm.rate, bits: comm.bits, kanaele: pcmZuKanaele(puffer, start, laenge, comm.kanaele, bytes, 'int', false) };\n                }\n                if (art === 'sowt') {\n                    return { format: 'AIFF', rate: comm.rate, bits: comm.bits, kanaele: pcmZuKanaele(puffer, start, laenge, comm.kanaele, bytes, 'int', true) };\n                }\n                if (art === 'fl32' || art === 'FL32' || art === 'fl64' || art === 'FL64') {\n                    return { format: 'AIFF', rate: comm.rate, bits: art.slice(2) === '32' ? 32 : 64, gleitkomma: true,\n                        kanaele: pcmZuKanaele(puffer, start, laenge, comm.kanaele, art.slice(2) === '32' ? 4 : 8, 'float', false) };\n                }\n                return { fehler: art };\n            }\n            o += 8 + groesse + (groesse % 2);\n        }\n        return { fehler: 'SSND' };\n    }<\/p>\n<p>    \/\/ Abtastrate komprimierter Formate aus dem Kopf, damit der Decoder des\n    \/\/ Browsers nicht auf eine fremde Rate umrechnet.\n    function kopfLesen(puffer) {\n        var n = puffer.byteLength, dv = new DataView(puffer);\n        var b = new Uint8Array(puffer, 0, Math.min(n, 4 << 20));\n        var k4 = ascii(dv, 0, 4);\n        if (k4 === 'fLaC' &#038;&#038; n > 22) {\n            return { format: 'FLAC', rate: (b[18] << 12) | (b[19] << 4) | (b[20] >> 4), kanaeleKopf: ((b[20] >> 1) & 7) + 1, bits: (((b[20] & 1) << 4) | (b[21] >> 4)) + 1 };\n        }\n        if (k4 === 'OggS' && n > 64) {\n            var d = 27 + b[26];\n            if (ascii(dv, d + 1, 6) === 'vorbis' && b[d] === 1) { return { format: 'Ogg Vorbis', rate: dv.getUint32(d + 12, true), kanaeleKopf: b[d + 11] }; }\n            if (ascii(dv, d, 8) === 'OpusHead') { return { format: 'Opus', rate: 48000, kanaeleKopf: b[d + 9] }; }\n            if (ascii(dv, d + 1, 4) === 'FLAC' && ascii(dv, d + 9, 4) === 'fLaC') {\n                var s = d + 17;\n                return { format: 'Ogg FLAC', rate: (b[s + 10] << 12) | (b[s + 11] << 4) | (b[s + 12] >> 4) };\n            }\n            return { format: 'Ogg', rate: null };\n        }\n        if (ascii(dv, 4, 4) === 'ftyp') {\n            var suchen = function (a, bb, c, dd) {\n                for (var i = 4; i + 36 < b.length; i++) {\n                    if (b[i] === a &#038;&#038; b[i + 1] === bb &#038;&#038; b[i + 2] === c &#038;&#038; b[i + 3] === dd) { return i - 4; }\n                }\n                return -1;\n            };\n            var box = suchen(0x6D, 0x70, 0x34, 0x61), name = 'AAC';\n            if (box < 0) { box = suchen(0x61, 0x6C, 0x61, 0x63); name = 'ALAC'; }\n            var rate = box >= 0 ? dv.getUint16(box + 32, false) : 0;\n            return { format: name, rate: rate >= 8000 ? rate : null };\n        }\n        var start = 0;\n        if (ascii(dv, 0, 3) === 'ID3' && n > 10) {\n            start = 10 + ((b[6] & 0x7f) << 21 | (b[7] &#038; 0x7f) << 14 | (b[8] &#038; 0x7f) << 7 | (b[9] &#038; 0x7f)) + ((b[5] &#038; 0x10) ? 10 : 0);\n        }\n        var bis = Math.min(b.length - 4, start + 65536);\n        for (var j = start; j < bis; j++) {\n            if (b[j] !== 0xFF || (b[j + 1] &#038; 0xE0) !== 0xE0) { continue; }\n            var version = (b[j + 1] >> 3) & 3, schicht = (b[j + 1] >> 1) & 3;\n            if (schicht === 0 && (b[j + 1] & 0xF6) === 0xF0) {\n                var idx = (b[j + 2] >> 2) & 15;\n                var raten = [96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350];\n                if (idx < raten.length) { return { format: 'AAC', rate: raten[idx] }; }\n                continue;\n            }\n            var ri = (b[j + 2] >> 2) & 3, bri = b[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: schicht === 1 ? 'MP3' : 'MPEG', rate: version === 3 ? basis : (version === 2 ? basis \/ 2 : basis \/ 4), kanaeleKopf: (b[j + 3] >> 6) === 3 ? 1 : 2 };\n        }\n        return { format: null, rate: null };\n    }\n    \/\/ Komprimierte Formate uebernimmt der Browser; die Rate stammt aus dem Kopf,\n    \/\/ damit Web Audio nicht auf seine eigene Rate umrechnet.\n    function dekodieren(puffer, rate) {\n        return new Promise(function (ok, fehler) {\n            var Ctx = window.OfflineAudioContext || window.webkitOfflineAudioContext;\n            if (!Ctx) { fehler(new Error('webaudio')); return; }\n            var ctx;\n            try { ctx = new Ctx(2, 1, rate); } catch (e) {\n                try { ctx = new Ctx(2, 1, 48000); } catch (e2) { fehler(new Error('webaudio')); return; }\n            }\n            var fertig = false;\n            function gut(buf) { if (!fertig) { fertig = true; ok(buf); } }\n            function schlecht(e) { if (!fertig) { fertig = true; fehler(e || new Error('dekodieren')); } }\n            try {\n                var p = ctx.decodeAudioData(puffer, gut, schlecht);\n                if (p && typeof p.then === 'function') { p.then(gut, schlecht); }\n            } catch (e) { schlecht(e); }\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>    function messenAsync(kanaele, fs) {\n        return new Promise(function (ok, fehler) {\n            var m;\n            try { m = messungAnlegen(kanaele, fs); } catch (e) { fehler(e); return; }\n            function weiter() {\n                try {\n                    var fertig = messungSchritt(m, STUECK);\n                    zeigeStatus(T.status_messen, m.n ? m.pos \/ m.n : 1);\n                    if (fertig) { ok(messungAuswerten(m)); return; }\n                } catch (e) { fehler(e); return; }\n                spaeter(weiter);\n            }\n            spaeter(weiter);\n        });\n    }<\/p>\n<p>    \/\/ WAV und AIFF selbst lesen, alles andere ueber Web Audio.\n    function einlesen(puffer) {\n        var dv = new DataView(puffer), k4 = ascii(dv, 0, 4), art = ascii(dv, 8, 4);\n        if ((k4 === 'RIFF' || k4 === 'RF64' || k4 === 'BW64') && art === 'WAVE') {\n            var w = wavLesen(puffer);\n            if (!w.fehler) { return Promise.resolve(w); }\n            return Promise.reject({ format: w.fehler });\n        }\n        if (k4 === 'FORM' && (art === 'AIFF' || art === 'AIFC')) {\n            var a = aiffLesen(puffer, art === 'AIFC');\n            if (!a.fehler) { return Promise.resolve(a); }\n        }\n        var kopf = kopfLesen(puffer);\n        var rate = kopf.rate && kopf.rate >= 3000 && kopf.rate <= 768000 ? kopf.rate : 48000;\n        return dekodieren(puffer, rate).then(function (buf) {\n            var kanaele = [];\n            for (var c = 0; c < buf.numberOfChannels; c++) { kanaele.push(buf.getChannelData(c)); }\n            return { format: kopf.format, rate: buf.sampleRate, kanaele: kanaele };\n        });\n    }\n\n    function verarbeitenPuffer(puffer, name) {\n        zeigeStatus(T.status_dekodieren, 0);\n        return einlesen(puffer).then(function (d) {\n            var kanaele = d.kanaele;\n            if (!kanaele.length || !kanaele[0].length) { throw { leer: true }; }\n            return messenAsync(kanaele, d.rate).then(function (e) {\n                status.hidden = true;\n                return darstellen(e, { name: name, format: d.format });\n            });\n        }).catch(function (f) {\n            if (window.LW_TEST &#038;&#038; window.LW_TEST.SK) { window.LW_TEST.SK.letzterFehler = f; }\n            if (f &#038;&#038; f.leer) { fehlerZeigen(T.fehler_leer); }\n            else if (f &#038;&#038; f.format) { fehlerZeigen(text('fehler_format', { detail: f.format })); }\n            else if (f &#038;&#038; f.message === 'webaudio') { fehlerZeigen(T.fehler_webaudio); }\n            else if (f &#038;&#038; (f.name === 'RangeError' || \/memory|allocation\/i.test(String(f.message || '')))) { fehlerZeigen(T.fehler_speicher); }\n            else { fehlerZeigen(T.fehler_dekodieren); }\n            return null;\n        });\n    }\n\n    function dateiNehmen(datei) {\n        if (!datei) { return; }\n        zeigeStatus(T.status_lesen, 0);\n        var leser = new FileReader();\n        leser.onload = function () { verarbeitenPuffer(leser.result, datei.name); };\n        leser.onerror = function () { fehlerZeigen(T.fehler_dekodieren); };\n        try { leser.readAsArrayBuffer(datei); } catch (x) { fehlerZeigen(T.fehler_speicher); }\n    }\n\n    window.LW_TEST = window.LW_TEST || {};\n    window.LW_TEST.SK = {\n        T: T, BAENDER: BAENDER, analysiere: analysiere, befunde: befunde, biquad: biquad, bandFiltern: bandFiltern,\n        auswerten: auswerten, summenAnlegen: summenAnlegen, summenNehmen: summenNehmen, zahl: zahl, text: text,\n        darstellen: darstellen, verarbeitenPuffer: verarbeitenPuffer, einlesen: einlesen, wavLesen: wavLesen,\n        aiffLesen: aiffLesen, kopfLesen: kopfLesen, dauerText: dauerText, db: db\n    };\n\n    var zone = el('sk-zone'), eingabe = el('sk-datei'), knopf = el('sk-knopf');\n    if (!zone || !eingabe || !ausgabe) { 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 (typ) {\n        zone.addEventListener(typ, function (ev) { ev.preventDefault(); zone.classList.add('sk-ueber'); });\n    });\n    ['dragleave', 'drop'].forEach(function (typ) {\n        zone.addEventListener(typ, function (ev) { ev.preventDefault(); zone.classList.remove('sk-ueber'); });\n    });\n    zone.addEventListener('drop', function (ev) {\n        var f = ev.dataTransfer &#038;&#038; ev.dataTransfer.files &#038;&#038; ev.dataTransfer.files[0];\n        dateiNehmen(f);\n    });\n    var warten = null;\n    window.addEventListener('resize', function () {\n        clearTimeout(warten);\n        warten = setTimeout(function () { if (letztes) { verlaufZeichnen(letztes.e); } }, 150);\n    });\n    if (window.MutationObserver) {\n        new MutationObserver(function () { if (letztes) { verlaufZeichnen(letztes.e); } })\n            .observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] });\n    }\n})();\n<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Odczytuje plik audio w przegl\u0105darce i mierzy korelacj\u0119 mi\u0119dzy kana\u0142em lewym i prawym, poziom sygna\u0142u bocznego wobec \u015brodkowego, strat\u0119 sumy mono oraz balans kana\u0142\u00f3w, \u0142\u0105cznie i w trzech pasmach cz\u0119stotliwo\u015bci, a do tego przebieg korelacji w czasie.<\/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-19926","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>Miernik korelacji stereo i mid\/side: korelacja w pasmach, udzia\u0142 sygna\u0142u bocznego, zgodno\u015b\u0107 mono i balans kana\u0142\u00f3w z 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\/stereo-correlation-mid-side-meter\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Miernik korelacji stereo i mid\/side: korelacja w pasmach, udzia\u0142 sygna\u0142u bocznego, zgodno\u015b\u0107 mono i balans kana\u0142\u00f3w z pliku audio - Lukas Wojcik - Blog\" \/>\n<meta property=\"og:description\" content=\"Odczytuje plik audio w przegl\u0105darce i mierzy korelacj\u0119 mi\u0119dzy kana\u0142em lewym i prawym, poziom sygna\u0142u bocznego wobec \u015brodkowego, strat\u0119 sumy mono oraz balans kana\u0142\u00f3w, \u0142\u0105cznie i w trzech pasmach cz\u0119stotliwo\u015bci, a do tego przebieg korelacji w czasie.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/stereo-correlation-mid-side-meter\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\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\\\/stereo-correlation-mid-side-meter\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/stereo-correlation-mid-side-meter\\\/\",\"name\":\"Miernik korelacji stereo i mid\\\/side: korelacja w pasmach, udzia\u0142 sygna\u0142u bocznego, zgodno\u015b\u0107 mono i balans kana\u0142\u00f3w z pliku audio - Lukas Wojcik - Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-09-17T18:06:56+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/stereo-correlation-mid-side-meter\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/stereo-correlation-mid-side-meter\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/stereo-correlation-mid-side-meter\\\/#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\":\"Miernik korelacji stereo i mid\\\/side: korelacja w pasmach, udzia\u0142 sygna\u0142u bocznego, zgodno\u015b\u0107 mono i balans kana\u0142\u00f3w z 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":"Miernik korelacji stereo i mid\/side: korelacja w pasmach, udzia\u0142 sygna\u0142u bocznego, zgodno\u015b\u0107 mono i balans kana\u0142\u00f3w z 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\/stereo-correlation-mid-side-meter\/","og_locale":"en_US","og_type":"article","og_title":"Miernik korelacji stereo i mid\/side: korelacja w pasmach, udzia\u0142 sygna\u0142u bocznego, zgodno\u015b\u0107 mono i balans kana\u0142\u00f3w z pliku audio - Lukas Wojcik - Blog","og_description":"Odczytuje plik audio w przegl\u0105darce i mierzy korelacj\u0119 mi\u0119dzy kana\u0142em lewym i prawym, poziom sygna\u0142u bocznego wobec \u015brodkowego, strat\u0119 sumy mono oraz balans kana\u0142\u00f3w, \u0142\u0105cznie i w trzech pasmach cz\u0119stotliwo\u015bci, a do tego przebieg korelacji w czasie.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/stereo-correlation-mid-side-meter\/","og_site_name":"Lukas Wojcik - Blog","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\/stereo-correlation-mid-side-meter\/","url":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/stereo-correlation-mid-side-meter\/","name":"Miernik korelacji stereo i mid\/side: korelacja w pasmach, udzia\u0142 sygna\u0142u bocznego, zgodno\u015b\u0107 mono i balans kana\u0142\u00f3w z pliku audio - Lukas Wojcik - Blog","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"datePublished":"2026-09-17T18:06:56+00:00","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/stereo-correlation-mid-side-meter\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/stereo-correlation-mid-side-meter\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/stereo-correlation-mid-side-meter\/#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":"Miernik korelacji stereo i mid\/side: korelacja w pasmach, udzia\u0142 sygna\u0142u bocznego, zgodno\u015b\u0107 mono i balans kana\u0142\u00f3w z 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\/19926","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=19926"}],"version-history":[{"count":0,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/19926\/revisions"}],"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=19926"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=19926"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}