Тонкость в преобразовании удваивается в вывод звука байта - PullRequest
0 голосов
/ 06 февраля 2019

Я хочу преобразовать двойной массив с диапазоном от -1 до 1 в байтовый вывод, который будет сохранен в формате WAVE.Ради аргумента я сконцентрируюсь на простой 8-битной волне.

Насколько я вижу, есть два конкурирующих способа сделать это, оба, которые предлагают очень немного отличающиеся результаты, и тонкостьдовольно сложный.


Метод 1: вывод = (байт) (ввод * 128.0 + 128) .В этом случае значение 1 не может быть входным, в противном случае недопустимое значение 256 будет выходным.Результаты усекаются до размера байта.Результаты демонстрации:

  • -1 --------> 0
  • -0,5 ------> 64
  • 0 ---------> 128
  • 0,5 -------> 192
  • 1- (1/128) -> 255
  • 0,9999999 ->255 (равно 255,999872 усеченным, допустимым)
  • 1 ---------> 256 (недопустимым)

Метод 2: вывод = (байт) Вокруг(ввод * 127,5 + 127,5) .В этом случае значение 1 IS может быть входным с выходным значением 255.В отличие от ранее, результаты округлены.Результаты демонстрации:

  • -1 --------> 0
  • -0,5 ------> 64 (равно 63,75 округлено)
  • 0 ---------> 128 (округляется до 127,5)
  • 0,5 -------> 191 (округляется до 191,25)
  • 1- (1 /128) -> 254 (равно 254,00390625 округлено)
  • 0,999999 -> 255 (равно 254,9998725 округлено)
  • 1 ---------> 255 (законно)

Кажется, что оба они имеют свои недостатки и преимущества.

При первом методе не требуется округления, выходные данные чистые, а результаты согласованы вплоть до конечной позиции.К сожалению, 1 - недопустимый вход, и поэтому (например) синусоидальные входы могут быть проблемой.Либо пользователь должен убедиться, что ввод никогда не равен единице, либо, что желательно, функция просто убедится, что все, что выше позиции 255, обрезано до 255.

При втором методе +1 - разрешенный вход, поэтому не стоит беспокоиться о выдаче недопустимых выходных данных 256. К сожалению, результаты кажутся немного безобразными при простых входных данных.Они должны быть округлены, и скачок, скажем, с 64 до 128 не является таким же скачком, как с 128 до 191 (что составляет разницу 63 вместо 64).И это несмотря на то, что входные данные имеют равные различия (от -0,5 до 0 и от 0 до 0,5 соответственно).

Я также заметил, что при первом методе диапазон для первой и конечной позиции удваивается, поскольку с 255 до255,999 обрезают до 255, а от 0 до 0,999 обрезают до нуля.Во втором методе только от 0 до 0,499 усекаются до нуля, и только от 254,5 до 255 усекаются до 255. Все остальные числа допускают выбор размера 1,0 (например, от 42,5 до 43,499 с округлением до 43), поэтомуСорта имеет смысл, что первая и последняя позиция байта также должна позволять «полный» диапазон размера 1.0 для себя.С другой стороны, если 255 - это фактическое число 255 в числовой строке, то можно также привести аргумент, что для этого байта выделена только половина диапазона.

Так что я просто ищу ещепонимание и свойства обеих систем.Какой правильный способ сделать это?

Ответы [ 2 ]

0 голосов
/ 18 марта 2019

Метод 1 - начало математически правильного способа квантования.Вам просто нужно добавить обработку для максимального значения в качестве особого случая (второе предложение в ответ Алексея о насыщении продукта).Как вы заметили, этот метод обеспечивает «сегменты» одинакового размера, включая первый и последний.

Общее решение состоит из двух шагов: нормализация входных значений с последующим масштабированием.

Нормализация ваших входных значений от -1 до 1 просто:

j = (input + 1) / 2

, которая переводит их в диапазон 0-1.значение, где N - количество сегментов кватизации:

output = Floor (N * j)

Floor () эквивалентно усечению.Вы можете доказать себе, что это «правильный» способ, представив простой случай N = 2. Реальные значения от 0 до, но не включая 1, справедливо попадают в 2 сегмента.В случае 8-битного квантования у нас N = 256, и поэтому:

Если вход <1, выход = Пол (128 * (вход + 1)) </strong>

или, ваша формула из метода 1.

Обработка особого случая, когда j = 1, нам нужно установить выходное значение равным N - 1. Это может показаться искусственным, и это так.Но это не вызовет никаких искажений;это просто произвольное присвоение в особом случае значения точки на строке действительных чисел.

Если input = 1, output = 255

Сказав всечто разница в результатах методов 1 и 2, обусловленная небольшой разницей в присвоении реальных значений 256 уровням, будет незаметной.Как отметил Алексей, большая часть информации все равно теряется при квантовании до 8-битных значений.

0 голосов
/ 06 февраля 2019

Либо умножьте на 127 (и добавьте 128), либо умножьте на 128, но насытите продукт до диапазона [-128, +127] (IOW, особенно обрабатывайте +1.0).

Если нетЛюбая конкретная необходимая обработка значений мин / макс, не стоит слишком беспокоиться о них.Ваш сигнал должен редко достигать этих значений.И когда это произойдет, ошибка около 1/128 на одном из концов не будет значительным.Вы теряете довольно много информации / качества, сокращая до 8 бит уже во всем диапазоне, а не только на одном из его концов.

Кстати, есть и нелинейные схемы.См., Например, алгоритм µ-закона , который, между прочим, делает что-то похожее при больших величинах, они кодируются более грубо, чем маленькие, и это нормально на практике (то есть для речи).

...