Уменьшение глубины образца, усеченным
-
26-09-2019 - |
Вопрос
Я должен уменьшить глубину бита цифрового аудиосигнала от 24 до 16 бит.
Принимая только 16 наиболее значимых битов (т.е. усечение) каждого образца эквивалентно выполнению пропорционального расчета (OUT = в * 0xFFFF / 0xFFFFFF)?
Решение
Я предполагаю, что вы имеете в виду (in * 0xFFFF) / 0xFFFFFF
, в этом случае, да.
Другие советы
Вы получите лучшие результаты для звучания, добавив тщательно продуманный сигнал шума к исходному сигналу, чуть ниже усеченного порога, перед усечением (сальник).
Циркулировать Добавление шума вообще даст вам лучшие результаты. Ключ к этому - это форма шума. Побула пауэн Образбивающие алгоритмы имеют особую форму, которая очень популярна во многих приложениях цифровых аудио рабочих станций (сонар Cakewalk, логика и т. Д.).
Если вам не нужна полная на верность POW-R, вы можете просто генерировать некоторые шум на довольно низкой амплитуде и смешиваю его в ваш сигнал. Вы найдете эту маску на некоторые эффекты квантования.
x * 0xffff / 0xffffff
слишком педантично, но не в хорошем смысле, если ваши образцы подписаны - и, вероятно, не в целом не в целом.
Да, вы хотите максимальное значение в вашем исходном диапазоне, чтобы соответствовать максимальному значению в диапазоне назначения, но значения, используемые в безгнинность, и распределение шагов квантований означает, что это будет очень редко, что вы используете Наибольшее возможное выходное значение.
Если образцы подписаны, то пиковые положительные значения будут 0x7FFF и 0x7fffff, в то время как пиковые отрицательные значения будут --0x8000 и -0x800000. Ваша первая проблема выбирает, равно ли +1 равно 0x7FFF, или -1 равен -0x8000. Если вы выберете последнюю, то это простое сдвига. Если вы попытаетесь иметь обои, тогда ноль останавливается расти нулю.
После этого у вас возникнут проблема, что подразделение раундов к нулю. Это означает, что слишком много значений округляются до нуля по сравнению с другими значениями. Это вызывает искажение.
Если вы хотите масштабировать в соответствии с пиковыми положительными значениями, правильная форма будет:
out = rint((float)in * 0x7fff / 0x7fffff);
Если вы немного рыбуете, вы, вероятно, можете найти эффективный способ сделать это с целочисленными арифметическими и без подразделения.
Эта форма должна правильно раунд до ближайшего доступного выходного значения для любого данного ввода, и оно должно сопоставить наибольшее возможное входное значение для наибольшего возможного выходного значения, но он будет иметь уродливое распределение скоростей количественных элементов, разбросанных по всему диапазону.
Большинство людей предпочитают:
out = (in + 128) >> 8;
if (out > 0x7fff) out = 0x7fff;
Эта форма делает вещи самым крошечным битом, до такой степени, что положительные значения могут немного закрепить, но шаги квантования распределяются равномерно.
Вы добавляете 128, потому что правые раунды к отрицательной бесконечности. То средний Ошибка количественной оценки --128, и вы добавляете 128, чтобы исправить это, чтобы сохранить 0 в точно так, что тест на переполнение необходимо, потому что входное значение 0x7FFFFF в противном случае в противном случае даст результат 0x8000, а при хранении этого в 16-битном слове Это обернутся вокруг, давая пиковое отрицательное значение.
C Педанты могут ткать дыры в предположениях о поведении правого сдвига и разделения, но я упускаю их для ясности.
Однако, поскольку другие указали, вы, как правило, не должны уменьшить битовую глубину звука без однопрочего, а в идеале шумопользования. TPDF Dithy следующим образом:
out = (in + (rand() & 255) - (rand() & 255)) >> 8;
if (out < -0x8000) out = -0x8000;
if (out > 0x7fff) out = 0x7fff;
Снова, большие проблемы с использованием rand()
который я собираюсь упускать из виду на ясность.