OWMB 3D-Cloud View

Dieses Handbuch habe ich aus allen möglichen Informationsquellen zusammengezogen und beschreibt die Installation, Bedienung und Funktionen von OWMB, einer Software zur Verwaltung, Erkundung und Nutzung von Sample-Bibliotheken. OWMB ist als eigenständige Anwendung und für Linux, Windows, MacOs als Audio-Plugin (VST3, AU) verfügbar.

1. Installation und erste Schritte

1.1 Systemanforderungen

OWMB läuft auf folgenden Betriebssystemen:

  • Windows 11 und 10 (64-bit)
  • macOS mit Apple Silicon (M1, M2, M3, M4) oder Intel-Prozessor
  • Linux (x86_64) mit Distributionen wie Ubuntu, Debian, Fedora oder Arch

1.2 Installation

Die Installation erfolgt über fertige Pakete, die von der GitHub-Releases-Seite heruntergeladen werden können.

Linux

Für Linux wird die Datei OWMB-Linux-Distros-x64.tar.gz bereitgestellt. Nach dem Entpacken des Archives sind die Standalone-Executable und das VST3-Plugin verfügbar.

Windows

Für Windows wird die Datei OWMB-Windows-11-x64.zip bereitgestellt. Nach dem Entpacken der Zip-Datei stehen die Standalone-Anwendung (.exe) und das VST3-Plugin zur Verfügung. Die Anwendung kann direkt gestartet oder das Plugin in den üblichen Plugin-Ordner der Digital Audio Workstation (DAW) kopiert werden.

MacOs

Für macOS wird die Datei OWMB-macOS-Universal-Installer.pkg angeboten. Die Ausführung der pkg-Datei installiert die Standalone-Anwendung, das VST3-Plugin und das AU-Plugin. Die Software ist signiert und notarisiert.

1.3 Die Benutzeroberfläche

Die Oberfläche von OWMB gliedert sich in vier Hauptbereiche. Die Kopfleiste befindet sich am oberen Rand des Fensters. Sie enthält die Suchleiste, Schalter zum Umschalten der Hauptansichten sowie die Transport-Steuerung für die Wiedergabe.

Die Seitenleiste befindet sich links im Fenster. Sie dient der Verwaltung von Filtern und enthält die Tag-Cloud, Bewertungen (Sterne), Dateiformate und BPM-Angaben.

Der Hauptbereich nimmt den zentralen Teil des Fensters ein. Hier kann zwischen der Sample-Tabelle, der 3D-Sample-Constellation und der Wellenform-Ansicht gewechselt werden.

Das Performance-Grid befindet sich am unteren Rand des Fensters. Es bietet 32 Pads für Live-Triggering.

2. Tastaturkürzel

Die folgenden Tastaturkürzel sind für die Bedienung der Software verfügbar.

TasteAktion
LeertasteWiedergabe starten oder pausieren
EnterAuswahl bestätigen oder Aktion ausführen
EscapeDialog schließen oder Vorgang abbrechen
Entf oder RücktasteAusgewähltes Sample löschen
Pfeiltaste nach oben oder untenZum vorherigen oder nächsten Element navigieren; Wert erhöhen oder verringern
Pfeiltaste nach links oder rechtsZum vorherigen oder nächsten Element navigieren; Note erhöhen oder verringern
Num-Taste +Auswahl oder Wert erhöhen
Num-Taste -Auswahl oder Wert verringern
Num-Taste 0Auswahl oder Wert zurücksetzen

3. Verwaltung der Sample-Bibliothek

3.1 Scannen der Bibliothek

OWMB verfügt über einen asynchronen Scanner, der im Hintergrund arbeitet. Der Scanner indiziert Audio-Dateien in den Formaten WAV, MP3, FLAC, OGG und AIFF. Während des Scanvorgangs bleibt die Bedienung der Software und die Wiedergabe von Audio ungestört. Die erfassten Metadaten werden in einer internen Datenbank gespeichert.

