{"id":20130,"date":"2026-09-23T18:48:24","date_gmt":"2026-09-23T16:48:24","guid":{"rendered":"https:\/\/www.lukaswojcik.com\/blog\/narzedzia\/release-file-checker-sample-rate-bit-depth-peaks-isrc-cover\/"},"modified":"2026-09-23T18:54:20","modified_gmt":"2026-09-23T16:54:20","slug":"release-file-checker-sample-rate-bit-depth-peaks-isrc-cover","status":"publish","type":"page","link":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/release-file-checker-sample-rate-bit-depth-peaks-isrc-cover\/","title":{"rendered":"Kontrola pliku do wydania: cz\u0119stotliwo\u015b\u0107 pr\u00f3bkowania, g\u0142\u0119bia bitowa, szczyty, cisza, ISRC i ok\u0142adka przed wysy\u0142k\u0105"},"content":{"rendered":"<div class=\"lw-rp\" id=\"rp-wurzel\" style=\"background: var(--bg-panel, #1e1e24); padding: 25px; border-radius: 8px; border: 1px solid var(--border, #2a2a35);\">\n<style>\n.lw-rp { --rp-warn: #e8a33d; }\n:root[data-theme=\"light\"] .lw-rp { --rp-warn: #8f5300; }\n.lw-rp .rp-zone { border: 2px dashed var(--border, #2a2a35); border-radius: 8px; padding: 22px; text-align: center; }\n.lw-rp .rp-zone.rp-ueber { border-color: var(--accent, #2ba6df); }\n.lw-rp .rp-gesamt { border-radius: 8px; padding: 12px 15px; margin-top: 4px; border: 1px solid var(--border, #2a2a35); background: var(--bg-body, #14141a); }\n.lw-rp .rp-gesamt-kopf { font-weight: 700; color: var(--text-primary, #e8e8ee); margin-bottom: 4px; }\n.lw-rp .rp-g-ok .rp-gesamt-kopf { color: var(--ok, #7ee787); }\n.lw-rp .rp-g-hinweis .rp-gesamt-kopf { color: var(--rp-warn); }\n.lw-rp .rp-g-problem .rp-gesamt-kopf { color: var(--fehler, #f0857a); }\n.lw-rp .rp-tabelle { overflow-x: auto; margin-top: 6px; }\n.lw-rp table { border-collapse: collapse; width: 100%; font-size: 0.86rem; }\n.lw-rp th, .lw-rp td { text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--border, #2a2a35); vertical-align: top; }\n.lw-rp th { color: var(--text-primary, #e8e8ee); white-space: nowrap; }\n.lw-rp td { color: var(--text-primary, #e8e8ee); }\n.lw-rp td.rp-wert { font-family: monospace; color: var(--text-secondary, #a0a0b0); white-space: nowrap; }\n.lw-rp td.rp-text { color: var(--text-secondary, #a0a0b0); line-height: 1.5; }\n.lw-rp .rp-stufe { display: inline-block; font-size: 0.74rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.4px; padding: 2px 7px; border-radius: 4px; border: 1px solid currentColor; white-space: nowrap; }\n.lw-rp .rp-s-ok { color: var(--ok, #7ee787); }\n.lw-rp .rp-s-hinweis { color: var(--rp-warn); }\n.lw-rp .rp-s-problem { color: var(--fehler, #f0857a); }\n.lw-rp .rp-s-info, .lw-rp .rp-s-offen { color: var(--text-secondary, #a0a0b0); }\n.lw-rp .rp-h { font-weight: 700; color: var(--text-primary, #e8e8ee); font-size: 0.95rem; margin: 24px 0 8px; }\n.lw-rp .rp-klein { font-size: 0.84rem; color: var(--text-secondary, #a0a0b0); line-height: 1.55; }\n.lw-rp .rp-knopf { background: transparent; color: var(--text-secondary, #a0a0b0); border: 1px solid var(--border, #2a2a35); padding: 9px 14px; border-radius: 6px; cursor: pointer; font-size: 0.9rem; margin-top: 14px; }\n.lw-rp .rp-name { margin-top: 4px; }\n.lw-rp .rp-fehler { color: var(--fehler, #f0857a); font-size: 0.88rem; margin-top: 12px; }\n.lw-rp a { color: var(--accent, #2ba6df); }\n@media (max-width: 480px) {\n    .lw-rp th, .lw-rp td { padding: 6px 5px; }\n    .lw-rp td.rp-wert { white-space: normal; word-break: break-word; }\n}\n\/* Schmal: die Checkliste als gestapelte Karten, sonst wird der Befund abgeschnitten. *\/\n@media (max-width: 600px) {\n    .lw-rp table.rp-karten thead { display: none; }\n    .lw-rp table.rp-karten tr { display: block; padding: 9px 0; border-bottom: 1px solid var(--border, #2a2a35); }\n    .lw-rp table.rp-karten td { display: block; border: none; padding: 2px 2px; }\n    .lw-rp table.rp-karten td.rp-wert { white-space: normal; margin-top: 3px; }\n    .lw-rp table.rp-karten .rp-name { display: inline; margin: 0 0 0 7px; font-weight: 700; }\n}\n<\/style>\n<p style=\"color: var(--text-secondary, #a0a0b0); margin-bottom: 18px;\">Sprawdza plik audio przed wys\u0142aniem do dystrybutora: format, cz\u0119stotliwo\u015b\u0107 pr\u00f3bkowania i g\u0142\u0119bi\u0119 bitow\u0105 wzgl\u0119dem wymaga\u0144 Apple, bity, kt\u00f3re tylko wype\u0142niaj\u0105 plik, clipping, true peak, sk\u0142adow\u0105 sta\u0142\u0105, cisz\u0119 na pocz\u0105tku i na ko\u0144cu oraz tytu\u0142, wykonawc\u0119, ISRC i ok\u0142adk\u0119 z tag\u00f3w. Plik jest odczytywany w przegl\u0105darce i nie trafia na serwer.<\/p>\n<div id=\"rp-zone\" class=\"rp-zone\">\n<p style=\"margin: 0 0 12px; color: var(--text-primary, #e8e8ee); font-weight: 700;\">Wyb\u00f3r pliku do wydania<\/p>\n<p>        <button id=\"rp-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=\"rp-datei\" type=\"file\" accept=\"audio\/*,.wav,.wave,.aif,.aiff,.aifc,.flac,.mp3,.m4a,.mp4,.aac,.ogg,.oga,.opus\" hidden><\/p>\n<p class=\"rp-klein\" style=\"margin: 12px 0 0;\">WAV, RF64, AIFF, FLAC, MP3, M4A, Ogg Vorbis i Opus. WAV i AIFF s\u0105 odczytywane pr\u00f3bka po pr\u00f3bce, pozosta\u0142e formaty przechodz\u0105 przez dekoder przegl\u0105darki.<\/p>\n<\/p><\/div>\n<div id=\"rp-status\" class=\"rp-klein\" data-mp-mask style=\"margin-top: 12px;\" aria-live=\"polite\"><\/div>\n<div id=\"rp-fehler\" class=\"rp-fehler\" data-mp-mask hidden><\/div>\n<div id=\"rp-ausgabe\" data-mp-mask style=\"margin-top: 18px;\" aria-live=\"polite\" hidden>\n<div id=\"rp-gesamt\" class=\"rp-gesamt\"><\/div>\n<div class=\"rp-h\">Lista kontrolna<\/div>\n<div class=\"rp-tabelle\">\n<table class=\"rp-karten\">\n<thead>\n<tr>\n<th>Punkt kontroli<\/th>\n<th>Warto\u015b\u0107<\/th>\n<th>Wynik<\/th>\n<\/tr>\n<\/thead>\n<tbody id=\"rp-liste\"><\/tbody>\n<\/table><\/div>\n<div class=\"rp-h\">Tagi w pliku<\/div>\n<div class=\"rp-tabelle\">\n<table>\n<thead>\n<tr>\n<th>Pole<\/th>\n<th>Warto\u015b\u0107<\/th>\n<th>Zapisane w<\/th>\n<\/tr>\n<\/thead>\n<tbody id=\"rp-tags\"><\/tbody>\n<\/table><\/div>\n<p>        <button id=\"rp-kopieren\" type=\"button\" class=\"rp-knopf\">Kopiowanie wyniku<\/button><br \/>\n        <span id=\"rp-kopiert\" class=\"rp-klein\" style=\"margin-left: 10px;\"><\/span>\n    <\/div>\n<div class=\"rp-h\">Co jest sprawdzane i dlaczego<\/div>\n<p class=\"rp-klein\" style=\"margin: 0 0 6px;\">Apple Music przyjmuje d\u017awi\u0119k 44,1, 48, 88,2, 96, 176,4 lub 192\u00a0kHz przy 16 lub 24 bitach i prosi o master w najwy\u017cszej dost\u0119pnej rozdzielczo\u015bci. Plik stratny tego nie spe\u0142nia: koder odrzuci\u0142 ju\u017c cz\u0119\u015b\u0107 sygna\u0142u, a serwis koduje jeszcze raz.<\/p>\n<p class=\"rp-klein\" style=\"margin: 0 0 6px;\">U\u017cywane bity: dla ka\u017cdej pr\u00f3bki sprawdzane s\u0105 najni\u017csze bity. Je\u015bli w ca\u0142ym pliku s\u0105 zerowe, dodatkowa g\u0142\u0119bia nic nie niesie, jak w masterze 16-bitowym zapisanym jako 24-bitowy. Apple Digital Masters wyra\u017anie wyklucza takie dope\u0142nianie. W plikach zmiennoprzecinkowych kontrola sprawdza, czy ka\u017cda warto\u015b\u0107 le\u017cy na siatce 16- lub 24-bitowej.<\/p>\n<p class=\"rp-klein\" style=\"margin: 0 0 6px;\">Pe\u0142na skala to najwy\u017csza warto\u015b\u0107 ca\u0142kowita; trzy lub wi\u0119cej takich pr\u00f3bek z rz\u0119du licz\u0105 si\u0119 jako miejsce z clippingiem. True peak jest liczony wed\u0142ug ITU-R BS.1770 filtrem o 48 wsp\u00f3\u0142czynnikach przy czterokrotnym nadpr\u00f3bkowaniu. Wykrywa szczyty mi\u0119dzy pr\u00f3bkami, kt\u00f3re konwersja lub koder zamienia w rzeczywiste.<\/p>\n<p class=\"rp-klein\" style=\"margin: 0 0 6px;\">Cisza oznacza tu poziom poni\u017cej \u221260\u00a0dBFS. Granice jednej sekundy na pocz\u0105tku, pi\u0119ciu sekund na ko\u0144cu, \u221240\u00a0dBFS dla pierwszej i ostatniej pr\u00f3bki oraz \u221260\u00a0dBFS dla sk\u0142adowej sta\u0142ej to regu\u0142y tej kontroli, a nie wymagania serwisu. Wskazuj\u0105 miejsca, kt\u00f3re przed przes\u0142aniem zas\u0142uguj\u0105 na ods\u0142uch.<\/p>\n<p class=\"rp-klein\" style=\"margin: 0 0 6px;\">Odczytywane s\u0105 ID3v2 i ID3v1, komentarze Vorbis w FLAC, Ogg i Opus, RIFF INFO i chunki ID3 w WAV i AIFF oraz metadane MP4. Przy ISRC decyduje pole: TSRC w ID3, ISRC w komentarzach Vorbis. ffmpeg zapisuje przy -metadata ISRC=\u2026 inne pola, co zmierzy\u0142 artyku\u0142 o metadanych wydawnictwa.<\/p>\n<p class=\"rp-klein\" style=\"margin: 0 0 6px;\">Apple zaleca 3000\u00a0\u00d7\u00a03000\u00a0pikseli lub wi\u0119cej, wymaga co najmniej 1400\u00a0\u00d7\u00a01400 i kwadratowego obrazu w JPEG lub PNG. Kontrola dotyczy osadzonego obrazu; ok\u0142adka dla dystrybutora to osobny plik.<\/p>\n<p class=\"rp-klein\" style=\"margin: 20px 0 0;\">\u0179r\u00f3d\u0142a:<br \/>\n        <a href=\"https:\/\/itunespartner.apple.com\/music\/support\/5215-digital-packaging-music\" rel=\"noopener\">Apple Music Provider Support: Digital packaging for music<\/a> \u00b7<br \/>\n        <a href=\"https:\/\/www.apple.com\/apple-music\/apple-digital-masters\/docs\/apple-digital-masters.pdf\" rel=\"noopener\">Apple Digital Masters<\/a> \u00b7<br \/>\n        <a href=\"https:\/\/www.itu.int\/rec\/R-REC-BS.1770\" rel=\"noopener\">ITU-R BS.1770<\/a> \u00b7<br \/>\n        <a href=\"https:\/\/aes2.org\/wp-content\/uploads\/2024\/01\/20210924_TD1008_v3.13.pdf\" rel=\"noopener\">AES TD1008<\/a> \u00b7<br \/>\n        <a href=\"https:\/\/isrc.ifpi.org\/images\/downloads\/ISRC_Handbook.pdf\" rel=\"noopener\">ISRC Handbook<\/a> \u00b7<br \/>\n        <a href=\"https:\/\/mutagen-specs.readthedocs.io\/en\/latest\/id3\/id3v2.4.0-frames.html\" rel=\"noopener\">ID3v2.4 frames<\/a> \u00b7<br \/>\n        <a href=\"https:\/\/xiph.org\/vorbis\/doc\/v-comment.html\" rel=\"noopener\">Vorbis comment<\/a> \u00b7<br \/>\n        <a href=\"https:\/\/exiftool.org\/TagNames\/RIFF.html\" rel=\"noopener\">RIFF Tags (ExifTool)<\/a>\n    <\/p>\n<p class=\"rp-klein\" style=\"font-size: 0.8rem; margin: 14px 0 0;\">Przytoczone wymagania pochodz\u0105 od Apple; inni dystrybutorzy publikuj\u0105 w\u0142asne. Formaty inne ni\u017c WAV i AIFF zale\u017c\u0105 od dekodera przegl\u0105darki, kt\u00f3ry w niekt\u00f3rych przegl\u0105darkach nie czyta ALAC ani skompresowanego AIFC. G\u0142o\u015bno\u015b\u0107 mierzy miernik LUFS.<\/p>\n<\/div>\n<p><script>\n(function () {\n    'use strict';\n    const T = {\"dezimal\":\",\",\"tausender\":\"\",\"einleitung\":\"Sprawdza plik audio przed wys\u0142aniem do dystrybutora: format, cz\u0119stotliwo\u015b\u0107 pr\u00f3bkowania i g\u0142\u0119bi\u0119 bitow\u0105 wzgl\u0119dem wymaga\u0144 Apple, bity, kt\u00f3re tylko wype\u0142niaj\u0105 plik, clipping, true peak, sk\u0142adow\u0105 sta\u0142\u0105, cisz\u0119 na pocz\u0105tku i na ko\u0144cu oraz tytu\u0142, wykonawc\u0119, ISRC i ok\u0142adk\u0119 z tag\u00f3w. Plik jest odczytywany w przegl\u0105darce i nie trafia na serwer.\",\"zone_titel\":\"Wyb\u00f3r pliku do wydania\",\"knopf_datei\":\"Wyb\u00f3r pliku\",\"zone_hinweis\":\"WAV, RF64, AIFF, FLAC, MP3, M4A, Ogg Vorbis i Opus. WAV i AIFF s\u0105 odczytywane pr\u00f3bka po pr\u00f3bce, pozosta\u0142e formaty przechodz\u0105 przez dekoder przegl\u0105darki.\",\"h_liste\":\"Lista kontrolna\",\"sp_pruefpunkt\":\"Punkt kontroli\",\"sp_wert\":\"Warto\u015b\u0107\",\"sp_befund\":\"Wynik\",\"h_tags\":\"Tagi w pliku\",\"sp_feld\":\"Pole\",\"sp_ort\":\"Zapisane w\",\"status_lesen\":\"Odczyt pliku \u2026\",\"status_dekodieren\":\"Dekodowanie \u2026\",\"status_messen\":\"Pomiar \u2026 {p}\u00a0%\",\"gesamt_ok\":\"Brak problem\u00f3w i uwag\",\"gesamt_hinweis\":\"Brak problem\u00f3w \u00b7 Uwagi: {h}\",\"gesamt_problem\":\"Problemy: {p} \u00b7 Uwagi: {h}\",\"gesamt_text_ok\":\"Wszystko, co jest tu mierzone, spe\u0142nia wymagania ze \u017ar\u00f3de\u0142. To, co dystrybutor sprawdza poza tym, na przyk\u0142ad dane w formularzu przesy\u0142ania, nie znajduje si\u0119 w tym pliku.\",\"gesamt_text_hinweis\":\"Nic nie blokuje dostawy, ale uwagi zas\u0142uguj\u0105 na przejrzenie przed przes\u0142aniem.\",\"gesamt_text_problem\":\"Co najmniej jeden punkt jest sprzeczny z wymaganiem dostawy albo wskazuje na uszkodzenie pliku. Kt\u00f3ry, podaj\u0105 wyniki poni\u017cej.\",\"stufe_ok\":\"OK\",\"stufe_hinweis\":\"Uwaga\",\"stufe_problem\":\"Problem\",\"stufe_info\":\"Info\",\"stufe_offen\":\"Bez pomiaru\",\"p_format\":\"Format\",\"p_rate\":\"Cz\u0119stotliwo\u015b\u0107 pr\u00f3bkowania\",\"p_bits\":\"G\u0142\u0119bia bitowa\",\"p_wirksam\":\"U\u017cywane bity\",\"p_kanaele\":\"Kana\u0142y\",\"p_messung\":\"D\u017awi\u0119k\",\"p_dauer\":\"Czas trwania\",\"p_spitze\":\"Szczyt pr\u00f3bki\",\"p_clipping\":\"Miejsca z clippingiem\",\"p_ueber\":\"Warto\u015bci powy\u017cej 0\u00a0dBFS\",\"p_truepeak\":\"True peak\",\"p_dc\":\"Sk\u0142adowa sta\u0142a\",\"p_stille_anfang\":\"Cisza na pocz\u0105tku\",\"p_stille_ende\":\"Cisza na ko\u0144cu\",\"p_sprung\":\"Pierwsza i ostatnia pr\u00f3bka\",\"p_kanalvergleich\":\"Lewy a prawy\",\"p_titel\":\"Tytu\u0142\",\"p_kuenstler\":\"Wykonawca\",\"p_isrc\":\"ISRC\",\"p_cover\":\"Ok\u0142adka\",\"wert_float\":\"zmiennoprzecinkowo\",\"wert_keine_tags\":\"Brak tytu\u0142u, wykonawcy, ISRC i ok\u0142adki\",\"bericht_kopf\":\"Kontrola pliku do wydania\",\"f_titel\":\"Tytu\u0142\",\"f_kuenstler\":\"Wykonawca\",\"f_isrc\":\"ISRC\",\"f_cover\":\"Ok\u0142adka\",\"ort_id3\":\"tag ID3v2\",\"ort_id3v1\":\"tag ID3v1\",\"ort_tsrc\":\"ramka ID3 TSRC\",\"ort_txxx\":\"ramka ID3 TXXX:ISRC\",\"ort_vorbis\":\"komentarz Vorbis\",\"ort_vorbis_bild\":\"komentarz Vorbis METADATA_BLOCK_PICTURE\",\"ort_flac_bild\":\"blok FLAC PICTURE\",\"ort_riff\":\"RIFF INFO\",\"ort_riff_isrc\":\"pole RIFF INFO ISRC\",\"ort_aiff\":\"chunk AIFF\",\"ort_mp4\":\"tag MP4\",\"ort_mdta\":\"klucz metadanych QuickTime\",\"ort_mp4_frei\":\"pole swobodne MP4 ISRC\",\"b_format_verlustfrei\":\"{format} przechowuje d\u017awi\u0119k bezstratnie.\",\"b_format_verlustbehaftet\":\"{format} to format stratny. Apple prosi o master w najwy\u017cszej dost\u0119pnej rozdzielczo\u015bci, a plik stratny nim nie jest.\",\"b_format_unbekannt\":\"Kontener {format} zosta\u0142 rozpoznany, kodek w nim \u2013 nie.\",\"b_offen_kopf\":\"Nag\u0142\u00f3wek pliku nie podaje tej warto\u015bci.\",\"b_rate_ok\":\"{rate} nale\u017cy do cz\u0119stotliwo\u015bci przyjmowanych przez Apple: 44,1, 48, 88,2, 96, 176,4 i 192\u00a0kHz.\",\"b_rate_andere\":\"{rate} nie nale\u017cy do cz\u0119stotliwo\u015bci przyjmowanych przez Apple (44,1, 48, 88,2, 96, 176,4 i 192\u00a0kHz). Przed dostaw\u0105 konieczna jest konwersja.\",\"b_bits_verlustbehaftet\":\"Format stratny nie ma sta\u0142ej g\u0142\u0119bi bitowej; dekoder zwraca warto\u015bci zmiennoprzecinkowe.\",\"b_bits_float\":\"Zapis zmiennoprzecinkowy {bits}-bitowy. Apple wymienia 16 i 24\u00a0bity, wi\u0119c przed dostaw\u0105 plik wymaga konwersji do 24-bitowych liczb ca\u0142kowitych.\",\"b_bits_24\":\"24\u00a0bity, zgodnie z zaleceniem Apple dla Apple Digital Masters.\",\"b_bits_16\":\"Zapis 16-bitowy jest przyjmowany. Dla Apple Digital Masters Apple wymaga \u017ar\u00f3de\u0142 24-bitowych.\",\"b_bits_wenig\":\"Zapis {bits}-bitowy to mniej ni\u017c 16 lub 24\u00a0bity przyjmowane przez Apple.\",\"b_bits_andere\":\"Zapis ca\u0142kowity {bits}-bitowy nie nale\u017cy do g\u0142\u0119bi wymienianych przez Apple (16 i 24\u00a0bity).\",\"b_wirksam_stille\":\"Plik zawiera wy\u0142\u0105cznie cyfrow\u0105 cisz\u0119, wi\u0119c u\u017cywane bity pozostaj\u0105 nieustalone.\",\"b_wirksam_float16\":\"Ka\u017cda warto\u015b\u0107 le\u017cy dok\u0142adnie na siatce 16-bitowej: sygna\u0142 16-bitowy w pliku zmiennoprzecinkowym. Dodatkowa precyzja jest pusta.\",\"b_wirksam_float24\":\"Ka\u017cda warto\u015b\u0107 le\u017cy dok\u0142adnie na siatce 24-bitowej, wi\u0119c konwersja do 24-bitowych liczb ca\u0142kowitych nic nie traci.\",\"b_wirksam_float\":\"Warto\u015bci wykorzystuj\u0105 precyzj\u0119 zmiennoprzecinkow\u0105; konwersja do 24\u00a0bit\u00f3w wymaga ditheringu.\",\"b_wirksam_offen\":\"Dla tego pliku warto\u015b\u0107 pozostaje nieustalona.\",\"b_wirksam_voll\":\"Sygna\u0142 niesie ca\u0142a g\u0142\u0119bia {bits}-bitowa.\",\"b_wirksam_aufgefuellt\":\"Sygna\u0142 niesie tylko {wirksam} z {bits}\u00a0bit\u00f3w, pozosta\u0142e s\u0105 zawsze zerowe. Plik to sygna\u0142 {wirksam}-bitowy dope\u0142niony do {bits}\u00a0bit\u00f3w \u2013 dok\u0142adnie to Apple Digital Masters wyra\u017anie wyklucza.\",\"b_wirksam_weniger\":\"Sygna\u0142 niesie tylko {wirksam} z {bits}\u00a0bit\u00f3w; najni\u017csze bity s\u0105 zawsze zerowe.\",\"b_kanaele_2\":\"Stereo.\",\"b_kanaele_1\":\"Mono. Czy dystrybutor przyjmuje plik mono, czy oczekuje dw\u00f3ch identycznych kana\u0142\u00f3w, okre\u015bla jego w\u0142asna specyfikacja.\",\"b_kanaele_mehr\":\"Liczba kana\u0142\u00f3w: {n}. Miks wielokana\u0142owy, taki jak Dolby Atmos, trafia do dostawy osobno i dostaje w\u0142asny ISRC.\",\"b_offen_ton\":\"Przegl\u0105darka nie zdekodowa\u0142a d\u017awi\u0119ku tego pliku, dlatego szczyty, cisza i sk\u0142adowa sta\u0142a pozosta\u0142y bez pomiaru. Nag\u0142\u00f3wek i tagi s\u0105 mimo to pokazane.\",\"b_dauer\":\"D\u0142ugo\u015b\u0107 d\u017awi\u0119ku zapisana w pliku.\",\"b_spitze_ok\":\"Najwy\u017csza pr\u00f3bka pozostaje poni\u017cej pe\u0142nej skali.\",\"b_spitze_voll\":\"Pr\u00f3bki na pe\u0142nej skali: {n}. Czy to clipping, pokazuje nast\u0119pny wiersz.\",\"b_clipping_keine\":\"Brak ci\u0105gu trzech lub wi\u0119cej kolejnych pr\u00f3bek na pe\u0142nej skali.\",\"b_clipping\":\"Miejsca z trzema lub wi\u0119cej kolejnymi pr\u00f3bkami na pe\u0142nej skali: {n}. Tam przebieg jest p\u0142asko \u015bci\u0119ty.\",\"b_ueber_keine\":\"\u017badna warto\u015b\u0107 nie przekracza pe\u0142nej skali.\",\"b_ueber\":\"Warto\u015bci powy\u017cej 0\u00a0dBFS: {n}. Plik zmiennoprzecinkowy je przechowuje, ale konwersja do ca\u0142kowitego PCM je obcina.\",\"b_tp_ok\":\"Najwy\u017cej \u22121\u00a0dBTP, zgodnie z zaleceniem AES TD1008 dla wej\u015bcia kodeka.\",\"b_tp_hinweis\":\"Mi\u0119dzy \u22121 a 0\u00a0dBTP. AES TD1008 zaleca na wej\u015bciu kodeka najwy\u017cej \u22121\u00a0dBTP, poniewa\u017c kodowanie dalej podnosi szczyty.\",\"b_tp_problem\":\"Powy\u017cej 0\u00a0dBTP: mi\u0119dzy pr\u00f3bkami przebieg ju\u017c przekracza pe\u0142n\u0105 skal\u0119, a ka\u017cda konwersja lub kodowanie mo\u017ce go przesterowa\u0107.\",\"b_dc_ok\":\"Brak istotnej sk\u0142adowej sta\u0142ej (granica tej kontroli: \u221260\u00a0dBFS).\",\"b_dc_hoch\":\"Warto\u015b\u0107 \u015brednia wynosi \u221260\u00a0dBFS lub wi\u0119cej. Sk\u0142adowa sta\u0142a zabiera zapas wysterowania i zamienia pocz\u0105tek i koniec pliku w skok.\",\"b_stille_ganz\":\"Plik nie zawiera \u017cadnej pr\u00f3bki powy\u017cej \u221260\u00a0dBFS.\",\"b_stille_anfang_ok\":\"Czas do pierwszej pr\u00f3bki powy\u017cej \u221260\u00a0dBFS.\",\"b_stille_anfang_lang\":\"Do pierwszej pr\u00f3bki powy\u017cej \u221260\u00a0dBFS mija co najmniej sekunda, a odtwarzacz gra t\u0119 cisz\u0119 przed muzyk\u0105.\",\"b_stille_ende_ok\":\"Czas po ostatniej pr\u00f3bce powy\u017cej \u221260\u00a0dBFS.\",\"b_stille_ende_lang\":\"Po ostatniej pr\u00f3bce powy\u017cej \u221260\u00a0dBFS zostaje co najmniej pi\u0119\u0107 sekund; na albumie wyd\u0142u\u017caj\u0105 one przerw\u0119 przed nast\u0119pnym utworem.\",\"b_sprung_ok\":\"Plik zaczyna i ko\u0144czy si\u0119 poni\u017cej \u221240\u00a0dBFS, wi\u0119c odtwarzanie rusza i ustaje bez skoku.\",\"b_sprung_anfang\":\"Pierwsza pr\u00f3bka le\u017cy na poziomie \u221240\u00a0dBFS lub wy\u017cej. Odtwarzanie zaczyna si\u0119 skokiem z ciszy do tej warto\u015bci, s\u0142yszalnym jako trzask.\",\"b_sprung_ende\":\"Ostatnia pr\u00f3bka le\u017cy na poziomie \u221240\u00a0dBFS lub wy\u017cej. Odtwarzanie ko\u0144czy si\u0119 skokiem do ciszy, s\u0142yszalnym jako trzask.\",\"b_sprung_beide\":\"Pierwsza i ostatnia pr\u00f3bka le\u017c\u0105 na poziomie \u221240\u00a0dBFS lub wy\u017cej: skoki na obu ko\u0144cach, s\u0142yszalne jako trzaski.\",\"b_kanal_ok\":\"Kana\u0142y si\u0119 r\u00f3\u017cni\u0105 i oba nios\u0105 sygna\u0142.\",\"b_kanal_gleich\":\"Lewy i prawy kana\u0142 s\u0105 identyczne pr\u00f3bka po pr\u00f3bce: sygna\u0142 mono w pliku stereo.\",\"b_kanal_stumm\":\"Kana\u0142 {kanal} milczy, podczas gdy drugi niesie sygna\u0142.\",\"b_titel_da\":\"\u0179r\u00f3d\u0142o: {ort}.\",\"b_titel_fehlt\":\"Brak tytu\u0142u w pliku. Dystrybutor przejmuje tytu\u0142 z formularza przesy\u0142ania; tag pomaga wsz\u0119dzie tam, gdzie plik kr\u0105\u017cy sam.\",\"b_kuenstler_da\":\"\u0179r\u00f3d\u0142o: {ort}.\",\"b_kuenstler_fehlt\":\"Brak wykonawcy w pliku. U dystrybutora liczy si\u0119 formularz przesy\u0142ania; poza nim tag towarzyszy plikowi wsz\u0119dzie.\",\"b_isrc_ok\":\"Poprawnie zbudowany kod w polu przewidzianym do tego celu ({ort}).\",\"b_isrc_txxx\":\"Kod stoi w ramce TXXX o nazwie ISRC \u2013 tak\u0105 ramk\u0119 zapisuje ffmpeg przy -metadata ISRC=\u2026. ID3v2.4 przewiduje do tego ramk\u0119 TSRC.\",\"b_isrc_riff\":\"Pole RIFF INFO ISRC oznacza wed\u0142ug dokumentacji tag\u00f3w ExifTool \u201eSource\u201d, a nie kod nagrania. Program odczytuj\u0105cy ten plik nie mo\u017ce na nim polega\u0107.\",\"b_isrc_form\":\"Warto\u015b\u0107 ({ort}) nie jest poprawnie zbudowanym kodem ISRC: dwie litery, trzy litery lub cyfry, dwie cyfry roku i pi\u0119\u0107 cyfr.\",\"b_isrc_mehrere\":\"Plik zawiera r\u00f3\u017cne kody ISRC, \u0142\u0105cznie {n}. Wed\u0142ug podr\u0119cznika ISRC nagranie ma dok\u0142adnie jeden.\",\"b_isrc_fehlt\":\"Brak ISRC w pliku. Wed\u0142ug podr\u0119cznika ISRC kod powinien w miar\u0119 mo\u017cliwo\u015bci trafi\u0107 do pliku razem z nagraniem; dystrybutor dostarcza go dodatkowo przez DDEX.\",\"b_cover_fehlt\":\"Brak osadzonej ok\u0142adki. Dystrybutorzy przyjmuj\u0105 ok\u0142adk\u0119 jako osobny plik.\",\"b_cover_format\":\"Osadzony obraz to {typ}; Apple przyjmuje JPEG lub PNG.\",\"b_cover_masse\":\"Osadzony plik nie zdradza rozmiaru obrazu.\",\"b_cover_quadrat\":\"{breite}\u00a0\u00d7\u00a0{hoehe}\u00a0px to nie kwadrat; Apple wymaga proporcji 1:1.\",\"b_cover_klein\":\"{breite}\u00a0\u00d7\u00a0{hoehe}\u00a0px to mniej ni\u017c minimum Apple, czyli 1400\u00a0\u00d7\u00a01400\u00a0px.\",\"b_cover_mittel\":\"Powy\u017cej minimum Apple (1400\u00a0\u00d7\u00a01400\u00a0px), poni\u017cej zalecanych 3000\u00a0\u00d7\u00a03000\u00a0px.\",\"b_cover_ok\":\"Kwadrat o boku co najmniej 3000\u00a0px, zgodnie z zaleceniem Apple.\",\"knopf_kopieren\":\"Kopiowanie wyniku\",\"kopiert\":\"skopiowano\",\"kopieren_fehler\":\"kopiowanie niemo\u017cliwe\",\"fehler_format\":\"Ten plik nie nale\u017cy do odczytywanych tu format\u00f3w: WAV, RF64, AIFF, FLAC, MP3, M4A, Ogg Vorbis i Opus.\",\"fehler_lesen\":\"Odczyt pliku zako\u0144czy\u0142 si\u0119 b\u0142\u0119dem.\",\"h_erklaerung\":\"Co jest sprawdzane i dlaczego\",\"erkl_format\":\"Apple Music przyjmuje d\u017awi\u0119k 44,1, 48, 88,2, 96, 176,4 lub 192\u00a0kHz przy 16 lub 24 bitach i prosi o master w najwy\u017cszej dost\u0119pnej rozdzielczo\u015bci. Plik stratny tego nie spe\u0142nia: koder odrzuci\u0142 ju\u017c cz\u0119\u015b\u0107 sygna\u0142u, a serwis koduje jeszcze raz.\",\"erkl_bits\":\"U\u017cywane bity: dla ka\u017cdej pr\u00f3bki sprawdzane s\u0105 najni\u017csze bity. Je\u015bli w ca\u0142ym pliku s\u0105 zerowe, dodatkowa g\u0142\u0119bia nic nie niesie, jak w masterze 16-bitowym zapisanym jako 24-bitowy. Apple Digital Masters wyra\u017anie wyklucza takie dope\u0142nianie. W plikach zmiennoprzecinkowych kontrola sprawdza, czy ka\u017cda warto\u015b\u0107 le\u017cy na siatce 16- lub 24-bitowej.\",\"erkl_spitzen\":\"Pe\u0142na skala to najwy\u017csza warto\u015b\u0107 ca\u0142kowita; trzy lub wi\u0119cej takich pr\u00f3bek z rz\u0119du licz\u0105 si\u0119 jako miejsce z clippingiem. True peak jest liczony wed\u0142ug ITU-R BS.1770 filtrem o 48 wsp\u00f3\u0142czynnikach przy czterokrotnym nadpr\u00f3bkowaniu. Wykrywa szczyty mi\u0119dzy pr\u00f3bkami, kt\u00f3re konwersja lub koder zamienia w rzeczywiste.\",\"erkl_stille\":\"Cisza oznacza tu poziom poni\u017cej \u221260\u00a0dBFS. Granice jednej sekundy na pocz\u0105tku, pi\u0119ciu sekund na ko\u0144cu, \u221240\u00a0dBFS dla pierwszej i ostatniej pr\u00f3bki oraz \u221260\u00a0dBFS dla sk\u0142adowej sta\u0142ej to regu\u0142y tej kontroli, a nie wymagania serwisu. Wskazuj\u0105 miejsca, kt\u00f3re przed przes\u0142aniem zas\u0142uguj\u0105 na ods\u0142uch.\",\"erkl_tags\":\"Odczytywane s\u0105 ID3v2 i ID3v1, komentarze Vorbis w FLAC, Ogg i Opus, RIFF INFO i chunki ID3 w WAV i AIFF oraz metadane MP4. Przy ISRC decyduje pole: TSRC w ID3, ISRC w komentarzach Vorbis. ffmpeg zapisuje przy -metadata ISRC=\u2026 inne pola, co zmierzy\u0142 artyku\u0142 o metadanych wydawnictwa.\",\"erkl_cover\":\"Apple zaleca 3000\u00a0\u00d7\u00a03000\u00a0pikseli lub wi\u0119cej, wymaga co najmniej 1400\u00a0\u00d7\u00a01400 i kwadratowego obrazu w JPEG lub PNG. Kontrola dotyczy osadzonego obrazu; ok\u0142adka dla dystrybutora to osobny plik.\",\"quellen_titel\":\"\u0179r\u00f3d\u0142a\",\"grenze\":\"Przytoczone wymagania pochodz\u0105 od Apple; inni dystrybutorzy publikuj\u0105 w\u0142asne. Formaty inne ni\u017c WAV i AIFF zale\u017c\u0105 od dekodera przegl\u0105darki, kt\u00f3ry w niekt\u00f3rych przegl\u0105darkach nie czyta ALAC ani skompresowanego AIFC. G\u0142o\u015bno\u015b\u0107 mierzy miernik LUFS.\"};<\/p>\n<p>    \/\/ KERN-ANFANG ------------------------------------------------------------\n    \/\/ Leser und Messung ohne Dokument: derselbe Text laeuft im Browser und in Node.<\/p>\n<p>    \/\/ Apple Music Provider Support, \"Digital packaging for music\": zulaessige Raten.\n    var RATEN_APPLE = [44100, 48000, 88200, 96000, 176400, 192000];\n    var STILLE = Math.pow(10, -60 \/ 20);          \/\/ Grenze fuer Stille: -60 dBFS\n    var SPRUNG = Math.pow(10, -40 \/ 20);          \/\/ erster\/letzter Wert ab -40 dBFS gilt als Sprung\n    var DC_GRENZE = Math.pow(10, -60 \/ 20);       \/\/ Gleichanteil ab -60 dBFS wird gemeldet\n    var STILLE_ANFANG_S = 1, STILLE_ENDE_S = 5;   \/\/ Hinweisgrenzen in Sekunden\n    var COVER_EMPFOHLEN = 3000, COVER_MINDEST = 1400;<\/p>\n<p>    \/\/ ITU-R BS.1770-5, Anhang 2: 4-fach ueberabtastendes FIR, vier Phasen zu je zwoelf Werten.\n    var TP_PHASEN = [\n        [0.0017089843750, 0.0109863281250, -0.0196533203125, 0.0332031250000, -0.0594482421875, 0.1373291015625,\n         0.9721679687500, -0.1022949218750, 0.0476074218750, -0.0266113281250, 0.0148925781250, -0.0083007812500],\n        [-0.0291748046875, 0.0292968750000, -0.0517578125000, 0.0891113281250, -0.1665039062500, 0.4650878906250,\n         0.7797851562500, -0.2003173828125, 0.1015625000000, -0.0582275390625, 0.0330810546875, -0.0189208984375],\n        [-0.0189208984375, 0.0330810546875, -0.0582275390625, 0.1015625000000, -0.2003173828125, 0.7797851562500,\n         0.4650878906250, -0.1665039062500, 0.0891113281250, -0.0517578125000, 0.0292968750000, -0.0291748046875],\n        [-0.0083007812500, 0.0148925781250, -0.0266113281250, 0.0476074218750, -0.1022949218750, 0.9721679687500,\n         0.1373291015625, -0.0594482421875, 0.0332031250000, -0.0196533203125, 0.0109863281250, 0.0017089843750]\n    ];<\/p>\n<p>    \/\/ ---- Bytes --------------------------------------------------------------\n    function str(u8, o, l) {\n        var s = '';\n        for (var i = 0; i < l &#038;&#038; o + i < u8.length; i++) { s += String.fromCharCode(u8[o + i]); }\n        return s;\n    }\n    function be16(u8, o) { return (u8[o] << 8) | u8[o + 1]; }\n    function be32(u8, o) { return ((u8[o] << 24) >>> 0) + (u8[o + 1] << 16) + (u8[o + 2] << 8) + u8[o + 3]; }\n    function le16(u8, o) { return u8[o] | (u8[o + 1] << 8); }\n    function le32(u8, o) { return (u8[o] | (u8[o + 1] << 8) | (u8[o + 2] << 16)) + ((u8[o + 3] << 24) >>> 0); }\n    function syncsafe(u8, o) {\n        return ((u8[o] & 0x7F) << 21) | ((u8[o + 1] &#038; 0x7F) << 14) | ((u8[o + 2] &#038; 0x7F) << 7) | (u8[o + 3] &#038; 0x7F);\n    }\n\n    function utf8(u8) {\n        if (typeof TextDecoder !== 'undefined') { return new TextDecoder('utf-8').decode(u8); }\n        var s = str(u8, 0, u8.length);\n        try { return decodeURIComponent(escape(s)); } catch (e) { return s; }\n    }\n    \/\/ art wie im ID3-Kodierungsbyte: 0 Latin-1, 1 UTF-16 mit BOM, 2 UTF-16BE, 3 UTF-8\n    function text(u8, art) {\n        var s = '', i;\n        if (art === 3) { s = utf8(u8); }\n        else if (art === 1 || art === 2) {\n            var gross = art === 2;\n            i = 0;\n            if (u8.length >= 2 && u8[0] === 0xFF && u8[1] === 0xFE) { gross = false; i = 2; }\n            else if (u8.length >= 2 && u8[0] === 0xFE && u8[1] === 0xFF) { gross = true; i = 2; }\n            for (; i + 1 < u8.length; i += 2) {\n                s += String.fromCharCode(gross ? (u8[i] << 8) | u8[i + 1] : u8[i] | (u8[i + 1] << 8));\n            }\n        } else { s = str(u8, 0, u8.length); }\n        \/\/ ID3v2.4 trennt mehrere Werte mit Nullzeichen; der erste zaehlt.\n        var teile = s.split('\\u0000');\n        for (i = 0; i < teile.length; i++) { if (teile[i].trim() !== '') { return teile[i].trim(); } }\n        return '';\n    }\n    function nullStelle(u8, p, breit) {\n        if (breit) {\n            for (var i = p; i + 1 < u8.length; i += 2) { if (u8[i] === 0 &#038;&#038; u8[i + 1] === 0) { return i; } }\n            return u8.length;\n        }\n        for (var j = p; j < u8.length; j++) { if (u8[j] === 0) { return j; } }\n        return u8.length;\n    }\n    function base64(s) {\n        s = s.replace(\/[^A-Za-z0-9+\\\/=]\/g, '');\n        var roh = typeof atob === 'function' ? atob(s) : Buffer.from(s, 'base64').toString('binary');\n        var u8 = new Uint8Array(roh.length);\n        for (var i = 0; i < roh.length; i++) { u8[i] = roh.charCodeAt(i); }\n        return u8;\n    }\n\n    \/\/ ---- Bilder -------------------------------------------------------------\n    function bildMasse(u8) {\n        if (u8.length >= 24 && u8[0] === 0x89 && u8[1] === 0x50 && u8[2] === 0x4E && u8[3] === 0x47) {\n            return { typ: 'PNG', breite: be32(u8, 16), hoehe: be32(u8, 20) };\n        }\n        if (u8.length >= 4 && u8[0] === 0xFF && u8[1] === 0xD8) {\n            var p = 2;\n            while (p + 9 < u8.length) {\n                if (u8[p] !== 0xFF) { p++; continue; }\n                var m = u8[p + 1];\n                if (m === 0xFF) { p++; continue; }\n                if (m === 0xD8 || m === 0x01 || (m >= 0xD0 && m <= 0xD7)) { p += 2; continue; }\n                if (m >= 0xC0 && m <= 0xCF &#038;&#038; m !== 0xC4 &#038;&#038; m !== 0xC8 &#038;&#038; m !== 0xCC) {\n                    return { typ: 'JPEG', hoehe: be16(u8, p + 5), breite: be16(u8, p + 7) };\n                }\n                if (m === 0xDA) { break; }\n                p += 2 + be16(u8, p + 2);\n            }\n            return { typ: 'JPEG', breite: null, hoehe: null };\n        }\n        if (u8.length >= 2 && u8[0] === 0x42 && u8[1] === 0x4D) { return { typ: 'BMP', breite: null, hoehe: null }; }\n        if (u8.length >= 3 && u8[0] === 0x47 && u8[1] === 0x49 && u8[2] === 0x46) { return { typ: 'GIF', breite: le16(u8, 6), hoehe: le16(u8, 8) }; }\n        return { typ: null, breite: null, hoehe: null };\n    }\n    function bildEintrag(daten, ort, bildtyp, breite, hoehe) {\n        var m = bildMasse(daten);\n        return { ort: ort, bildtyp: bildtyp === undefined ? null : bildtyp, typ: m.typ,\n                 breite: m.breite || breite || null, hoehe: m.hoehe || hoehe || null, bytes: daten.length };\n    }<\/p>\n<p>    function neueTags() { return { titel: [], kuenstler: [], isrc: [], cover: [] }; }<\/p>\n<p>    \/\/ ---- ID3v2 und ID3v1 ----------------------------------------------------\n    function entSync(u8) {\n        var raus = new Uint8Array(u8.length), n = 0;\n        for (var i = 0; i < u8.length; i++) {\n            raus[n++] = u8[i];\n            if (u8[i] === 0xFF &#038;&#038; u8[i + 1] === 0x00) { i++; }\n        }\n        return raus.subarray(0, n);\n    }\n\n    function id3Rahmen(id, b, tags) {\n        if (!b.length) { return; }\n        var art = b[0], breit = art === 1 || art === 2, e;\n        if (id === 'TIT2' || id === 'TT2') { tags.titel.push({ wert: text(b.subarray(1), art), ort: 'id3' }); }\n        else if (id === 'TPE1' || id === 'TP1') { tags.kuenstler.push({ wert: text(b.subarray(1), art), ort: 'id3' }); }\n        else if (id === 'TSRC' || id === 'TRC') { tags.isrc.push({ wert: text(b.subarray(1), art), ort: 'tsrc' }); }\n        else if (id === 'TXXX' || id === 'TXX') {\n            e = nullStelle(b, 1, breit);\n            var beschreibung = text(b.subarray(1, e), art);\n            if (\/^isrc$\/i.test(beschreibung)) {\n                tags.isrc.push({ wert: text(b.subarray(e + (breit ? 2 : 1)), art), ort: 'txxx' });\n            }\n        } else if (id === 'APIC') {\n            var m = nullStelle(b, 1, false);\n            var bildtyp = b[m + 1];\n            e = nullStelle(b, m + 2, breit);\n            tags.cover.push(bildEintrag(b.subarray(e + (breit ? 2 : 1)), 'id3', bildtyp));\n        } else if (id === 'PIC') {\n            e = nullStelle(b, 5, breit);\n            tags.cover.push(bildEintrag(b.subarray(e + (breit ? 2 : 1)), 'id3', b[4]));\n        }\n    }\n\n    \/\/ Gibt die Laenge des Tags zurueck, 0 wenn an o keiner beginnt.\n    function id3Lesen(u8, o, tags) {\n        if (o + 10 > u8.length || u8[o] !== 0x49 || u8[o + 1] !== 0x44 || u8[o + 2] !== 0x33) { return 0; }\n        var ver = u8[o + 3], flaggen = u8[o + 5], groesse = syncsafe(u8, o + 6);\n        if (ver < 2 || ver > 4) { return 0; }\n        var d = u8.subarray(o + 10, Math.min(u8.length, o + 10 + groesse));\n        if ((flaggen & 0x80) && ver < 4) { d = entSync(d); }\n        var p = 0;\n        if ((flaggen &#038; 0x40) &#038;&#038; ver >= 3) { p += ver === 4 ? syncsafe(d, 0) : be32(d, 0) + 4; }\n        var kopf = ver === 2 ? 6 : 10;\n        while (p + kopf <= d.length) {\n            var id, fg;\n            if (ver === 2) { id = str(d, p, 3); fg = (d[p + 3] << 16) | (d[p + 4] << 8) | d[p + 5]; }\n            else { id = str(d, p, 4); fg = ver === 4 ? syncsafe(d, p + 4) : be32(d, p + 4); }\n            if (!\/^[A-Z0-9]{3,4}$\/.test(id) || fg <= 0 || p + kopf + fg > d.length) { break; }\n            var format = ver >= 3 ? d[p + 9] : 0;\n            var inhalt = d.subarray(p + kopf, p + kopf + fg);\n            var gesperrt = ver === 4 ? (format & 0x0C) : (ver === 3 ? (format & 0xC0) : 0);\n            if (ver === 4 && (format & 0x02)) { inhalt = entSync(inhalt); }\n            if (ver === 4 && (format & 0x01)) { inhalt = inhalt.subarray(4); }\n            if (!gesperrt) { id3Rahmen(id, inhalt, tags); }\n            p += kopf + fg;\n        }\n        return 10 + groesse + (flaggen & 0x10 ? 10 : 0);\n    }<\/p>\n<p>    function id3v1Lesen(u8, tags) {\n        if (u8.length < 128) { return; }\n        var o = u8.length - 128;\n        if (str(u8, o, 3) !== 'TAG') { return; }\n        var titel = text(u8.subarray(o + 3, o + 33), 0), kuenstler = text(u8.subarray(o + 33, o + 63), 0);\n        if (titel) { tags.titel.push({ wert: titel, ort: 'id3v1' }); }\n        if (kuenstler) { tags.kuenstler.push({ wert: kuenstler, ort: 'id3v1' }); }\n    }\n\n    \/\/ ---- Vorbis-Kommentar und FLAC-Bild -------------------------------------\n    function flacBild(u8, p, ende, tags, ort) {\n        if (p + 32 > ende) { return; }\n        var bildtyp = be32(u8, p), ml = be32(u8, p + 4);\n        var q = p + 8 + ml, bl = be32(u8, q);\n        q += 4 + bl;\n        var breite = be32(u8, q), hoehe = be32(u8, q + 4), dl = be32(u8, q + 16);\n        var daten = u8.subarray(q + 20, Math.min(ende, q + 20 + dl));\n        tags.cover.push(bildEintrag(daten, ort, bildtyp, breite, hoehe));\n    }<\/p>\n<p>    function vorbisKommentar(u8, p, ende, tags) {\n        if (p + 8 > ende) { return; }\n        p += 4 + le32(u8, p);\n        var anzahl = le32(u8, p);\n        p += 4;\n        for (var k = 0; k < anzahl &#038;&#038; p + 4 <= ende; k++) {\n            var l = le32(u8, p);\n            if (p + 4 + l > ende) { break; }\n            var eintrag = u8.subarray(p + 4, p + 4 + l);\n            p += 4 + l;\n            var gleich = -1;\n            for (var i = 0; i < eintrag.length &#038;&#038; i < 64; i++) { if (eintrag[i] === 0x3D) { gleich = i; break; } }\n            if (gleich < 1) { continue; }\n            var name = str(eintrag, 0, gleich).toUpperCase();\n            if (name === 'METADATA_BLOCK_PICTURE') {\n                var bild = base64(str(eintrag, gleich + 1, eintrag.length - gleich - 1));\n                flacBild(bild, 0, bild.length, tags, 'vorbis_bild');\n            } else if (name === 'COVERART') {\n                tags.cover.push(bildEintrag(base64(str(eintrag, gleich + 1, eintrag.length - gleich - 1)), 'vorbis_bild', 3));\n            } else if (name === 'TITLE' || name === 'ARTIST' || name === 'ISRC') {\n                var wert = utf8(eintrag.subarray(gleich + 1)).trim();\n                if (name === 'TITLE') { tags.titel.push({ wert: wert, ort: 'vorbis' }); }\n                else if (name === 'ARTIST') { tags.kuenstler.push({ wert: wert, ort: 'vorbis' }); }\n                else { tags.isrc.push({ wert: wert, ort: 'vorbis' }); }\n            }\n        }\n    }\n\n    \/\/ ---- WAV, RF64, AIFF: Kopf, Tags und Abtastwerte ------------------------\n    \/\/ Liest die Werte selbst, damit nichts umgerechnet wird, und haelt dabei fest,\n    \/\/ welche Bits ueberhaupt vorkommen (Bit-Padding) und ob Gleitkommawerte genau\n    \/\/ auf ein 16- oder 24-Bit-Raster fallen.\n    function pcmLesen(puffer, start, laenge, anzahl, bytes, art, klein) {\n        var rahmen = Math.floor(laenge \/ (bytes * anzahl)), raus = [], c, i, k, v, s;\n        for (c = 0; c < anzahl; c++) { raus.push(new Float32Array(rahmen)); }\n        var oder = 0, alle16 = true, alle24 = true, n = rahmen * anzahl;\n        if (art === 'float') {\n            var dvf = new DataView(puffer, start, n * bytes);\n            for (i = 0, k = 0; i < rahmen; i++) {\n                for (c = 0; c < anzahl; c++, k++) {\n                    v = bytes === 4 ? dvf.getFloat32(k * 4, klein) : dvf.getFloat64(k * 8, klein);\n                    raus[c][i] = v;\n                    if (alle24) {\n                        s = v * 8388608;\n                        if (s !== Math.floor(s)) { alle24 = false; alle16 = false; }\n                        else if (alle16) { s = v * 32768; if (s !== Math.floor(s)) { alle16 = false; } }\n                    }\n                }\n            }\n            return { kanaele: raus, oder: null, alle16: alle16, alle24: alle24 };\n        }\n        var teiler = Math.pow(2, bytes * 8 - 1);\n        if (klein &#038;&#038; (bytes === 2 || bytes === 4)) {\n            var stueck = puffer.slice(start, start + n * bytes);\n            var a = bytes === 2 ? new Int16Array(stueck) : new Int32Array(stueck);\n            for (i = 0, k = 0; i < rahmen; i++) {\n                for (c = 0; c < anzahl; c++, k++) { v = a[k]; oder |= v; raus[c][i] = v \/ teiler; }\n            }\n            return { kanaele: raus, oder: oder, alle16: null, alle24: null };\n        }\n        var u8 = new Uint8Array(puffer, start, n * bytes), dv = new DataView(puffer, start, n * bytes), o = 0;\n        for (i = 0; i < rahmen; i++) {\n            for (c = 0; c < anzahl; c++) {\n                if (bytes === 1) { v = klein ? u8[o] - 128 : dv.getInt8(o); }\n                else if (bytes === 2) { v = dv.getInt16(o, klein); }\n                else if (bytes === 3) {\n                    v = klein ? (u8[o] | (u8[o + 1] << 8) | (u8[o + 2] << 16)) : ((u8[o] << 16) | (u8[o + 1] << 8) | u8[o + 2]);\n                    if (v &#038; 0x800000) { v -= 0x1000000; }\n                } else { v = dv.getInt32(o, klein); }\n                oder |= v;\n                raus[c][i] = v \/ teiler;\n                o += bytes;\n            }\n        }\n        return { kanaele: raus, oder: oder, alle16: null, alle24: null };\n    }\n\n    function riffInfo(u8, p, ende, tags) {\n        while (p + 8 <= ende) {\n            var id = str(u8, p, 4), l = le32(u8, p + 4);\n            var wert = text(u8.subarray(p + 8, Math.min(ende, p + 8 + l)), 3);\n            if (id === 'INAM') { tags.titel.push({ wert: wert, ort: 'riff' }); }\n            else if (id === 'IART') { tags.kuenstler.push({ wert: wert, ort: 'riff' }); }\n            else if (id === 'ISRC') { tags.isrc.push({ wert: wert, ort: 'riff_isrc' }); }\n            p += 8 + l + (l &#038; 1);\n        }\n    }\n\n    function wavLesen(puffer, info) {\n        var u8 = new Uint8Array(puffer), n = u8.length, p = 12, fmt = null, ds64 = null, daten = null;\n        while (p + 8 <= n) {\n            var id = str(u8, p, 4), l = le32(u8, p + 4);\n            if (id === 'ds64' &#038;&#038; l >= 16) { ds64 = le32(u8, p + 16) + le32(u8, p + 20) * 4294967296; }\n            if (id === 'data' && l === 0xFFFFFFFF && ds64 !== null) { l = ds64; }\n            if (id === 'fmt ') {\n                var tag = le16(u8, p + 8);\n                if (tag === 0xFFFE && l >= 26) { tag = le16(u8, p + 32); }\n                fmt = { tag: tag, anzahl: le16(u8, p + 10), rate: le32(u8, p + 12), bits: le16(u8, p + 22) };\n            } else if (id === 'data') {\n                daten = { start: p + 8, laenge: Math.min(l, n - p - 8) };\n            } else if (id === 'LIST' && str(u8, p + 8, 4) === 'INFO') {\n                riffInfo(u8, p + 12, Math.min(n, p + 8 + l), info.tags);\n            } else if (id === 'id3 ' || id === 'ID3 ') {\n                id3Lesen(u8, p + 8, info.tags);\n            }\n            if (l === 0xFFFFFFFF) { break; }\n            p += 8 + l + (l & 1);\n        }\n        if (!fmt) { info.fehler = 'fmt'; return info; }\n        info.rate = fmt.rate;\n        info.kanaeleAnzahl = fmt.anzahl;\n        info.bits = fmt.bits;\n        info.gleitkomma = fmt.tag === 3;\n        info.verlustfrei = fmt.tag === 1 || fmt.tag === 3;\n        info.ganzzahl = fmt.tag === 1;\n        var bytes = fmt.bits \/ 8;\n        if (!daten || !info.verlustfrei || !fmt.anzahl || (fmt.tag === 1 && [1, 2, 3, 4].indexOf(bytes) === -1) ||\n            (fmt.tag === 3 && bytes !== 4 && bytes !== 8)) {\n            info.fehler = daten ? 'codec' : 'data';\n            return info;\n        }\n        var w = pcmLesen(puffer, daten.start, daten.laenge, fmt.anzahl, bytes, fmt.tag === 3 ? 'float' : 'int', true);\n        info.kanaele = w.kanaele;\n        info.oder = w.oder; info.alle16 = w.alle16; info.alle24 = w.alle24;\n        return info;\n    }<\/p>\n<p>    function erweitert80(u8, o) {\n        var exp = be16(u8, o) & 0x7FFF, hi = be32(u8, o + 2), lo = be32(u8, o + 6);\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, info, aifc) {\n        var u8 = new Uint8Array(puffer), n = u8.length, p = 12, comm = null, ssnd = null;\n        while (p + 8 <= n) {\n            var id = str(u8, p, 4), l = be32(u8, p + 4);\n            if (id === 'COMM') {\n                comm = { anzahl: be16(u8, p + 8), bits: be16(u8, p + 14), rate: Math.round(erweitert80(u8, p + 16)), art: 'NONE' };\n                if (aifc &#038;&#038; l >= 22) { comm.art = str(u8, p + 26, 4); }\n            } else if (id === 'SSND') {\n                var versatz = be32(u8, p + 8);\n                ssnd = { start: p + 16 + versatz, laenge: Math.min(l - 8 - versatz, n - p - 16 - versatz) };\n            } else if (id === 'NAME') { info.tags.titel.push({ wert: text(u8.subarray(p + 8, p + 8 + l), 0), ort: 'aiff' }); }\n            else if (id === 'AUTH') { info.tags.kuenstler.push({ wert: text(u8.subarray(p + 8, p + 8 + l), 0), ort: 'aiff' }); }\n            else if (id === 'ID3 ' || id === 'id3 ') { id3Lesen(u8, p + 8, info.tags); }\n            p += 8 + l + (l & 1);\n        }\n        if (!comm) { info.fehler = 'COMM'; return info; }\n        info.rate = comm.rate;\n        info.kanaeleAnzahl = comm.anzahl;\n        var art = comm.art, gleit = \/^(fl32|FL32|fl64|FL64)$\/.test(art);\n        info.bits = gleit ? (art.slice(2) === '32' ? 32 : 64) : comm.bits;\n        info.gleitkomma = gleit;\n        info.ganzzahl = art === 'NONE' || art === 'twos' || art === 'sowt';\n        info.verlustfrei = info.ganzzahl || gleit;\n        if (!info.verlustfrei) { info.format = 'AIFC (' + art.trim() + ')'; info.verlustfrei = null; info.fehler = 'codec'; return info; }\n        if (!ssnd) { info.fehler = 'SSND'; return info; }\n        var bytes = gleit ? info.bits \/ 8 : Math.ceil(comm.bits \/ 8);\n        var w = pcmLesen(puffer, ssnd.start, ssnd.laenge, comm.anzahl, bytes, gleit ? 'float' : 'int', art === 'sowt');\n        info.kanaele = w.kanaele;\n        \/\/ Bei weniger als voller Byte-Breite (etwa 20 Bit) sind die unteren Bits laut Norm leer.\n        info.oder = w.oder === null ? null : w.oder >> (bytes * 8 - comm.bits);\n        info.alle16 = w.alle16; info.alle24 = w.alle24;\n        return info;\n    }<\/p>\n<p>    \/\/ ---- FLAC ---------------------------------------------------------------\n    function flacLesen(u8, o, info) {\n        var p = o + 4, letzter = false;\n        info.format = 'FLAC';\n        info.verlustfrei = true;\n        info.ganzzahl = true;\n        while (!letzter && p + 4 <= u8.length) {\n            var kopf = u8[p], typ = kopf &#038; 0x7F, l = (u8[p + 1] << 16) | (u8[p + 2] << 8) | u8[p + 3];\n            letzter = (kopf &#038; 0x80) !== 0;\n            var d = p + 4, ende = Math.min(u8.length, d + l);\n            if (typ === 0 &#038;&#038; l >= 18) {\n                info.rate = (u8[d + 10] << 12) | (u8[d + 11] << 4) | (u8[d + 12] >> 4);\n                info.kanaeleAnzahl = ((u8[d + 12] >> 1) & 7) + 1;\n                info.bits = (((u8[d + 12] & 1) << 4) | (u8[d + 13] >> 4)) + 1;\n                info.abtastwerte = (u8[d + 13] & 0x0F) * 4294967296 + be32(u8, d + 14);\n            } else if (typ === 4) { vorbisKommentar(u8, d, ende, info.tags); }\n            else if (typ === 6) { flacBild(u8, d, ende, info.tags, 'flac_bild'); }\n            p = ende;\n        }\n        return info;\n    }<\/p>\n<p>    \/\/ ---- Ogg ----------------------------------------------------------------\n    function oggPakete(u8, hoechstens) {\n        var pakete = [], teile = [], p = 0;\n        function verbinden() {\n            var l = 0, i;\n            for (i = 0; i < teile.length; i++) { l += teile[i].length; }\n            var r = new Uint8Array(l), o = 0;\n            for (i = 0; i < teile.length; i++) { r.set(teile[i], o); o += teile[i].length; }\n            teile = [];\n            return r;\n        }\n        while (p + 27 <= u8.length &#038;&#038; pakete.length < hoechstens) {\n            if (str(u8, p, 4) !== 'OggS') { break; }\n            var segmente = u8[p + 26], q = p + 27 + segmente;\n            for (var s = 0; s < segmente &#038;&#038; pakete.length < hoechstens; s++) {\n                var l = u8[p + 27 + s];\n                teile.push(u8.subarray(q, Math.min(u8.length, q + l)));\n                q += l;\n                if (l < 255) { pakete.push(verbinden()); }\n            }\n            p = q;\n        }\n        return pakete;\n    }\n\n    function oggLesen(u8, info) {\n        var pakete = oggPakete(u8, 6);\n        if (!pakete.length) { info.fehler = 'ogg'; return info; }\n        var erst = pakete[0];\n        if (erst[0] === 1 &#038;&#038; str(erst, 1, 6) === 'vorbis') {\n            info.format = 'Ogg Vorbis'; info.verlustfrei = false;\n            info.kanaeleAnzahl = erst[11]; info.rate = le32(erst, 12);\n            if (pakete[1] &#038;&#038; pakete[1][0] === 3 &#038;&#038; str(pakete[1], 1, 6) === 'vorbis') {\n                vorbisKommentar(pakete[1], 7, pakete[1].length, info.tags);\n            }\n        } else if (str(erst, 0, 8) === 'OpusHead') {\n            info.format = 'Opus'; info.verlustfrei = false;\n            info.kanaeleAnzahl = erst[9]; info.rate = 48000;\n            if (pakete[1] &#038;&#038; str(pakete[1], 0, 8) === 'OpusTags') {\n                vorbisKommentar(pakete[1], 8, pakete[1].length, info.tags);\n            }\n        } else if (erst[0] === 0x7F &#038;&#038; str(erst, 1, 4) === 'FLAC' &#038;&#038; str(erst, 9, 4) === 'fLaC') {\n            var s = 17;\n            info.format = 'Ogg FLAC'; info.verlustfrei = true; info.ganzzahl = true;\n            info.rate = (erst[s + 10] << 12) | (erst[s + 11] << 4) | (erst[s + 12] >> 4);\n            info.kanaeleAnzahl = ((erst[s + 12] >> 1) & 7) + 1;\n            info.bits = (((erst[s + 12] & 1) << 4) | (erst[s + 13] >> 4)) + 1;\n            for (var i = 1; i < pakete.length; i++) {\n                var t = pakete[i][0] &#038; 0x7F, l = (pakete[i][1] << 16) | (pakete[i][2] << 8) | pakete[i][3];\n                if (t === 4) { vorbisKommentar(pakete[i], 4, Math.min(pakete[i].length, 4 + l), info.tags); }\n                else if (t === 6) { flacBild(pakete[i], 4, Math.min(pakete[i].length, 4 + l), info.tags, 'flac_bild'); }\n            }\n        } else { info.fehler = 'ogg'; }\n        return info;\n    }\n\n    \/\/ ---- MP4 \/ M4A ----------------------------------------------------------\n    function mp4Lesen(u8, info) {\n        var schluessel = null;\n        info.format = 'MP4';\n        function eintrag(name, von, bis) {\n            var werte = [], frei = null, p = von;\n            while (p + 8 <= bis) {\n                var g = be32(u8, p), n = str(u8, p + 4, 4);\n                if (g < 8 || p + g > bis) { break; }\n                if (n === 'name') { frei = str(u8, p + 12, g - 12); }\n                else if (n === 'data') { werte.push({ typ: be32(u8, p + 8) & 0xFFFFFF, daten: u8.subarray(p + 16, p + g) }); }\n                p += g;\n            }\n            var schl = name;\n            if (name === '----' && frei) { schl = '----:' + frei; }\n            werte.forEach(function (w) {\n                if (schl === '\u00a9nam' || \/^(title|com\\.apple\\.quicktime\\.title)$\/i.test(schl)) {\n                    info.tags.titel.push({ wert: utf8(w.daten).trim(), ort: schl.length === 4 ? 'mp4' : 'mdta' });\n                } else if (schl === '\u00a9ART' || \/^(artist|com\\.apple\\.quicktime\\.artist)$\/i.test(schl)) {\n                    info.tags.kuenstler.push({ wert: utf8(w.daten).trim(), ort: schl.length === 4 ? 'mp4' : 'mdta' });\n                } else if (schl === 'covr' || \/artwork$\/i.test(schl)) {\n                    info.tags.cover.push(bildEintrag(w.daten, 'mp4', 3));\n                } else if (\/^----:isrc$\/i.test(schl)) {\n                    info.tags.isrc.push({ wert: utf8(w.daten).trim(), ort: 'mp4_frei' });\n                } else if (\/(^|\\.)isrc$\/i.test(schl)) {\n                    info.tags.isrc.push({ wert: utf8(w.daten).trim(), ort: 'mdta' });\n                }\n            });\n        }\n        function ilst(von, bis) {\n            var p = von;\n            while (p + 8 <= bis) {\n                var g = be32(u8, p);\n                if (g < 8 || p + g > bis) { break; }\n                var name = str(u8, p + 4, 4);\n                if (u8[p + 4] === 0 && u8[p + 5] === 0 && schluessel) {\n                    var nr = be32(u8, p + 4);\n                    name = schluessel[nr - 1] || name;\n                }\n                eintrag(name, p + 8, p + g);\n                p += g;\n            }\n        }\n        function kaesten(von, bis, tiefe) {\n            var p = von;\n            while (p + 8 <= bis &#038;&#038; tiefe < 12) {\n                var g = be32(u8, p), name = str(u8, p + 4, 4), innen = p + 8;\n                if (g === 1) { g = be32(u8, p + 8) * 4294967296 + be32(u8, p + 12); innen = p + 16; }\n                if (g === 0) { g = bis - p; }\n                if (g < 8 || p + g > bis) { break; }\n                var ende = p + g;\n                if (\/^(moov|trak|mdia|minf|stbl|udta)$\/.test(name)) { kaesten(innen, ende, tiefe + 1); }\n                else if (name === 'meta') {\n                    \/\/ iTunes: volle Box mit vier Bytes Version; QuickTime: ohne.\n                    kaesten(str(u8, innen + 4, 4) === 'hdlr' ? innen : innen + 4, ende, tiefe + 1);\n                } else if (name === 'mdhd') {\n                    var v = u8[innen];\n                    info.rate = v === 1 ? be32(u8, innen + 20) : be32(u8, innen + 12);\n                } else if (name === 'stsd' && !info.codec) {\n                    var e = innen + 8, c = e + 8;\n                    info.codec = str(u8, e + 4, 4);\n                    info.kanaeleAnzahl = be16(u8, c + 16);\n                    var tiefeBits = be16(u8, c + 18);\n                    if (info.codec === 'alac') {\n                        var innenAlac = c + 28;\n                        if (str(u8, innenAlac + 4, 4) === 'alac') { tiefeBits = u8[innenAlac + 17] || tiefeBits; }\n                        info.bits = tiefeBits;\n                    } else if (info.codec === 'fLaC') { info.bits = tiefeBits; }\n                } else if (name === 'keys') {\n                    var anzahl = be32(u8, innen + 4), q = innen + 8;\n                    schluessel = [];\n                    for (var k = 0; k < anzahl &#038;&#038; q + 8 <= ende; k++) {\n                        var kl = be32(u8, q);\n                        if (kl < 8) { break; }\n                        schluessel.push(str(u8, q + 8, kl - 8));\n                        q += kl;\n                    }\n                } else if (name === 'ilst') { ilst(innen, ende); }\n                p = ende;\n            }\n        }\n        kaesten(0, u8.length, 0);\n        if (info.codec === 'alac' || info.codec === 'fLaC') { info.verlustfrei = true; info.ganzzahl = true; info.format = info.codec === 'alac' ? 'ALAC (MP4)' : 'FLAC (MP4)'; }\n        else if (info.codec === 'mp4a' || info.codec === 'Opus' || info.codec === '.mp3') { info.verlustfrei = false; info.format = info.codec === 'mp4a' ? 'AAC (MP4)' : info.codec + ' (MP4)'; }\n        else { info.verlustfrei = null; }\n        return info;\n    }\n\n    \/\/ ---- MP3 und AAC (ADTS) -------------------------------------------------\n    function mpegLesen(u8, info) {\n        var start = 0, l;\n        while ((l = id3Lesen(u8, start, info.tags)) > 0) { start += l; }\n        id3v1Lesen(u8, info.tags);\n        var bis = Math.min(u8.length - 4, start + 65536);\n        for (var j = start; j < bis; j++) {\n            if (u8[j] !== 0xFF || (u8[j + 1] &#038; 0xE0) !== 0xE0) { continue; }\n            var version = (u8[j + 1] >> 3) & 3, schicht = (u8[j + 1] >> 1) & 3;\n            if (schicht === 0 && (u8[j + 1] & 0xF6) === 0xF0) {\n                var idx = (u8[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) { continue; }\n                info.format = 'AAC (ADTS)'; info.rate = raten[idx]; info.verlustfrei = false;\n                info.kanaeleAnzahl = ((u8[j + 2] & 1) << 2) | (u8[j + 3] >> 6);\n                return info;\n            }\n            var ri = (u8[j + 2] >> 2) & 3, bri = u8[j + 2] >> 4;\n            if (version === 1 || schicht === 0 || ri === 3 || bri === 15 || bri === 0) { continue; }\n            var basis = [44100, 48000, 32000][ri];\n            info.format = schicht === 1 ? 'MP3' : 'MPEG Audio';\n            info.rate = version === 3 ? basis : (version === 2 ? basis \/ 2 : basis \/ 4);\n            info.kanaeleAnzahl = (u8[j + 3] >> 6) === 3 ? 1 : 2;\n            info.verlustfrei = false;\n            return info;\n        }\n        info.fehler = 'format';\n        return info;\n    }<\/p>\n<p>    \/\/ Liest Kopf, Tags und - bei WAV und AIFF - die Abtastwerte.\n    function lesen(puffer) {\n        var u8 = new Uint8Array(puffer);\n        var info = { format: null, verlustfrei: null, ganzzahl: false, gleitkomma: false, rate: null, bits: null,\n                     kanaeleAnzahl: null, kanaele: null, oder: null, alle16: null, alle24: null,\n                     tags: neueTags(), fehler: null, codec: null };\n        if (u8.length < 16) { info.fehler = 'format'; return info; }\n        var k4 = str(u8, 0, 4), art = str(u8, 8, 4);\n        if ((k4 === 'RIFF' || k4 === 'RF64' || k4 === 'BW64') &#038;&#038; art === 'WAVE') { info.format = k4 === 'RIFF' ? 'WAV' : k4; return wavLesen(puffer, info); }\n        if (k4 === 'FORM' &#038;&#038; (art === 'AIFF' || art === 'AIFC')) { info.format = art; return aiffLesen(puffer, info, art === 'AIFC'); }\n        if (k4 === 'OggS') { return oggLesen(u8, info); }\n        if (str(u8, 4, 4) === 'ftyp') { return mp4Lesen(u8, info); }\n        var o = 0, l;\n        while ((l = id3Lesen(u8, o, info.tags)) > 0) { o += l; }\n        if (str(u8, o, 4) === 'fLaC') { return flacLesen(u8, o, info); }\n        info.tags = neueTags();\n        return mpegLesen(u8, info);\n    }<\/p>\n<p>    \/\/ Bei dekodierten FLAC-Dateien: stehen alle Werte auf dem Raster der\n    \/\/ angegebenen Bit-Tiefe, laesst sich die Oder-Maske auch hier bilden.\n    function oderAusGleitkomma(kanaele, bits) {\n        if (!bits || bits > 24) { return null; }\n        var f = Math.pow(2, bits - 1), oder = 0;\n        for (var c = 0; c < kanaele.length; c++) {\n            var d = kanaele[c];\n            for (var i = 0; i < d.length; i++) {\n                var s = d[i] * f;\n                if (s !== Math.floor(s)) { return null; }\n                oder |= s;\n            }\n        }\n        return oder;\n    }\n\n    function wirksameBits(oder, bits) {\n        if (oder === null || oder === undefined || !bits) { return null; }\n        if (oder === 0) { return 0; }\n        var frei = 0;\n        while (frei < bits &#038;&#038; ((oder >> frei) & 1) === 0) { frei++; }\n        return bits - frei;\n    }<\/p>\n<p>    \/\/ ---- Messung in Scheiben ------------------------------------------------\n    function messungAnlegen(kanaele, fs, schwelleVoll) {\n        var anzahl = kanaele.length, n = anzahl ? kanaele[0].length : 0, k = [];\n        for (var c = 0; c < anzahl; c++) {\n            k.push({ summe: 0, spitze: 0, tp: 0, voll: 0, stellen: 0, lauf: 0, flach: -1, ueber: 0, erster: -1, letzter: -1 });\n        }\n        return { kanaele: kanaele, fs: fs, n: n, anzahl: anzahl, schwelleVoll: schwelleVoll, k: k,\n                 kanal: 0, pos: 0, ring: new Float64Array(24), rp: 0, diffMax: 0 };\n    }\n\n    function tpNachlauf(m, s) {\n        var P0 = TP_PHASEN[0], P1 = TP_PHASEN[1], P2 = TP_PHASEN[2], P3 = TP_PHASEN[3];\n        for (var nach = 0; nach < 12; nach++) {\n            m.ring[m.rp] = 0; m.ring[m.rp + 12] = 0;\n            var o = m.rp + 12, q0 = 0, q1 = 0, q2 = 0, q3 = 0;\n            for (var t = 0; t < 12; t++) {\n                var v = m.ring[o - t];\n                q0 += P0[t] * v; q1 += P1[t] * v; q2 += P2[t] * v; q3 += P3[t] * v;\n            }\n            m.rp = m.rp === 11 ? 0 : m.rp + 1;\n            s.tp = Math.max(s.tp, Math.abs(q0), Math.abs(q1), Math.abs(q2), Math.abs(q3));\n        }\n        s.tp = Math.max(s.tp, s.spitze);\n    }\n\n    \/\/ Verarbeitet hoechstens \"budget\" Abtastwerte; true, wenn alle Kanaele durch sind.\n    function messungSchritt(m, budget) {\n        var P0 = TP_PHASEN[0], P1 = TP_PHASEN[1], P2 = TP_PHASEN[2], P3 = TP_PHASEN[3];\n        while (budget > 0 && m.kanal < m.anzahl) {\n            var c = m.kanal, d = m.kanaele[c], s = m.k[c], ende = Math.min(m.n, m.pos + budget);\n            var ring = m.ring, rp = m.rp, sv = m.schwelleVoll;\n            var summe = s.summe, spitze = s.spitze, tp = s.tp, voll = s.voll, stellen = s.stellen, lauf = s.lauf, flach = s.flach;\n            var ueber = s.ueber, erster = s.erster, letzter = s.letzter;\n            var links = c === 1 &#038;&#038; m.anzahl === 2 ? m.kanaele[0] : null, diffMax = m.diffMax;\n            for (var i = m.pos; i < ende; i++) {\n                var x = d[i], ax = x < 0 ? -x : x;\n                summe += x;\n                if (ax > spitze) { spitze = ax; }\n                \/\/ Geclippt ist, was flach abgeschnitten ist: derselbe Betrag an der\n                \/\/ Vollaussteuerung mehrmals hintereinander. Schwankende Werte ueber 1\n                \/\/ in einer Gleitkommadatei sind keine Stelle, sondern Ueberschreitung.\n                if (ax >= sv) {\n                    voll++;\n                    if (ax === flach) { lauf++; } else { lauf = 1; flach = ax; }\n                    if (lauf === 3) { stellen++; }\n                } else { lauf = 0; flach = -1; }\n                if (ax > 1) { ueber++; }\n                if (ax > STILLE) { if (erster < 0) { erster = i; } letzter = i; }\n                if (links) { var df = x - links[i]; if (df < 0) { df = -df; } if (df > diffMax) { diffMax = df; } }<\/p>\n<p>                \/\/ True Peak: Ringpuffer doppelt beschrieben, damit die zwoelf\n                \/\/ letzten Werte zusammenhaengend lesbar sind.\n                ring[rp] = x; ring[rp + 12] = x;\n                var o = rp + 12, s0 = 0, s1 = 0, s2 = 0, s3 = 0;\n                for (var t = 0; t < 12; t++) {\n                    var v = ring[o - t];\n                    s0 += P0[t] * v; s1 += P1[t] * v; s2 += P2[t] * v; s3 += P3[t] * v;\n                }\n                rp = rp === 11 ? 0 : rp + 1;\n                if (s0 < 0) { s0 = -s0; } if (s1 < 0) { s1 = -s1; } if (s2 < 0) { s2 = -s2; } if (s3 < 0) { s3 = -s3; }\n                if (s0 > tp) { tp = s0; } if (s1 > tp) { tp = s1; } if (s2 > tp) { tp = s2; } if (s3 > tp) { tp = s3; }\n            }\n            budget -= ende - m.pos;\n            m.pos = ende; m.rp = rp; m.diffMax = diffMax;\n            s.summe = summe; s.spitze = spitze; s.tp = tp; s.voll = voll; s.stellen = stellen; s.lauf = lauf; s.flach = flach;\n            s.ueber = ueber; s.erster = erster; s.letzter = letzter;\n            if (m.pos >= m.n) {\n                tpNachlauf(m, s);\n                m.kanal++; m.pos = 0; m.ring = new Float64Array(24); m.rp = 0;\n            }\n        }\n        return m.kanal >= m.anzahl;\n    }<\/p>\n<p>    function messungAuswerten(m) {\n        var e = { n: m.n, fs: m.fs, anzahl: m.anzahl, dauer: m.n \/ m.fs, spitze: 0, tp: 0, voll: 0, stellen: 0,\n                  ueber: 0, dc: 0, erster: -1, letzter: -1, anfangWert: 0, endeWert: 0,\n                  gleich: false, stumm: [] };\n        for (var c = 0; c < m.anzahl; c++) {\n            var s = m.k[c], d = m.kanaele[c];\n            e.spitze = Math.max(e.spitze, s.spitze);\n            e.tp = Math.max(e.tp, s.tp);\n            e.voll += s.voll; e.stellen += s.stellen; e.ueber += s.ueber;\n            e.dc = Math.max(e.dc, m.n ? Math.abs(s.summe \/ m.n) : 0);\n            if (s.erster >= 0 && (e.erster < 0 || s.erster < e.erster)) { e.erster = s.erster; }\n            if (s.letzter > e.letzter) { e.letzter = s.letzter; }\n            if (m.n) {\n                e.anfangWert = Math.max(e.anfangWert, Math.abs(d[0]));\n                e.endeWert = Math.max(e.endeWert, Math.abs(d[m.n - 1]));\n            }\n        }\n        for (var k = 0; k < m.anzahl; k++) { if (m.k[k].spitze === 0 &#038;&#038; e.spitze > 0) { e.stumm.push(k + 1); } }\n        e.gleich = m.anzahl === 2 && e.spitze > 0 && m.diffMax === 0;\n        return e;\n    }<\/p>\n<p>    function messen(kanaele, fs, schwelleVoll) {\n        if (!kanaele || !kanaele.length || !kanaele[0].length || !fs) { return null; }\n        var m = messungAnlegen(kanaele, fs, schwelleVoll);\n        while (!messungSchritt(m, 1 << 30)) { \/* weiter *\/ }\n        return messungAuswerten(m);\n    }\n\n    \/\/ Ab diesem Betrag steht ein Wert auf Vollaussteuerung.\n    function vollSchwelle(info) {\n        if (info.ganzzahl &#038;&#038; info.bits) { var f = Math.pow(2, info.bits - 1); return (f - 1) \/ f; }\n        return 1;\n    }\n\n    \/\/ ---- Befunde ------------------------------------------------------------\n    function db(wert) { return wert > 0 ? 20 * Math.log10(wert) : -Infinity; }\n    function runden(wert, stellen) { var f = Math.pow(10, stellen); return Math.round(wert * f) \/ f; }<\/p>\n<p>    function isrcNormal(s) { return String(s || '').replace(\/^ISRC[:\\s]*\/i, '').replace(\/[\\s\\-]\/g, '').toUpperCase(); }\n    function isrcGut(s) { return \/^[A-Z]{2}[A-Z0-9]{3}[0-9]{7}$\/.test(isrcNormal(s)); }<\/p>\n<p>    \/\/ Gibt je Pruefpunkt {id, stufe, schluessel, werte, wert} zurueck; die Texte\n    \/\/ setzt die Oberflaeche ein. stufe: ok, hinweis, problem, info, offen.\n    function befunde(info, e, wirksam) {\n        var liste = [];\n        function b(id, stufe, schluessel, werte, wert) {\n            liste.push({ id: id, stufe: stufe, schluessel: schluessel, werte: werte || {}, wert: wert === undefined ? null : wert });\n        }\n        \/\/ Format\n        if (info.verlustfrei === true) { b('format', 'ok', 'b_format_verlustfrei', { format: info.format }, info.format); }\n        else if (info.verlustfrei === false) { b('format', 'problem', 'b_format_verlustbehaftet', { format: info.format }, info.format); }\n        else { b('format', 'hinweis', 'b_format_unbekannt', { format: info.format || '' }, info.format); }\n        \/\/ Abtastrate\n        if (!info.rate) { b('rate', 'offen', 'b_offen_kopf'); }\n        else if (RATEN_APPLE.indexOf(info.rate) !== -1) { b('rate', 'ok', 'b_rate_ok', { rate: info.rate }, { hz: info.rate }); }\n        else { b('rate', 'problem', 'b_rate_andere', { rate: info.rate }, { hz: info.rate }); }\n        \/\/ Bit-Tiefe\n        if (info.verlustfrei === false) { b('bits', 'info', 'b_bits_verlustbehaftet'); }\n        else if (!info.bits) { b('bits', 'offen', 'b_offen_kopf'); }\n        else if (info.gleitkomma) { b('bits', 'hinweis', 'b_bits_float', { bits: info.bits }, { bits: info.bits, float: true }); }\n        else if (info.bits === 24) { b('bits', 'ok', 'b_bits_24', { bits: 24 }, { bits: 24 }); }\n        else if (info.bits === 16) { b('bits', 'ok', 'b_bits_16', { bits: 16 }, { bits: 16 }); }\n        else if (info.bits < 16) { b('bits', 'problem', 'b_bits_wenig', { bits: info.bits }, { bits: info.bits }); }\n        else { b('bits', 'hinweis', 'b_bits_andere', { bits: info.bits }, { bits: info.bits }); }\n        \/\/ Wirksame Bits (Bit-Padding)\n        if (info.verlustfrei !== false &#038;&#038; e) {\n            if (e.spitze === 0) { b('wirksam', 'offen', 'b_wirksam_stille'); }\n            else if (info.gleitkomma &#038;&#038; info.alle16) { b('wirksam', 'problem', 'b_wirksam_float16', { bits: info.bits }, { bits: 16 }); }\n            else if (info.gleitkomma &#038;&#038; info.alle24) { b('wirksam', 'ok', 'b_wirksam_float24', { bits: info.bits }, { bits: 24 }); }\n            else if (info.gleitkomma) { b('wirksam', 'ok', 'b_wirksam_float', { bits: info.bits }, { bits: info.bits, float: true }); }\n            else if (wirksam === null || wirksam === undefined) { b('wirksam', 'offen', 'b_wirksam_offen'); }\n            else if (wirksam >= info.bits) { b('wirksam', 'ok', 'b_wirksam_voll', { bits: info.bits }, { bits: wirksam }); }\n            else if (info.bits > 16 && wirksam <= 16) { b('wirksam', 'problem', 'b_wirksam_aufgefuellt', { wirksam: wirksam, bits: info.bits }, { bits: wirksam }); }\n            else { b('wirksam', 'hinweis', 'b_wirksam_weniger', { wirksam: wirksam, bits: info.bits }, { bits: wirksam }); }\n        }\n        \/\/ Kanaele\n        var anzahl = e ? e.anzahl : info.kanaeleAnzahl;\n        if (!anzahl) { b('kanaele', 'offen', 'b_offen_kopf'); }\n        else if (anzahl === 2) { b('kanaele', 'ok', 'b_kanaele_2', {}, anzahl); }\n        else if (anzahl === 1) { b('kanaele', 'hinweis', 'b_kanaele_1', {}, anzahl); }\n        else { b('kanaele', 'hinweis', 'b_kanaele_mehr', { n: anzahl }, anzahl); }\n\n        if (!e) { b('messung', 'offen', 'b_offen_ton'); return liste; }\n\n        b('dauer', 'info', 'b_dauer', {}, { s: e.dauer });\n        \/\/ Spitzen\n        if (e.voll > 0) { b('spitze', 'hinweis', 'b_spitze_voll', { n: e.voll }, { dbfs: db(e.spitze) }); }\n        else { b('spitze', 'ok', 'b_spitze_ok', {}, { dbfs: db(e.spitze) }); }\n        if (e.stellen > 0) { b('clipping', 'problem', 'b_clipping', { n: e.stellen }, { n: e.stellen }); }\n        else { b('clipping', 'ok', 'b_clipping_keine', {}, { n: 0 }); }\n        if (!info.ganzzahl) {\n            if (e.ueber > 0) { b('ueber', 'problem', 'b_ueber', { n: e.ueber }, { n: e.ueber }); }\n            else { b('ueber', 'ok', 'b_ueber_keine', {}, { n: 0 }); }\n        }\n        var tpDb = runden(db(e.tp), 1);\n        if (tpDb > 0) { b('truepeak', 'problem', 'b_tp_problem', {}, { dbtp: db(e.tp) }); }\n        else if (tpDb > -1) { b('truepeak', 'hinweis', 'b_tp_hinweis', {}, { dbtp: db(e.tp) }); }\n        else { b('truepeak', 'ok', 'b_tp_ok', {}, { dbtp: db(e.tp) }); }\n        \/\/ Gleichanteil\n        if (e.dc >= DC_GRENZE) { b('dc', 'hinweis', 'b_dc_hoch', {}, { dbfs: db(e.dc) }); }\n        else { b('dc', 'ok', 'b_dc_ok', {}, { dbfs: db(e.dc) }); }\n        \/\/ Stille und Spruenge\n        if (e.erster < 0) {\n            b('stille_anfang', 'problem', 'b_stille_ganz', {}, null);\n        } else {\n            var vorne = e.erster \/ e.fs, hinten = (e.n - 1 - e.letzter) \/ e.fs;\n            if (vorne >= STILLE_ANFANG_S) { b('stille_anfang', 'hinweis', 'b_stille_anfang_lang', {}, { s: vorne }); }\n            else { b('stille_anfang', 'ok', 'b_stille_anfang_ok', {}, { s: vorne }); }\n            if (hinten >= STILLE_ENDE_S) { b('stille_ende', 'hinweis', 'b_stille_ende_lang', {}, { s: hinten }); }\n            else { b('stille_ende', 'ok', 'b_stille_ende_ok', {}, { s: hinten }); }\n        }\n        var vorneSprung = e.anfangWert >= SPRUNG, hintenSprung = e.endeWert >= SPRUNG;\n        var sprungWert = { anfang: db(e.anfangWert), ende: db(e.endeWert) };\n        if (vorneSprung && hintenSprung) { b('sprung', 'hinweis', 'b_sprung_beide', {}, sprungWert); }\n        else if (vorneSprung) { b('sprung', 'hinweis', 'b_sprung_anfang', {}, sprungWert); }\n        else if (hintenSprung) { b('sprung', 'hinweis', 'b_sprung_ende', {}, sprungWert); }\n        else { b('sprung', 'ok', 'b_sprung_ok', {}, sprungWert); }\n        \/\/ Kanalvergleich\n        if (e.anzahl >= 2) {\n            if (e.stumm.length) { b('kanalvergleich', 'problem', 'b_kanal_stumm', { kanal: e.stumm.join(', ') }, null); }\n            else if (e.gleich) { b('kanalvergleich', 'hinweis', 'b_kanal_gleich', {}, null); }\n            else { b('kanalvergleich', 'ok', 'b_kanal_ok', {}, null); }\n        }\n        return liste;\n    }<\/p>\n<p>    function tagBefunde(tags) {\n        var liste = [];\n        function b(id, stufe, schluessel, werte, wert) {\n            liste.push({ id: id, stufe: stufe, schluessel: schluessel, werte: werte || {}, wert: wert === undefined ? null : wert });\n        }\n        function erster(feld) { for (var i = 0; i < feld.length; i++) { if (feld[i].wert) { return feld[i]; } } return null; }\n        var t = erster(tags.titel), k = erster(tags.kuenstler);\n        if (t) { b('titel', 'ok', 'b_titel_da', { ort: t.ort }, t.wert); } else { b('titel', 'info', 'b_titel_fehlt'); }\n        if (k) { b('kuenstler', 'ok', 'b_kuenstler_da', { ort: k.ort }, k.wert); } else { b('kuenstler', 'info', 'b_kuenstler_fehlt'); }\n\n        var codes = tags.isrc.filter(function (x) { return x.wert; });\n        var richtig = codes.filter(function (x) { return \/^(tsrc|vorbis|mp4_frei|mdta)$\/.test(x.ort) &#038;&#038; isrcGut(x.wert); });\n        var txxx = codes.filter(function (x) { return x.ort === 'txxx' &#038;&#038; isrcGut(x.wert); });\n        var riff = codes.filter(function (x) { return x.ort === 'riff_isrc'; });\n        var verschieden = {};\n        codes.forEach(function (x) { if (isrcGut(x.wert) &#038;&#038; x.ort !== 'riff_isrc') { verschieden[isrcNormal(x.wert)] = 1; } });\n        var falsch = codes.filter(function (x) { return x.ort !== 'riff_isrc' &#038;&#038; !isrcGut(x.wert); });\n        if (Object.keys(verschieden).length > 1) { b('isrc', 'problem', 'b_isrc_mehrere', { n: Object.keys(verschieden).length }, Object.keys(verschieden).join(', ')); }\n        else if (falsch.length) { b('isrc', 'problem', 'b_isrc_form', { ort: falsch[0].ort }, falsch[0].wert); }\n        else if (richtig.length) { b('isrc', 'ok', 'b_isrc_ok', { ort: richtig[0].ort }, isrcNormal(richtig[0].wert)); }\n        else if (txxx.length) { b('isrc', 'hinweis', 'b_isrc_txxx', { ort: 'txxx' }, isrcNormal(txxx[0].wert)); }\n        else if (riff.length) { b('isrc', 'hinweis', 'b_isrc_riff', { ort: 'riff_isrc' }, riff[0].wert); }\n        else { b('isrc', 'hinweis', 'b_isrc_fehlt'); }<\/p>\n<p>        var bilder = tags.cover.slice().sort(function (x, y) { return (x.bildtyp === 3 ? 0 : 1) - (y.bildtyp === 3 ? 0 : 1); });\n        var c = bilder[0];\n        if (!c) { b('cover', 'info', 'b_cover_fehlt'); }\n        else if (c.typ !== 'JPEG' && c.typ !== 'PNG') { b('cover', 'problem', 'b_cover_format', { typ: c.typ || '?' }, c); }\n        else if (!c.breite || !c.hoehe) { b('cover', 'hinweis', 'b_cover_masse', {}, c); }\n        else if (c.breite !== c.hoehe) { b('cover', 'problem', 'b_cover_quadrat', { breite: c.breite, hoehe: c.hoehe }, c); }\n        else if (c.breite < COVER_MINDEST) { b('cover', 'problem', 'b_cover_klein', { breite: c.breite, hoehe: c.hoehe }, c); }\n        else if (c.breite < COVER_EMPFOHLEN) { b('cover', 'hinweis', 'b_cover_mittel', { breite: c.breite, hoehe: c.hoehe }, c); }\n        else { b('cover', 'ok', 'b_cover_ok', { breite: c.breite, hoehe: c.hoehe }, c); }\n        return liste;\n    }\n\n    function gesamtUrteil(liste) {\n        var p = 0, h = 0;\n        liste.forEach(function (x) { if (x.stufe === 'problem') { p++; } else if (x.stufe === 'hinweis') { h++; } });\n        return { stufe: p ? 'problem' : (h ? 'hinweis' : 'ok'), probleme: p, hinweise: h };\n    }\n    \/\/ KERN-ENDE --------------------------------------------------------------\n\n    function el(id) { return document.getElementById(id); }\n    function satz(schluessel, werte) {\n        var s = T[schluessel] || '';\n        return s.replace(\/\\{(\\w+)\\}\/g, function (_, k) { return werte &#038;&#038; werte[k] !== undefined ? werte[k] : ''; });\n    }\n    var NB = '\u00a0';\n    function zahl(wert, stellen) {\n        if (wert === -Infinity) { return '\u2212\u221e'; }\n        if (wert === null || wert === undefined || !isFinite(wert)) { return '\u2013'; }\n        var s = Number(wert).toFixed(stellen === undefined ? 1 : stellen);\n        if (\/^-0(\\.0+)?$\/.test(s)) { s = s.slice(1); }\n        s = s.replace('-', '\u2212');\n        return T.dezimal === ',' ? s.replace('.', ',') : s;\n    }\n    function ganz(n) {\n        var s = String(Math.round(n)), t = T.tausender || '';\n        return t ? s.replace(\/\\B(?=(\\d{3})+(?!\\d))\/g, t) : s;\n    }\n    function dauerText(s) {\n        if (s < 60) { return zahl(s, 2) + NB + 's'; }\n        var min = Math.floor(s \/ 60), rest = s - min * 60;\n        return min + NB + 'min ' + zahl(rest, 1) + NB + 's';\n    }\n    function ortText(ort) { return T['ort_' + ort] || ort; }\n\n    \/\/ Anzeigewert je Pruefpunkt\n    function wertText(x) {\n        var w = x.wert;\n        if (w === null || w === undefined) { return '\u2013'; }\n        switch (x.id) {\n            case 'format': return String(w);\n            case 'rate': return zahl(w.hz \/ 1000, w.hz % 1000 ? 1 : 0) + NB + 'kHz';\n            case 'bits': case 'wirksam': return w.bits + NB + 'Bit' + (w.float ? ' ' + T.wert_float : '');\n            case 'kanaele': return String(w);\n            case 'dauer': return dauerText(w.s);\n            case 'spitze': case 'dc': return zahl(w.dbfs, 1) + NB + 'dBFS';\n            case 'truepeak': return zahl(w.dbtp, 1) + NB + 'dBTP';\n            case 'clipping': case 'ueber': return ganz(w.n);\n            case 'stille_anfang': case 'stille_ende': return zahl(w.s, w.s < 10 ? 2 : 1) + NB + 's';\n            case 'sprung': return zahl(w.anfang, 1) + ' \/ ' + zahl(w.ende, 1) + NB + 'dBFS';\n            case 'cover': return w.breite &#038;&#038; w.hoehe ? w.breite + ' \u00d7 ' + w.hoehe + NB + 'px' : (w.typ || '\u2013');\n            default: return String(w);\n        }\n    }\n    function befundText(x) {\n        var werte = {};\n        Object.keys(x.werte).forEach(function (k) {\n            var v = x.werte[k];\n            if (k === 'ort') { werte[k] = ortText(v); }\n            else if (k === 'rate') { werte[k] = zahl(v \/ 1000, v % 1000 ? 1 : 0) + NB + 'kHz'; }\n            else if (typeof v === 'number') { werte[k] = ganz(v); }\n            else { werte[k] = v; }\n        });\n        return satz(x.schluessel, werte);\n    }\n\n    function tagZeilen(tags) {\n        var zeilen = [];\n        tags.titel.forEach(function (t) { zeilen.push([T.f_titel, t.wert, ortText(t.ort)]); });\n        tags.kuenstler.forEach(function (t) { zeilen.push([T.f_kuenstler, t.wert, ortText(t.ort)]); });\n        tags.isrc.forEach(function (t) { zeilen.push([T.f_isrc, t.wert, ortText(t.ort)]); });\n        tags.cover.forEach(function (c) {\n            var w = (c.typ || '?') + (c.breite &#038;&#038; c.hoehe ? ', ' + c.breite + ' \u00d7 ' + c.hoehe + NB + 'px' : '') + ', ' + ganz(c.bytes) + NB + 'Byte';\n            zeilen.push([T.f_cover, w, ortText(c.ort)]);\n        });\n        return zeilen;\n    }\n\n    function bericht(ergebnis) {\n        var z = [T.bericht_kopf + ': ' + (ergebnis.name || '')];\n        ergebnis.liste.forEach(function (x) {\n            z.push('[' + T['stufe_' + x.stufe] + '] ' + T['p_' + x.id] + ': ' + wertText(x) + ' \u2013 ' + befundText(x));\n        });\n        var g = ergebnis.gesamt;\n        z.push(satz('gesamt_' + g.stufe, { p: g.probleme, h: g.hinweise }));\n        return z.join('\\n');\n    }\n\n    \/\/ ---- Darstellung -------------------------------------------------------\n    function darstellen(ergebnis) {\n        var liste = el('rp-liste'), tags = el('rp-tags'), gesamt = el('rp-gesamt');\n        if (!liste) { return ergebnis; }\n        var g = ergebnis.gesamt;\n        gesamt.className = 'rp-gesamt rp-g-' + g.stufe;\n        gesamt.textContent = '';\n        var kopf = document.createElement('div');\n        kopf.className = 'rp-gesamt-kopf';\n        kopf.textContent = satz('gesamt_' + g.stufe, { p: g.probleme, h: g.hinweise });\n        var txt = document.createElement('div');\n        txt.className = 'rp-klein';\n        txt.textContent = satz('gesamt_text_' + g.stufe, { name: ergebnis.name || '' });\n        gesamt.appendChild(kopf); gesamt.appendChild(txt);\n\n        liste.textContent = '';\n        ergebnis.liste.forEach(function (x) {\n            var tr = document.createElement('tr');\n            tr.setAttribute('data-id', x.id);\n            var td1 = document.createElement('td');\n            var marke = document.createElement('span');\n            marke.className = 'rp-stufe rp-s-' + x.stufe;\n            marke.textContent = T['stufe_' + x.stufe];\n            var name = document.createElement('div');\n            name.className = 'rp-name';\n            name.textContent = T['p_' + x.id];\n            td1.appendChild(marke); td1.appendChild(name);\n            var td2 = document.createElement('td'); td2.className = 'rp-wert'; td2.textContent = wertText(x);\n            var td3 = document.createElement('td'); td3.className = 'rp-text'; td3.textContent = befundText(x);\n            tr.appendChild(td1); tr.appendChild(td2); tr.appendChild(td3);\n            liste.appendChild(tr);\n        });\n\n        tags.textContent = '';\n        var zeilen = tagZeilen(ergebnis.info.tags);\n        if (!zeilen.length) { zeilen.push([T.wert_keine_tags, '', '']); }\n        zeilen.forEach(function (z) {\n            var tr = document.createElement('tr');\n            z.forEach(function (w, i) {\n                var td = document.createElement('td');\n                if (i > 0) { td.className = 'rp-wert'; }\n                td.textContent = w;\n                tr.appendChild(td);\n            });\n            tags.appendChild(tr);\n        });\n        el('rp-ausgabe').hidden = false;\n        el('rp-fehler').hidden = true;\n        return ergebnis;\n    }<\/p>\n<p>    function fehlerZeigen(s) {\n        var f = el('rp-fehler');\n        if (!f) { return; }\n        f.textContent = s;\n        f.hidden = false;\n        el('rp-ausgabe').hidden = true;\n        el('rp-status').textContent = '';\n    }<\/p>\n<p>    \/\/ ---- Ablauf ------------------------------------------------------------\n    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, sv, fortschritt) {\n        return new Promise(function (ok, fehler) {\n            if (!kanaele || !kanaele.length || !kanaele[0].length || !fs) { ok(null); return; }\n            var m = messungAnlegen(kanaele, fs, sv), gesamt = m.n * m.anzahl || 1;\n            function schritt() {\n                try {\n                    var fertig = messungSchritt(m, 1 << 18);\n                    if (fortschritt) { fortschritt(Math.min(1, (m.kanal * m.n + m.pos) \/ gesamt)); }\n                    if (fertig) { ok(messungAuswerten(m)); } else { spaeter(schritt); }\n                } catch (e) { fehler(e); }\n            }\n            spaeter(schritt);\n        });\n    }\n\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, erledigt = false;\n            try { ctx = new Ctx(1, 1, rate); } catch (e) { ctx = new Ctx(1, 1, 48000); }\n            function gut(buf) { if (!erledigt) { erledigt = true; ok(buf); } }\n            function schlecht(e) { if (!erledigt) { erledigt = true; fehler(e || new Error('dekodieren')); } }\n            setTimeout(function () { schlecht(new Error('zeit')); }, 60000);\n            try {\n                var p = ctx.decodeAudioData(puffer, gut, schlecht);\n                if (p &#038;&#038; typeof p.then === 'function') { p.then(gut, schlecht); }\n            } catch (e) { schlecht(e); }\n        });\n    }\n\n    var letztes = null;\n    \/\/ optionen.dekodieren: false laesst den Decoder des Browsers aus (Pruefung).\n    function verarbeiten(puffer, name, optionen) {\n        optionen = optionen || {};\n        var info;\n        try { info = lesen(puffer); } catch (x) { info = null; }\n        if (!info || (info.fehler &#038;&#038; !info.format)) { fehlerZeigen(T.fehler_format); return Promise.resolve(null); }\n        var status = el('rp-status');\n        var wegZumTon;\n        if (info.kanaele) { wegZumTon = Promise.resolve(info.kanaele); }\n        else if (optionen.dekodieren === false || info.fehler === 'codec') { wegZumTon = Promise.resolve(null); }\n        else {\n            if (status) { status.textContent = T.status_dekodieren; }\n            var rate = info.rate &#038;&#038; info.rate >= 3000 && info.rate <= 768000 ? info.rate : 48000;\n            wegZumTon = dekodieren(puffer.slice(0), rate).then(function (buf) {\n                var k = [];\n                for (var c = 0; c < buf.numberOfChannels; c++) { k.push(buf.getChannelData(c)); }\n                if (buf.sampleRate !== info.rate) { info.rateDekodiert = buf.sampleRate; }\n                if (info.verlustfrei &#038;&#038; info.ganzzahl &#038;&#038; !info.rateDekodiert) { info.oder = oderAusGleitkomma(k, info.bits); }\n                return k;\n            }, function () { return null; });\n        }\n        return wegZumTon.then(function (kanaele) {\n            var fs = info.rateDekodiert || info.rate;\n            return messenAsync(kanaele, fs, vollSchwelle(info), function (anteil) {\n                if (status) { status.textContent = satz('status_messen', { p: Math.round(anteil * 100) }); }\n            });\n        }).then(function (e) {\n            var wirksam = info.ganzzahl ? wirksameBits(info.oder, info.bits) : null;\n            var liste = befunde(info, e, wirksam).concat(tagBefunde(info.tags));\n            var ergebnis = { name: name || '', info: info, messung: e, liste: liste, gesamt: gesamtUrteil(liste) };\n            letztes = ergebnis;\n            if (status) { status.textContent = ''; }\n            return darstellen(ergebnis);\n        });\n    }\n\n    function dateiNehmen(datei) {\n        if (!datei) { return; }\n        var leser = new FileReader();\n        el('rp-status').textContent = T.status_lesen;\n        leser.onload = function () {\n            verarbeiten(leser.result, datei.name).then(null, function () { fehlerZeigen(T.fehler_lesen); });\n        };\n        leser.onerror = function () { fehlerZeigen(T.fehler_lesen); };\n        try { leser.readAsArrayBuffer(datei); } catch (x) { fehlerZeigen(T.fehler_lesen); }\n    }\n\n    window.LW_TEST = window.LW_TEST || {};\n    window.LW_TEST.RP = {\n        T: T, lesen: lesen, id3Lesen: id3Lesen, vorbisKommentar: vorbisKommentar, bildMasse: bildMasse,\n        mp4Lesen: mp4Lesen, oggLesen: oggLesen, pcmLesen: pcmLesen, messen: messen, vollSchwelle: vollSchwelle,\n        wirksameBits: wirksameBits, oderAusGleitkomma: oderAusGleitkomma, befunde: befunde, tagBefunde: tagBefunde,\n        gesamtUrteil: gesamtUrteil, isrcGut: isrcGut, isrcNormal: isrcNormal, wertText: wertText,\n        befundText: befundText, bericht: bericht, verarbeiten: verarbeiten, zahl: zahl,\n        letztes: function () { return letztes; }\n    };\n\n    var zone = el('rp-zone'), eingabe = el('rp-datei'), knopf = el('rp-knopf');\n    if (!zone || !eingabe || !knopf) { return; }\n    knopf.addEventListener('click', function () { eingabe.click(); });\n    eingabe.addEventListener('change', function () { dateiNehmen(eingabe.files &#038;&#038; eingabe.files[0]); eingabe.value = ''; });\n    ['dragenter', 'dragover'].forEach(function (typ) {\n        zone.addEventListener(typ, function (ev) { ev.preventDefault(); zone.classList.add('rp-ueber'); });\n    });\n    ['dragleave', 'drop'].forEach(function (typ) {\n        zone.addEventListener(typ, function (ev) { ev.preventDefault(); zone.classList.remove('rp-ueber'); });\n    });\n    zone.addEventListener('drop', function (ev) {\n        ev.preventDefault();\n        dateiNehmen(ev.dataTransfer &#038;&#038; ev.dataTransfer.files &#038;&#038; ev.dataTransfer.files[0]);\n    });\n    var kopieren = el('rp-kopieren'), kopiert = el('rp-kopiert');\n    if (kopieren) {\n        kopieren.addEventListener('click', function () {\n            if (!letztes) { return; }\n            var t = bericht(letztes);\n            if (navigator.clipboard &#038;&#038; navigator.clipboard.writeText) {\n                navigator.clipboard.writeText(t).then(function () { kopiert.textContent = T.kopiert; },\n                    function () { kopiert.textContent = T.kopieren_fehler; });\n            } else {\n                kopiert.textContent = T.kopieren_fehler;\n            }\n        });\n    }\n})();\n<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Czyta w przegl\u0105darce plik WAV, AIFF, FLAC, MP3, M4A lub Ogg i wylicza, co stoi mi\u0119dzy nim a dostaw\u0105: format, cz\u0119stotliwo\u015b\u0107 pr\u00f3bkowania i g\u0142\u0119bi\u0119 bitow\u0105 wzgl\u0119dem wymaga\u0144 Apple, dope\u0142nione bity, clipping, true peak, sk\u0142adow\u0105 sta\u0142\u0105, cisz\u0119 i skoki na obu ko\u0144cach oraz tytu\u0142, wykonawc\u0119, ISRC i ok\u0142adk\u0119 z tag\u00f3w.<\/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-20130","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>Kontrola pliku do wydania: cz\u0119stotliwo\u015b\u0107 pr\u00f3bkowania, g\u0142\u0119bia bitowa, szczyty, cisza, ISRC i ok\u0142adka przed wysy\u0142k\u0105 - 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\/release-file-checker-sample-rate-bit-depth-peaks-isrc-cover\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Kontrola pliku do wydania: cz\u0119stotliwo\u015b\u0107 pr\u00f3bkowania, g\u0142\u0119bia bitowa, szczyty, cisza, ISRC i ok\u0142adka przed wysy\u0142k\u0105 - Lukas Wojcik - Blog\" \/>\n<meta property=\"og:description\" content=\"Czyta w przegl\u0105darce plik WAV, AIFF, FLAC, MP3, M4A lub Ogg i wylicza, co stoi mi\u0119dzy nim a dostaw\u0105: format, cz\u0119stotliwo\u015b\u0107 pr\u00f3bkowania i g\u0142\u0119bi\u0119 bitow\u0105 wzgl\u0119dem wymaga\u0144 Apple, dope\u0142nione bity, clipping, true peak, sk\u0142adow\u0105 sta\u0142\u0105, cisz\u0119 i skoki na obu ko\u0144cach oraz tytu\u0142, wykonawc\u0119, ISRC i ok\u0142adk\u0119 z tag\u00f3w.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/release-file-checker-sample-rate-bit-depth-peaks-isrc-cover\/\" \/>\n<meta property=\"og:site_name\" content=\"Lukas Wojcik - Blog\" \/>\n<meta property=\"article:modified_time\" content=\"2026-09-23T16:54:20+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"630\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"2 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/release-file-checker-sample-rate-bit-depth-peaks-isrc-cover\\\/\",\"url\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/release-file-checker-sample-rate-bit-depth-peaks-isrc-cover\\\/\",\"name\":\"Kontrola pliku do wydania: cz\u0119stotliwo\u015b\u0107 pr\u00f3bkowania, g\u0142\u0119bia bitowa, szczyty, cisza, ISRC i ok\u0142adka przed wysy\u0142k\u0105 - Lukas Wojcik - Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/#website\"},\"datePublished\":\"2026-09-23T16:48:24+00:00\",\"dateModified\":\"2026-09-23T16:54:20+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/release-file-checker-sample-rate-bit-depth-peaks-isrc-cover\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/release-file-checker-sample-rate-bit-depth-peaks-isrc-cover\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.lukaswojcik.com\\\/blog\\\/pl\\\/narzedzia\\\/release-file-checker-sample-rate-bit-depth-peaks-isrc-cover\\\/#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\":\"Kontrola pliku do wydania: cz\u0119stotliwo\u015b\u0107 pr\u00f3bkowania, g\u0142\u0119bia bitowa, szczyty, cisza, ISRC i ok\u0142adka przed wysy\u0142k\u0105\"}]},{\"@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":"Kontrola pliku do wydania: cz\u0119stotliwo\u015b\u0107 pr\u00f3bkowania, g\u0142\u0119bia bitowa, szczyty, cisza, ISRC i ok\u0142adka przed wysy\u0142k\u0105 - 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\/release-file-checker-sample-rate-bit-depth-peaks-isrc-cover\/","og_locale":"en_US","og_type":"article","og_title":"Kontrola pliku do wydania: cz\u0119stotliwo\u015b\u0107 pr\u00f3bkowania, g\u0142\u0119bia bitowa, szczyty, cisza, ISRC i ok\u0142adka przed wysy\u0142k\u0105 - Lukas Wojcik - Blog","og_description":"Czyta w przegl\u0105darce plik WAV, AIFF, FLAC, MP3, M4A lub Ogg i wylicza, co stoi mi\u0119dzy nim a dostaw\u0105: format, cz\u0119stotliwo\u015b\u0107 pr\u00f3bkowania i g\u0142\u0119bi\u0119 bitow\u0105 wzgl\u0119dem wymaga\u0144 Apple, dope\u0142nione bity, clipping, true peak, sk\u0142adow\u0105 sta\u0142\u0105, cisz\u0119 i skoki na obu ko\u0144cach oraz tytu\u0142, wykonawc\u0119, ISRC i ok\u0142adk\u0119 z tag\u00f3w.","og_url":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/release-file-checker-sample-rate-bit-depth-peaks-isrc-cover\/","og_site_name":"Lukas Wojcik - Blog","article_modified_time":"2026-09-23T16:54:20+00:00","og_image":[{"width":1200,"height":630,"url":"https:\/\/www.lukaswojcik.com\/blog\/wp-content\/uploads\/2026\/08\/og-default.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_misc":{"Est. reading time":"2 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/release-file-checker-sample-rate-bit-depth-peaks-isrc-cover\/","url":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/release-file-checker-sample-rate-bit-depth-peaks-isrc-cover\/","name":"Kontrola pliku do wydania: cz\u0119stotliwo\u015b\u0107 pr\u00f3bkowania, g\u0142\u0119bia bitowa, szczyty, cisza, ISRC i ok\u0142adka przed wysy\u0142k\u0105 - Lukas Wojcik - Blog","isPartOf":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/#website"},"datePublished":"2026-09-23T16:48:24+00:00","dateModified":"2026-09-23T16:54:20+00:00","breadcrumb":{"@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/release-file-checker-sample-rate-bit-depth-peaks-isrc-cover\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/release-file-checker-sample-rate-bit-depth-peaks-isrc-cover\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.lukaswojcik.com\/blog\/pl\/narzedzia\/release-file-checker-sample-rate-bit-depth-peaks-isrc-cover\/#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":"Kontrola pliku do wydania: cz\u0119stotliwo\u015b\u0107 pr\u00f3bkowania, g\u0142\u0119bia bitowa, szczyty, cisza, ISRC i ok\u0142adka przed wysy\u0142k\u0105"}]},{"@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\/20130","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=20130"}],"version-history":[{"count":1,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/20130\/revisions"}],"predecessor-version":[{"id":20133,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/pages\/20130\/revisions\/20133"}],"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=20130"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.lukaswojcik.com\/blog\/wp-json\/wp\/v2\/tags?post=20130"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}