Gab es ein Leben vor einer Audio-CD? PCM-Software-Decoder

Im letzten Artikel haben wir über dynamische QR-Codes gesprochen, die auf VHS-Bändern aufgezeichnet wurden. Die PCM-Epidemie hat mich auch erwischt, also ist es Zeit, dieses Format aufzugreifen.

Mit einem PCM-Prozessor aufnehmen

In der ersten Phase werden wir versuchen, einen Software-Decoder zu implementieren. Dies ist nicht der letzte Artikel zu diesem Thema, da bei japanischen Auktionen die Prozessoren möglicherweise enden und PCM in jedem Haus sein sollte! Das Finden eines Videoplayers ist kein Problem.

Zum Arbeiten benötigen Sie eine Datei mit der Aufzeichnung derselben QR-Codes. Sie können es mit der Videoaufnahmekarte erhalten. Nun, die Signalquelle natürlich. Sie können die Prozessorausgabe direkt erfassen oder auf einem Kassettenrekorder aufnehmen. Arbeiten Sie im Idealfall sofort mit dem Erfassungsgerät zusammen, um das Signal in Echtzeit zu decodieren.

Jede Sprache reicht aus. Ich habe mit Python angefangen. Aber es stellte sich heraus, dass es auf meinem Laptop ziemlich langsam war, weshalb ich zu C ++ wechselte. Übrigens entwickelt unsere kleine Community (fast) unabhängig voneinander drei Decoderprojekte: auf OpenCV (C ++), auf Qt (C ++) und auf LabView. Der erste wird diskutiert. OpenCV wurde aufgrund der einfachen Arbeit mit Aufnahmegeräten und aufgezeichneten Videos ausgewählt. Außerdem sind alle Manipulationen mit dem Bild dort stark optimiert.

Das erste Problem, auf das Sie stoßen, sind Datenverlust. In jedem Fall werden und können sie ohne „spezielle“ Ausrüstung in keiner Weise vermieden werden. PCM verwendet mehr Linien als in den sichtbaren Bereich des Rahmens passen. Im Fall der NTSC-Region beträgt diese Zahl 492 Zeilen pro Frame mit einem sichtbaren Bereich von 480. Im Fall von PAL ist alles viel trauriger.
1. PCM NTSC 44,056 kHz, PAL 44,1 kHz.
2. VHS . ( ). , . , . , . .
Für dieses Problem gibt es zwei Lösungen. Arbeiten Sie auf schwierige Weise mit der Capture-Karte, indem Sie den Treiber umgehen und Daten vom ADC abrufen. Anschließend können sie in einen vollständigen PCM-Frame konvertiert oder auf fehlende Zeilen gehämmert werden. Die zweite Option klingt etwas wild, aber das Datenspeicherformat ermöglicht es Ihnen, einen Teil der Daten wiederherzustellen. Im Fall der NTSC-Region stellt sich heraus, dass sie die Einschränkungen des Fehlerkorrektursystems erfüllt.

Aufgrund der Verwendung von Serviceleitungen können Sie keine Grafikkarte mit Composite-Ausgang nehmen und den PCM-Prozessor abspielen lassen. Iron ignoriert den gesamten Frame, wenn der Titel in einer bestimmten Zeile nicht gefunden wird. Es gibt ein paar Gedanken zu diesem Thema, aber darüber irgendwie später.

Zunächst wird das Videosignal verschachtelt. Jeder Frame enthält sozusagen zwei, bestehend aus ungeraden und geraden Linien. Sie werden Felder genannt. Mit den Feldern arbeitet der PCM-Prozessor. Daher müssen wir auch den ursprünglichen Stream teilen. Kurz zuvor wäre es schön, ein Schwarzweißbild (Graustufenbild) in ein Binärbild umzuwandeln, damit es einfacher zu arbeiten wäre.

An dieser Stelle stoßen wir auf drei Schwierigkeiten, die mit den Funktionen von Videoaufnahmegeräten verbunden sind. Sie können keinen statischen Schwellenwert zum Binärisieren eines Bildes verwenden. Aber OpenCV selbst löst dieses Problem, mit dessen Hilfe wir mit einer magischen Linie ein recht anständiges Ergebnis erzielen.

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

Das zweite Problem ist plötzlich die Farbe. PCM-Prozessoren verwenden nicht die Farbkomponente des Videosignals, aber Capture-Karten versuchen möglicherweise, es aus dem Rauschen zu extrahieren. Dies macht sich insbesondere beim günstigsten EasyCAP bemerkbar. Dies kann das Ergebnis der Binarisierung etwas beeinträchtigen. Daher müssen Sie das Bild zuerst in Graustufen konvertieren.