Zum Scannen wird in der Seitenleiste die Funktion zur Ordnerverwaltung aufgerufen. Dort können Pfade zu Sample-Ordnern hinzugefügt werden. Der Scanvorgang beginnt automatisch.

3.2 Filtern mit Tags

Die Filterung der Bibliothek erfolgt über das Tag-Panel in der Seitenleiste. Folgende Filterkriterien stehen zur Verfügung:

  • Boolesche Abfragen mit UND- und ODER-Verknüpfungen
  • Bewertungen in Form von Sternen
  • Dateiformate (Format-Pills)
  • BPM-Angaben
  • Benutzerdefinierte Tags

Die Auswahl eines Filters reduziert die Anzeige im Hauptbereich entsprechend.

4. Ansichten für die Sample-Erkundung

4.1 Die Sample-Tabelle

Die Sample-Tabelle ist eine Listenansicht, die alle Samples mit ihren Metadaten anzeigt. Zu den angezeigten Informationen gehören Dateiname, Dauer, BPM, Tonart und zugewiesene Tags. Die Spalten der Tabelle können sortiert werden.

4.2 Die 3D-Sample-Constellation

Die 3D-Sample-Constellation ist eine interaktive Punktwolke. Jeder Punkt repräsentiert ein Sample. Die Anordnung der Punkte erfolgt automatisch nach klanglicher Ähnlichkeit, Tonhöhe und akustischer Textur. Samples mit ähnlichen Eigenschaften befinden sich nahe beieinander.

Die Navigation in der 3D-Ansicht ermöglicht Zoomen, Drehen und Schwenken. Ein Klick auf einen Punkt wählt das entsprechende Sample aus und lädt es in den Wellenform-Transport.

4.3 Der Wellenform-Transport

Die Wellenform-Ansicht zeigt die Wellenform des ausgewählten Samples. Die Wiedergabe wird über die Leertaste oder den Play-Button gesteuert. Die Wellenform kann gezoomt werden, um Details zu betrachten. Transienten können automatisch erkannt und geslicet werden.

5. Audio-Aufnahme und -Analyse

5.1 Der Audio-Recorder mit 9-Band-Equalizer

OWMB ermöglicht die Aufnahme von Audio aus Live-Quellen oder über DAW-Routing. Der Recorder bietet folgende Funktionen:

  • Einen Count-in zur Vorbereitung der Aufnahme
  • Eine Auto-Normalisierung zur Pegelanpassung
  • Einen interaktiven 9-Band-parametrischen Equalizer zur klanglichen Formung vor der Aufnahme
  • Ein Live-Oszilloskop zur visuellen Kontrolle des Audiomaterials

5.2 Die timbrale akustische Analyse

Die Analyse zeigt ein Echtzeit-Spinnen-Chart-Diagramm mit vier akustischen Parametern:

  • Zero Crossing Rate (Nulldurchgangsrate): Ein Maß für die Rauigkeit oder Helligkeit
  • Crest Factor (Crest-Faktor): Das Verhältnis von Spitzen- zu Effektivwert
  • High Frequency Ratio (Hochfrequenzanteil): Der Anteil der hohen Frequenzen
  • Spectral Decay (Spektraler Abfall): Die Abklinggeschwindigkeit der hohen Frequenzen

Diese Analyse dient dem objektiven Vergleich von Klängen und der Unterstützung bei der Kategorisierung.

6. Performance und Mapping

6.1 Das Keyzone-Multisample-Mapping

Das Mapping erlaubt die Zuordnung von Samples zu Noten einer MIDI-Tastatur. Die folgenden Funktionen stehen zur Verfügung:

  • Chromatisches Mapping, bei dem Samples bestimmten Noten zugewiesen werden
  • Automatische Erkennung der Tonhöhe (Pitch) und der Grundnote (Root Note) eines Samples
  • Velocity Layering, das die Verwendung mehrerer Samples pro Note mit unterschiedlichen Anschlagsstärken ermöglicht
  • Sofortiges Laden und Abspielen einer erstellten Map über MIDI

