Rolf B: Wie genau (Takte zu Ablaufzeit) sind mp3-Dateien?

Beitrag lesen

Hallo Martin,

Außerdem hat eine Musik-Aufnahme ja meist noch etwas Zugabe vor dem ersten sowie nach dem letzten Takt.

Das dürfte das Hauptproblem sein, daran habe ich bei meinem Vorschlag gar nicht gedacht. Wenn man mehrere Spuren hat, könnten die jeweiligen Spur-MP3s sogar noch verschiedene Zugaben haben. Und es könnte auch noch ein Lied mit Auftakt sein!

Heißt: Man muss pro MP3 einen Kalibrationsoffset haben, und pro Song die Info, wieviele Auftakte drin sind.

An so Merkwürdigkeiten wie Ritardando oder einen Dirigenten, der keinen stabilen inneren Takt hat, mag ich gar nicht denken…

..., function () {
  durationSec = this.duration.toFixed(2);  // Sekunden mit 2 Nachkommastellen
  let arr     = durationSec.split(".");
  minuten     = ("00" + Math.floor( arr[0] / 60 )) . slice(-2);
  sekunden    = ("00" + ( arr[0] - minuten * 60 )) . slice(-2);
  if ( document.querySelector( "#duration" ) ) {
    document.querySelector( "#duration" ).innerHTML = minuten +":" +sekunden;
  }
});

Dieser Code hat gleich mehrere Macken - aber die dürften nicht unbedingt zum Versatz führen.

  • durationSec ist nicht deklariert - Absicht?
  • Text weist man an textContent zu, nicht an innerHTML
  • Wenn überhaupt, rundet man ab, indem man Math.floor(this.duration) aufruft. In einen String verwandeln und den am Punkt zerhacken ist sicher nicht bester Code.
  • Der Grund für's Abrunden dürfte darin bestehen, dass sonst die Formatierung der Sekunden nicht passt. Aber das ist doch eine "display only" Anzeige; wie er die Platzierung der Elemente durchführt, geht daraus nicht hervor.
  • Eine mm:ss oder mm:ss.ff Anzeige könnte man eleganter so bilden:
  const durationElement = document.querySelector( "#duration" );
  if (durationElement) {
    const minutes = Math.floor(this.duration) / 60,
          seconds = this.duration % 60;             // sic! 
          mmFormatter = Intl.NumberFormat("de-DE", 
                             { "minimumIntegerDigits": 2 }),
          ssFormatter = Intl.NumberFormat("de-DE",
                             { "minimumIntegerDigits": 2,
                               "minimumFractionDigits": 2,
                               "maximumFractionDigits": 2 } );

    durationElement.textContent = mmFormatter.format(minutes)
                                + ":"
                                + ssFormatter.format(seconds);
  }

Ich habe einige Zeilenumbrüche und Temp-Variablen eingefügt, um die Lesbarkeit im Forum zu verbessern.

Und ja, NumberFormat ist mühsam zu konstruieren. Für sowas kann man sich aber auch einen Wrapper bauen - diese Formatiererei passiert ja öfters.

class LFormatter {
   static decimalFormatter(vorkomma, nachkomma=0, leadingZero=false) {
      let options = {
        minimumFractionDigits: nachkomma,
        maximumFractionDigits: nachkomma };
      if (leadingZero) {
        options.minimumIntegerDigits = vorkomma;
      }
      return Intl.NumberFormat("de-DE", options);
   }

   static getMmSsFormatter() {
      let mf = LFormatter.decimalFormatter(2, 0, true);
      let sf = LFormatter.decimalFormatter(2, 2, true);
      return function(time) {
        return mf.format(time / 60) + ":" + sf.format(time % 60);
      }
   }
}

Und dann sieht es im Eventhandler so aus:

..., function() {
   let durationElement = document.querySelector( "#duration" );
   if ( durationElement ) {
      durationElement.textContent = LFormatter.getMmSsFormatter().format(this.duration)
   }
}

Rolf

--
sumpsi - posui - obstruxi