Quantized DPCM (Differential Pulse Code Modulation)

Vicente González Ruiz

October 5, 2015

Contents

Debido a su naturaleza continua, una señal de audio digital en formato PCM tiende a general pulsos vecinos de valor parecido. Esto puede utilizarse para reducir el rango dinámico de la señal, representando la muestra s[n] en función de la anterior s[n 1]. En otras palabras, en lugar de codificar s[n], es posible codificar el error de predicción

e[n] = s[n] s[n 1]. (1)

Es evidente que esta codificación predictiva es revesible (podemos determinar s[n] a partir de e[n]). Sin embargo, en aras de aumentar el nivel de compresión, el error de predicción se cuantifica. Esta acción complica ligeramente el codificador porque en él es necesario usar para las predicciones las mismas muestras que el descodificador va a generar, o de lo contrario, se producía una diferencia incremental entre las predicciones generadas en el compresor y el descompresor (drift error). Gráficamente:

PIC

Nótese que las muestras reconstruidas son igual a

s[n] = e[n] + s[n 1] (2)

y

e[n] = Q(e[n]). (3)

El módulo M representa un modulador digital (PCM, por ejemplo) que para esta práctica debería usar un código de longitud fija de 8 bits para representar los errores de predicción cuantificados e[n]. Por tanto, diséñese el correspondiente quantificador que posea 256 niveles de representación. Más información en http://web.stanford.edu/class/ee368b/Handouts/15-DPCM.pdf y en http://en.wikipedia.org/wiki/Quantization_%28signal_processing%29.

Usense las entradas y salidas standard para que la modulación/desmodulación pueda aplicarse en tiempo real. Compuebe que el codificador funciona con:

arecord -f cd -t raw | DPCM -c | DPCM -d | aplay -f cd -t raw

donde DPCM -c ejecuta el codificador y DPCM -d el descodificador. La nota para este trabajo será proporcional a la relación señal/ruido conseguida. Más información en http://en.wikipedia.org/wiki/Signal-to-noise_ratio y en http://www.ual.es/~vruiz/Software/snr.tar.gz.

Finalmente, en Python es posible leer y escribir la salida estándar usando:

#!/usr/bin/env python2 
 
import sys 
import struct 
 
while True: 
    x = struct.unpack(’h’, sys.stdin.read(2))[0] # Leemos un entero con signo de 2 bytes 
    sys.stdout.write(struct.pack(’h’, x))        # Escribimos un entero con signo de 2 bytes 
 
#!/usr/bin/env python3 
 
import sys 
import struct 
 
while True: 
    x = struct.unpack(’h’, sys.stdin.buffer.read(2))[0] # Leemos un entero con signo de 2 bytes 
    sys.stdout.buffer.write(struct.pack(’h’, x))        # Escribimos un entero con signo de 2 bytes