6.2 Das 32-Pad-Performance-Grid

Das Performance-Grid ist ein MPC-artiges Bedienelement mit 32 Pads. Die Pads können mit Samples belegt werden. Folgende Funktionen sind verfügbar:

  • Multi-Bank-Triggering mit den Banken A, B, C und D
  • Auto-Fill zur Generierung von Rhythmen
  • Randomisierung für Variationen
  • ADSR-Hüllkurven zur Steuerung von Attack, Decay, Sustain und Release

7. Integration und zusätzliche Werkzeuge

7.1 Drag & Drop in DAWs

Samples oder geslicte Transienten können per Drag & Drop aus OWMB in eine Digital Audio Workstation gezogen werden. Unterstützt werden die DAWs Ableton Live, FL Studio, Logic Pro, Reaper, Cubase und Bitwig.

Auf macOS muss beim Ziehen die Control-Taste gedrückt werden, um den Drag-and-Drop-Vorgang auf Betriebssystem-Ebene korrekt auszuführen.

7.2 Online-Soundbanks über Pixeldrain

OWMB integriert den Zugriff auf kuratierte, lizenzfreie Soundbanks und Sample-Kollektionen über die Pixeldrain-Cloud. Die Online-Inhalte können durchsucht und mit einem Klick in die lokale Bibliothek heruntergeladen werden.

7.3 Loris Additive Resynthesis

Die Loris Additive Resynthesis ist ein Werkzeug zur spektralen Analyse und Neusynthese von Klängen. Ein Klang wird auf seine spektralen Bestandteile (Partialtöne) analysiert und kann anschließend neu zusammengesetzt werden. Dies ermöglicht die Manipulation der spektralen Zusammensetzung für Sound-Design und die Erzeugung neuer Texturen.

7.4 Sample-Map-Management

Die Software unterstützt den Export und Import von Sample-Map-Bundles. Eine komplette Map mit allen zugeordneten Samples kann als Zip-Datei exportiert werden. Der Import einer solchen Zip-Datei stellt die gesamte Zuordnung und die Sample-Pfade automatisch wieder her.

Download & Git

Was ist ein Sample-Map-Bundle

Ein Sample-Map-Bundle ist eine spezielle Sicherungs- und Austauschdatei für OWMB. Es handelt sich um eine einzige .zip-Datei, die alle Informationen einer erstellten Sample-Zuordnung (Map) sowie die zugehörigen Audiodateien selbst enthält .

Zweck und Inhalt eines Bundles

Der primäre Zweck eines Sample-Map-Bundles ist der Austausch und die Sicherung von kompletten Sample-Instrumenten oder -Setups. Der Export und Import wird in OWMB durch die Funktion zum “Sample Map Management” ermöglicht . Ein solches Bundle enthält typischerweise:

  • die Zuordnungsinformationen (welches Sample auf welche MIDI-Note oder welches Pad gelegt wurde, inklusive Velocity-Layering und Einstellungen)
  • die audiodateien selbst (die Samples), die für diese Map verwendet werden

Verwendung und Vorteile

  • Export: Ein Anwender kann eine selbst erstellte Map in OWMB mit all ihren Samples als Bundle exportieren.
  • Import: Dieses Bundle kann dann von einem anderen OWMB-Nutzer importiert werden. Die Software stellt dabei automatisch die gesamte Zuordnung und die Sample-Pfade wieder her.

Die MAP-Datei enthält also nur die Zuordnungsdaten, während das Bundle die MAP-Datei plus die Samples in einem praktischen, austauschbaren Paket vereint.

Aufbau der Sample-Map-Bundle Zip-Datei

