Audio-Daten-Komprimierung



  • Hi,

    ich weiß ehrlich gesagt nicht, was mein Prof. genau von mir will. Die Aufgabe hat nicht mal einen Titel, aber ich glaube, es geht um Audio-Daten-Komprimierung.
    Hier die Aufgabenstellng:

    Aufgabenbeschreibung

    Bei dieser Übung soll die Anwendung der schnellen Fourier-Transformation (FFT) zur Codierung von Audiodaten verdeutlicht werden. Wie bei einem sogenannten LPC-Verfahren werden die Audiodaten in Blöcke unterteilt. Jeder Block wird mit dem Befehl fft transformiert. Anschließend werden die Frequenzen mit den kleinsten Amplituden gesucht und gelöscht, d.h. zu Null gesetzt. Der resultierende Datenvektor wird schließlich mittels ifft zurück in den Zeitbereich transformiert und das Ausgangssignal aus der Abfolge dieser Vektoren zusammengesetzt. Da viele der leisen Frequenzanteile maskiert werden, sind die Änderungen auch bei einer großen Anzahl an gelöschten Frequenzen nur als leichte Störung wahrzunehmen.

    Für die Umsetzung finden Sie eine Vorlag und fünf Audio-Dateien:
    1. run_fft.m: Vorlage für den Aufruf der Transformation.
    2. *.wav: Audio-Dateien als Beispiele.

    Hinweise zu Matlab:

    * Zum Lesen und Schreiben von Audio-Dateien gibt es die Befehle wavread und wavwrite.

    * Das Zerlegen der Daten in Fragmente und der Zusammenbauen des gesamten Datenvektors erfolgt effizient über Indexvektoren: Mit index=1:block_length wird ein Indexvektor erzeugt und mit x(index) auf die ersten Elemente im Vektor x zugegriffen. Dies kann auch bei Zuweisungen geschehen, z.B. setzt x(index)=0 alle Werte im Vektor x, die durch index indiziert werden, gleich Null. Am Ende einer Bearbeitungsiteration muss der Indexvektor z.B. mit index=index+block_length inkrementiert werden.

    * Die Wiedergabe kann mit sound bzw. soundsc erfolgen (Abtastfrequenz 12000 bzw. 16000).

    * Mit dem Befehl specgram können die Audio-Daten visualisiert werden. Beim Vergleich von Eingangs- und Ausgangsdaten wird deutlich, welche Frequenzpunkte gelöscht wurden.

    * Die Suche nach den Werten mit der kleinsten Amplitude kann mit den beiden Befehlen abs und sort umgesetzt werden.

    Erstens, musste ich nichts in Blöcke aufteilen, zweitens, gefällt mir das Ergebnis nicht. Ich kann damit einfach nichts anfangen. Die Datei ist gleich groß und ich höre ein leichtes Rauschen (hab wohl zu viele Informationen gelöscht).

    Hier mein Skript:

    function compress()
        [data,sampleRate] = audioread('ceremony.wav');
    
        trans=fft(data);
    
        sorted = abs(trans);
        sorted=sort(sorted, 'ascend');
    
        frequencies_to_delete = 10000;
    
        for i = 1 : length(data)
            if abs(trans(i)) <= sorted(frequencies_to_delete)
                trans(i) = 0;
            end
        end
    
        out = ifft(trans);
    
        audiowrite('test.wav', out, 12000);
    end
    

    Das Komische ist, dass bei der Rücktransformation Werte, die von mir bei trans auf 0 gesetzt wurden, plötzlich bei out einen kleinen Wert besitzen. 😕 Natürlich kann dadurch nichts komprimiert werden. Wenn Werte in die Audio-Datei geschrieben werden, dann brauchen sie Speicherplatz, egal wie klein sie sind. Nur, wie löse ich das Problem?

    Das hier war übrigens die Original-Vorlage:

    % function [out]=run_fft(in,nd,fft_length)
    %
    % in            :     Eingangssignal
    % out           :     Ausgangssignal
    % nd            :     Anzahl der zu löschenden Frequenzen
    % fft_length    :     Länge der FFT
    %
    % nützliche Matlab-Befehle: fft, ifft, specgram(in,512,fs)
    % abs, real
    % wavread, wavwrite
    % sound, soundsc
    % sort, min, max
    
    function [out]=run_fft(in, nd, fft_length)
    
    end
    

    Und zu guter letzt, sollte ich euch vll. nicht die Warnung vorenthalten, die ich erhalte, wenn ich die wav-Datei schreibe. 🙂

    Warning: Data clipped when writing file.
    > In audiowrite>clipInputData at 389
    In audiowrite at 167
    In compress at 19

    Alles klar? 🙂

    Dank im Voraus!


  • Mod

    FFT_IFFT schrieb:

    Natürlich kann dadurch nichts komprimiert werden. Wenn Werte in die Audio-Datei geschrieben werden, dann brauchen sie Speicherplatz, egal wie klein sie sind. Nur, wie löse ich das Problem?

    Der Trick ist, dass nach dem Nullsetzen vieler Frequenzen sehr viele Redundanzen in den Daten vorliegen (eben die vielen Nullen) und man dadurch dann die Daten komprimieren kann, indem man häufig vorkommende Sequenzen (zum Beispiel mehrere aufeinander folgende Nullen) auf kürzere Sequenzen abbildet.

    Beim Speichern als wav-Datei wirst du davon natürlich nichts mitbekommen, da wav unkomprimiert ist*. Auch wenn du hinterher die wav-Datei komprimierst, wird das keinen (oder kaum einen) Unterschied machen, da wav die Daten nicht im Frequenzraum (wo man die Redundanzen hat) speichert*.

    Guck mal hier, für eine relativ verständliche Erklärung, wie mp3-Kompression funktioniert. Andere Audiokompressionen nutzen ähnliche Verfahren:
    https://www.c-plusplus.net/forum/328548

    *: Zumindest in der Form, wie es am häufigsten eingesetzt wird. An sich ist wav nur ein Container, das alles mögliche enthalten könnte. Meistens ist es aber unkomprimiertes LPCM.



  • Ok, dann ist diese Übung ein Fake, oder? 🙂 Hab ich das so umgesetzt, wie das der Prof wollte?


  • Mod

    FFT_IFFT schrieb:

    Ok, dann ist diese Übung ein Fake, oder? 🙂

    Nur, wenn du annimmst, dass es um Audiodatenkompression geht. In der Aufgabenstellung sehe ich nur etwas zum Thema Audiodatencodierung. Wahrscheinlich ist der Sinn der Aufgabe vorbereitender Natur und in der nächsten Aufgabe sollen dann Daten komprimiert werden. Hier geht es um das Verständnis, dass man Audiodaten sowohl als zeitabhängigen Signalverlauf als auch als Frequenzgemisch betrachten kann und dass man im Frequenzraum leicht einige mächtige psychoakustische Transformationen vornehmen kann.

    Hab ich das so umgesetzt, wie das der Prof wollte?

    Vermutlich ja, ich kenne die Sprache und die Bibliotheken nicht gut genug um das im Details zu prüfen.



  • FFT_IFFT schrieb:

    Ok, dann ist diese Übung ein Fake, oder? 🙂

    ???

    Du machst lauter Annahmen, denen ich überhaupt nicht folgen kann.
    Warum blockst Du nicht wie der Prof vorgeschlagen hat? Das würde Laufzeitgarantien geben.
    Warum gefällt Dir das Ergebnis nicht? Hört es sich doof an? Zu viel gelöscht. Oder einfach ein Programmierfehler. Versuch macht kluch. Ist der Code unhübsch? Vielleicht falsches Studium. Dateilänge zu groß? Hab ja auch keinen Nachbrenner gesehen. Packer haben fast immer Nachbrenner wie Burrows-Wheeler-Transformation -> Move-To-Front-List -> Entropiekodierer.

    FFT_IFFT schrieb:

    Das Komische ist, dass bei der Rücktransformation Werte, die von mir bei trans auf 0 gesetzt wurden, plötzlich bei out einen kleinen Wert besitzen. 😕 Natürlich kann dadurch nichts komprimiert werden.

    Die Rücktransformierte Version sollste doch nicht auf der Platte speichern, sondern die transformierte. Und die kannste elegant speichern, indem Du die Nullen wegläßt. Die Rücktransformierte sollte sollte Byteweise zum Original "am Arsch die Räuber" sagen, aber sich fast gleich anhören.



  • volkard schrieb:

    Warum blockst Du nicht wie der Prof vorgeschlagen hat? Das würde Laufzeitgarantien geben.

    Wieso?

    Warum gefällt Dir das Ergebnis nicht?

    Das schrieb ich doch.

    Dateilänge zu groß? Hab ja auch keinen Nachbrenner gesehen. Packer haben fast immer Nachbrenner wie Burrows-Wheeler-Transformation -> Move-To-Front-List -> Entropiekodierer.

    Willst du dich profilieren, oder so? Das war gar nicht verlangt!

    FFT_IFFT schrieb:

    Die Rücktransformierte Version sollste doch nicht auf der Platte speichern, sondern die transformierte.

    WTF?! Wie soll das noch decodiert werden?

    In der Aufgabenstellung steht auch:

    Der resultierende Datenvektor wird schließlich mittels ifft zurück in den Zeitbereich transformiert



  • FFT_IFFT schrieb:

    volkard schrieb:

    Warum blockst Du nicht wie der Prof vorgeschlagen hat? Das würde Laufzeitgarantien geben.

    Wieso?

    Weil die FFT glaub ich O(n*log(n)) hat und damit das Rechnen pro Byte um so langsamer wird je größer die Blocks. Außerdem kommt vielleicht jemand daher und will ein stundenlanges Werk packen, das würde ohne Blocken vielleicht gar nicht in den Speicher passen. Und hast automatisch die Anzahl der zu löschenden Frequenzen an die Werkslänge angepasst.

    Also du brauchst für den Rausch-Effekt nicht zu blocken, aber die Audiokompressoren machen es in der Praxis und deswegen hat der Prof es auch verlangt.

    FFT_IFFT schrieb:

    Warum gefällt Dir das Ergebnis nicht?

    Das schrieb ich doch.

    Leichtes Rauschen: Das ist ok. Diese Art der Kompression ist nicht verlustfrei.

    Nullen sind nach Hin- und Rücktransformation keine genauen Nullen mehr: Das ist auch ok.

    "Das Komische ist, dass bei der Rücktransformation Werte, die von mir bei trans auf 0 gesetzt wurden, plötzlich bei out einen kleinen Wert besitzen.": Ähm, daß trans Nullen kriegt erzeugt doch keine Nullen bei der Rücktranformierten. Sehe das Problem nicht.

    FFT_IFFT schrieb:

    Dateilänge zu groß? Hab ja auch keinen Nachbrenner gesehen. Packer haben fast immer Nachbrenner wie Burrows-Wheeler-Transformation -> Move-To-Front-List -> Entropiekodierer.

    Willst du dich profilieren, oder so? Das war gar nicht verlangt!

    Du sollst Dir den Zweck der Übung vorstellen. Nämlich die transponierte als Datei abzuspeichern. Und dabei braucht man die Nullen nicht zu speichern. Natürlich nicht plump weglassen, sondern man muss sich ein Dateiformat einfallen lassen, das es erlaubt, die Nullen wegzulassen. Oder man nutzt die mächtig gruße Anzahl der Nullen aus, um irgen einen anderen Packer als Nachstufe zu nehmen, was (genau wie das eigene Dateiformat) aber im Prinzip auch nix anderes ist, als eine weitere Transormation anzustellen. Die FFT ist nur die Vorstufe, die es dann irgendwie erlaubt, die beschnittene Transformierte recht klein zu speichern. Das speicher man dann nicht mehr als .wav, sondern als .mp8 oder wie man sein Format gernen nennen will.

    FFT_IFFT schrieb:

    FFT_IFFT schrieb:

    Die Rücktransformierte Version sollste doch nicht auf der Platte speichern, sondern die transformierte.

    WTF?! Wie soll das noch decodiert werden?

    Die Transformierte solltest Du auf die Platte speichern, wenn Du einen Audiokompressor bauen würdest. In der Übung brauchste das nicht zu machen, weils der Prof Euch nicht so viel zu Programmieren zumuten wollte. Stells Dir einfach vor und dann machts so richtig Sinn.
    Also das platzsparende Abspeichern der .mp9 und das Wiedereinladen der .mp9 wird einfach ausgelassen.



  • FFT_IFFT schrieb:

    volkard schrieb:

    Warum blockst Du nicht wie der Prof vorgeschlagen hat? Das würde Laufzeitgarantien geben.

    Wieso?

    Du sollst einfach blocken, die Frage nach dem Wieso stellt sich dabei erstmal nicht, wenn es ne Vorgabe ist, nen?

    Um sie trotzdem kurz zu beantworten: weil das Ergebnis dadurch viel besser wird. Ein längeres Signal bei dem die Spektrale Verteilung sich oft ändert mit einer einzigen riesigen (F)FT zu betrachten macht wenig Sinn.

    Wenn die Aufnahme z.B. ne Stelle hat wo alles bis auf einen leisen 1000 Hz Ton still ist, 1000 Hz über die gesamte Aufnahme betrachtet aber zu den leisesten Frequenzen gehört, dann würdest die 1000Hz - ohne zu Blocken - überall rauslöschen. Der Fehler wäre bei der leisen Stelle mit nur 1000Hz dann deutlich zu hören - die wäre dann ganz Still. Wenn du blockst löscht du den 1000 Hz Ton in diesen leisen "nur 1000 Hz" Blöcken nicht. In anderen, wo er vielleicht durch lautere Töne maskiert wird, aber schon.

    Davon abgesehen verteilen sich die durch das Nullsetzen einzelner Frequenzen entstehenden Fehler zeitlich über den gesamten FFT Block. Je grösser dieser wird, desto mehr ist also von Löschung einzelner Frequenzen betroffen.

    Und natürlich kann es passieren dass du "Phantom-Frequenzen" rauslöscht, die bloss in der Analyse aufscheinende Artefakte vom lauter und leiser Werden einzelner anderer Frequenzen sind. Die Löschung dieser Frequenzen über die gesamte Aufnahme beeinflusst dann diese Lautstärkenänderungen. Das Resultat sind viel viel mehr hörbare Artefakte als wenn du blockst.

    => Es hat schon einen Sinn dass das in der Aufgabe steht, und dass alle FFT/DFT/DCT/... basierten Kompressionsverfahren blocken.



  • hustbaer schrieb:

    Du sollst einfach blocken, die Frage nach dem Wieso stellt sich dabei erstmal nicht, wenn es ne Vorgabe ist, nen?

    FU mit U! 🤡

    Um sie trotzdem kurz zu beantworten

    Das macht Sinn, danke! 🙂



  • FFT_IFFT schrieb:

    hustbaer schrieb:

    Du sollst einfach blocken, die Frage nach dem Wieso stellt sich dabei erstmal nicht, wenn es ne Vorgabe ist, nen?

    FU mit U! 🤡

    Hä?
    FU wie in f

    uck you?
    Du mich auch!
    😕

    FFT_IFFT schrieb:

    Um sie trotzdem kurz zu beantworten

    Das macht Sinn, danke! 🙂

    Bitte.



  • hustbaer schrieb:

    FFT_IFFT schrieb:

    hustbaer schrieb:

    Du sollst einfach blocken, die Frage nach dem Wieso stellt sich dabei erstmal nicht, wenn es ne Vorgabe ist, nen?

    FU mit U! 🤡

    Hä?
    FU wie in f

    uck you?
    Du mich auch!
    😕

    😃

    hustbaer schrieb:

    FFT_IFFT schrieb:

    Um sie trotzdem kurz zu beantworten

    Das macht Sinn, danke! 🙂

    Bitte.

    🙂 👍


Anmelden zum Antworten