Der Cabaret-Codec ist entstanden auf der Suche nach einem extrem leichtgewichtigen Audiokompressionsverfahren zur digitalen Ausgabe von Sprachsamples oder Soundeffekten durch Microcontroller. Jedes Originalsample erzeugt genau ein Bit im Ausgangsdatenstrom, d.h. bei einer Samplerate von 31250 Hz (= 8 MHz / 256) ergibt sich eine Datenrate von 31250 bit/s oder 3906.25 byte/s. Der Speicherbedarf ist mit einer Handvoll Bytes nahezu gleich Null.
Das verwendete Verfahren ist grundsätzlich keine neue Erfindung, jedoch habe ich verschiedene Parameter so angepasst, dass eine Sprachausgabe bei einer Samplerate von 31250 Hz gut zu verstehen ist, und dass eine Implementierung auf einem 8-Bit Microcontroller so einfach wie möglich ist. Ebenfalls habe ich den Algorithmus dahingehend modifiziert, dass die Schrittweite step_size bei drei aufeinanderfolgenden gleichen Bits im komprimierten Datenstrom stärker erhöht wird, als sie bei drei nicht gleichen Bits erniedrigt wird, was zu einer besseren Hörbarkeit von in Sprache vorkommenden Zischlauten führt, jedoch gleichzeitig ein unerwünschtes Nebenrauschen zur Folge hat. Mit einem nachgeschalteten Tiefpassfilter (z.B. hinter einem PWM-Ausgang des Microcontrollers) kann dieses Rauschen noch etwas vermindert werden.
Der Kompressionsalgorithmus lässt sich in Pseudocode wie folgt beschreiben:
current_value := 0x8000 step_size := 0x00ff history := 0b11111111 foreach sample in input_samples do higher := (sample >= current_value) history := (history & 0b01111111) << 1 if higher then history := history | 0b00000001 end history := history & 0b11000111 if history == 0b000 or history == 0b111 then step_size := step_size + step_size div 16 if step_size > 0xffff then step_size := 0xffff end else step_size := step_size - step_size div 256 end if higher then current_value := current_value + step_size if current_value > 0xffff then current_value := 0xffff end write_bit(1) else current_value := current_value - step_size if current_value < 0x0000 then current_value := 0x0000 end write_bit(0) end end
Der Dekompressionsalgorithmus funktioniert entsprechend:
current_value := 0x8000 step_size := 0x00ff history := 0b11111111 foreach input_bit in input_bits do history := (history & 0b01111111) << 1 if input_bit then history := history | 0b00000001 end history := history & 0b11000111 if history == 0b000 or history == 0b111 then step_size := step_size + step_size div 16 if step_size > 0xffff then step_size := 0xffff end else step_size := step_size - step_size div 256 end if input_bit then current_value := current_value + step_size if current_value > 0xffff then current_value := 0xffff end else current_value := current_value - step_size if current_value < 0x0000 then current_value := 0x0000 end end write_word(current_value) end
Folgende Soundsamples können zur Beurteilung der erreichten Soundqualität heruntergeladen werden:
Ich habe folgende Schaltung zum Ausgeben des Sounds durch einen PWM-Ausgang des ATmega128 im schnellsten Modus verwendet. Bei 8 MHz ergibt sich eine Samplefrequenz von 31250 kHz bei einer 8 Bit Auflösung. Verwendet man drei Viertel des Programmspeichers für die digitalen Sounddaten, so kann man 25 Sekunden Sprache oder Soundeffekte direkt auf dem Chip vorhalten.
Das Pulsbreitenmodulierte-Audiosignal vom Microcontroller geht zunächst durch einen Tiefpass (1 kOhm Widerstand und 22 nF Kondensator). Anschließend wird der Pegel durch einen Spannungsteiler (10 kOhm Widerstand und 2,2 Ohm Poti) verkleinert. Der 12 Ohm Widerstand gegen +3,3 Versorgungsspannung des Microcontrollers dient dazu, im Falle eines hochohmigen Zustandes des Microcontroller-Ausgangspins einen neutralen Pegel zu erzeugen, damit kein Knacken beim Einschalten der Pulsbreitenmodulation entsteht. Die Kombination der bisher erwähnten Bauteile sorgt beim Tiefpass für eine Grenzfrequenz von 8440 Hz. Der 1 μF Kondensator vor dem LM 386 Verstärker-IC dient der Entfernung des Gleichspannungsanteils vom Signal. Die übrige Beschaltung ist dem Datenblatt des LM 386 entnommen, wobei die 470 μF etwas größer dimensioniert sind, als im Datenblatt vorgeschlagen.
Der Algorithmus, der Pseudo-Code sowie der Schaltplan dürfen beliebig verwendet bzw. kopiert oder modifiziert werden. Fehlerfreiheit und Funktionsfähigkeit werden nicht zugesichert; Benutzung erfolgt auf eigenes Risiko.