Der genaue interne Aufbau der Zip-Datei für Sample-Map-Bundles ist in den öffentlich zugänglichen Dokumentationen nicht im Detail beschrieben. Der Aufbau lässt sich jedoch aus der Beschreibung der Funktion ableiten:

Enthaltene Elemente

Die Zip-Datei ist ein Austausch- und Sicherungsformat für ein komplettes Sample-Instrument. Sie enthält:

  • Die Zuordnungsinformationen (Sample-Map), also welche Sample-Datei welcher MIDI-Note, Pad oder Velocity-Stufe zugewiesen ist.
  • Die Audiodateien selbst (die Samples), die für diese Map verwendet werden.

Zweck beim Import

Beim Importieren einer solchen Zip-Datei stellt die Software die gesamte Zuordnung automatisch wieder her, inklusive der Sample-Pfade. Das bedeutet, die Software entpackt die Datei, ordnet die enthaltenen Audiodateien den entsprechenden Noten oder Pads zu und macht das Instrument sofort spielbereit.

Unterschied zur reinen Map-Datei

Die reine MAP-Datei enthält nur die Zuordnungsdaten und verweist auf die externen Sample-Dateien. Ein Bundle (die Zip-Datei) hingegen vereint diese Zuordnungsdaten und die Samples in einem einzigen, austauschbaren Paket. Dies macht es einfach, komplette Instrumente oder Setups zwischen verschiedenen Systemen oder Nutzern zu teilen, ohne dass die Sample-Pfade manuell angepasst werden müssen.

Technischer Hinweis

Da es sich um ein Open-Source-Projekt handelt, könnte der genaue Aufbau (z.B. die Struktur der Metadaten-Datei innerhalb der Zip) im Quellcode von OWMB eingesehen werden. Die öffentliche Dokumentation selbst beschreibt die interne Struktur der Zip-Datei jedoch nicht weiter.

Sample-Map-Bundle Format

Basierend auf den bereitgestellten Dateien (MediaItem.h, TagDatabaseManager.h/.cpp) lässt sich das Format für Sample-Map-Bundles ableiten. Ein Sample-Map-Bundle ist eine .zip-Datei, die eine vollständige Sample-Zuordnung (Map) sowie alle zugehörigen Audiodateien enthält.

Aufbau der Zip-Datei

sample_map_bundle.zip
├── manifest.json          # Metadaten der Map (siehe unten)
├── samples/               # Ordner mit allen Audiodateien
│   ├── Kick_01.wav
│   ├── Snare_01.wav
│   ├── HiHat_01.wav
│   └── ...
└── (optional) map_data.json  # Zusätzliche Mapping-Konfiguration

manifest.json (Schema)

{
  "version": "1.0",
  "mapName": "My Drum Kit",
  "description": "Custom drum kit for electronic music",
  "author": "Producer Name",
  "created": "2026-08-31T10:00:00Z",
  "items": [
    {
      "id": "a1b2c3d4e5f6",
      "filePath": "samples/Kick_01.wav",
      "fileName": "Kick_01.wav",
      "fileExtension": ".wav",
      "fileSizeBytes": 1024000,
      "durationSeconds": 0.5,
      "sampleRate": 44100.0,
      "numChannels": 2,
      "bitDepth": 24,
      "bpm": 128.0,
      "isFavorite": false,
      "rating": 5,
      "tags": ["#Kick", "#OneShot", "#128BPM"],
      "dateAddedMs": 1725120000000,
      "comment": "Powerful kick drum",
      "zcr": 0.15,
      "highFreqRatio": 0.30,
      "decayRatio": 0.45,
      "crestFactor": 1.8
    },
    {
      "id": "f6e5d4c3b2a1",
      "filePath": "samples/Snare_01.wav",
      "fileName": "Snare_01.wav",
      "fileExtension": ".wav",
      "fileSizeBytes": 850000,
      "durationSeconds": 0.3,
      "sampleRate": 44100.0,
      "numChannels": 2,
      "bitDepth": 24,
      "bpm": 128.0,
      "isFavorite": false,
      "rating": 4,
      "tags": ["#Snare", "#OneShot"],
      "dateAddedMs": 1725120000000,
      "comment": "Snappy snare",
      "zcr": 0.35,
      "highFreqRatio": 0.50,
      "decayRatio": 0.30,
      "crestFactor": 2.1
    }
  ],
  "mapping": {
    "type": "chromatic",
    "rootNote": "C4",
    "velocityLayers": 1,
    "zones": [
      {
        "sampleId": "a1b2c3d4e5f6",
        "keyLow": 36,
        "keyHigh": 36,
        "rootKey": 36,
        "velocityLow": 0,
        "velocityHigh": 127
      },
      {
        "sampleId": "f6e5d4c3b2a1",
        "keyLow": 38,
        "keyHigh": 38,
        "rootKey": 38,
        "velocityLow": 0,
        "velocityHigh": 127
      }
    ]
  }
}

