Cabaret-Codec

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.


Zurück zur Hauptseite

Kontakt