Вопрос

Я должен уменьшить глубину бита цифрового аудиосигнала от 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() который я собираюсь упускать из виду на ясность.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top