Havia vida antes de um CD de áudio? Decodificador de software PCM

No último artigo, falamos sobre códigos QR dinâmicos que foram gravados em fitas VHS. A epidemia de PCM também me pegou, então é hora de pegar esse formato.

Capture com um processador PCM

Na primeira etapa, tentaremos implementar um decodificador de software. Este não é o último artigo sobre este tópico, uma vez que nos processadores de leilões japoneses pode terminar e o PCM deve estar em todas as casas! Encontrar um reprodutor de vídeo não é um problema.

Para funcionar, você precisa de um arquivo com a gravação desses mesmos códigos QR. Você pode obtê-lo usando a placa de captura de vídeo. Bem, a fonte do sinal, é claro. Você pode capturar diretamente a saída do processador ou gravar em um gravador. Idealmente, trabalhe imediatamente com o dispositivo de captura para decodificar o sinal em tempo real.

Qualquer idioma serve. Comecei com Python. Mas acabou sendo bastante lento no meu laptop, então, como resultado, mudei para C ++. A propósito, independentemente uma da outra (quase) nossa pequena comunidade está desenvolvendo três projetos de decodificadores: no OpenCV (C ++), no Qt (C ++) e no LabView. O primeiro será discutido. O OpenCV foi escolhido devido à simplicidade de trabalhar com dispositivos de captura e vídeos pré-gravados. Além disso, todas as manipulações com a imagem são altamente otimizadas.

O primeiro problema que você encontrará é a perda de dados. Em qualquer caso, eles serão e não poderão ser evitados de forma alguma sem equipamento "especializado". O PCM usa mais linhas do que cabem na área visível do quadro. No caso da região NTSC, esse número é de 492 linhas por quadro, com uma área visível de 480. No caso do PAL, tudo é muito mais triste.
1. PCM NTSC 44,056 kHz, PAL 44,1 kHz.
2. VHS . ( ). , . , . , . .
Há duas soluções para este problema. Trabalhe com a placa de captura de uma maneira complicada, ignorando o driver e obtenha dados do ADC, após o que eles podem ser convertidos em um quadro PCM completo ou martelar nas linhas ausentes. A segunda opção parece um pouco selvagem, mas o formato de armazenamento de dados permite recuperar parte dos dados. No caso da região NTSC, ela atende às limitações do sistema de correção de erros.

Devido ao uso de linhas de serviço, você não pode pegar uma placa de vídeo com uma saída composta e fazer com que o processador PCM seja executado. O ferro ignorará o quadro inteiro se não encontrar o título em uma linha específica. Há algumas reflexões sobre esse assunto, mas sobre isso de alguma forma mais tarde.

Para começar, o sinal de vídeo está entrelaçado. Cada quadro contém dois, compostos por linhas ímpares e pares. Eles são chamados de campos. É com os campos que o processador PCM funciona. Portanto, também precisamos dividir o fluxo original. Antes disso, seria bom converter uma imagem em preto-e-branco (escala de cinza) em binária para facilitar o trabalho.

Neste ponto, encontramos três dificuldades associadas aos recursos dos dispositivos de captura de vídeo. Você não pode usar um limite estático para binarizar uma imagem. Mas o próprio OpenCV resolve esse problema, com a ajuda da qual obtemos um resultado bastante decente com uma linha mágica.

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

O segundo problema é, de repente, a cor. Os processadores PCM não usam o componente colorido do sinal de vídeo, mas as placas de captura podem tentar extraí-lo do ruído. Isso é especialmente visível no EasyCAP mais barato. Isso pode prejudicar um pouco o resultado da binarização. Primeiro, você precisa converter a imagem em tons de cinza.

cvtColor(srcFrame, greyFrame, CV_BGR2GRAY);

Além do acima, o EasyCAP consegue confundir os campos em alguns lugares. Mais precisamente, pula a primeira linha, pela qual todas as outras linhas não estão no lugar. Para gravar uma matinê do jardim de infância, isso não é muito importante, mas aqui já se torna um problema. Organizar linhas na ordem correta é fácil. No final de cada quadro, há uma área sem dados. Se movermos as linhas que contêm o sinal útil até a parada, é garantido que os campos retornem aos seus lugares. Ao estudar, tentei usar três dispositivos de captura de diferentes faixas de preço, mas o mais útil no final acabou sendo o mais barato, pois revelou vários problemas.

Captura EasyCAP de cassete de vídeo

Pontos de cor e um nível mais alto de brilho dos bits de dados podem ser observados na imagem quando comparados com a primeira ilustração de um artigo capturado no Magewell Pro Capture AIO.

É hora de lembrar em que o sinal está armazenado. Os gravadores VHS não diferem em qualidade especial, pois este é um formato doméstico. Somente os pulsos de sincronização de quadro e linha não são suficientes para uma operação estável. Portanto, marcas de sincronização adicionais são adicionadas ao sinal de vídeo. Em cada linha no início, há uma sequência de dois “pixels” brancos e dois pretos alternados, e no final da linha há uma pequena área com brilho máximo, que ajusta o AGC. Os bits de dados em si têm um brilho de 60% do máximo para 1 e menos de 20% para 0. Aqui está um exemplo de por que essas etiquetas são necessárias: inversão da imagem das fitas no início e no final do quadro.

Torções no início do quadro

