Микширование цифрового звука

Если вы располагаете более чем 1 цифровым аудио буфером, и вы хотите, чтобы они воспроизводились одновременно, то как вам микшировать их содержание?

В реальной жизни, когда вы слышите звук одновременно от двух источников, то что вы слышите это сумма сигналов. В этом и заключается наша проблема. Если вы слышите пение группы из 10 человек, то результат будет громче, чем пение 1 человека. Гигантский хор в тысячу человек будет еще громче. 100 тысяч человек, исполняющих гимн на стадионе могут быть просто оглушительными. Момент: не существует верхнего предела, и чем больше голосов вы смешиваете, тем выше амплитуда.

С цифровым аудио, у нас есть ограниченный динамический диапазон. Скажем, мы используем 8-битный сэмплинг, а это значит, что каждая точка данных в аудио-потоке находится между 0 и 255. Когда мы добавляем два таких значения, результат может находиться где-то между 0 и 510, значениями, которые просто не укладываются в допустимый диапазон 0-255.

Так почему бы нам просто не нормализовать результат, разделив его на два? Звучит достаточно просто, но это не обязательно приводит к желаемому результату. Когда мы делим, мы теряем информацию; отдача сигнала, вместо того чтобы разрешить полный 8-битный динамический диапазон 0-255, будет снижена до диапазона 0-127. Это верно, даже если другой сигнал на мгновение замолчал. В самом деле, когда мы включаем такой тип микширования, даже если нет сигнала на одном из входов, другой сигнал будет заметно тише на выходе. Если у нас есть более чем два сигнала, этот эффект становится более выраженным. Деление амплитуды на 2 уменьшает динамический диапазон сигнала примерно на 6 дБ; деление ее на 8 сокращает диапазон на целых 18 дБ, что очень много, если вы предполагаете динамический диапазон 8-битного сигнала не слишком большим, лишь около 48 дБ (т. е. меньше, чем у дешевых магнитофонов.) Очевидно, здесь необходим какой-то более сложный подход.

Этот более сложный способ можно описать следующим образом:

Скажем у нас есть два сигнала, А и В. Если А тихо, мы хотим услышать В на выходе в неизменном виде. Если В тихо, мы хотим услышать А на выходе (т.е. А и В относятся симметрично.) Если А и В имеют ненулевые амплитуды, смешанный сигнал должен иметь амплитуду между наибольшей из А и B , и максимально допустимой амплитудой.

Если мы возьмем А и В со значениями значения от 0 до 1, получатся простые уравнения, удовлетворяющие все вышеперечисленные условия:

Z = А+В — A • В

Просто, не правда ли! Кроме того, это может быть легко адаптировано для более чем 2 сигналов. Рассмотрим, что произойдет, если мы смешиваем один сигнал, C, с Z:

T = Z+C — Z • C = A+В+C — A • B — A • C — B • C+A • B • C

В практической реализации значения сигнала находится не между 0 и 1, а в интервале от 0 до некоторого максимального значения целого, например, 255 для 8-битных сигналов.Такое уравнение нуждается в нормализации. Нормализованная версия выглядит следующим образом:

Z = А+В-А?В/256

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

При попытке поставить этот метод смешивания на практике, возникла неожиданная проблема. Клиент-серверное приложение использует специальный формат аудио со значениями представленными величинами со знаком. То есть, по тишина со значением 128, и фактическое значение амплитуды может идти вверх (129-255) или вниз (127-0). Метод микширования, разработанный выше, не применим в данном случае. Например, смешивая два бесшумных сигнала со значением 128, мы получаем результат 192, который не является звуком тишины. Как в этом случае можно смешивать эти типы аудио сигналов?

Давайте снова подходить к проблеме по аналогии с первой:
Если у нас есть два сигнала, А и Б и один из них – А или B имеет срединное значение, (означающее тишину), мы хотим, чтобы другой появился на выходе в неизменном виде. Если А или Б имеет экстремальное значение (минимум или максимум), то мы хотим, чтобы экстремальные значения появились на выходе. Если А и B ниже средней точки, результат должен быть ниже, чем середина А или Б, если оба они выше середины, по аналогии, результат должен быть выше, чем любой из них. Наконец, если А и В находятся по разные стороны от середины, результат должен представлять собой то, что два сигнала до некоторой степени отменяют друг друга.

Эти требования могут быть реализованы с помощью следующих уравнений (опять же при условии, что А и В имеют значения лежащие между 0 и 1):

Z = 2 • A • B в случае, если А<0,5 и B <0,5
Z = 2 (А+B) — 2 • A • B — 1 в противном случае

Нормализация значений от 0 до 255, в форме уравнения выглядит следующим образом:

Z = A • B / 128 или
Z = 2 (А+ B)-А?В/ 128 — 256

Это аудио микширование реализовано под Windows с помощью очень простого COM (Component Object Model) сервиса, который был создал с использованием ActiveX библиотеки шаблонов, или ATL. Преимуществом этого метода является то, что сервер COM может существовать в отдельном исполнении (и, следовательно, более чем 1 клиентское приложение может использовать его для воспроизведения звука в то же самое время), и это также легко и эффективно. Сервер осуществляет старт и остановку автоматически, благодаря магии COM.

Безусловно есть и другие решения этой проблемы: в дополнение к сторонним библиотекам, Windows 2000 имеет встроенную цифровую возможность микширования. Но задачи, чтобы решение работало только под Windows 2000, не стояло, а что касается покупки сторонних производителей, стало понятно, что расходы на приобретение, обучение по использованию продукта, и включения его в заявку (не говоря уже о рисках, связанных с потенциально недостаточной поддержкой и ошибками в программном коде) будет превышать уровень усилий, необходимых для разработки непосредственно функциональности микширования звука. Кроме того, где удовольствие в использовании чужого программного обеспечения?