Читання файлів VOC

Оскільки вже розроблено механізм обробки заголовка VOC і окремих блоків, опис решти класу VocRead не представляє труднощів

Лістинг 166 Програма voch

#ifndef VOC_H_INCLUDED

#define VOC_H_INCLUDED

#include &quotaudioh&quot

#include &quotcompressh&quot

#include &ltiostream&gt

bool IsVocFile(istream &ampfile)

class VocRead: public AudioAbstract {

}

#endif

Лістинг 167 Програма voccpp

#include &ltcstring&gt

#include &quotvoch&quot

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

private:

istream &amp_stream

public:

VocRead(istream &ampinput = cin)

~VocRead() {

if (_decoder) delete _decoder

}

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

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

VocRead::VocRead (istream &ampinput):AudioAbstract(),_stream(input)

{

/ / Формат файлу: Creative Labs VOC cerr << "File Format: Creative Labs VOC \ n";

ReadHeader()

do {/ / Шукаємо блок звукових блок або блок ознаки

/ / Закінчення

GetBlock()

} while ((_blockType = 1) &amp&amp (_blockType = 0))

}

Так як визначати параметри звуку можуть кілька типів блоків, важливо памятати, чи були перш встановлені ці значення Нижче представлена ​​ініціалізація основних звукових параметрів забороненим значенням (-1)

Лістинг 165 Ініціалізація даних формату VOC (продовження)

_fileChannels = 1

_fileSampleRate = 1

_fileCompression = 1

_fileWidth = 1

_decoder = 0

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

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

private:

int _fileChannels int _fileSampleRate int _fileWidth

int _fileCompression

AbstractDecompressor *_decoder

protected:

void MinMaxSamplingRate(long *min, long *max, long *preferred)

{

*min = *max = *preferred = _fileSampleRate

}

void MinMaxChannels(int *min, int *max, int *preferred) {

*min = *max = *preferred = _fileChannels

}

size_t GetSamples(AudioSample *buffer, size_t numSamples)

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

дані ІКМ, це не становить проблеми K жаль, фірма Creative Labs не визначила, яке значення це має для стислих аудіоданих (Незрозуміло, чи повинен компресор заново инициализироваться після блоку паузи або використання блоків пауз в стислих даних просто заборонено)

Метод GetSamples перевіряє тип поточного блоку і вирішує, ігноріроватьлі його (блок не містить звукових даних), заповнити буфер нульовими отсчетами (якщо це блок паузи) або запросити дані у декомпресора

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

size_t VocRead::GetSamples(AudioSample *buffer, size_t numSamples) {

size_t samplesReturned = 0

while (numSamples &gt 0) {

switch(_blockType) {

case 0: / / Кінець файлу

return samplesReturned

case 1: / / Закодовані звукові дані

case 2: {

size_t samplesRead = _decoder-

&gtGetSamples(buffer,numSamples) buffer += samplesRead numSamples = samplesRead samplesReturned += samplesRead

if (bytesRemaining == 0) GetBlock()

break

}

case 3: / / Блок паузи

while ((numSamples &gt 0) &amp&amp (bytesRemaining &gt 0)) {

*buffer++ = 0 samplesReturned++ numSamp1es– bytesRemaining–

}

if (bytesRemaining == 0) GetBlock()

break

default: GetBlock() break

}

}

return samplesReturned

}

Обєкт-декодер, що викликається GetSamples, викличе метод ReadBytes для отримання необроблених звукових даних Так як GetSamples гарантує, що ReadBytes викликається тільки при читанні блоків типу 1 або 2, процедура ReadBytes може бути простою

Зауважте, що ця версія ReadBytes здатна повертати кількість байтів менше запитаного, навіть якщо кінець файлу ще не досягнуто Метод GetSamples,

наведений вище, реалізує повторні виклики декодера (можливо, що виражаються в множинних викликах ReadBytes) до тих пір, поки запит не буде оброблено

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

public:

size_t ReadBytes(AudioByte *buffer, size_t length)

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

size_t VocRead::ReadBytes(AudioByte *buffer, size_t length) {

if (length &gt bytesRemaining) length = bytesRemaining

_streamread(reinterpret_cast&ltchar *&gt(buffer), length)

size_t bytesRead = _streamgcount()

if (bytesRead &lt length) {

cerr &lt&lt &quotError: VOC file ended prematurely"

exit(1)

}

bytesRemaining = bytesRead / / Кількість даних, що залишилися

в блоці

return bytesRead

}

Глава 17 Формат файлу WAVE

