Формат WAV изначально использовался в системе Windows для сохранения цифровых аудиоданных. Это самый известный и широко поддерживаемый формат благодаря популярности платформы Windows и большому количеству написанных для неё программ. Почти любая современная программа, работающая со звуком, может прочитать или записать формат WAV, поэтому этот формат очень интересен для разработчиков программного обеспечения. Далее подробно описываются структуры данных формата WAV.
[Форматы данных]
Поскольку формат WAV-файла пришел от операционной системы Windows, в которой традиционно использовались процессоры Intel, все значения данных формата хранятся как Little-Endian, т. е. самый младший значащий байт идет первым.
WAV-файлы могут содержать строки текста, например метки секций, информационные комментарии и т. д. Строки сохраняются таким образом, что первый байт указывает количество байт текста ASCII в строке.
7 |
'e' |
'x' |
'a' |
'm' |
'p' |
'l' |
'e' |
Пример формата строки Wave
[Структура файла]
WAV-файл использует стандартную RIFF-структуру, которая группирует содержимое файла из отдельных секций (chunks) - формат выборок аудиоданных, аудиоданные, и т. п. Каждая секция имеет свой отдельный заголовок секции и отдельные данные секции. Заголовок секции указывает на тип секции и количество содержащихся в секции байт. Такой принцип организации позволяет программам анализировать только необходимые секции, пропуская остальные секции, которые не известны или которые не требуют обработки. Некоторые определенные секции могут иметь в своем составе подсекции (sub-chunks). Например, как можно увидеть на диаграмме, описывающий основной формат WAV-файла, секции "fmt " и "data" являются подсекциями секции "RIFF".
Chunk ID "RIFF"
Chunk Data Size
|
RIFF Type ID "WAVE"
|
Chunk ID "fmt "
Chunk Data Size
|
Sample Format Info
|
|
Chunk ID "data"
Chunk Data Size
|
Digital Audio Samples
|
|
|
|
Заголовок секции (Chunk Header)
|
|
Данные секции (Chunk Data Bytes) |
Одна хитрая вещь, связанная с секциями файла RIFF, состоит в том, что адреса начала секций должны быть выровнены на размер слова (2 байта). Это означает, что общий размер секции должен быть кратен 2. Если секция содержит нечетное число байт данных (невыравненное до 2 байт), то добавляется дополнительный нулевой байт данных в конец данных секции. Этот дополнительный байт не учитывается в размере секции заголовка, таким образом программа всегда должна учитывать выравнивание для расчета смещения начала следующей секции.
[Заголовок WAV-файла, секция типа RIFF]
Заголовки WAV-файла используют стандартный формат RIFF. Первые 8 байт файла - стандартный заголовок секции RIFF, который имеет ID секции "RIFF" и размер секции, равный размеру файла минус 8 байт, используемых для RIFF-заголовка. Первые 4 байта данных в секции "RIFF" определяют тип ресурса, который можно найти в секции. WAV-файлы всегда используют тип ресурса "WAVE". После типа ресурса (ID "WAVE") идут все секции звукового файла, которые определяют аудиосигнал.
Смещение |
Размер |
Описание |
Значение |
0x00 |
4 |
Chunk ID |
"RIFF" (0x52494646) |
0x04 |
4 |
Chunk Data Size |
(file size) - 8 |
0x08 |
4 |
RIFF Type |
"WAVE" (0x57415645) |
0x10 |
Wave chunks (секции WAV-файла)
|
Значения полей секции RIFF |
[Секции WAV-файла]
Существует довольно много типов секций, заданных для файлов WAV, но большинство WAV-файлов содержат только две из них - секцию формата ("fmt ") и секцию данных ("data"). Это именно те секции, которые необходимы для описания формата выборок аудиоданных, и для хранения самих аудиоданных. Хотя официальная спецификация не задает жесткий порядок следования секций, наилучшей практикой будет размещение секции формата перед секцией данных. Многие программы ожидают именно такой порядок секций, и он наиболее разумен для передачи аудиоданных через медленные, последовательные источники наподобие Интернет. Иначе если формат придет после данных, то перед стартом воспроизведения необходимо считать и запомнить все аудиоданные, только после получения формата запускать воспроизведение.
Все секции формата RIFF и соответственно секции Wave сохраняются в следующем формате (см. диаграмму). Заметье, что даже вышеупомянутая секция RIFF соответствует этому формату.
Смещение |
Размер |
Описание |
0x00 |
4 |
Chunk ID |
0x04 |
4 |
Chunk Data Size |
0x08 |
Chunk Data Bytes |
Формат секций RIFF и Wave
|
Остальная часть этой статьи посвящена описанию различных типов секций Wave, их формату данных и что эти данные означают.
[Секция формата - "fmt "]
Секция формата содержит информацию от том, как сохранены аудиоданные и как они должны воспроизводиться. Информация включает в себя тип используемой компрессии, количество каналов, скорость выдачи выборок (sample rate), количество бит в выборке (bits per sample) и другие атрибуты.
Смещение |
Размер |
Описание |
Значение |
0x00 |
4 |
Chunk ID |
"fmt " (0x666D7420) |
0x04 |
4 |
Chunk Data Size |
16 + extra format bytes |
0x08 |
2 |
Compression code |
1 - 65,535 |
0x0a |
2 |
Number of channels |
1 - 65,535 |
0x0c |
4 |
Sample rate |
1 - 0xFFFFFFFF |
0x10 |
4 |
Average bytes per second |
1 - 0xFFFFFFFF |
0x14 |
2 |
Block align |
1 - 65,535 |
0x16 |
2 |
Significant bits per sample |
2 - 65,535 |
0x18 |
2 |
Extra format bytes |
0 - 65,535 |
0x1a |
Дополнительные данные формата (Extra format bytes) * |
Значения секции формата (Wave Format Chunk), * читайте для подробностей текст далее
Идентификатор секции (Chunk ID) и объем данных (Data Size)
Идентификатор секции всегда "fmt " (0x666D7420) и объем данных равен размеру стандартного формата WAV (16 байт) плюс размер всех дополнительных байт формата, необходимых для поддержки специфических форматов звука, если он не содержит несжатых данных PCM. Обратите внимание, что идентификатор секции "fmt " оканчивается на символ пробела (0x20).
Код сжатия (Compression Code)
Первое слово данных формата указывает на тип сжатия, используемого для данных звука. В таблице содержится список кодов сжатия, используемых в настоящее время.
Код |
Описание |
0 (0x0000) |
Unknown |
1 (0x0001) |
PCM/uncompressed |
2 (0x0002) |
Microsoft ADPCM |
6 (0x0006) |
ITU G.711 a-law |
7 (0x0007) |
ITU G.711 µ-law |
17 (0x0011) |
IMA ADPCM |
20 (0x0016) |
ITU G.723 ADPCM (Yamaha) |
49 (0x0031) |
GSM 6.10 |
64 (0x0040) |
ITU G.721 ADPCM |
80 (0x0050) |
MPEG |
65,536 (0xFFFF) |
Experimental |
Общеиспользуемые коды сжатия
(Common Wave Compression Codes)
Количество каналов (Number of Channels)
Количество каналов указывает, сколько отдельных аудиосигналов закодировано в секции данных звука (wave data chunk). Значение 1 означает монофонический сигнал, 2 означает стерео, и т. п.
Скорость выборок (Sample Rate)
Число выборок аудиосигнала, приходящихся на секунду. На эту величину не влияет количество каналов.
Среднее количество байт в секунду (Average Bytes Per Second)
Величина, показывающая, сколько байт за секунду данных должно быть пропущено через цифроаналоговый преобразователь (D/A converter, DAC) во время воспроизведения файла. эта информация полезна, чтобы определить - могут ли данные поступать от источника с нужной скоростью, чтобы не отставать от воспроизведения. Эта величина просто вычисляется по формуле:
AvgBytesPerSec = SampleRate * BlockAlign
Выравнивание блока (Block Align)
Количество байт на одну выборку. Эта величина может быть вычислена по формуле:
BlockAlign = SignificantBitsPerSample / 8 * NumChannels
Количество используемых бит на выборку (Significant Bits Per Sample)
Величина указывает количество бит, формирующих каждую выборку сигнала. Обычно эта величина 8, 16, 24 или 32. Если число бит не выравнено по байту (не делится нацело на 8), количество используемых байт на выборку округляется вверх к наименьшему количеству байт. Неиспользуемые биты устанавливаются в 0 и игнорируются. Такие форматы (с числом бит на выборку, некратным 8) встречаются редко.
Дополнительные данные формата (Extra Format Bytes)
Величина указывает, сколько далее идет дополнительных данных, описывающих формат. Она отсутствует, если код сжатия 1 (uncompressed PCM file), но может присутствовать и иметь любую другую величину для других типов сжатия, зависящую от количества необходимых для декодирования данных. Если величина не выравнена на слово (не делится нацело на 2), должен быть добавлен дополнительный байт в конец данных, но величина должна оставаться невыровненной.
[Секция данных - "data"]
Секция данных Wave (Wave Data Chunk) содержит данные цифровых выборок аудиосигнала, которые можно декодировать с использованием формата и метода компрессии, указанных в секции формата Wave (Wave Format Chunk). Если код компрессии 1 (несжатый PCM, Pulse Code Modulation), то данные представлены в виде сырых, непреобразованных (raw) величин выборок. Эта статья описывает, как сохранены несжатые данные PCM, однако не вдается в подробности многих используемых форматов с компрессией.
WAV-файлы обычно содержат только одну секцию данных, но секций может быть несколько, если они содержатся в секции списка Wave (Wave List Chunk "wavl").
Смещение |
Длина
|
Тип |
Описание |
Значение |
0x00 |
4 |
char[4] |
chunk ID |
"data" (0x64617461) |
0x04 |
4 |
dword |
chunk size |
зависит от количества выборок и компрессии |
0x08 |
данные выборок (sample data) |
Формат секции данных "data"
Аудиовыборки многоканального цифрового аудио сохраняются как чередуемые (interlaced) данные, которые просто означают последовательные аудиовыборки нескольких каналов (таких как стерео и каналы окружения surround). Выборки каналов сохранены последовательно друг за другом, перед тем как произойдет переход к следующему времени выборки. Это сделано с целью возможности последовательного проигрывания файла даже тогда, когда еще не весь файл прочитан целиком. Это удобно, когда проигрывается большой файл с диска (который не может быть размещен целиком в памяти) или файл передается в последовательном потоке данных через сетевое соединение (например Интернет). Значения в диаграмме ниже были бы сохранены в WAV-файле в порядке, как они перечислены в столбце значений (от начала до конца).
Время |
Канал |
Значение |
0 |
1 (левый) |
0x0053 |
2 (правый) |
0x0024 |
1 |
1 (левый) |
0x0057 |
2 (правый) |
0x0029 |
2 |
1 (левый) |
0x0063 |
2 (правый) |
0x003C |
Чередуемые выборки стерео Wave
Один момент, касающийся данных выборок, который может вызвать некоторое замешательство - когда выборки представлены 8 битами, они определены как значения без знака (unsigned). Все другие битовые размеры указываются как величины со знаком (signed). Например, выборка 16 бит может иметь значение в диапазоне от -32768 до +32767, где средняя точка (напряжение сигнала равно 0) соответствует значению 0.
Как уже было указано ранее, все секции RIFF (включая секции WAVE "data") должны быть выровнены по размеру на слово (2 байта). Если данные выборок содержатся в нечетном количестве байт, в конец данных выборок должен быть добавлен выравнивающий нулевой байт. За заголовке секции "data" размер не должен учитывать этот выравнивающий байт.
Далее описываются дополнительные секции WAV-файла, которые довольно редко используются. Поэтому для реализации простейшего программного анализа WAV-файла обработку этих секций можно опустить.
[Секция fact - "fact"]
Секция fact содержит информацию о содержимом WAV-файла, зависящую от кода компресии. Она требуется для всех форматов WAVE со сжатием, и требуется, если данные сигнала содержатся внутри секции списка (LIST) "wavl", но не требуется для несжатого формата PCM WAVE (код компресии 1), который содержит аудиоданные в секции "data".
Смещение |
Размер |
Описание |
Величина |
0x00 |
4 |
Chunk ID |
"fact" (0x66616374) |
0x04 |
4 |
Chunk Data Size |
зависит от формата
|
0x08 |
Данные, зависящие от формата (Format Dependant Data) |
Формат секции Fact
Данные, зависящие от формата (Format Dependant Data)
В настоящий момент задано только одно поле для данных, зависящих от формата. Это единственное 4-байтное значение, которое указывает число выборок в секции данных аудиосигнала. Эта величина может использоваться вместе с количеством выборок в секунду (Samples Per Second value) указанном в секции формата - для вычисления продолжительности звучания сигнала в секундах.
По мере появления новых форматов WAVE секция fact будет расширена с добавлением полей после поля числа выборок. Программы могут использовать размер секции fact для определения, какие поля представлены в секции.
[Секция списка Wave - "wavl"]
Секция списка wave (wave list chunk) используется для указания нескольких чередований секций "slnt" и "data". Эти секции могут помочь уменьшить размер файла путем указания слышимых сегментов выборок, когда поток аудиоданных содержит несколько интервалов тишины.
Этот тип секции по мнению многих программистов является злоупотреблением в формате WAV-файла, и его использование не рекомендуется. Также много программ не будут распознавать этот тип секции, просто игнорируя его. Эта форма сжатия усложняет без надобности структуру WAV-файла и может быть выгодно реализована другими способами, включая несколько существующих форматов компресии.
Смещение |
Размер |
Описание |
Значение |
0x00 |
4 |
Chunk ID |
"wavl" (0x736C6E74) |
0x04 |
4 |
Chunk Data Size |
зависит от размера секций "data" и "slnt" |
0x08 |
Список чередования секций "slnt" и "data" |
Формат секции Wave List
[Секция тишины - "slnt"]
Секция тишины (silent chunk) используется для указания сегмента паузы звучания, которая имеет некоторую продолжительность в выборках сигнала. Секция тишины всегда содержится только внутри секции списка wave (wave list chunk). Когда эта секция объявляет тишину, не нужно задавать нулевую громкость или базовую выборку. Это фактически удерживается последняя выборка сигнала, считанная в предыдущей секции данных ((Wave Data Chunk)) секции списка Wave (wave list chunk). Если не было предыдущих секций данных, должно использоваться базовое значение выборки, равное 127 для 8-битных данных, 0 для 16-битных данных или всех данных с бОльшим количеством бит на выборку. Эти требования могут казаться тривиальными, но если это не выполнить, то могут появится нежелательные щелчки и перепады в аудиосигнале.
Смещение |
Размер |
Описание |
Величина |
0x00 |
4 |
Chunk ID |
"slnt" (0x736C6E74) |
0x04 |
4 |
Chunk Data Size |
4 |
0x08 |
4 |
Number of Silent Samples |
0 - 0xFFFFFFFF |
Silent Chunk Format
Количество выборок тишины (Number of Silent Samples)
Эта величина указывает число выборок тишины, которое должно появиться в аудиосигнале на точке списка wave (wave list chunk).
[Секция cue - "cue "]
Секция cue определяет один или более смещения выборок, которые часто используются, чтобы отметить примечательные разделы аудио. Например, у начала и конца стиха в песне могут быть метки, по которым легче найти начало и конец стиха. Секция cue является необязательной, и если она добавлена, то одна секция cue должна указать все примечательные точки для секции "WAVE". Не допускается больше одной секции cue внутри секции "WAVE".
Смещение |
Размер |
Описание |
Значение |
0x00 |
4 |
Chunk ID |
"cue " (0x63756520) |
0x04 |
4 |
Chunk Data Size |
depends on Num Cue Points |
0x08 |
4 |
Num Cue Points |
количество точек cue в списке
|
0x0c |
Список интересующих точек (List of Cue Points) |
Формат секции Cue
Индентификатор ID секции и объем данных (Chunk ID and Data Size)
Индентификатор ID секции для секции cue всегда "cue " (0x666D7420). Обратите внимание, что строка ID оканчивается на символ пробела (0x20). Размер данных секции равен размеру Num Cue Points (4) плюс количество последующих точек cue, помноженное на размер данных каждой точки cue (24). Следующая формула может использоваться для вычисления размера данных секции Cue:
ChunkDataSize = 4 + (NumCuePoints * 24)
Количество примечательных точек (Num Cue Points)
Эта величина указывает количество последующих cue-точек в этой секции.
Список примечательных точек (List of Cue Points)
Список точек cue - просто набор описаний последовательных точек, который имеет следующий формат.
Смещение |
Размер |
Описание |
Значение |
0x00 |
4 |
ID |
unique identification value |
0x04 |
4 |
Position |
play order position |
0x08 |
4 |
Data Chunk ID |
RIFF ID of corresponding data chunk |
0x0c |
4 |
Chunk Start |
Byte Offset of Data Chunk * |
0x10 |
4 |
Block Start |
Byte Offset to sample of First Channel |
0x14 |
4 |
Sample Offset |
Byte Offset to sample byte of First Channel |
Формат точки Cue
ID
Каждая примечательная (cue) точка имеет уникальное идентификационное значение, используемое для связи точек cue с информацией в других секциях. Например, секция метки (Label chunk) содержит текст, который описывает точку в WAV-файле со ссылкой на связанную точку cue.
Позиция (Position)
Позиция определяет смещение выборки, связанное точкой cue, с точки зрения позиции выборки в заключительном потоке выборок, сгенерированных списком воспроизведения. Другими словами, если указана секция списка воспроизведения (play list chunk), значение позиции равно номеру выборки, на которой эта точка cue встретится при воспроизведении всего списка (play list) в заданном порядке. Если нет секции списка воспроизведения (play list chunk), то значение позиции должно быть равно 0.
ID секции данных (Data Chunk ID)
Эта величина указывает ID из 4 байт, используемый секцией, содержащей выборку, которая соответствует этой точке cue. WAV-файл без списка воспроизведения (play list chunk) всегда имеет "data". WAV-файл, имеющий список воспроизведения (play list chunk) с секциями данных и тишины, может быть либо "data", либо "slnt".
Начало секции (Chunk Start)
Значение начала секции указывает байтовое смещение в секции списка Wave (Wave List Chunk) секции, содержащей выборку, соответствующую этой точке. Это та же самая секция, описанная значением ID секции данных (Data Chunk ID). Если в WAV-файле нет секции списка Wave (Wave List Chunk), эта величина равна 0, иначе эта величина равна смещени. в секцию "wavl". Первая секция в секции списка (Wave List Chunk) должна быть указана со значением 0.
Начало блока (Block Start)
Значение Block Start указывает смещение в байтах в секцию "data" или секцию "slnt" для начала блока, содержащего выборку. Начало блока задает первый байт несжатых данных звука PCM или последний байт в сжатых данных звука, где декомпрессия может начаться для нахождения значения соответствующего значения выборки.
Смещение выборки (Sample Offset)
Смещение выборки указывает смещение в блок (указанный Block Start) для выборки, соответствующей интересующей точке (cue point). В несжатых данных звука PCM это просто байтовое смещение в секцию "data". В сжатых данных звука это значение равно количеству выборок (которое может и не быть в байтах) от Block Start до выборки, соответствующей интересующей точке (cue point).
[Секция списка воспроизведения (плейлиста) - "plst"]
Секция плейлиста указывает порядок воспроизведения последовательности интересующих точек (cue points). Эти точки заданы в секции "cue ", где-то в другом месте файла. Плейлист состоит из массива сегментов, каждый из которых содержит информацию о том, какой сегмент откуда должен стартовать на проигрывание, какой длительности сегмент проигрывания (в выборках) и сколько раз должен повториться сегмент перед переходом к следующему по списку сегменту.
Смещение |
Размер |
Описание |
Величина |
0x00 |
4 |
Chunk ID |
"plst" (0x736C6E74) |
0x04 |
4 |
Chunk Data Size |
num segments * 12 |
0x08 |
4 |
Number of Segments |
1 - 0xFFFFFFFF |
0x0a |
List of Segments |
Формат секции Playlist
Количество сегментов (Number of Segments)
Это значение задает количество последующих сегментов в секции плейлиста.
Список сегментов (List of Segments)
Список сегментов - просто набор следующих друг за другом описаний сегментов, которые составлены по формату, приведенному в таблице ниже. Сегменты не должны быть ни в каком определенном порядке, потому что для определения порядка воспроизведения используется позиция интересующей точки (cue point position), связанная с каждым описанием списка.
Смещение |
Размер |
Описание |
Величина |
0x00 |
4 |
Cue Point ID |
0 - 0xFFFFFFFF |
0x04 |
4 |
Length (in samples) |
1 - 0xFFFFFFFF |
0x08 |
4 |
Number of Repeats |
1 - 0xFFFFFFFF |
Формат сегмента плейлиста
ID интересующей точки (Cue Point ID)
Cue Point ID указывает начальную выборку для этого сегмента путем указания значения Cue Point, заданного в списке Cue Point List. ID связывающий этот сегмент с интересующей точкой (Cue Point), должен быть уникальным по отношению ко всем другим ID интересующих точек (Cue Point ID).
Длина (Length)
Длина сегмента указывает количество выборок для воспроизведения или зацикливания от начальной выборки, заданной в связанной Cue Point.
Количество повторений (Number of Repeats)
Количество повторений определяет, сколько раз сегмент должен повторить свое воспроизведение, перед продолжением воспроизведения на следующем сегменте.
[Секция связанного списка данных - "list"]
Секция связанного списка данных (Associated Data List Chunk) используется для задания текстовых меток и имен, которые связаны с интересующими точками - для предоставления для каждой позиции текстовой метки или имени.
Смещение |
Размер |
Описание |
Величина |
0x00 |
4 |
Chunk ID |
"list" (0x6C696E74) |
0x04 |
4 |
Chunk Data Size |
зависит от содержащегося текста |
0x08 |
4 |
Type ID |
"adtl" (0x6164746C) |
0x0c |
список текстовых меток и имен |
Формат связанного списка данных
Type ID
Идентификатор типа (type ID) используется для обозначение типа связанного списка данных и всегда имеет значение "adtl".
Список текстовых меток и имен
Список текстовых меток и имен - просто список рассортированных секций, которые определяют текст различными способами. В файлах WAVE используются три основные типы секций -
секция метки (Label Chunk), секция примечания (Note Chunk) и секция помеченного текста (Labeled Text Chunk).
[Секция метки - "labl"]
Секция метки (Label Chunk) всегда содержится внутри секции связанного списка данных (associated data list chunk). Она используется для связывания текстовой метки с интересующей точкой (Cue Point). Эта информация часто отображается на маркерах или флажках в аудиоредакторах.
Смещение |
Размер |
Описание |
Величина |
0x00 |
4 |
Chunk ID |
"labl" (0x6C61626C) |
0x04 |
4 |
Chunk Data Size |
зависит от содержащегося текста |
0x08 |
4 |
Cue Point ID |
0 - 0xFFFFFFFF |
0x0c |
текст |
Формат секции метки
Cue Point ID
Идентификатор интересующей точки (Cue Point ID) указывает точку расположения выборки, соответствующей этой текстовой метке, путем предоставления ID интересующей точки (Cue Point), заданной в списке интересующих точек (Cue Point List). ID, который связывает эту метку с интересующей точкой (Cue Point), должен быть уникальным по отношению ко всем другим идентификаторам интересующих точек (Cue Point ID).
Текст
Текст - строка символов, оканчивающихся нулем. Если количество символов в строке нечетно, к строке должно быть добавлено однобайтовое выравнивание. Добавленное выравнивание не учитывается в поле размера секции метки.
[Секция примечания или комментария - "note"]
Секция примечания (Note Chunk) всегда содержится внутри секции связанного списка данных (associated data list chunk). Она используется для связывания текстового комментария с интересующей точкой (Cue Point). Эта информация сохраняется тем же самым способом, как и метки в секции метки.
Смещение |
Размер |
Описание |
Величина |
0x00 |
4 |
Chunk ID |
"note" (0x6E6F7465) |
0x04 |
4 |
Chunk Data Size |
зависит от содержащегося текста |
0x08 |
4 |
Cue Point ID |
0 - 0xFFFFFFFF |
0x0C |
текст |
Формат секции примечания
Cue Point ID
Идентификатор интересующей точки (Cue Point ID) указывает точку расположения
выборки, соответствующей этому текстовому примечанию, путем предоставления ID
интересующей точки (Cue Point), заданной в списке интересующих точек
(Cue Point List). ID, который связывает это примечание с интересующей точкой (Cue Point),
должен быть уникальным по отношению ко всем другим идентификаторам
интересующих точек (Cue Point ID).
Text
Текст - строка символов, оканчивающихся нулем. Если количество символов в
строке нечетно, к строке должно быть добавлено однобайтовое
выравнивание. Добавленное выравнивание не учитывается в поле размера
секции примечания (комментария).
[Секция помеченного текста - "ltxt"]
Секция помеченного текста (Labeled Text Chunk) всегда содержится внутри секции связанного списка данных (associated data list chunk). Она используется для связывания текстовой метки с регионом или секцией данных звука. Эта информация часто отображается в помеченных регионах звука в аудиоредакторах.
Смещение |
Размер |
Описание |
Величина |
0x00 |
4 |
Chunk ID |
"ltxt" (0x6C747874) |
0x04 |
4 |
Chunk Data Size |
зависит от содержащегося текста |
0x08 |
4 |
Cue Point ID |
0 - 0xFFFFFFFF |
0x0c |
4 |
Sample Length |
0 - 0xFFFFFFFF |
0x10 |
4 |
Purpose ID |
0 - 0xFFFFFFFF |
0x12 |
2 |
Country |
0 - 0xFFFF |
0x14 |
2 |
Language |
0 - 0xFFFF |
0x16 |
2 |
Dialect |
0 - 0xFFFF |
0x18 |
2 |
Code Page |
0 - 0xFFFF |
0x1A |
текст |
Формат секции помеченного текста
Cue Point ID
Идентификатор интересующей точки (Cue Point ID) указывает начальную выборку, которая соответствует этой текстовой метке, с помощью предоставления ID интересующей точки, заданного в списке интересующих точек (Cue Point List). ID интересующей точки, связанный с этой меткой, должен быть уникальным по отношению ко всем другим ID интересующих точек.
Sample Length
Длина выборок (sample length) задает, сколько выборок входит в регион или интервал секции, начиная с интересующей точки.
Purpose ID
Поле предназначения указывает, для чего используется текст. Например, значение "scrp" означает текст скрипта, "capt" означает close-caption (поясняющая подпись, субтитр). Имеется несколько большее количество значений purpose ID, но они предназначены для использования с другими типами файлов формата RIFF (которые обычно не используются в файлах WAVE).
Country, Language, Dialect, Code Page
Эти поля (страна, язык, диалдект, кодовая страница) используются для указания информации о месторасположении и языке, используемых в тексте. Обычно они нужны для запросов о получении информации от операционной системы.
Text
Текст - строка символов, оканчивающихся нулем. Если количество символов в
строке нечетно, к строке должно быть добавлено однобайтовое
выравнивание. Добавленное выравнивание не учитывается в поле размера
секции.
[Sampler Chunk - "smpl"]
Секция семплера (Sampler Chunk) задает основные параметры инструмента, как например семплер MIDI, который должен использоваться для воспроизведения данных звука. Наиболее важно, что он включает в себя информацию о зацикливаниях звука во время воспроизведения. Конечно, Вы можете найти, что это является дублированием информации, которую можно найти в секциях Cue и Playlist формата WAVE, но, к счастью, в секции семплера это сделано более гибко, непротиворечиво, и лучше задокументированным способом.
Смещение |
Размер |
Описание |
Величина |
0x00 |
4 |
Chunk ID |
"smpl" (0x736D706C) |
0x04 |
4 |
Chunk Data Size |
36 + (Num Sample Loops * 24) + Sampler Data |
0x08 |
4 |
Manufacturer |
0 - 0xFFFFFFFF |
0x0C |
4 |
Product |
0 - 0xFFFFFFFF |
0x10 |
4 |
Sample Period |
0 - 0xFFFFFFFF |
0x14 |
4 |
MIDI Unity Note |
0 - 127 |
0x18 |
4 |
MIDI Pitch Fraction |
0 - 0xFFFFFFFF |
0x1C |
4 |
SMPTE Format |
0, 24, 25, 29, 30 |
0x20 |
4 |
SMPTE Offset |
0 - 0xFFFFFFFF |
0x24 |
4 |
Num Sample Loops |
0 - 0xFFFFFFFF |
0x28 |
4 |
Sampler Data |
0 - 0xFFFFFFFF |
0x2C |
List of Sample Loops |
Формат секции семплера
Manufacturer
Поле производителя (manufacturer) указывает код MIDI Manufacturer's Association (MMA) для семплера предназначенного для приема звука этого файла. Каждый производитель продукта MIDI имеет свой уникальный ID, который идентифицирует компанию. Если не указан конкретный производитель, то должно быть подставлено значение 0.
В значении имеется некоторая дополнительная информация, которую можно использовать для трансляции в величину, используемую в передаче на семплер формата MIDI System Exclusive. Старший байт показывает количество младших байт (1 или 3), которые значимы для кода производителя. Например, значение для Digidesign будет 0x01000013 (0x13) и значение для Microsoft будет 0x30000041 (0x00, 0x00, 0x41). См. список MIDI Manufacturers List.
Product
Поле продукта указывает ID модели MIDI, заданный произодителем. Для получения идентификаторов продукта связывайтесь с производителем семплера. Если не указан конкретный продукт производителя, то должно быть подставлено значение 0.
Sample Period
Период выборки указывает длительность времени воспроизведения одной выборки в наносекундах (обычно равно 1 / [количество выборок в секунду], где [количество выборок в секунду] равно величине, указанной в секции формата).
MIDI Unity Note
MIDI unity note (что-то типа тональности MIDI, решил этот термин не переводить) - величина, имеющая то же самое значение как и MIDI Unshifted Note секции инструмента (instrument chunk). Поле MIDI Unshifted Note указывает музыкальную ноту, на которой выборка будет воспроизведена на её оригинальной скорости выборок sample rate (sample rate указано в секции формата).
MIDI Pitch Fraction
MIDI pitch fraction (тоже какой-то специфический музыкальный термин, что-то типа "доля высоты звука") указывает доли полутона вверх от величины, указанной в поле MIDI unity note. Значение 0x80000000 означает 1/2 полутона (50 cents) и значение 0x00000000 означает неточную настройку между полутонами (лично для меня это все звучит как китайская грамота).
SMPTE Format
SMPTE формат указывает формат времени Society of Motion Pictures and Television E, используемый в следующем поле SMPTE Offset. Если установлено значение 0, SMPTE Offset также должно быть равно 0.
Значение |
SMPTE Format |
0 |
нет смещения SMPTE offset |
24 |
24 фрейма в секунду |
25 |
25 фреймов в секунду |
29 |
30 фреймов в секунду с выпадением фрейма (30 выпадает) |
30 |
30 фреймов в секунду |
Значения формата SMPTE
SMPTE Offset
Смещение SMPTE Offset - величина, указывающая на смещение времени, используемое для синхронизации / калибровки первой выборки звука. Здесь используется форма 0xhhmmssff, где hh - число со знаком, указывающее количество часов (-23 .. 23), mm - беззнаковая величина количества минут (0 .. 59), ss - (0 .. 59) беззнаковая величина количества секунд и ff - беззнаковая величина количества фреймов (0 .. -1).
Sample Loops
Поле циклов выборок указывает количество определений зацикливания выборок в последующем списке (см. list of sample loops). Это значение может быть установлено в 0, что означает отсутствие последующих зацикливаний.
Sampler Data
Величина данных семплера (sampler data value) указывает количество байт, которые последуют за этой секцией (включая весь список sample loop list). Эта величина больше, чем 0, когда приложение нуждается в сохранении дополнительной информации. Эта величина отражена в значении chunks data size.
List of Sample Loops
Список зацикливаний (list of sample loops) - простой набор последовательных описаний циклов, которые следуют нижеописанному формату. Зацикливания не имеют какой-либо определенный порядок, поскольку каждый цикл выборок, связанный с интересующей точкой, используется для определения порядка воспроизведения. Секция семплера не является обязательной.
Смещение |
Размер |
Описание |
Величина |
0x00 |
4 |
Cue Point ID |
0 - 0xFFFFFFFF |
0x04 |
4 |
Type |
0 - 0xFFFFFFFF |
0x08 |
4 |
Start |
0 - 0xFFFFFFFF |
0x0C |
4 |
End |
0 - 0xFFFFFFFF |
0x10 |
4 |
Fraction |
0 - 0xFFFFFFFF |
0x14 |
4 |
Play Count |
0 - 0xFFFFFFFF |
Формат цикла выборок
Cue Point ID
Идентификатор интересующей точки (Cue Point ID) - указывает уникальный ID, который соответствует одной из заданных интересующих точек в списке (cue point list). Кроме того, этот ID соответствует любой из меток, заданных в связанной секции данных (data list chunk), которая позволяет назначать текстовые метки различным циклам выборок.
Type
Поле типа задает, каким образом зацикливаются выборки звука.
Значение |
Loop Type (тип зацикливания)
|
0 |
Цикл вперед (обычный) |
1 |
Альтернативный цикл (вперед/назад, известный также как Ping Pong) |
2 |
Цикл назад (обратный) |
3 - 31 |
Зарезервировано для будущих стандартных типов |
32 - 0xFFFFFFFF |
Специфические типы, относящиеся к семплеру (задаются производителем) |
Значения Loop Type
Start
Значение старта указывает байтовое смещение в данные звука первой выборки, проигрываемой в цикле.
End
Значение окончания указывает байтовое смещение в данные звука последней выборки, проигрываемой в цикле.
Fraction
Дробное (fractional) значение указывает дробную часть выборки, котороая принадлежит циклу. Это позволяет точно настроить длительность цикла с точностью выше, чем позволяет одна выборка. Величина может находиться в диапазоне 0x00000000 .. 0xFFFFFFFF. Значение 0 означает отсутствие дробной части, значение 0x80000000
означает 1/2 от длительности выборки. Значение 0xFFFFFFFF соответствует минимальной дробной части выборки, которую можно задать.
Play Count
Значение счетчика воспроизведений (play count) определяет количество проигрываний цикла. 0 означает постоянный бесконечный цикл, который не прервется, пока не произойдет принудительное внешнее вмешательство (например, музыкант отпустит клавишу). Все другие значения указывают абсолютное количество проигрываний цикла.
[Секция инструмента - "inst"]
Секция инструмента (instrument chunk) используется для описания - каким образом звук должен быть проигран как звук инструмента. Эта информация полезна для обмена музыкальной информацией между музыкальными редакторами-семплерами, основанными на выборках (семплах), трекерами или программными таблицами звука. Эта секция является необязательной, и не может встречаться в WAVE-файле больше одного раза.
Смещение |
Размер |
Описание |
Величина |
0x00 |
4 |
Chunk ID |
"ltxt" (0x6C747874) |
0x04 |
4 |
Chunk Data Size |
7 |
0x08 |
1 |
Unshifted Note |
0 - 127 |
0x09 |
1 |
Fine Tune (dB) |
-50 - +50 |
0x0A |
1 |
Gain |
-64 - +64 |
0x0B |
1 |
Low Note |
0 - 127 |
0x0C |
1 |
High Note |
0 - 127 |
0x0D |
1 |
Low Velocity |
1 - 127 |
0x0E |
1 |
High Velocity |
1 - 127 |
Формат секции инструмента
Unshifted Note
Поле несмещенной ноты (unshifted note) имеет то же самое предназначение, что и у MIDI Unity Note секции семплера - указывает музыкальную ноту, на которой выборка будет проиграна с её оригинальной скоростью (sample
rate, указывается в секции формата).
Fine Tune
Значение точной настройки (fine tune) указывает, насколько подача выборки должна быть изменена, когда звук воспроизведен в центах (1/100 полутона). Отрицательная величина означает, что высота тона должна быть снижена, а позитивная величина означает, что высота тона должна быть повышена.
Gain
Значение усиления (gain) указывает количество децибел для настройки выхода при проигрывании. Значение 0 dB означает отсутствие изменений, 6 dB означает удвоение амплитуды каждой выборки, -6 dB означает уменьшение амплитуды каждой выборки вдвое. Каждые дополнительные +/- 6 dB удваивают или делят амплитуду надвое соответственно.
Low Note и High Note
Поля нот указывают диапазон нот MIDI, в которых звук должен быть проигран, когда происходит событие приема ноты MIDI (от программного обеспечения или команды контроллера MIDI. Контроллером может выступать, например, клавиатура MIDI). Этот диапазон необязательно должен включать значение Unshifted Note.
Low Velocity и High Velocity
Поля скорости (velocity) указывают диапазон скоростей MIDI (MIDI velocity), с которыми должен проигрываться звук. 1 относится к самому легкому проигрыванию, 127 к самому жесткому.
[Изменения формата]
Обратная сторона популярности формата файла WAVE - из сотен программ, которые поддерживают этот формат, многие злоупотребляют или неправильно используют формат из-за плохого программирования и/или плохой документации. Как только некоторые из этих "непослушных" программ становятся довольно популярными и производят в большом количестве миллионы неправильных WAVE файлов, остальная часть отрасли программного обеспечения вынуждена иметь дело с этим и производить код, который может распознавать эти неправильные файлы. Новый код не должен записывать эти ошибки, но должен читать ошибочный WAVE-файл. Ниже описано несколько таких исключений, которые были сделаны в дополнение к строгому/исходному формату WAVE.
* Некорректная величина блока выравнивания (Block Alignment) - с этим можно иметь дело, вычисляя Block Alignment по указанной ранее формуле.
* Некорректная величина среднего количества выборок в секунду (Average Samples Per Second) - с этим можно иметь дело, вычисляя Average Samples Per Second по указанной ранее формуле.
* Отсутствие пустых байт для выравнивания на слово (Missing word alignment padding) - с этим трудно бороться, но можно давать пользователю предупреждение, если имеется нераспознанный ID блока, и одно смещение побайтового чтения дает возможность распознанать ID блока. Это не полное решение, но оно обычно работает, даже если у программы нет полного списка легальных ID.
[Ссылки]
1. Пример простейшей обработки WAV-файла (допускается только несжатый PCM).
2. Простой SD/microSD звуковой плеер на 8-выводном микроконтроллере ATtiny85.
3. Библиотека Petit FatFS: модуль файловой системы FAT.
|
Комментарии
2013-04-0415:04:04 Спасибо большое, для новичков статья очень хорошо понимается!!! А вот как воспроизвести wav-файлы с помощью AVR не будет статьи случайно? Очень хотелось бы!
microsin: Вы могли бы взять исходный код из статьи [1], несмотря на то, что там описан проект на ARM. Модули оттуда можно легко вставить в проект AVR Studio, и взять для файловой системы облегченную библиотеку FAT - PetitFS. Она очень хорошо работает на микроконтроллер ах AVR. Добавил также ссылки [2, 3], они должны Вам помочь.
2012-03-2709:06:18 Все бы хорошо, смысл доходчив. Только цифры смещения не везде верные. Для общего понимания хорошо, а для практического применения
microsin: как-то Вы слишком туманно выражаетесь. "Не везде" - это где конкретно?
2012-03-2217:25:26 Статья хороша, спасибо!
2011-08-1915:23:00 Очень даже неплохая статья
2011-06-0914:52:25 Хороший, технически грамотный перевод вот отсюда:
http://www.sonicspot.com/guide/wavefiles.html
Спасибо!
2011-05-2600:15:44 Интересно, автор сам-то понимает, что написал? Судя по тому, что терминологией он не владеет, вряд ли
microsin: наверное, Вы просто не весь материал поняли. Мне кажется - наоборот, автор отлично разбирается в вопросе, и очень подробно и доходчиво излагает структуру формата WAV-файла.
2011-03-1723:05:30 сверхкрутая статья