¿Había vida antes de un CD de audio? Decodificador de software PCM

En el último artículo, hablamos sobre códigos QR dinámicos que se grabaron en cintas VHS. La epidemia de PCM también me atrapó, así que es hora de elegir este formato.

Capture con un procesador PCM

En la primera etapa, intentaremos implementar un decodificador de software. Este no es el último artículo sobre este tema, ya que en las subastas japonesas los procesadores pueden terminar, ¡y PCM debería estar en cada hogar! Encontrar un reproductor de video no es un problema.

Para trabajar, necesita un archivo con la grabación de estos mismos códigos QR. Puede obtenerlo usando la tarjeta de captura de video. Bueno, la fuente de señal, por supuesto. Puede capturar directamente la salida del procesador o grabar en una grabadora de cinta. Idealmente, trabaje inmediatamente con el dispositivo de captura para decodificar la señal en tiempo real.

Cualquier idioma servirá. Empecé con Python. Pero resultó ser bastante lento en mi computadora portátil, por lo que cambié a C ++. Por cierto, independientemente uno del otro (casi) nuestra pequeña comunidad está desarrollando 3 proyectos de decodificadores: en OpenCV (C ++), en Qt (C ++) y en LabView. El primero será discutido. Se eligió OpenCV debido a la simplicidad de trabajar con dispositivos de captura y videos pregrabados. Además, todas las manipulaciones con la imagen están altamente optimizadas.

El primer problema que encontrará es la pérdida de datos. En cualquier caso, se evitarán y no se pueden evitar de ninguna manera sin un equipo "especializado". PCM usa más líneas de las que caben en el área visible del marco. En el caso de la región NTSC, este número es de 492 líneas por cuadro con un área visible de 480. En el caso de PAL, todo es mucho más triste.
1. PCM NTSC 44,056 kHz, PAL 44,1 kHz.
2. VHS . ( ). , . , . , . .
Hay dos soluciones para este problema. Trabaje con la tarjeta de captura de una manera complicada sin pasar por el controlador y tome datos del ADC, después de lo cual se pueden convertir a un marco PCM completo o martillar en las líneas que faltan. La segunda opción suena un poco salvaje, pero el formato de almacenamiento de datos le permite recuperar parte de los datos. En el caso de la región NTSC, resulta que cumple con las limitaciones del sistema de corrección de errores.

Debido al uso de líneas de servicio, no puede tomar una tarjeta de video con una salida compuesta y hacer que se reproduzca el procesador PCM. Iron ignorará todo el cuadro si no encuentra el título en una línea específica. Hay un par de pensamientos sobre este tema, pero sobre esto de alguna manera más adelante.

Para empezar, la señal de video está entrelazada. Cada cuadro contiene, por así decirlo, dos, compuestos de líneas pares e impares. Se llaman campos. Es con los campos que funciona el procesador PCM. Por lo tanto, también necesitamos dividir la secuencia original. Justo antes de eso, sería bueno convertir una imagen en blanco y negro (escala de grises) a binaria para que sea más fácil trabajar.

En este punto, encontramos tres dificultades asociadas con las características de los dispositivos de captura de video. No puede usar un umbral estático para binarizar una imagen. Pero OpenCV en sí mismo resuelve este problema, con la ayuda del cual obtenemos un resultado bastante decente con una línea mágica.

threshold(greyFrame, fullFrame, 0, 255, THRESH_BINARY + THRESH_OTSU);

El segundo problema es, de repente, el color. Los procesadores PCM no usan el componente de color de la señal de video, pero las tarjetas de captura pueden intentar extraerlo del ruido. Esto es especialmente notable en el EasyCAP más barato. Esto puede estropear un poco el resultado de la binarización, por lo que primero debe convertir la imagen a tonos de gris.

cvtColor(srcFrame, greyFrame, CV_BGR2GRAY);

Además de lo anterior, EasyCAP logra confundir los campos en algunos lugares. Más precisamente, omite la primera línea, debido a que todas las demás líneas no están en su lugar. Para grabar una matiné del jardín de niños, esto no es muy importante, pero aquí ya se convierte en un problema. Organizar líneas en el orden correcto es bastante fácil. Al final de cada cuadro hay un área sin datos. Si movemos las líneas que contienen la señal útil hasta la parada, se garantiza que los campos volverán a sus lugares. Al estudiar, intenté usar tres dispositivos de captura de diferentes rangos de precios, pero al final el más útil resultó ser el más barato, ya que reveló una serie de problemas.

Captura EasyCAP de videocasete

Se pueden observar manchas de color y un mayor nivel de brillo de los bits de datos en la imagen en comparación con la primera ilustración de un artículo capturado en el Magewell Pro Capture AIO.

Es hora de recordar en qué se almacena la señal. Las grabadoras de cinta VHS no difieren en calidad especial, ya que este es un formato doméstico. Los pulsos de sincronización de trama y línea por sí solos no son suficientes para un funcionamiento estable. Por lo tanto, se agregan marcas de sincronización adicionales a la señal de video. Cada línea al principio tiene una secuencia de alternar dos "píxeles" blancos y dos negros, y al final de la línea hay un área pequeña con brillo máximo que ajusta el AGC. Los bits de datos tienen un brillo del 60% del máximo para 1 y menos del 20% para 0. Aquí hay un ejemplo de por qué estas etiquetas son necesarias: inversión de la imagen desde los casetes al principio y al final del marco.

Giros al comienzo del cuadro