Datenmodell-Zusammenhang

Die manifest.json verwendet die gleichen Felder wie das MediaItem-Datenmodell. Die entscheidende Besonderheit des Bundles ist die mapping-Struktur, die die Zuordnung der Samples zu Noten, Pads oder Velocity-Stufen definiert:

+------------------------------------------------------+
|              Sample-Map-Bundle (ZIP)                 |
+------------------------------------------------------+
|                                                      |
|  +------------------------------------------------+  |
|  |  manifest.json                                 |  |
|  |  - version: String                             |  |
|  |  - mapName: String                             |  |
|  |  - items: MediaItem[]                          |  |
|  |  - mapping: MappingConfig                      |  |
|  |    - type: "chromatic" | "drum" | "custom"     |  |
|  |    - rootNote: String                          |  |
|  |    - velocityLayers: int                       |  |
|  |    - zones: Zone[]                             |  |
|  |      - sampleId: String (referenziert Item)    |  |
|  |      - keyLow, keyHigh: int                    |  |
|  |      - rootKey: int                            |  |
|  |      - velocityLow, velocityHigh: int          |  |
|  +------------------------------------------------+  |
|                                                      |
|  +------------------------------------------------+  |
|  |  samples/                                      |  |
|  |  - Kick_01.wav                                 |  |
|  |  - Snare_01.wav                                |  |
|  |  - HiHat_01.wav                                |  |
|  +------------------------------------------------+  |
|                                                      |
+------------------------------------------------------+

Hinweise zur Implementierung

  1. MediaItem-Format: Die MediaItem-Struktur aus MediaItem.h definiert die persistenten Felder. Die Methoden toVar() und fromVar() ermöglichen die Serialisierung/Deserialisierung.
  2. Dateipfade: Im Bundle werden relative Pfade (z.B. samples/Kick_01.wav) verwendet. Beim Import werden diese in absolute Pfade umgewandelt.
  3. Tags: Die Tags aus MediaItem.tags werden im Bundle gespeichert. Die Methode sanitizeTags() aus TagDatabaseManager.cpp bereinigt die Tags beim Import.
  4. BPM-Erkennung: Die Methode extractBpmFromFilename() extrahiert BPM-Werte aus Dateinamen. Dies wird beim Import automatisch angewendet, falls im Bundle keine BPM-Angabe vorhanden ist.

Weitere Datenmodelle zum Zeitpunkt des Artikels

OWMB - Datenmodell von MediaItem (ASCII-Grafik)

