Обробка потоку байтів

Щоб спростити виділення бітів з потоку даних, я використовую один байтовий буфер, який зміщується вперед B результаті постійно працюю з суцільним блоком памяті Мінлива _bufferStorage це блок памяті, в якому зберігаються дані Допоміжні методи будуть змінювати значення змінної

_buffer так, щоб вона вказувала вперед, за кордон останніх використаних даних Мінлива _header вказує на розташування наступного заголовка кадру

Для простоти роботи з даними як Layer 1, так і Layer 2, потрібно, щоб стислі одиниці інформації йшли слідом за заголовком кадру По суті, ми можемо працювати з пакетами стислих даних Однак у форматі Layer 3 зроблено ще одне поліпшення Оскільки частина аудіоданих може стискуватися легше, ніж інші, в рівні 3 дозволяється розміщувати стислі дані за кордонами фрейма

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

Лістинг 144 Змінні для зберігання надходять байтів MPEG

void FillBuffer () / / Підтримка буферів даних

/ / У заповненому стані

void ResetBits () / / Перезапуск процесу вилучення бітів

long GetBits (int numBits) / / Витяг бітів

AudioByte _bufferStorage[2048]

AudioByte * _buffer / / Початок області активних

/ / Даних в буфері

int _bitsRemaining / / Залишилося бітів в старшому байті

AudioByte * _bufferEnd / / Кінець області активних даних

/ / В буфері

AudioByte * _header / / Положення заголовка в буфері

Лістинг 145 Ініціалізація змінних буфера MPEG

_buffer = _bufferStorage + sizeof(_bufferStorage)

_header = _bufferEnd = _buffer

_headerSpacing = 0 / / He заданий

Лістинг 146 Управління буфером MPEG

/ / Переміщаємо дані до початку буфера і заповнюємо

/ / Інше простір

void DecompressMpeg::FillBuffer() {

/ / Вихід за кінець буфера!

if (_header &gt _bufferStorage+sizeof(_bufferStorage)) {

/ / Внутрішня помилка: буфер вичерпаний

cerr &lt&lt &quotInternal error buffer exhausted\n"

_buffer = _header

}

if (_buffer> _header) {/ / Пропустили черговий заголовок!

/ / Помилка синхронізації: фрейм занадто великий

cerr &lt&lt &quotSynchronization error frame too big\n"

_buffer = _header

}

/ / Блокуємо часті виклики ReadBytes () для отримання

/ / Маленьких порцій даних

if (_buffer &lt (_bufferStorage+512)) return int totalBufferSize = sizeof(_bufferStorage) int bufferSize = _bufferEnd _buffer memmove(_bufferStorage,_buffer, bufferSize)

_header = _buffer _bufferStorage

_bufferEnd = _buffer _bufferStorage

_buffer = _bufferStorage

_bufferEnd += ReadBytes(_bufferEnd, totalBufferSize bufferSize)

}

Розглянутий вище метод FillBuffer гарантує, що у нас завжди буде оброблятися безперервний блок даних Ha наступному етапі потрібно зібрати механізм, за допомогою якого можна буде витягувати з потоку змінне число бітів Ключовим моментом такої ситуації є змінна _bitsRemaining, контролююча кількість невикористаних бітів в першому байті буфера

Лістинг 146 Управління буфером MPEG (продовження)

void DecompressMpeg::ResetBits() {

_bitsRemaining = 8

}

int masks[] = {0,1,3,7,0xF,0x1F,0x3F,0x7F,0xFF}

long DecompressMpeg::GetBits(int numBits) {

if (_bitsRemaining == 0) {/ / Якщо в цьому байті всі біти

/ / Оброблені ..

_buffer + + / / .. Переходимо до наступного

_bitsRemaining = 8

}

if (_bitsRemaining> = numBits) {/ / Можна використовувати дані

/ / З цього байта

/ / Для заповнення

_bitsRemaining = numBits

return (*_buffer&gt&gt_bitsRemaining)&ampmasks[numBits]

}

/ / Витратимо решту цього байта, а потім

/ / Повертаємося, щоб зчитувати дані далі

long result = (*_buffer &amp masks[_bitsRemaining])

&lt&lt (numBits _bitsRemaining)

numBits = _bitsRemaining / / B даний момент нам стільки

/ / Бітів не потрібно

_bitsRemaining = 8 / / Переходимо на наступний біт

_buffer++

return result | GetBits(numBits)

}

Джерело: Кінтцель Т Керівництво програміста по роботі зі звуком = A Programmers Guide to Sound: Пер з англ М: ДМК Пресс, 2000 432 с, іл (Серія «Для програмістів»)

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*