Главная » Программирование звука » Компрессия ?-Law Реализация методов кодировки мю-типа

0

B  Соединенных  Штатах  наибольшее  распространение  получила  так  называемая  кодировка  мю-muna  (иногда  пишется  u-Law  или  mu-Law).  Чтобы  не  усложнять  записи  формул,  будем  считать,  что  все  моментальные  значения  представляютсобой дробные числа в диапазоне от -1 до +1.

Если  вы  работаете  с  16-битными  отсчетами,  то  вам  необходимо  перед  приме-

нением формул поделить их на 32768.

Пусть  у  нас  есть  выборка  s.  Тогда  соответствующий  ей  отсчет  мю-типа  sm

вычисляется по формуле: sm = sign(s) log(1 + 255|s|) / log(1 + 255).  Эту

формулу проще запомнить, если рассматривать ее только для положительных значений.  В  таком  случае  она  сразу  принимает  вид  log(1+255s) / log(1+255). Используемое здесь число 255 иногда заменяется другими величинами.

Для  преобразования  выборок  мю-типа  обратно  в  линейные  отсчеты  достаточно воспользоваться обратной формулой: s = (256sm 1) / 255. He забудьте, что это  верно  только  для  положительных  чисел:  при  работе  с  отрицательными  величинами  вам  придется  пользоваться  абсолютными  значениями  и  менять  знак у числа, получаемого в результате преобразования.

Рассмотренные  нами  формулы  напрямую  в  программах  не  применяются,  так как  вычисление  логарифма  и  возведение  числа  в  степень  требуют  много  машинного  времени.  Затрат  времени  можно  избежать,  используя  в  программах  заранее просчитанные   таблицы   преобразования.   Однако   изначально   кодирование   мютипа  разрабатывалось  для  аппаратной  реализации,  а  в  таком  случае  справочные таблицы  не  так эффективны.  По  этой причине  в  стандарте  ITU G.711  описывается  особая  аппроксимация,  которая  может  быть  легко  вычислена  аппаратно.  Как видно из рис. 11.1, результаты, получаемые с помощью этой аппроксимации, очень близки  к  данным,  получаемым  с  помощью  формул.  Хотя  различий  достаточно, чтобы не смешивать два эти способа.

Описанный   ниже   класс   DecompressG711MuLaw обеспечивает   выполнение процедур декомпресии, соответствующих стандарту G.711.

Листинг 11.3. Интерфейс для кодировки мю-типа

class DecompressG711MuLaw: public AbstractDecompressor {

public:

DecompressG711MuLaw(AudioAbstract &a);

size_t GetSamples(AudioSample *buffer, size_t length);

};

AudioSample MuLawDecode(AudioByte); AudioByte MuLawEncode(AudioSample);

Чтобы   вы   могли,   при   желании,   поэкспериментировать,   я   сделал   методы

MuLawDecode и MuLawEncode открытыми.

Для   ускорения   обработки   данных   класс   DecompressG711MuLaw применяет метод  MuLawEncode для  инициализации  внутренней  таблицы,  после  чего  полученная  таблица  используется  для  быстрого  декодирования.  Инициализация  таблицы  требуется  только  один  раз,  при  создании  объекта  класса  DecompressG711MuLaw.

Листинг 11.4. Реализация методов кодировки мю-типа

/* Преобразования  мю-типа  */

static bool muLawDecodeTableInitialized = false;

static AudioSample muLawDecodeTable[256];

// Конструктор инициализирует таблицу  декодирования.

DecompressG711MuLaw::DecompressG711MuLaw(AudioAbstract &a)

: AbstractDecompressor(a) {

// Кодировка: мю-типа, стандарт ITU G.711

cerr << “Encoding: ITU G.711 mu-Law\n”;

if (!muLawDecodeTableInitialized) { muLawDecodeTableInitialized = true; for(int i=0;i<256;i++)

muLawDecodeTable[i] = MuLawDecode(i);

}

}

