Блоки даних

При роботі з файлом VOC читання і обробка блоків даних ведеться в порядку їх появи в файлі Є ряд випадків, в яких різні блоки можуть визначати одні й ті ж дані перше визначення завжди перекриває наступні Формат блоку показаний в табл 162

Таблиця 162 Формат блоку даних Vос

Довжина Опис

1 Тип блоку

3 біт даних: л

n Дані

Лістинг 162 Члени класу VocRead (продовження)

private:

void GetBlock(void)

int _blockType / / Тип поточного блоку

Лістинг 163 Реалізація класу VocRead (продовження)

void VocRead::GetBlock(void) {

long blockLength = 0

_blockType = ReadIntLsb(_stream,1) if(_streameof()) _blockType = 0 if (_blockType = 0)

blockLength = ReadIntLsb(_stream,3)

switch(_blockType) {

}

}

Найбільш важливі типи блоків це блок ознаки закінчення (тип 0), блоки розширення (типи 8 і 9) і блок звукових даних (тип 1)

Блок ознаки закінчення (тип 0)

Блок ознаки закінчення файлу це єдиний блок, формат якого відрізняється від формату блоку, показаного в табл 162 Він складається з єдиного нульового байта без асоційованого поля довжини Цей блок відзначає кінець файлу формату VOC

Лістинг 164 Обробка різних типів блоків формату VOC

case 0: / / Кінець даних break

Блок звукових даних (тип 1)

Блок звукових даних (тип 1) починається з двох байт, що визначають частоту дискретизації і компресії Далі йдуть власне звукові дані Код частоти дискретизації вважається за значенням частоти дискретизації наступним чином: 256 (1000000/частота дискретизації) І навпаки, якщо у вас є код, частота дискретизації дорівнює 1000000 / (256 код) Коди компресії показані в табл 163 Врахуйте, що файл VOC може містити тільки один блок звукових даних додаткові можуть бути збережені в блоці їх продовження

Таблиця 163 Коди компресії

Код Опис

0 Беззнакові 8-бітові дані ІКМ

1 Стислі, 4 біта на відлік

2 Стислі, 2,6 біта на відлік

3 Стислі, 2 біта на відлік

4 Знакові 16-бітові дані ІКМ

6 Α-функція відповідно до стандарту CCITT

7 Мю-функція відповідно до стандарту CCITT

512 16-бітний формат Creative Labs в 4-бітної АДІКМ

Зверніть увагу, що коди зі значенням більше 3 призначені для ис-

користування тільки в блоках розширення типу 9

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

Лістинг 162 Члени класу VocRead (продовження)

private:

unsigned long bytesRemaining / / Залишок байтів в цьому

/ / Блоці

void ReadBlock1(long blockLength)

Щоб не допустити надмірного збільшення розмірів методу GetBlock (деякі компілятори відмовляються працювати із занадто великими функціями), виділимо обробку в окремий метод ReadBlock1

Лістинг 164 Обробка різних типів блоків формату VOC (продовження)

case 1: / / Блок звукових даних

ReadBlock1(blockLength)

break

Формат VOC був удосконалений шляхом додавання нових типів блоків, визначальними звуковий формат різними способами Ці блоки (типу 8 і 9) завжди передують блоку звукових даних, тому необхідно врахувати, що не можна перевизначати жоден параметр, який вже міг бути встановлений в блоці, обробленому раніше

Лістинг 163 Реалізація класу VocRead (продовження)

