С Новым Годом! С Новым Годом!
Blog. Just Blog

Парсинг метаданных файлов VQF на Ассемблере

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Парсинг метаданных файлов VQF на Ассемблере
Парсинг метаданных файлов VQF на Ассемблере

VQF (Vector Quantization File) - это аудиоформат, разработанный в середине 1990-х годов японской компанией NTT (Nippon Telegraph and Telephone) в сотрудничестве с Yamaha. Он основан на кодеке TwinVQ (Transform-domain Weighted Interleave Vector Quantization), который позже был включен как объектный тип в стандарт MPEG-4 Audio. Формат отличался высокой эффективностью сжатия: при битрейтах 80-112 кбит/с проприетарная реализация VQF (SoundVQ) часто обеспечивала лучшее субъективное качество по сравнению с MP3, особенно ниже 96 кбит/с.

Как уже указано, формат считается проприетарным, и ни нормальной документации, ни официального описания структуры файлов найти не удалось. Пришлось разбираться на основе готовых файлов, тем не менее, ничего особо сложного в них нет. Внутреннее устройство VQF-файлов достаточно прозрачно: формат следует четкой структуре.

Метаданные в файле
Метаданные в файле

Файл в формате VQF состоит из сигнатуры, заголовка, содержащего несколько секций, и данных. Сигнатура представляет собой строку "TWIN97012000" из 12 символов, за которой следует DWORD с указанием размера заголовка в формате big-endian. Здесь и далее в статье будет подразумеваться, что все размеры данных указаны в формате big-endian, это сделано, чтобы не повторяться. Затем идет заголовок, состоящий из нескольких секций. После него следует DWORD со сигнатурой "DATA", за которым располагаются сами аудиоданные. Это уже не интересно, нам нужны только метаданные.

Метаданные в файле
Метаданные в файле

В заголовке дальше идут секции. Каждая секция также начинается с четырехбайтовой сигнатуры и DWORD с размером данных секции. Я нашел несколько сигнатур: "COMM", "NAME", "(c)_", "FILE", "DSIZ" или "AUTH", точные названия и их количество установить не удалось. Обратите внимание, строка "(c)_" тоже является сигнатурой (последний символ - пробел). Если данные секции пусты, размер данных остается нулевым, записывается DWORD со значением 0. Повторяем это для каждой секции до окончания заголовка. Для проверки можно заглянуть в аудиоданные - там будет первая сигнатура "DATA". Осталось только оформить это в виде кода.
  1.         ; Прочитать сигнатуру файла
  2.         invoke  _llseek,[desc],0,FILE_BEGIN
  3.         invoke  _lread,[desc],buff,16
  4.         mov     esi,buff
  5.         lodsd
  6.         cmp     eax,'TWIN'
  7.         jne     loc_close_vqf
  8.         lodsd
  9.         cmp     eax,'9701'
  10.         jne     loc_close_vqf
  11.         lodsd
  12.         cmp     eax,'2000'
  13.         jne     loc_close_vqf
  14.  
  15.         ; Размер заголовка
  16.         lodsd
  17.         bswap   eax
  18.  
  19.         ; Размер начала данных
  20.         add     eax,4
  21.         ; Проверить корректность заголовка
  22.         cmp     eax,BUFF_SIZE
  23.         ; Размер слишколм большой
  24.         ja      loc_close_vqf
  25.  
  26.         ; Прочитать данные
  27.         mov     ebx,eax
  28.         invoke  _lread,[desc],buff,eax
  29.         cmp     dword [buff+ebx-4],'DATA'
  30.         jne     loc_close_vqf
  31.  
  32.         mov     esi,buff
  33. loc_parse_vqf:
  34.         ; Проверить окончание заголовка
  35.         lodsd
  36.         cmp     eax,'DATA'
  37.         je      loc_close_vqf
  38.  
  39.         mov     edi,album
  40.         cmp     eax,'AUTH'
  41.         je      @f
  42.         mov     edi,artist
  43.         cmp     eax,'(c) '
  44.         je      @f
  45.         mov     edi,title
  46.         cmp     eax,'NAME'
  47.         je      @f
  48.  
  49.         ; Пропустить данные
  50.         lodsd
  51.         bswap   eax
  52.         add     esi,eax
  53.         jmp     loc_parse_vqf
  54. @@:
  55.         ; Длина строк
  56.         lodsd
  57.         bswap   eax
  58.  
  59.         ; UTF-8 -> юникод
  60.         push    eax
  61.         push    esi
  62.         invoke  MultiByteToWideChar,CP_UTF8,0,esi,eax,0,0
  63.         invoke  MultiByteToWideChar,CP_UTF8,0,esi,-1,edi,eax
  64.         pop     esi
  65.         pop     eax
  66.  
  67.         ; Следующий тег
  68.         add     esi,eax
  69.         jmp     loc_parse_vqf
  70.  
  71. loc_close_vqf:
  72.         invoke  CloseHandle,[desc]
  73.  
  74.         ; title -> название композиции
  75.         ; artist -> исполнитель
  76.         ; album -> альбом  
