{"id":19925,"date":"2026-09-17T20:06:52","date_gmt":"2026-09-17T18:06:52","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/werkzeuge\/stereo-correlation-mid-side-meter\/"},"modified":"2026-09-17T20:06:52","modified_gmt":"2026-09-17T18:06:52","slug":"stereo-correlation-mid-side-meter","status":"publish","type":"page","link":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/stereo-correlation-mid-side-meter\/","title":{"rendered":"Stereo-Korrelation und Mid\/Side messen: Korrelation je Band, Seitenanteil, Mono-Vertr\u00e4glichkeit und Kanalbalance aus einer Audiodatei"},"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;\">Ein Mix kann im Kopfh\u00f6rer breit klingen und in Mono zusammenfallen. Das Messger\u00e4t liest eine Audiodatei im Browser und bestimmt die Korrelation zwischen linkem und rechtem Kanal, den Anteil des Seitensignals, den Pegelverlust einer Mono-Summe und die Balance der Kan\u00e4le, gesamt und in drei Frequenzb\u00e4ndern, dazu den Verlauf \u00fcber die Zeit.<\/p>\n<div id=\"sk-zone\" class=\"sk-zone\">\n<p style=\"margin: 0 0 12px; color: var(--text-primary, #e8e8ee); font-weight: 700;\">Audiodatei hierher ziehen<\/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;\">Datei w\u00e4hlen<\/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;\">Die Datei bleibt im Browser, nichts wird hochgeladen. WAV, FLAC, MP3, M4A, OGG und Opus, soweit der Browser sie abspielt.<\/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\">Was die Zahlen bedeuten<\/div>\n<p class=\"sk-klein\" style=\"margin: 0 0 6px;\">Die Korrelation vergleicht linken und rechten Kanal: +1 hei\u00dft gleiches Signal (in Mono unver\u00e4ndert), 0 hei\u00dft unabh\u00e4ngig, \u22121 hei\u00dft gegenphasig, dann l\u00f6scht sich die Mono-Summe aus. Im Vektorskop von FL Studio erscheint ein mittiges Monosignal als senkrechte Linie, eine waagerechte Linie bedeutet 180 Grad Phasenversatz.<\/p>\n<p class=\"sk-klein\" style=\"margin: 0 0 6px;\">Die Mitte ist (L + R) \u00f7 2, die Seite ist (L \u2212 R) \u00f7 2. Angegeben ist der Abstand beider Effektivwerte: \u22126 dB ist schmal, 0 dB hei\u00dft, dass Seite und Mitte gleich laut sind. Stereo-Werkzeuge arbeiten laut Handbuch von FL Studio genau auf dieser Differenz zwischen den Kan\u00e4len.<\/p>\n<p class=\"sk-klein\" style=\"margin: 0 0 6px;\">Die Mono-Summe ist der Pegel von (L + R) \u00f7 2 gegen\u00fcber dem Effektivwert des Stereosignals. 0 dB hei\u00dft, dass nichts verloren geht; unabh\u00e4ngige Kan\u00e4le verlieren rund 3 dB, gegenphasige Anteile mehr.<\/p>\n<p class=\"sk-klein\" style=\"margin: 0 0 6px;\">Die B\u00e4nder entstehen durch Hoch- und Tiefp\u00e4sse zweiter Ordnung, f\u00fcr beide Kan\u00e4le gleich. So zeigt sich, ob nur die H\u00f6hen breit sind oder auch der Bass auseinanderl\u00e4uft.<\/p>\n<p class=\"sk-klein\" style=\"margin: 20px 0 0;\">Quellen:<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;\">Alles wird im Browser berechnet, die Datei verl\u00e4sst den Rechner nicht. Gemessen wird die ganze Datei; kurze gegenphasige Stellen fallen im Gesamtwert kaum auf und stehen deshalb im Verlauf. Kan\u00e4le \u00fcber die ersten beiden hinaus bleiben unber\u00fccksichtigt.<\/p>\n<\/div>\n<p><script>\n(function () {\n    'use strict';<\/p>\n<p>    const T = {\"einleitung\":\"Ein Mix kann im Kopfh\u00f6rer breit klingen und in Mono zusammenfallen. Das Messger\u00e4t liest eine Audiodatei im Browser und bestimmt die Korrelation zwischen linkem und rechtem Kanal, den Anteil des Seitensignals, den Pegelverlust einer Mono-Summe und die Balance der Kan\u00e4le, gesamt und in drei Frequenzb\u00e4ndern, dazu den Verlauf \u00fcber die Zeit.\",\"zone_titel\":\"Audiodatei hierher ziehen\",\"knopf_datei\":\"Datei w\u00e4hlen\",\"zone_hinweis\":\"Die Datei bleibt im Browser, nichts wird hochgeladen. WAV, FLAC, MP3, M4A, OGG und Opus, soweit der Browser sie abspielt.\",\"status_lesen\":\"Datei wird gelesen \u2026\",\"status_dekodieren\":\"Datei wird dekodiert \u2026\",\"status_messen\":\"Messung l\u00e4uft \u2026\",\"fehler_dekodieren\":\"Die Datei lie\u00df sich nicht dekodieren. Der Browser muss das Format abspielen k\u00f6nnen.\",\"fehler_webaudio\":\"Dieser Browser bietet keine Web-Audio-Dekodierung.\",\"fehler_speicher\":\"Die Datei ist zu gro\u00df f\u00fcr den Speicher des Browsers.\",\"fehler_leer\":\"Die Datei enth\u00e4lt keine Abtastwerte.\",\"fehler_format\":\"Dieses Format l\u00e4sst sich hier nicht lesen: {detail}.\",\"datei_satz\":\"{name} \u00b7 {dauer} \u00b7 {rate} kHz \u00b7 {kanaele}\",\"kanal_mono\":\"1 Kanal\",\"kanal_stereo\":\"2 Kan\u00e4le\",\"kanal_mehr\":\"{n} Kan\u00e4le (gemessen werden die ersten beiden)\",\"k_korrelation\":\"Korrelation\",\"k_seite\":\"Seite gegen Mitte\",\"k_mono\":\"Mono-Summe\",\"k_balance\":\"Balance L gegen R\",\"h_befunde\":\"Befunde\",\"h_baender\":\"B\u00e4nder\",\"sp_band\":\"Band\",\"sp_korrelation\":\"Korrelation\",\"sp_seite\":\"Seite gegen Mitte (dB)\",\"sp_mono\":\"Mono-Summe (dB)\",\"sp_anteil\":\"Anteil an der Energie (%)\",\"band_tief\":\"Tiefen ({von}\u2013{bis} Hz)\",\"band_mitten\":\"Mitten ({von}\u2013{bis} Hz)\",\"band_hoehen\":\"H\u00f6hen ({von}\u2013{bis} Hz)\",\"h_verlauf\":\"Verlauf der Korrelation\",\"verlauf_hinweis\":\"Ein Balken je {fenster} s. Unter null liegen {unter} % der Fenster, der kleinste Wert ist {kleinste}.\",\"h_erklaerung\":\"Was die Zahlen bedeuten\",\"erkl_korrelation\":\"Die Korrelation vergleicht linken und rechten Kanal: +1 hei\u00dft gleiches Signal (in Mono unver\u00e4ndert), 0 hei\u00dft unabh\u00e4ngig, \u22121 hei\u00dft gegenphasig, dann l\u00f6scht sich die Mono-Summe aus. Im Vektorskop von FL Studio erscheint ein mittiges Monosignal als senkrechte Linie, eine waagerechte Linie bedeutet 180 Grad Phasenversatz.\",\"erkl_seite\":\"Die Mitte ist (L + R) \u00f7 2, die Seite ist (L \u2212 R) \u00f7 2. Angegeben ist der Abstand beider Effektivwerte: \u22126 dB ist schmal, 0 dB hei\u00dft, dass Seite und Mitte gleich laut sind. Stereo-Werkzeuge arbeiten laut Handbuch von FL Studio genau auf dieser Differenz zwischen den Kan\u00e4len.\",\"erkl_mono\":\"Die Mono-Summe ist der Pegel von (L + R) \u00f7 2 gegen\u00fcber dem Effektivwert des Stereosignals. 0 dB hei\u00dft, dass nichts verloren geht; unabh\u00e4ngige Kan\u00e4le verlieren rund 3 dB, gegenphasige Anteile mehr.\",\"erkl_baender\":\"Die B\u00e4nder entstehen durch Hoch- und Tiefp\u00e4sse zweiter Ordnung, f\u00fcr beide Kan\u00e4le gleich. So zeigt sich, ob nur die H\u00f6hen breit sind oder auch der Bass auseinanderl\u00e4uft.\",\"quellen_titel\":\"Quellen\",\"grenze\":\"Alles wird im Browser berechnet, die Datei verl\u00e4sst den Rechner nicht. Gemessen wird die ganze Datei; kurze gegenphasige Stellen fallen im Gesamtwert kaum auf und stehen deshalb im Verlauf. Kan\u00e4le \u00fcber die ersten beiden hinaus bleiben unber\u00fccksichtigt.\",\"befund_mono\":\"Die Datei ist mono || Beide Kan\u00e4le sind gleich; Korrelation, Seitenanteil und Mono-Summe haben hier keine Aussage.\",\"befund_gegenphase\":\"Die Kan\u00e4le laufen gegeneinander || Die Korrelation liegt bei {k}. In Mono verliert die Datei {mono} dB, gro\u00dfe Teile l\u00f6schen sich aus.\",\"befund_mono_verlust\":\"Die Mono-Summe verliert {mono} dB || Bei einer Korrelation von {k} f\u00e4llt in Mono h\u00f6rbar Pegel weg. Das betrifft Clubanlagen, Telefone und viele Lautsprecher in L\u00e4den.\",\"befund_bass_breit\":\"Der Bass steht nicht in der Mitte || Bis {hz} Hz liegt die Korrelation bei {k}. Tiefe Anteile in der Seite verlieren in Mono am meisten Pegel.\",\"befund_sehr_breit\":\"Seite lauter als Mitte || Der Seitenanteil liegt {seite} dB \u00fcber der Mitte. Das klingt im Kopfh\u00f6rer weit, in Mono bleibt wenig \u00fcbrig.\",\"befund_balance_links\":\"Der linke Kanal ist lauter || Der linke Kanal liegt {db} dB \u00fcber dem rechten.\",\"befund_balance_rechts\":\"Der rechte Kanal ist lauter || Der rechte Kanal liegt {db} dB \u00fcber dem linken.\",\"befund_kurz\":\"Kurzer Ausschnitt || Die Datei dauert {s} s. F\u00fcr einen belastbaren Gesamtwert ist das wenig.\",\"befund_gut\":\"Unauff\u00e4llig || Korrelation {k}, Seite {seite} dB gegen\u00fcber der Mitte. Die Mono-Summe bleibt nahezu vollst\u00e4ndig.\",\"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>Liest eine Audiodatei im Browser und misst die Korrelation zwischen linkem und rechtem Kanal, den Pegel des Seitensignals gegen\u00fcber der Mitte, den Verlust einer Mono-Summe und die Kanalbalance, gesamt und in drei Frequenzb\u00e4ndern, dazu den Verlauf der Korrelation \u00fcber die Zeit.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":9283,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template-tool-base.php","meta":{"footnotes":""},"tags":[92903],"class_list":["post-19925","page","type-page","status-publish","hentry","tag-music-production-de"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Stereo-Korrelation und Mid\/Side messen: Korrelation je Band, Seitenanteil, Mono-Vertr\u00e4glichkeit und Kanalbalance aus einer Audiodatei - Lukas Wojcik - Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/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=\"Stereo-Korrelation und Mid\/Side messen: Korrelation je Band, Seitenanteil, Mono-Vertr\u00e4glichkeit und Kanalbalance aus einer Audiodatei - Lukas Wojcik - Blog\" \/>\n<meta property=\"og:description\" content=\"Liest eine Audiodatei im Browser und misst die Korrelation zwischen linkem und rechtem Kanal, den Pegel des Seitensignals gegen\u00fcber der Mitte, den Verlust einer Mono-Summe und die Kanalbalance, gesamt und in drei Frequenzb\u00e4ndern, dazu den Verlauf der Korrelation \u00fcber die Zeit.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/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=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/stereo-correlation-mid-side-meter\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/stereo-correlation-mid-side-meter\\\/\",\"name\":\"Stereo-Korrelation und Mid\\\/Side messen: Korrelation je Band, Seitenanteil, Mono-Vertr\u00e4glichkeit und Kanalbalance aus einer Audiodatei - Lukas Wojcik - Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-09-17T18:06:52+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/stereo-correlation-mid-side-meter\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/stereo-correlation-mid-side-meter\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/de\\\/werkzeuge\\\/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-2\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Stereo-Korrelation und Mid\\\/Side messen: Korrelation je Band, Seitenanteil, Mono-Vertr\u00e4glichkeit und Kanalbalance aus einer Audiodatei\"}]},{\"@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":"Stereo-Korrelation und Mid\/Side messen: Korrelation je Band, Seitenanteil, Mono-Vertr\u00e4glichkeit und Kanalbalance aus einer Audiodatei - Lukas Wojcik - Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/stereo-correlation-mid-side-meter\/","og_locale":"en_US","og_type":"article","og_title":"Stereo-Korrelation und Mid\/Side messen: Korrelation je Band, Seitenanteil, Mono-Vertr\u00e4glichkeit und Kanalbalance aus einer Audiodatei - Lukas Wojcik - Blog","og_description":"Liest eine Audiodatei im Browser und misst die Korrelation zwischen linkem und rechtem Kanal, den Pegel des Seitensignals gegen\u00fcber der Mitte, den Verlust einer Mono-Summe und die Kanalbalance, gesamt und in drei Frequenzb\u00e4ndern, dazu den Verlauf der Korrelation \u00fcber die Zeit.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/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":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/stereo-correlation-mid-side-meter\/","url":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/stereo-correlation-mid-side-meter\/","name":"Stereo-Korrelation und Mid\/Side messen: Korrelation je Band, Seitenanteil, Mono-Vertr\u00e4glichkeit und Kanalbalance aus einer Audiodatei - Lukas Wojcik - Blog","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"datePublished":"2026-09-17T18:06:52+00:00","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/stereo-correlation-mid-side-meter\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/stereo-correlation-mid-side-meter\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/de\/werkzeuge\/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-2\/"},{"@type":"ListItem","position":3,"name":"Stereo-Korrelation und Mid\/Side messen: Korrelation je Band, Seitenanteil, Mono-Vertr\u00e4glichkeit und Kanalbalance aus einer Audiodatei"}]},{"@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\/19925","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=19925"}],"version-history":[{"count":0,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/19925\/revisions"}],"up":[{"embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/9283"}],"wp:attachment":[{"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/media?parent=19925"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=19925"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}