Born Dead
#0G
31 марта 2000 |
|
Coding своими руками - Алгоритм сжатия звука ADPCM.
════════════════════════════════════════════════════════════════ ЇЄ╒▐╟░░╟▐╒ЄєЇCODING СВОИМИ РУКАМИ ЇєЄ╒▐╟░░╟▐╒ЄєЇ ════════════════════════════════════════════════════════════════ (c) MoNz7eR^Sa9e Итак, ADPCM: сжатие с потерями, но если сжимать 16bit оригинал (вся фишка в том, что чем качественней оригинал, имею в виду разрядность, тем качественней полученный архив) и использовать 4bit для архива, то это звучит даже на PC очень сильно (чуть хуже MP3), а если 2bit на выборку юзать, то на спеке с MCC методом тоже солидно звучит (я имею в виду выходной сигнал 8-7bit!) Тема такая, за основу взят простейший дельта паковщик, разрядностью 1bit. (рис.1) ^ ,-. o | ; o\ o | ; o \ o | ,'o :: o o-o-o--------(------o----------> | \ o _,o | ~. o_-~o | ~-____-' o | [рис.1] Он стремится догнать изменяющийся сигнал с помощью одинаковых смещений по X. Типа если INсигнал > PACсигнал, то bit = 1, а если INсигнал < PACсигнал, то bit = 0. ADPCM адаптирует смещения с помощью таблицы и с помощью умножения. Не буду описывать общий метод, объясню на примере 2bit'ного сжатия. В сжатом 2bit'ном виде хранится: [ S ] [ k0 ] ... sign - знак коэффициент "+" или "-" умножения При распаковке получаем формулу: X = X + (-1) * S * (TAB(i) * k0 + TAB(i)/2) (при большей разрядности ... + k1*TAB(i)/2 + k2*TAB(i)/4 + TAB(i)/8 и т.д.) Причём если 2bit = 0 или 2, то i = i - 1, если 1 или 3, то i = i + 2. (i - смещение по табличке приращений по X.) В итоге пакуемый сигнал быстро адаптируется под оригинал. (см. рис.2) ^ | o max + - - - - -o- - - - - - - - - - | o,-. | ; \ ° | ° \ | o' :: o o-°----------(---------------o-> | \ o_,- | ~.o o-~ | ~-____-' | o ° + - - - - - - - - - -o- - - - - и т.д. [рис.2] Есть у меня оригинал таблички приращений, выдранный из PC'шного Encoder'а, так, что файлы, спакованные с этой таблой, играются где угодно (если заголовок правильный у файла). Одна проблема на спеке, подобрать амплитуду сигнала так, чтобы быстрый распаковщик (есть исходник, играет по MCC примерно 20кГц с распаковкой из 2bit!!!) после сложений не выпрыгнул за пределы (не перешёл через ноль и не сменил знак), а так метод - просто рульный! В итоге для паковки каждую выборку (а точнее, разницу между выборками из оригинала и из компаратора - из запакованного сигнала) анализируют так: в начале сохраняем первое значение оригинала [pac(0) = in(0)]. Потом: let bit1 = 0 : let bit0 = 0 : let d(n) = in(n) - pac(n) if d(n) < 0 then bit1 = 1 : let d(n) = ABS d(n) if d(n) > tabl(i) then bit0 = 1 : let i = i + 2 else i = i - 1 (для многобитного сжатия вместо -1 и +2 используем таблицу с кучей значений) if i < 0 then i = 0 pac(n+1) = pac(n) + (-1)*bit1 + bit0*tabl(i) + tabl(i)/2 и всё... весь принцип, конечно, без tabl(i) это не сработает, кстати для эксперимента можете сгенерить её сами, начинается она с числа 7, далее Xn+1 = Xn * 1,1 (получается примерно похоже). Почему сразу с такого большого числа? Потому что сжимать надо как минимум 16it сигнал, или пересэмплированный 8bit'ный сигнал с отфильтрованной частотой среза (1/2 частоты дискретизации). А для распаковки имеем: OUT(0) = сохр. первая выборка сигнала OUT(n+1) = OUT(n) + (-1)*bit1 + bit0*tabl(i) + tabl(i)/2 if bit0 = 1 then i = i + 2 else i = i - 1 (i>=0!!!) Вроде, совсем всё... Кстати, ADPCM расшифровывается как Adaptive Differencial Pulse Code Modulation!
Другие статьи номера:
Похожие статьи:
В этот день... 21 ноября