Pergunta

Tenho para reduzir a profundidade de bits de um sinal de áudio digital a partir de 24 para 16 bits.

Tomando apenas os 16 bits mais significativos (por exemplo,truncar) de cada amostra é equivalente a fazer um cálculo proporcional (out = na * 0xFFFF / 0xFFFFFF)?

Foi útil?

Solução

Eu presumo que você quer dizer (in * 0xFFFF) / 0xFFFFFF, nesse caso, sim.

Outras dicas

Você obterá melhores resultados, adicionando um sinal de ruído cuidadosamente criado ao sinal original, logo abaixo do limite truncador, antes de truncar (também conhecido como Dithering).

Dithering Ao adicionar ruído, em geral, dará melhores resultados. A chave para isso é a forma do ruído. A popula Pow-r Os algoritmos de endividamento têm uma forma específica muito popular em muitos aplicativos de estação de trabalho de áudio digital (sonar de Cakewalk, lógica etc.).

Se você não precisa de toda a fidelidade do Pow-R, você pode simplesmente gerar alguns ruído com amplitude bastante baixa e misture -a em seu sinal. Você encontrará isso mascara alguns dos efeitos de quantização.

x * 0xffff / 0xffffff é excessivamente de pedante, mas não em um bom caminho se o seu amostras são assinados, e provavelmente não em um bom caminho, em geral.

Sim, você deseja que o valor máximo no intervalo de origem para coincidir com o valor máximo no intervalo de destino, mas os valores aqui utilizados são apenas para unsigned intervalos, e a distribuição de quantização passos significa que ele vai ser muito raro que você usar o maior valor de saída.

Se as amostras são assinados, em seguida, o pico de valores positivos seria 0x7fff e 0x7fffff, enquanto o pico de valores negativos seria -0 x 8000 e -0x800000.O primeiro problema é decidir se o +1 é igual a 0x7fff, ou -1 é igual a-0 x 8000.Se você escolher o último, então, é uma mudança simples operação.Se você tentar ter os dois, em seguida, zero deixa de ser zero.

Depois que você tem um problema que a divisão arredonda em direção a zero.Isso significa que muitos valores se arredondado para zero, em comparação com outros valores.Isso faz com que a distorção.

Se você deseja dimensionar de acordo com o pico de valores positivos, a forma correta seria:

out = rint((float)in * 0x7fff / 0x7fffff);

Se você pescar em torno de um bit você pode provavelmente encontrar uma forma eficiente de fazer isso com inteiro aritmética e sem divisão.

Este formulário corretamente deve arredondar para o mais próximo valor de saída para um dado de entrada, e deve mapear o maior valor de entrada possível para o maior valor de saída, mas ele vai ter uma feia distribuição de quantização etapas espalhadas por toda a gama.

A maioria das pessoas prefere:

out = (in + 128) >> 8;
if (out > 0x7fff) out = 0x7fff;

Esta forma torna as coisas um pouquinho mais alto, a ponto de que os valores positivos pode clip ligeiramente, mas a quantização passos são distribuídos uniformemente.

Adicionar 128 porque clique com o botão direito shift rodadas em direção ao infinito negativo.O média erro de quantização é -128 e adicionar 128 corrigir isso para manter a 0, precisamente 0.O teste de sobrecarga é necessário porque um valor de entrada de 0x7fffff de outra forma daria um resultado de 0 x 8000, e quando você store esta em uma palavra de 16 bits seria envoltório em torno dando um pico de valor negativo.

C pedantes pode picar furos nos pressupostos sobre a direita shift e divisão de comportamento, mas estou com vistas para aqueles que por motivos de clareza.

No entanto, como outros têm apontado que você geralmente não deve reduzir a profundidade de bits de áudio sem hesitar, e, idealmente, noise shaping.TPDF dither é como segue:

out = (in + (rand() & 255) - (rand() & 255)) >> 8;
if (out < -0x8000) out = -0x8000;
if (out > 0x7fff) out = 0x7fff;

Novamente, grandes problemas com o uso de rand() o que eu vou têm vista para a clareza.

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