cvtColor(srcFrame, greyFrame, CV_BGR2GRAY);

Darüber hinaus gelingt es EasyCAP, die Felder stellenweise zu verwirren. Genauer gesagt wird die erste Zeile übersprungen, wodurch nicht alle anderen Zeilen vorhanden sind. Für die Aufnahme einer Matinee aus dem Kindergarten ist dies nicht sehr wichtig, aber hier wird es bereits zum Problem. Das Anordnen von Zeilen in der richtigen Reihenfolge ist einfach genug. Am Ende jedes Frames befindet sich ein Bereich ohne Daten. Wenn wir die Zeilen mit dem Nutzsignal bis zum Stopp verschieben, kehren die Felder garantiert an ihren Platz zurück. Während des Studiums habe ich versucht, drei Aufnahmegeräte aus verschiedenen Preisklassen zu verwenden, aber das nützlichste erwies sich am Ende als das billigste, da es eine Reihe von Problemen aufzeigte.

EasyCAP-Aufnahme von der Videokassette

Sie können Farbflecken im Bild und eine höhere Helligkeit der Datenbits im Vergleich zur ersten Abbildung eines Artikels beobachten, der mit Magewell Pro Capture AIO aufgenommen wurde.

Es ist Zeit, sich daran zu erinnern, worauf das Signal gespeichert ist. VHS-Tonbandgeräte unterscheiden sich nicht in der besonderen Qualität, da dies ein Haushaltsformat ist. Frame- und Line-Sync-Impulse allein reichen für einen stabilen Betrieb nicht aus. Daher werden dem Videosignal zusätzliche Synchronisationsmarkierungen hinzugefügt. In jeder Zeile am Anfang gibt es eine Abfolge von zwei weißen und zwei schwarzen „Pixeln“, und am Ende der Zeile befindet sich ein kleiner Bereich mit maximaler Helligkeit, der die AGC anpasst. Die Datenbits selbst haben eine Helligkeit von 60% des Maximums für 1 und weniger als 20% für 0. Hier ein Beispiel, warum diese Beschriftungen erforderlich sind: Inversion des Bildes von den Kassetten am Anfang und Ende des Rahmens.

Drehungen am Anfang des Rahmens

Entsprechend den Synchronisationsmarkierungen gibt es in jeder Zeile einen Datenbereich. Als nächstes müssen Sie die Bitbreite bestimmen (nur 128 Bit pro Zeile) und die Bildzeile auf 16 Byte verkleinern.

Schauen wir uns das Datenformat genauer an. Die Zeile besteht aus 8 Blöcken mit jeweils 14 Bits, die Werte für die Ausgabe an den DAC (Abtastwerte) und Fehlerkorrekturcodes enthalten, sowie einem Block mit einer Prüfsumme (CRC-16 / CCITT-FALSE). Durch Prüfsummen werden die verworfenen Zeilen ermittelt, die Daten, in denen das Gerät versucht, sie wiederherzustellen. Jede Zeile enthält drei Abtastwerte für den linken und rechten Kanal, einen Paritätsblock P (xoder aller Abtastwerte) und ein mysteriöses Q. Die Reihenfolge ist wie folgt: L0, R0, L1, R1, L2, R2, P, Q. Heute ist eine Q-Korrektur nicht möglich Wir werden es tun, da dieses Material noch nicht vollständig verstanden ist und die Implementierung ein Debugging erfordert.

Datenreihenfolge in Zeilen

Wenn Sie "wie besehen" verwenden, bedeutet eine gestrichelte Linie den Verlust von drei Proben gleichzeitig, was für das Ohr an einem Metallring erkennbar ist. Aber dida war schlauer und beschloss, Daten mit Leitern aufzuzeichnen. Aus einer Zeile wird nur ein Block entnommen. Der nächste wird mit einem leichten Versatz aufgenommen. Die Treppe dauert 16 Zeilen. Block L0 wird aus 1 Zeile entnommen. Block R0 mit Zeile 17 ... Mit dem Paritätsblock können Sie also Daten aus 16 Zeilen wiederherstellen, die in einer Zeile verloren gegangen sind. Aber nur, wenn es einen Fehler in der Leiter gibt. Mit Block Q können Sie zwei Fehler beheben, wodurch bis zu 32 verlorene Zeilen wiederhergestellt werden.

Bild

