Для передачи звука по CAN нам необходимо уместить его в полосу 1 МБит/с. Но двухканальный 16-битный звук с частотой дискретизации 44.1 кГц требует 1.41 МБит/с. Плохое решение проблемы — передавать один канал, либо уменьшить дискретизацию, либо уменьшить разрядность. Хорошее решение — написать кодек, который без потерь качества сможет устранить избыточную информацию.

Устранение избыточности

Где в звуке содержится лишняя информация? Звук — это не последовательность случайных сигналов, это довольно гладкая функция. Значит, мы можем вместо  значения нового отсчёта записывать разницу с предыдущим отчётом. Тогда весь звуковой поток превратится в «значение первого отсчёта + массив разностей».

Тут мы не придумали ничего нового, это давно известно в виде «ДИКМ/DPCM«. Однако сейчас у нас нет никакого выигрыша, мы же храним разности в прежнем виде.

Хранение остатков

Теперь нужно рассмотреть, какова амплитуда этих разностей. По моим измерениям, на обычных звуковых файлах она не превышает 10% от амплитуды звука. Значит, мы можем сэкономить минимум три бита на хранении этих амплитуд (поскольку 2^3 = 8, а у нас разница даже больше — 10). Более того, можно обрабатывать кусочек звука (чанк) заранее, и динамически настраивать степень экономии битов. Важно, что мы ничего не потеряли в звуке — просто устранили избыточную информацию.

Сжатие остатков

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

После всех манипуляций битрейт звука уменьшился на 30%, и составил 0,99 МБит/с. Этого достаточно для передачи по CAN, а самое главное что алгоритмы довольно легки, и их (особенно декодирование) можно реализовать даже на слабых микроконтроллерах.

Методы улучшения кодека

  1. Нужно воспользоваться корреляцией между каналами, и хранить не отдельно правый и левый каналы, а их полусумму и полуразность.
  2. Можно ещё сильнее воспользоваться гладкостью функций, и описать отчёты квадратичной или кубической функцией. Такое описание будет гораздо лучше себя вести на пиках звукового давления, т.е. на максимумах волн. Обычному ДИКМ придётся сильно увеличивать значение разности в этих моментах. Вполне возможно, что это даст ещё 1-2 бита экономии.
  3. Для кодирования остатков лучше воспользоваться каким-либо специализированным кодером, например использовать коды Райса.