Die beste Codierung hängt stark von der Verteilung Ihrer Samples ab. Sie haben uns gesagt, dass die Deltas größtenteils recht klein sind, was bedeutet, dass Ihr erster Schritt mit ziemlicher Sicherheit die Delta-Codierung sein wird (wobei jeder Wert in seine Differenz zum vorherigen Wert umgewandelt wird).
Eine weitere Einschränkung ist das System, auf dem Sie die Codierung durchführen. Sie haben gesagt, es ist "eingebettet", aber das umfasst eine ganze Reihe von Funktionen. Sie haben auch gesagt, dass SD-Karten außerhalb des Gültigkeitsbereichs liegen und dass Sie jeweils nur 450 Samples im RAM puffern, was auf ein sehr kleines System hindeutet. In diesem Fall erscheint eine Optimierung zur Vereinfachung und Erhaltung von CPU / RAM angebracht.
Wenn der häufigste Delta-Wert genau 0 ist - das heißt, viele Stichproben sind dieselben wie im vorherigen Beispiel -, ist es wahrscheinlich eine gute Idee, diese Läufe mit 0-Werten zuerst "in Lauflänge zu codieren". (Das heißt, nur speichern, wie viele in einer Reihe waren.)
Der Rest hängt weiter davon ab, wie die Werteverteilung aussieht. Ich werde aus Übungsgründen davon ausgehen, dass sie fast alle im Bereich von -64 < x < 63 (d. H. Eine 7-Bit-Ganzzahl mit Vorzeichen) liegen. Ich gehe auch davon aus, dass es am einfachsten ist, mit Bytes anstatt mit Bits zu arbeiten (was wahrscheinlich zutrifft, wenn Sie beispielsweise C schreiben). Wenn dies nicht zutrifft, finden Sie ein bitweises Schema ganz unten in der Antwort. Eine sehr einfache byteweise Codierung könnte ungefähr so aussehen:
0b0xxxxxxx
- Ein Literalwert (Delta), der im Teil "xxxxxxx" als 7-Bit-Ganzzahl mit Vorzeichen dargestellt wird. (Werte von -64 bis 63.)
0b10xxxxxx
- eine Folge von Nullen (Deltas), deren Länge durch "xxxxxx" dargestellt wird (6 vorzeichenlose Bits können bis zu 63 ausdrücken, und wenn wir mehr benötigen, können wir einfach einen weiteren Eintrag hinzufügen.)
0b110xxxxx 0byyyyyyyy
- Ein Literalwert (Delta), der im Teil "xxxxxyyyyyyyy" als 13-Bit-Ganzzahl mit Vorzeichen dargestellt wird.
0b11111111 0bxxxxxxxx 0byyyyyyyy
- ein Literalwert (Delta), der als 16-Bit-Ganzzahl mit Vorzeichen dargestellt wird. Dies ist (offensichtlich) eine sehr ineffiziente Codierung, da ein 16-Bit-Wert in eine 3-Byte-Darstellung umgewandelt wird. Es verschwendet unnötig Speicherplatz, um die Ausgabebytes ausgerichtet zu halten. Dieses Schema ist nur dann sinnvoll, wenn so große Deltas sehr selten sind. (Jedes nichttriviale Komprimierungsschema hat einige Eingaben, für die die resultierende Ausgabe tatsächlich größer ist; dies ist ein Satz der Informationstheorie.)
(Das obige Schema ist leicht von der UTF-8-Codierung von Unicode inspiriert.)
Im Gegensatz zu Huffman-Codes (in einer anderen Antwort erwähnt) wird die angenommene Werteverteilung im Voraus festgelegt. Dies ist eine Tugend, weil es die Dinge einfach hält und es vermeidet, den Anfang jedes Probenblocks mit Overhead zu belasten. Dies ist ein Laster, da für ein adaptiveres Schema keine Handabstimmung der Verteilung erforderlich wäre.
Wenn Deltas üblich sind, die viel kleiner als -64 bis 63 sind, muss eine bessere byteweise Codierung als die oben genannte mehr als ein Sample gleichzeitig verarbeiten, um eine bessere Komprimierung als 2: 1 zu erzielen (d. h. mehr als ein Abtastwert pro Ausgangsbyte.)
Wenn die bitweise Codierung in Ordnung ist, lautet das viel einfacher zu beschreibende Schema wie folgt: Immer noch zuerst Delta-Codierung, dann Codierung wie folgt. Auf ein 0-Bit folgt eine positive Ganzzahl variabler Länge, die die Anzahl der folgenden Nullen codiert. Auf ein 1-Bit folgt ein Vorzeichenbit, dann eine positive Ganzzahl variabler Länge, die zusammen den nächsten (Delta) Wert codiert. Die positiven Ganzzahlen variabler Länge können mit einem der Codes von https://en.wikipedia.org/wiki/Universal_code_(data_compression) wie einem der Elias-Codes codiert werden. (Welche Codierung am besten ist, hängt wiederum von der Verteilung der Daten ab, aber wahrscheinlich ist jede davon großartig.)