Según las marcas de sincronización, en cada fila hay un área de datos. A continuación, debe determinar el ancho de bits (solo 128 bits por línea) y reducir la línea de la imagen a 16 bytes.

Echemos un vistazo más de cerca al formato de datos. La línea consta de 8 bloques de 14 bits, cada uno con valores para la salida al DAC (muestras) y los códigos de corrección de errores, y un bloque con una suma de verificación (CRC-16 / CCITT-FALSE). Por sumas de verificación, se determinan las líneas descartadas, los datos en los que el dispositivo intentará recuperarse. Cada línea contiene tres muestras para los canales izquierdo y derecho, un bloque de paridad P (xor de todas las muestras) y una Q misteriosa. El orden es el siguiente: L0, R0, L1, R1, L2, R2, P, Q. Hoy, la corrección Q no es posible lo haremos, ya que este material aún no se comprende completamente y la implementación requiere depuración.

Orden de datos en filas

Si usa "tal cual", entonces una línea discontinua significa la pérdida de tres muestras a la vez, lo que se notará en el oído en un anillo de metal. Pero dida fue más inteligente y decidió registrar datos con escaleras. Solo se toma un bloque de una línea. La siguiente se toma con un ligero desplazamiento. El peldaño de la escalera lleva 16 líneas. El bloque L0 se toma de 1 línea. Bloque R0 con la línea 17 ... Por lo tanto, utilizando el bloque de paridad, puede recuperar datos de 16 filas perdidas en una fila. Pero solo si hay un error dentro de la escalera. El bloque Q le permite corregir dos errores, lo que restaura hasta 32 líneas perdidas.

imagen

Considere un ejemplo simple. Hay un fragmento de un marco PCM en el que varias líneas se rompen (resaltadas en rojo). Las primeras 4 escaleras se procesan normalmente. El quinto capturará la línea discontinua. El bloque Q se pierde primero, pero como sirve para corregir errores y las muestras en sí no están dañadas, puede ir más allá. Con la sexta escalera, hacemos lo mismo. Por otra parte, hay escaleras sin daños de hasta 21. El bloque P sufre en él. También sirve para restaurar los datos. Puedes saltarte. Así que vamos a 37 escaleras, donde se dañará la muestra del canal derecho. Para restaurarlo, debe realizar XOR para el bloque de paridad y todas las demás muestras:

R2=L0R0L1R1L2P


Como resultado, obtenemos el valor inicial. Si hay dos errores, se intenta restaurar utilizando el bloque Q. Si hay más de ellos, entonces no hay nada que hacer con esto, excepto interpolar los valores de las muestras batidas o restablecerlos.

El proceso de pasar por el campo se puede observar en una pequeña animación GIF.

imagen

Y así vamos hasta que el último escalón de la escalera descanse contra el final del campo. Hardware PCM tiene un búfer circular. Tan pronto como se haya procesado la línea, se puede llenar con nuevos datos. Por lo tanto, el último paso salta sin interrumpir la reproducción.

Elegí un principio de trabajo ligeramente diferente. Ahora ya no existe ese límite de memoria, por lo que el búfer tiene un tamaño ligeramente mayor: la altura del campo más la altura de la escalera. Tan pronto como la escalera llega al final del búfer, las últimas 111 líneas se transfieren al principio, y el llenado de datos nuevos ya proviene de 112 líneas. Por supuesto, no debemos olvidar que al trabajar con la tarjeta de captura perdemos algunas de las líneas. Por lo tanto, asegúrese de completar las líneas que faltan con ceros para marcarlas para una mayor recuperación por errores de CRC.

PCM era originalmente de 14 bits. Pero con el tiempo, cuando las grabadoras de video VHS mejoraron la calidad de imagen, los fabricantes cambiaron a 16 bits, sin olvidar la compatibilidad con versiones anteriores.
3. 14- PCM 12 . ( ).
En el PCM de 16 bits, no hay ningún bloque Q, por lo que hay una marca especial en el encabezado del campo "La corrección Q no es posible". En cambio, se recolectaron 2 bits faltantes de muestras y P. En este caso, la altura de la escalera no es de 8 pasos, sino solo 7, ya que los bits faltantes del bloque se almacenan en su propia línea, y no por separado. Comprender cómo funciona un PCM de 16 bits es bastante simple usando el ejemplo de capturar un meandro con una frecuencia de 100 Hz y una amplitud máxima. Todo inmediatamente cae en su lugar.

Comparación de PCM de 14 bits y 16 bits

Ahora es el momento de guardar el resultado en un archivo wav. La biblioteca libsndfile ayudará en esto. Aunque ... PCM no guarda los archivos, sino que los reproduce de inmediato. Aquí puedes recordar algo tan genial, como la pipa. Cuando la salida de un programa se ingresa a otro. Simplemente especificamos stdout como destino y redirigimos la transmisión al programa ffplay.

./ggg -i easycap.avi -o - | ffplay -

Ahora puede disfrutar de las gotas y continuar depurando el código para deshacerse de ellas ...

Eso es todo por hoy. Puede descargar la fuente del decodificador desde la página en GitHub: https://github.com/walhi/pcm . También hay un generador. Algún día lo diseñaré como un complemento para foobar ...

El trabajo activo está en marcha para terminar la recuperación en el bloque Q, por lo que para un trabajo más o menos correcto, tendrá que saltar sobre los commits. Pero estos son pequeños. Aquellos que deseen jugar pueden descargar el ejemplo de captura.

All Articles