De acordo com as marcas de sincronização, em cada linha há uma área de dados. Em seguida, você precisa determinar a largura do bit (apenas 128 bits por linha) e reduzir a linha da imagem para 16 bytes.

Vamos dar uma olhada no formato dos dados. A linha consiste em 8 blocos de 14 bits, cada um contendo valores para saída para o DAC (amostras) e códigos de correção de erros, e um bloco com uma soma de verificação (CRC-16 / CCITT-FALSE). Por somas de verificação, as linhas descartadas são determinadas, os dados nos quais o dispositivo tentará recuperar. Cada linha contém três amostras para os canais esquerdo e direito, um bloco de paridade P (xou de todas as amostras) e um Q misterioso. A ordem é a seguinte: L0, R0, L1, R1, L2, R2, P, Q. Hoje, a correção Q não é possível iremos, pois esse material ainda não foi totalmente compreendido e a implementação requer depuração.

Ordem de dados em linhas

Se você usar "no estado em que se encontra", uma linha quebrada significa a perda de três amostras ao mesmo tempo, que serão perceptíveis ao ouvido em um anel de metal. Mas os Dida eram mais inteligentes e decidiram gravar dados com escadas. Apenas um bloco é retirado de uma linha. O próximo é tirado com um leve deslocamento. O degrau da escada leva 16 linhas. O bloco L0 é retirado de 1 linha. Bloco R0 com a linha 17 ... Assim, usando o bloco de paridade, você pode recuperar dados de 16 linhas perdidas em uma linha. Mas somente se houver um erro dentro da escada. O bloco Q permite corrigir dois erros, que restauram até 32 linhas perdidas.

imagem

Considere um exemplo simples. Há um fragmento de um quadro PCM no qual várias linhas são quebradas (destacadas em vermelho). As 4 primeiras escadas são processadas normalmente. O quinto irá capturar a linha quebrada. O bloco Q é perdido primeiro, mas como serve para corrigir erros e as próprias amostras não são danificadas, você pode ir além. Com a sexta escada, fazemos o mesmo. Então, novamente, existem escadas não danificadas de até 21. O bloco P sofre nele e também serve para restaurar dados. Você pode pular. Então vamos para 37 escadas, onde a amostra do canal certo será danificada. Para restaurá-lo, é necessário executar o XOR para o bloco de paridade e todas as outras amostras:

R2=L0R0L1R1L2P


Como resultado, obtemos o valor inicial. Se houver dois erros, é feita uma tentativa de restauração usando o bloco Q. Se houver mais deles, nada poderá ser feito com isso, exceto para interpolar os valores das amostras batidas ou para redefini-las.

O processo de passagem pelo campo pode ser observado em uma pequena animação GIF.

imagem

E assim vamos até o último degrau da escada descansar no final do campo. O hardware PCM possui um buffer circular. Assim que a linha for processada, ela poderá ser preenchida com novos dados. Assim, o último passo salta sem interromper a reprodução.

Eu escolhi um princípio ligeiramente diferente do trabalho. Agora, não existe mais esse limite de memória; portanto, o buffer possui um tamanho um pouco maior: a altura do campo mais a altura da escada. Assim que a escada chega ao final do buffer, as últimas 111 linhas são transferidas para o início e o preenchimento de novos dados já é de 112 linhas. Obviamente, não devemos esquecer que, ao trabalhar com a placa de captura, perdemos algumas das linhas. Portanto, certifique-se de preencher as linhas ausentes com zeros para marcá-las para recuperação adicional por erros de CRC.

O PCM era originalmente de 14 bits. Porém, com o tempo, quando os gravadores de vídeo VHS melhoraram a qualidade da imagem, os fabricantes mudaram para 16 bits, sem esquecer a compatibilidade com versões anteriores.
3. 14- PCM 12 . ( ).
No PCM de 16 bits, não há nenhum bloco Q; portanto, há uma marca especial no cabeçalho do campo "A correção Q não é possível". Em vez disso, foram coletados 2 bits ausentes de amostras e P. Nesse caso, a altura da escada não é de 8 etapas, mas apenas 7, uma vez que os bits ausentes do bloco são armazenados em sua própria linha e não separadamente. Para entender como o PCM de 16 bits funciona, é bastante simples usar o exemplo de capturar um meandro com uma frequência de 100 Hz e amplitude máxima. Tudo imediatamente se encaixa.

Comparação de PCM de 14 e 16 bits

Agora é hora de salvar o resultado em um arquivo wav. A biblioteca libsndfile ajudará nisso. Embora ... PCM não salva arquivos, mas os reproduz imediatamente. Aqui você pode se lembrar de uma coisa tão legal, como um cachimbo. Quando a saída de um programa é inserida em outro. Simplesmente especificamos stdout como destino e redirecionamos o fluxo para o programa ffplay.

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

Agora você pode aproveitar as gotas e continuar depurando o código para se livrar delas ...

Isso é tudo por hoje. Você pode baixar a fonte do decodificador na página do GitHub: https://github.com/walhi/pcm . Há também um gerador. Algum dia eu irei projetá-lo como um plug-in para o foobar ... O

trabalho ativo está em andamento para concluir a recuperação no bloco Q, portanto, para um trabalho mais ou menos correto, você terá que pular as confirmações. Mas estes são triviais. Quem quiser jogar pode baixar o exemplo de captura.

All Articles