void VocRead::ReadBlock1(long blockLength) {

/ / Читаємо і інтерпретуємо перші два байти ..

int sampleRateCode = ReadIntLsb(_stream,1)

int compressionCode = ReadIntLsb(_stream,1)

if (_fileSampleRate == 1)

_fileSampleRate = 1000000L/(256-sampleRateCode)

if (_fileCompression == 1)

_fileCompression = compressionCode

if (_fileChannels == 1)

_fileChannels = 1

if (_fileWidth == 1)

_fileWidth = 8

if (_decoder == 0) {/ / Ще немає обєкта-декодувальнику

switch(_fileCompression) {

case 0: / / Беззнаковая 8-бітна ІКМ

_decoder = new DecompressPcm8Unsigned(*this)

break

case 4: / / Знакова 16-бітна ІКМ

_decoder = new DecompressPcml6LsbSigned(*this)

break

case 1: / / 8-бітний Creative Labs в 4-бітну АДІКМ

case 2: / / 8-бітний Creative Labs в 2,6-бітну АДІКМ

case 3: / / 8-бітний Creative Labs в 2-бітну АДІКМ

case 6: / / CCITT А-функція

case 7: / / CCITT мю-функція

case 512: / / 16-бітний Creative Labs в 4-бітну АДІКМ

default:

/ / Цей тип компресії VOC-файлів

/ / Не підтримується

cerr &lt&lt &quotI dont support VOC compression type "

cerr &lt&lt _fileCompression &lt&lt &quot.\n"

exit(1)

}

}

bytesRemaining = blockLength 2

}

Блок продовження даних (тип 2)

Файл VOC може мати всього один блок звукових даних типу 1 Проте може виникнути необхідність розбити звукові дані на кілька блоків Це зазвичай відбувається, коли ви хочете вставити блок іншого типу (наприклад, маркер повторення) в середину звукових даних Подальша інформація зберігається в блоці їх продовження типу 2 Він містить тільки дані, що відносяться до звукових отсчетам B ньому не повторюється ніяка інформація про формат з попереднього блоку типу 1

Лістинг 164 Обробка різних типів блоків формату VOC (продовження)

case 2: / / Продовження звукових даних bytesRemaining = blockLength

break

Блок паузи (тип 3)

Для зменшення загального розміру даних проміжки відсутності звучання можуть бути замінені блоками паузи, визначальними період тиші Дані цього блоку містять 2-байтное число, що задає кількість використовуваних відліків тиші, і однобайтовий код частоти дискретизації Теоретично це дозволяє використовувати в паузі частоту дискретизації, відмінну від застосовуваної для звукових даних Ha практиці слід працювати тією ж частотою дискретизації, що і в попередніх звукових даних

Лістинг 164 Обробка різних типів блоків формату Vос (продовження)

case 3: / / Тиша

{

if (blockLength = 3) {

/ / Блок паузи VOC-файлу має довжину ..

cerr &lt&lt &quotVOC Silence Block has length &quot &lt&lt blockLength

/ / Має бути 3

cerr &lt&lt &quot(should be 3)\n"

}

bytesRemaining = ReadIntLsb(_stream,2) + 1 int sampleRateCode = ReadIntLsb(_stream,1) if (_fileSampleRate == 1)

_fileSampleRate = 1000000/(256-sampleRateCode)

bytesRemaining = blockLength 3

break

}

Маркерний блок (тип 4)

Дані маркерного блоку являють собою 2-байтное число Воно може використовуватися мультимедійними додатками для синхронізації подій Наприклад, додаток послідовного перегляду зображень кожен раз, коли зустрічає маркерний блок, змінює картинку на екрані, щоб вона відповідала звуковому супроводу Значення 0 і 65 536 зарезервовані і не повинні використовуватися

Лістинг 164 Обробка різних типів блоків формату Vос (продовження)

case 4: / / Маркерний блок if (blockLength = 2) {

/ / Маркерний блок VOC-файлу має довжину ..

cerr &lt&lt &quotVOC Marker Block has length &quot &lt&lt blockLength

/ / Має бути 2

cerr &lt&lt &quot(should be 2)\n"

}

/ / VOC маркер:

cerr &lt&lt &quotVOC Marker: "

cerr &lt&lt ReadIntLsb(_stream,blockLength)

cerr &lt&lt &quot\n"

bytesRemaining = blockLength 2

break

Текстовий блок (тип 5)

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

Лістинг 164 Обробка різних типів блоків формату VOC (продовження)

case 5: / / Блок ASCII-тексту

{

char *text = new char[blockLength+1]

_streamread(text,blockLength)

text[blockLength] = 0

/ / Коментар:

cerr &lt&lt &quotComment: &quot &lt&lt text &lt&lt &quot\n"

delete [] text bytesRemaining = 0 break

}

Цикли повторення (типи 6 і 7)