Несмотря на это преимущество, VQF так и не получил широкого распространения. TwinVQ остался интересной, но исторически проигравшей технологией из-за закрытости, крайне медленного кодирования и отсутствия аппаратной и программной экосистемы. Сегодня формат считается устаревшим и практически неподдерживаемым: файлы .vqf встречаются лишь в архивах или как цифровые раритеты.

В приложении пример программы с исходным текстом, которая парсит и выводит метаданные из файла в формате VQF.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

VQF.Metadata.Demo.zip (302,581 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 231 | Комментариев: 3

Комментарии

Отзывы посетителей сайта о статье
ManHunter (12.01.2026 в 15:42):
Спасибо, пригодится
Лестер Глючный (12.01.2026 в 15:38):
COMM — обязательная метка:
long channelMode # 0: mono, 1:stereo
long bitRate # integer in kbit/s
long samplingRate # integer in kHz, (e.g. 44.1 kHz -> 44)
long securityLevel # always 0
DSIZ — размер сжатых аудиоданных…
т.о., esvorbei_drum.vqf: mono 20kbps 22kHz, 300325 байт сжатых аудиоданных, KakOsennij.vqf: stereo 48kbps 22kHz, 1071314 б.
правильно ли подсчитана длительность: ?2?7?48? и 2?58?33? соответственно?
COMT — комментарий # (в отличие от COMM у ID3)
Порадовало наличие метки FILE (compressed file name) — вот такое пару десятков лет назад было очень полезно, не только из-за вмещаемости больше 8.3 символов, но банально из-за повреждения файловых систем на флешках (оказавшиеся в папках FOUND.###) ну или интернетовских "цифробуквы.mp3" тьфу, .vqf… Хорошо, что "не NULL-terminated", т.о. можно смело использовать Юникод (хоть UTF-8, хоть UTF-16LE или даже BE)…

WORD (songwriter) # TEXT
MUSC (composer) # TCOM
ARNG (arranger)
PROD (producer)
PRSN (player | personnel)
NOTE (liner notes)
REMX (remixer) # TPE4
CDCT (conductor) # TPE3
BAND (band, orchestra, group) # TPE2
SING (singer) # TPE1
ISRC (International Standard Record Code) # TSRC
ABLM # TALB
LABL # TPUB
LYRC # USLT
YEAR # YEAR/TYER
short year
char month
ENCD (compressed date) # TDAT
short year
char month
char day
char hour
char minute
char timeZone
TRAC # TRCK
short trackNumber
GUID (Globally Unique Identifier) # UFID
byte[16] guid
SCND (auxiliary information) # SCND/NAME <=> TIT3
while ( StringChunk subChunks[ ])
EXTR (reserved)
_ID3 (reserved for ID3v2; priority should be defined in case of conflict with TwinVQ)
char[ ] data
_YMH (отсылка на Я?маха)
_NTT (на Японский Телеграф и Телефон)
bodrox (19.12.2025 в 12:24):
Да, помню тогда появились кодировщик и плагин к винампу. Быстро забросил этот кодек, так как уже тогда старался в библиотеке теги вбивать, а с ямахой были какие-то проблемы. Потом я очень быстро перешёл на foobar2000 и про vqf забыл полностью, особенно когда на телефонах и в машине воспроизводить только mp3 да wma было можно

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2026
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0054 сек.) / Память: 4.5 Mb
Наверх