Pergunta

Eu tenho um buffer com muitos valores positivos de 16 bits (que são armazenados como duplos) que gostaria de quantizar para 8 bits (0-255 valores).

De acordo com Wikipédia o processo seria:

  • Normalize valores de 16 bits.Ou sejaencontre o maior e divida com ele.
  • Use a fórmula Q(x) com M=8.

Então eu me pergunto, se C tem uma função que possa fazer essa quantização, ou alguém sabe de uma implementação em C que eu possa usar?

Muito amor, Louise

Foi útil?

Solução

Assumindo o valor d está no intervalo [0.0, max]:

unsigned char quantize(double d, double max)
{
    return (unsigned char)((d / max) * 255.0);
}

Não tenho certeza do que você quer dizer com "valores de 16 bits"; Os valores de precisão dupla são de 64 bits em qualquer sistema usando o IEEE-754. No entanto, se você tiver valores de outro tipo numérico, o processo será efetivamente o mesmo.

Outras dicas

Isso soa como o processamento de áudio da forma de onda, onde sua entrada é de 16 dados PCM, sua saída é de dados PCM de 8 bits e você está usando duplas como um valor intermediário.

No entanto, os dados de onda PCM de 8 bits não são apenas quantizados, a representação é de valores não assinados na notação excedente de 128. (Como a maneira como os expoentes são armazenados em números de ponto flutuante)

Encontrar o maior valor primeiro não seria apenas quantização, mas também escala. Então, no código pseudo

double dMax = max_of_all_values(); // 
...
foreach (dValue in array_of_doubles)
{
   signed char bValue = (signed char)((dValue / dMax)*127.0);
}

Você pode arredondar, em vez de truncar, se quiser mais precisão, mas no processamento de áudio, geralmente é melhor randomizar a ordem de truncamento ou até moldá -lo, executando essencialmente um algoritmo de filtragem como parte do truncamento de duplas a chars assinados.

Nota: Esse char assinado não está correto se a saída for dados de 8 bits PCM, mas como as perguntas não solicitam especificamente isso, eu o deixei fora.

EDIT: Se isso for usado como dados de pixels, você deseja valores não assinados. Vejo James já deu a resposta correta para valores não assinados quando a entrada não é assinada (os valores de db de dados normalizados devem ser negativos, na verdade)

Não está claro na sua pergunta qual é a codificação, já que "valores positivos de 16 bits (que são armazenados como duplos)"não faz sentido;eles são de 16 bits ou são duplos, não podem ser ambos.

No entanto, supondo que se trate de dados não assinados de 16 bits normalizados para 1,0 (portanto, os valores variam de 0,0 <= é <= 1,0), tudo o que você precisa fazer para expandi-los para valores inteiros de 8 bits é multiplicar cada amostra por 255.

unsigned char s8 = s * 255 ;

Se o intervalo não for 0,0 <= é <= 1,0, mas 0,0 <= s <= máx. então:

unsigned char s8 = s / max * 255 ;

De qualquer forma, não existe outra função de "quantização" além daquela que você mesmo pode escrever;mas a transformação necessária será, sem dúvida, uma simples expressão aritmética (embora não tão simples se os dados forem compactados, talvez - ou seja,μ-lay ou A-law codificado, por exemplo).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top