B силу того що корпорація Microsoft використовувала формат WAVE в операційній системі Windows, він став одним із самих популярних форматів звукових файлів B цілому його структура заснована на форматі Interchange File Format (IFi формат файлу обміну даними), який спочатку був розроблений фірмою Electronic Arts для використання в компютерах Amiga (див главу 19) Наоснове IFF розроблений формат AIFF, застосовуваний фірмою Apple для запису звуку (див главу 18)

Слідом за IFF Microsoft розробила загальний файловий формат, названий Resource Interchanging File Format (RIFF, формат файлів для обміну ресурсами), RIFF-файл організований як набір вкладених блоків Для ідентіфікаціісодержімого RIFF-файлу використовуються дескриптори Широко распространенидве версії цього формату: файли WAVE (або WAV) для зберігання звуку і файли AVI, в яких зберігається відео

Ідентифікація WAVE-файлів

WAVE-файл це окремий випадок файлу у форматі RIFF, а кожен RIFFфайл починається з групи символів RIFF Після цих символів йдуть 4 байта, в яких записана довжина файлу, а за ними код типу Зараз нас цікавлять тільки WAVE-файли

Лістинг 171 Розпізнавання файлів WA VE

bool IsWaveFile (istream & file) {fileseekg (0) / / Шукаємо початок файлу unsigned long form = ReadIntMsb (file, 4) if (form = ChunkName (R, I, F, F))

return false / / He RIFF-файл

SkipBytes (file, 4) / / Пропускаємо розмір блоку

unsigned long type = ReadIntMsb(file,4)

if (type == ChunkName(W,A,V,E))

return true

return false / / Файл формату RIFF, але не WAVE

}

O файлах формату RIFF і IFF

Оскільки WAVE-файл є різновидом RIFF-файла, я начнусоб · судження основних властивостей формату RIFF To, про що я розповім, буде в більшості випадків справедливо і для інших модифікацій IFF, в тому числі AIFF і IFF /

8SVX

Як показано на рис 171, RIFF-файл являє собою набір вкладених блоків B початку кожного блоку коштує 4-символьний код (RIFF, fmt або LIST, короткі коди доповнюються пробілами) Він задає тип блоку Блок з кодом fmt, наприклад, містить інформацію про формат звуку Слідом за кодом типу блоку йдуть 4 байта, в яких міститься інформація про довжину даних, що зберігаються в блоці Зверніть увагу, що весь файл, зображений на рис 171, це один блок RIFF B поле довжини RIFF-блоку вказується величина рівно на 8 байт менше, ніж загальний обсяг файлу, так як тип і розмір блоку не враховуються

Кілька видів блоків, зокрема RIFF і LIST, показані на рис 171, відносяться до контейнернім блокам, до складу яких входять інші Дані в контейнерному блоці починаються з четирехсімвольного коду, що вказує тип містяться даних Наприклад, RIFF-блок на рис 171 має код WAVE, який означає, що тут записано аудіодані Внутрішні імена блоків можуть інтерпретуватися πο-різному залежно від того, в якій контейнер включений даний блок Оскільки блок формату fmt укладений в контейнер RIFF WAVE, ми знаємо, що він описує аудіодані, а будучи поміщений в контейнер іншого типу, міг би містити іншу інформацію

Формат WAVE Огляд

WAVE-файли це RIFF-файли, в яких самий зовнішній блок RIFFконтейнер типу WAVE Більшість WAVE-файлів містять блоки fmt і data (рис 172)

Оскільки дуже багато WAVE-файли володіють однією і тією ж базовою структурою, у багатьох програмах, написаних некваліфікованими програмістами, робиться розрахунок на те, що WAVE-файли мають фіксований заголовок, формат якого представлений в табл 171 Цей підхід відмінно працює при записі WAVE-файлів до тих пір, поки описуються тільки ІКМ-дані і правильно задаються розміри різних полів Програма читання WAVEфайла, однак, повинна бути більш ретельно продумана

Таблиця 171 Формат примітивного WAVE-файлу

Розмір Опис

4 Тип блоку: RIFF

4 Довжина файлу (мінус) 8

4 Тип RIFF-контейнера: WAVE

4 Тип блоку: fmt

4 Довжина області даних блоку формату: зазвичай 16

16 Область даних блоку формату

4 Тип блоку: data

4 Довжина області звукових даних

n Звукові вибірки

WAVE-файли можуть містити й інші блоки B Зокрема, замість одиночного блоку data іноді використовується контейнерний блок LIST, що складається з блоків типу slnt, відповідних періодів відсутності звуку, і data, що містять звукові дані

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

*

*