Betrachten Sie ein einfaches Beispiel. Es gibt ein Fragment eines PCM-Rahmens, in dem mehrere Zeilen unterbrochen sind (rot hervorgehoben). Die ersten 4 Leitern werden normal bearbeitet. Der fünfte erfasst die gestrichelte Linie. Der Q-Block geht zuerst verloren, aber da er zur Korrektur von Fehlern dient und die Samples selbst nicht beschädigt sind, können Sie weiter gehen. Mit der sechsten Leiter machen wir dasselbe. Andererseits gibt es unbeschädigte Leitern bis 21. Block P leidet darunter. Er dient auch zur Wiederherstellung von Daten. Du kannst überspringen. Also gehen wir zu 37 Stufen, wo die Probe des rechten Kanals beschädigt wird. Um es wiederherzustellen, müssen Sie XOR für den Paritätsblock und alle anderen Beispiele ausführen:

R2=L0R0L1R1L2P


Als Ergebnis erhalten wir den Anfangswert. Wenn zwei Fehler vorliegen, wird versucht, sie mithilfe des Q-Blocks wiederherzustellen. Wenn mehr davon vorhanden sind, ist nichts anderes zu tun, als die Werte der geschlagenen Proben zu interpolieren oder zurückzusetzen.

Der Prozess des Durchlaufens des Feldes kann auf einer kleinen GIF-Animation beobachtet werden.

Bild

Und so gehen wir, bis die letzte Stufe der Leiter am Ende des Feldes anliegt. Hardware-PCM verfügt über einen Ringpuffer. Sobald die Zeile verarbeitet wurde, kann sie mit neuen Daten gefüllt werden. Somit springt der letzte Schritt nach oben, ohne die Wiedergabe zu unterbrechen.

Ich habe ein etwas anderes Arbeitsprinzip gewählt. Jetzt gibt es keine solche Speicherbeschränkung mehr, sodass der Puffer eine etwas größere Größe hat: Feldhöhe plus Schritthöhe. Sobald die Leiter das Ende des Puffers erreicht, werden die letzten 111 Zeilen an den Anfang übertragen, und das Füllen mit neuen Daten erfolgt bereits aus 112 Zeilen. Natürlich dürfen wir nicht vergessen, dass wir bei der Arbeit mit der Capture-Karte einige Zeilen verlieren. Füllen Sie daher die fehlenden Zeilen unbedingt mit Nullen aus, um sie für die weitere Wiederherstellung durch CRC-Fehler zu markieren.

PCM war ursprünglich 14-Bit. Im Laufe der Zeit, als VHS-Videorecorder die Bildqualität verbesserten, stellten die Hersteller auf 16 Bit um, ohne die Abwärtskompatibilität zu vergessen.
3. 14- PCM 12 . ( ).
Im 16-Bit-PCM gibt es überhaupt keinen Q-Block, daher gibt es eine spezielle Markierung in der Feldüberschrift „Q-Korrektur ist nicht möglich“. Stattdessen wurden 2 fehlende Bits von Proben und P gesammelt. In diesem Fall beträgt die Höhe der Leiter nicht 8 Schritte, sondern nur 7, da die fehlenden Bits des Blocks in einer eigenen Zeile und nicht separat gespeichert werden. Am Beispiel der Erfassung eines Mäanders mit einer Frequenz von 100 Hz und maximaler Amplitude ist es recht einfach zu verstehen, wie ein 16-Bit-PCM funktioniert. Alles passt sofort zusammen.

Vergleich von 14-Bit- und 16-Bit-PCM

Jetzt ist es Zeit, das Ergebnis in einer WAV-Datei zu speichern. Die libsndfile-Bibliothek hilft dabei. PCM speichert zwar keine Dateien, spielt sie aber sofort ab. Hier können Sie sich an so eine coole Sache erinnern, wie Pfeife. Wenn die Ausgabe eines Programms in ein anderes eingegeben wird. Wir geben einfach stdout als Ziel an und leiten den Stream zum ffplay-Programm um.

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

Jetzt können Sie die Tropfen genießen und den Code weiter debuggen, um sie loszuwerden ...

Das ist alles für heute. Sie können die Decoderquelle von der Seite auf GitHub herunterladen: https://github.com/walhi/pcm . Es gibt auch einen Generator. Eines Tages werde ich es als Plugin für foobar entwerfen ... Es wird

aktiv daran gearbeitet, die Wiederherstellung des Q-Blocks abzuschließen. Für mehr oder weniger korrekte Arbeit müssen Sie also über die Commits springen. Aber das sind Kleinigkeiten. Wer spielen möchte, kann das Capture- Beispiel herunterladen .

All Articles