Блоки типів 6 і 7 використовуються для організації циклів всередині файлу формату VOC Блок типу 6 розміщується на початку області, яку необхідно повторити, а блок типу 7 позначає її кінець Дані маркера початку містять 2-байтное число, що показує, скільки разів область буде повторена (нульове значення вказує, що дані слід програти один раз) Завершальний блок даних не містить

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

Лістинг 162 Члени класу VocRead (продовження)

private:

int repeatDepth / / Кількість вкладених циклів

#define maxRepeat 5

int repeatCounts[maxRepeat]

streampos repeatPosition[maxRepeat]

Лістинг 165 Ініціалізація даних формату VOC

repeatDepth = 1

Лістинг 164 Обробка різних типів блоків формату VOC (продовження)

case 6: / / Цикл повторення

{

if (blockLength = 2) {

/ / Блок циклу повторення в VOC файлі має довжину .. cerr << "VOC Repeat Loop Block has length" << blockLength;

/ / Має бути 2

cerr &lt&lt &quot(should be 2)\n"

}

/ / Початок блоку повторення

cerr &lt&lt &quotStart of VOC Repeat Block\n" int repeatCount = ReadIntLsb(_stream,2) repeatDepth++

if (repeatDepth &gt maxRepeat) {

/ / Занадто багато вкладених повторень

cerr &lt&lt &quotToo many nested repeats\n"

exit(1)

}

repeatCounts[repeatDepth] = repeatCount repeatPosition[repeatDepth] = _streamtellg() bytesRemaining = blockLength 2

break

}

case 7: / / Кінець повторення

{

bytesRemaining = blockLength

if (blockLength = 0) {

/ / Блок кінця повторення в VOC файлі має довжину ..

cerr &lt&lt &quotVOC `End Repeat block has length &quot &lt&lt

blockLength

/ / Має бути 0 Cerr << "(Should be 0) \ n";

}

if (repeatDepth &lt 0) {

/ / Невірно вказано блок кінця повторення

cerr &lt&lt &quotImproper VOC `End Repeat block\n"

break

}

/ / Ha Маках значення repeatCounts [repeatDepth]

/ / Завжди виводиться як 1 або 0

/ / Це що, помилка в бібліотеці C + +

/ / Кінець блоку повторень у VOC-файлі

cerr &lt&lt &quotEnd of VOC Repeat Block("

cerr &lt&lt repeatCounts[repeatDepth] &lt&lt &quot)\n"

if (repeatCounts[repeatDepth] &lt= 0) { // End of repeat

repeatDepth–

} Else {/ / Позиція для наступної ітерації

_streamseekg(repeatPosition[repeatDepth])

repeatCounts[repeatDepth]–

}

break

}

Блок розширення (тип 8)

Блок розширення типу 8 не зустрічається в ранніх версіях формату VOC Він був доданий для підтримки файлів зі стереозвуком Якщо цей блок присутній, він завжди розташовується перед блоком звукових даних (типу 1) і перевизначає інформацію про частоту дискретизації і компресії в блоці звукових даних

Дані блоку розширення, структура якого наведена в табл 164, біль-

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

Код частоти дискретизації для стереозвуку обробляється досить НЕ-

зазвичай 2-байтний код, як правило, обчислюється таким чином: 65536 –

256 (1000000/частота дискретизації) Для стереозвуку, проте, частоту дискретизації необхідно подвоїти Як наслідок, програми, які не розуміють цього нововведення, будуть програвати перемежовуються відліки на частоті, найбільш точно відповідної звуковому сигналу B цілях повної зворотної сумісності код частоти дискретизації в блоці звукових даних типу 1 повинен завжди встановлюватися значенням старшого байта коду частоти дискретизації

Лістинг 162 Члени класу VocRead (продовження)

private:

void ReadBlock8(long blockLength)

Для оберігання GetBlock від надмірного розростання я знову виділив

обробку блоків типу 8 в окрему функцію

Лістинг 164 Обробка різних типів блоків формату VOC (продовження)

case 8: / / Розширення

ReadBlock8(blockLength)

break

Таблиця 164 Дані блоку розширення типу 8

Довжина Опис

2 Код точного значення частоти дискретизації

1 Код компресії

1 Режим (0 для моно, 1 для стерео)