+------------------------------------------------------------------------------+
|                        MediaItem                                             |
|                   (namespace openwav)                                        |
+------------------------------------------------------------------------------+
|  KERNDATEN (Persistente Felder)                                              |
+------------------------------------------------------------------------------+
|  - id: String                     // Eindeutige ID (Hash des Pfads)          |
|  - filePath: String               // Absoluter Systempfad                    |
|  - fileName: String               // Basis-Dateiname                         |
|  - fileExtension: String          // Dateiendung (klein)                     |
|  - fileSizeBytes: int64_t         // Größe in Bytes                          |
|  - durationSeconds: double        // Dauer in Sekunden                       |
|  - sampleRate: double             // Abtastrate in Hz                        |
|  - numChannels: int               // Anzahl Kanäle (Mono/Stereo)             |
|  - bitDepth: int                  // Bit-Auflösung (16, 24, 32)              |
|  - bpm: double                    // Geschätztes oder gesetztes BPM          |
|  - isFavorite: bool               // Favoriten-Status                        |
|  - rating: int (0-5)              // Bewertung in Sternen                    |
|  - tags: set<String>              // Aktive Tags (z.B. "Kick")               |
|  - dateAddedMs: int64_t           // Zeitstempel beim Hinzufügen             |
|  - comment: String                // Benutzer-Kommentar                      |
+------------------------------------------------------------------------------+
|  TIMBRALE ANALYSEWERTE                                                       |
+------------------------------------------------------------------------------+
|  - zcr: double                    // Zero Crossing Rate                      |
|  - highFreqRatio: double          // Hochfrequenz-Anteil                     |
|  - decayRatio: double             // Abkling-Verhältnis                      |
|  - crestFactor: double            // Crest-Faktor (Spitze/RMS)               |
+------------------------------------------------------------------------------+
|  GECACHETE DATEN (für Performance)                                           |
+------------------------------------------------------------------------------+
|  - cachedFormattedDuration: String  // Formatierte Dauer z.B. 1:23.4         |
|  - cachedFormattedSampleRate: String // Formatierte Rate z.B. 44.1 kHz / 16b |
|  - cachedUppercaseExtension: String  // Endung in Großbuchstaben             |
|  - cachedStarRating: String         // Sternsymbol-String (★☆)               |
|  - cachedLowerFileName: String      // Dateiname in Kleinbuchstaben          |
|  - cachedLowerFilePath: String      // Pfad in Kleinbuchstaben               |
|  - cachedTags: vector<CachedTag>    // Tags mit gemessenen Breiten           |
+------------------------------------------------------------------------------+
|  METHODEN                                                                    |
+------------------------------------------------------------------------------+
|  + precomputeCachedStrings()                                                 |
|    Berechnet alle gecacheten Strings und Tag-Breiten                         |
|                                                                              |
|  + toVar(): var                                                              |
|    Konvertiert das MediaItem in ein JSON-ähnliches var-Objekt                |
|                                                                              |
|  + fromVar(v: var): MediaItem (statisch)                                     |
|    Erstellt ein MediaItem aus einem var-Objekt (Deserialisierung)            |
+------------------------------------------------------------------------------+
|  HILFSSTRUKTUR: CachedTag                                                    |
+------------------------------------------------------------------------------+
|  - tag: String                                                               |
|  - width: int                  // Breite in Pixeln für UI-Rendering          |
+------------------------------------------------------------------------------+

Erläuterung der Felder

  • Kerndaten: Diese Felder werden in der JSON-Datenbank persistent gespeichert und beschreiben ein einzelnes Audio-Asset vollständig.
  • Timbrale Analysewerte: Diese vier Parameter werden während der akustischen Analyse berechnet und dienen der Klassifizierung und visuellen Darstellung im Spinnen-Chart-Diagramm.
  • Gecachete Daten: Diese Felder werden nicht gespeichert, sondern bei Bedarf aus den Kerndaten berechnet. Sie optimieren die Performance der Benutzeroberfläche, indem sie wiederholte Formatierungsoperationen vermeiden. Die Methode precomputeCachedStrings() wird nach jedem Laden oder Ändern eines MediaItems aufgerufen.
  • Serialisierung: Die Methoden toVar() und fromVar() ermöglichen die Konvertierung in ein plattformunabhängiges Format. Dies wird für die persistente Speicherung in der JSON-Datenbank und für die Kommunikation zwischen Komponenten verwendet.