Метод  GetSample несложен.  Мы  просто  считываем  байты  и  с  помощью  таблицы  преобразования  поочередно  декодируем  каждое  из  считанных  значений. Задав обратный порядок преобразования данных в буфере, мы избежим опасности стирания данных, которые еще не были декодированы.

Листинг 11.4. Реализация методов для кодировки мю-типа (продолжение)

size_t DecompressG711MuLaw::GetSamples(AudioSample *buffer, size_t length) {

AudioByte *byteBuff =

reinterpret_cast<AudioByte *>(buffer); size_t read = ReadBytes(byteBuff,length); for(long i=read-1; i>=0; i–)

buffer[i] = muLawDecodeTable[ byteBuff[i] ];

return read;

};

Для  аппроксимации  логарифма  в  стандарте  G.711  используются  простые  битовые  манипуляции.  Производится  начальная  коррекция,  затем  вычисляется  количество  битов,  которые  требуются  для  записи  старшего  байта.  Полученное  значение комбинируется с четырьмя старшими битами.

Листинг 11.4. Реализация методов кодировки мю-типа (продолжение)

AudioByte MuLawEncode(AudioSample s) {

unsigned char sign = (s<0)?0:0x80;   // Записываем  знак.

if (s<0) s=-s;                       // Делаем выборку

// положительной.

signed long adjusted = static_cast<long>(s) << (16sizeof(AudioSample)*8);

adjusted += 128L+4L;

if (adjusted > 32767) adjusted = 32767;

unsigned char exponent = numBits[(adjusted>>7)&0xFF] 1; unsigned char mantissa = (adjusted >> (exponent + 3)) & 0xF; return ~(sign | (exponent << 4) | mantissa);

};

Аналогичным  образом  работает  и декодер.  Старший бит  используется  для  записи  знака,  три  следующих   для  определения,  насколько  надо  сдвинуть  4  младших бита.

Листинг 11.4. Реализация методов кодировки мю-типа (продолжение)

AudioSample MuLawDecode(AudioByte ulaw) {

ulaw = ~ulaw;

unsigned char exponent = (ulaw >> 4) & 0x7;

unsigned char mantissa = (ulaw & 0xF) + 16;

unsigned long adjusted = (mantissa << (exponent + 3))1284;

return (ulaw & 0x80)? adjusted : adjusted;

};

Если  вы  хорошо  разбираетесь  в  форматах  арифметики  с  плавающей  точкой, вы  должны  заметить,  что  предложенный  вариант  записи  очень  сильно  напоминает формат записи 8-битного числа с плавающей точкой: один бит для знака, три для экспоненты и четыре для записи мантиссы. Обратите внимание, что подобно большинству форматов с плавающей точкой старший бит мантиссы отбрасывается,  и  в  методе  MuLawDecode вам  приходится  восстанавливать  его,  добавляя  16 к мантиссе.

При  изучении  данного  алгоритма  вы  должны  обратить  внимание  на  один момент, требующий дополнительного  обсуждения. Заметим, что в методе MuLawENcode производится смещение 16-битного отсчета ИКМ на 128, а затем на 4 перед остальным преобразованием. B методе MuLawDecode эти значения аналогичным образом  вычитаются  после  преобразования.  Если  рассматривать  такие  преобразования как аппроксимацию логарифма, то число 128 используется для обхода разрывности основной функции. Если вы посмотрите на данный алгоритм внимательнее, вы также заметите, что используются вообще только 13 старших бит.

Добавление  четырех  округляет  значение  до  ближайшего,  кратного  восьми,

повышая тем самым точность.

Источник: Кинтцель Т.  Руководство программиста по работе со звуком = A Programmer’s Guide to Sound: Пер. с англ. М.: ДМК Пресс, 2000. 432 с, ил. (Серия «Для программистов»).

По теме:

  • Комментарии