Лістинг 163 Реалізація класу VocRead (продовження)

void VocRead::ReadBlock8(long blockLength) {

if (blockLength = 4) {

/ / Блок розширення 8 типу має довжину ..

cerr &lt&lt &quotVOC Extension Block 8 has length &quot &lt&lt blockLength

/ / Має бути 4

cerr &lt&lt &quot(should be 4)\n"

}

int sampleRateCode = ReadIntLsb(_stream,2)

if (_fileSampleRate == 1)

_fileSampleRate = 256000000L/(65536L-sampleRateCode)

int compressionCode = ReadIntLsb(_stream,1)

if (_fileCompression == 1)

_fileCompression = compressionCode int channels = ReadIntLsb(_stream,1) if (_fileChannels == 1) {

_fileChannels = channels + 1

_fileSampleRate /= _fileChannels

}

if (_fileWidth == 1)

_fileWidth = 8

bytesRemaining = blockLength 4

}

Блок розширення (тип 9)

Подібно блоку розширення типу 8 блок типу 9 був введений з метою додавання нових можливостей B Зокрема, він підтримує додаткові методи компресії і в явному вигляді зберігає інформацію про форматі звуку Даний блок передує блокам типу 1 або 8, а інформація в ньому перевизначає інформацію в зазначених блоках

Блок типу 9, описаний в табл 165, зберігає звукову інформацію спосо-

бом, який значно відрізняється від способів представлення звуку в блоках типу 1 або 8 Наприклад, частота дискретизації зберігається безпосередньо, а не кодується Крім того, вона не коригується за кількістю каналів Поле, що кількість бітів на відлік, може приймати значення від 2 (для стислих даних) до 16 (для 16-бітних даних ІКМ) Останні 4 байта зарезервовані для майбутнього розширення

Таблиця 165 Дані блоку розширення типу 9

Довжина Опис

4 Частота дискретизації

1 Кількість бітів, використовуваних для кожної вибірки

1 Кількість каналів (1 для моно, 2 для стерео)

2 Код компресії

4 Зарезервовано на майбутнє

B цілях забезпечення зворотної сумісності процедура запису, яка створює блоки типу 9, повинна по можливості вставляти за ними блок типу 8 Однак, оскільки блок типу 9 вводить кілька нових кодів компресії (включаючи

16-бітний ІКМ, див табл 163), це буде виходити не завжди

Лістинг 162 Члени класу VocRead (продовження)

private:

void ReadBlock9(long blockLength)

Лістинг 164 Обробка різних типів блоків формату VOC (продовження)

case 9: / / Розширення

ReadBlock9(blockLength)

break

Лістинг 163 Реалізація класу VocRead (продовження)

void VocRead::ReadBlock9(long blockLength) {

if (blockLength = 12) {

/ / Блок розширення типу 9 має довжину ..

cerr &lt&lt &quotVOC Extension Block 9 has length &quot &lt&lt blockLength

/ / Має бути 12

cerr &lt&lt &quot(should be 12)\n"

}

long sampleRate = ReadIntLsb(_stream,4)

if (_fileSampleRate == 1)

_fileSampleRate = sampleRate

int bitsPerSample = ReadIntLsb(_stream,1)

if (_fileWidth == 1)

_fileWidth = bitsPerSample

int channels = ReadIntLsb(_stream,1)

if (_fileChannels == 1)

_fileChannels = channels

int compressionCode = ReadIntLsb(_stream,2)

if (_fileCompression == 1)

_fileCompression = compressionCode SkipBytes(_stream,blockLength 8)

}

Інші блоки

B даний час визначені тільки блоки з типами від 0 до 9 Будь Нерасп-

Знань тип блоку слід ігнорувати

Лістинг 164 Обробка різних типів блоків формату VOC (продовження)

default: / / Пропускаємо блоки всіх інших типів

/ / Пропускаємо VOC-блок нерозпізнаного типу

cerr &lt&lt &quotIgnoring unrecognized VOC block type &quot &lt&lt _blockType

&lt&lt &quot\n" SkipBytes(_stream,blockLength) break

Джерело: Кінтцель Т Керівництво програміста по роботі зі звуком = 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>

*

*