+----------------------------------------------------------------------------------------------------+
|                                          MediaItem                                                 |
|                                     (namespace openwav)                                            |
+----------------------------------------------------------------------------------------------------+
|  KERNDATEN (Persistente Felder)                                                                    |
+----------------------------------------------------------------------------------------------------+
|  - id: String                                       // Eindeutige ID (Hash des Pfads)              |
|  - filePath: String                                 // Absoluter Systempfad                        |
|  - fileName: String                                 // Basis-Dateiname                             |
|  - fileExtension: String                            // Dateiendung (klein)                         |
|  - fileSizeBytes: int64_t                           // Größe in Bytes                              |
|  - durationSeconds: double                          // Dauer in Sekunden                           |
|  - sampleRate: double                               // Abtastrate in Hz                            |
|  - numChannels: int                                 // Anzahl Kanäle (Mono/Stereo)                 |
|  - bitDepth: int                                    // Bit-Auflösung (16, 24, 32)                  |
|  - bpm: double                                      // Geschätztes oder gesetztes BPM              |
|  - isFavorite: bool                                 // Favoriten-Status                            |
|  - rating: int (0-5)                                // Bewertung in Sternen                        |
|  - tags: set<String>                                // Aktive Tags (z.B. "Kick")                   |
|  - dateAddedMs: int64_t                             // Zeitstempel beim Hinzufügen                 |
|  - comment: String                                  // Benutzer-Kommentar                          |
+----------------------------------------------------------------------------------------------------+
|  TIMBRALE ANALYSEWERTE                                                                             |
+----------------------------------------------------------------------------------------------------+
|  - zcr: double                                      // Zero Crossing Rate                          |
|  - highFreqRatio: double                            // Hochfrequenz-Anteil                         |
|  - decayRatio: double                               // Abkling-Verhältnis                          |
|  - crestFactor: double                              // Crest-Faktor (Spitze/RMS)                   |
+----------------------------------------------------------------------------------------------------+
|  GECACHETE DATEN (für Performance)                                                                 |
+----------------------------------------------------------------------------------------------------+
|  - cachedFormattedDuration: String                  // Formatierte Dauer z.B. 1:23.4               |
|  - cachedFormattedSampleRate: String                // Formatierte Rate z.B. 44.1 kHz / 16b        |
|  - cachedUppercaseExtension: String                 // Endung in Großbuchstaben                    |
|  - cachedStarRating: String                         // Sternsymbol-String (★☆)                     |
|  - cachedLowerFileName: String                      // Dateiname in Kleinbuchstaben                |
|  - cachedLowerFilePath: String                      // Pfad in Kleinbuchstaben                     |
|  - cachedTags: vector<CachedTag>                    // Tags mit gemessenen Breiten                 |
+----------------------------------------------------------------------------------------------------+
|  METHODEN                                                                                          |
+----------------------------------------------------------------------------------------------------+
|  + precomputeCachedStrings()                                                                       |
|    Berechnet alle gecacheten Strings und Tag-Breiten                                               |
|                                                                                                    |
|  + toVar(): var                                                                                    |
|    Konvertiert das MediaItem in ein JSON-ähnliches var-Objekt                                      |
|                                                                                                    |
|  + fromVar(v: var): MediaItem (statisch)                                                           |
|    Erstellt ein MediaItem aus einem var-Objekt (Deserialisierung)                                  |
+----------------------------------------------------------------------------------------------------+
|  HILFSSTRUKTUR: CachedTag                                                                          |
+----------------------------------------------------------------------------------------------------+
|  - tag: String                                                                                     |
|  - width: int                                     // Breite in Pixeln für UI-Rendering             |
+----------------------------------------------------------------------------------------------------+