Парсинг метаданных AIFF-файлов на Ассемблере
Парсинг метаданных AIFF-файлов на Ассемблере
AIFF (Audio Interchange File Format) - это формат файлов для сохранения аудиоинформации без потерь, обеспечивающий высокое качество звука. Не самый популярный формат, в дикой природе встречается редко, в основном на устройствах производства Apple, но все равно имеет место быть. Меня же интересуют исключительно метаданные, которые в нем хранятся.
По внутренней структуре AIFF-файлы очень напоминают формат WAV. Файл начинается с 12-байтного заголовка, который состоит из строки "FORM", Big-Endian DWORD'а с размером файла без учета первых восьми символов и строки "AIFF" или "AIFC", обозначающей тип использованного кодека. По этим значениям можно и нужно проверять корректность файла перед дальнейшей обработкой. Остальное содержимое контейнера состоит из последовательности секций (чанков), которые начинаются с восьмибайтных заголовков. Первые 4 байта представляют собой идентификатор секции, затем следует Big-Endian DWORD с размером данных секции и после него уже находится содержимое. Каждая секция обязательно выравнивается на границу 2 байт и при необходимости дополняется нулевым байтом. Важно, что дополнительный байт в размер секции не входит.
Метаданные хранятся в секции с идентификатором "ID3_" (в конце символ пробела). Как и в случае с WAV-файлами, все размеры данных внутри секции ID3 записаны DWORD'ами, в остальном формат совпадает с ID3v2.3. Код для парсинга метаданных будет следующим:
Code (Assembler) : Убрать нумерацию
- ; Открыть файл для чтения
- invoke CreateFile,sample,GENERIC_READ,\
- FILE_SHARE_READ,0,OPEN_EXISTING,0,0
- mov [desc],eax
- ; Прочитать заголовок файла
- invoke _lread,[desc],buff,12
- ; Проверить корректность файла
- mov eax,dword[buff]
- or eax,20202020h
- cmp eax,'form'
- jne loc_close_aiff
- mov eax,dword[buff+8]
- or eax,20202020h
- ; Учесть оба формата
- cmp eax,'aiff'
- je loc_chk_section_aiff
- cmp eax,'aifc'
- jne loc_close_aiff
- loc_chk_section_aiff:
- ; Прочитать заголовок секции
- invoke _lread,[desc],buff,8
- cmp eax,-1
- je loc_close_aiff
- cmp eax,8
- jne loc_close_aiff
- ; Название секции
- mov eax,dword [buff]
- ; Перевести в нижний регистр
- or eax,20202020h
- ; Метаданные в секции ID3?
- cmp eax,'id3 '
- je loc_read_id3
- ; Перейти к следующей секции
- mov eax,dword [buff+4]
- bswap eax
- ; Учесть выравнивание секции
- inc eax
- and eax,0FFFFFFFEh
- invoke _llseek,[desc],eax,FILE_CURRENT
- ; Весь файл обработали?
- cmp eax,-1
- jne loc_chk_section_aiff
- jmp loc_close_aiff
- loc_read_id3:
- ;----------------------------------------------
- ; Обработка секции ID3
- ;----------------------------------------------
- ; Выделить память под метаданные
- mov ebx,dword [buff+4]
- bswap ebx
- invoke GlobalAlloc,GMEM_ZEROINIT,ebx
- mov [hMem],eax
- invoke GlobalLock,[hMem]
- mov [pMem],eax
- ; Прочитать метаданные
- invoke _lread,[desc],[pMem],ebx
- mov esi,[pMem]
- ; ID3v2.3
- cmp dword [esi],0x03334449
- je @f
- ; ID3v2.4
- cmp dword [esi],0x04334449
- jne loc_free_aiff
- @@:
- add esi,10
- loc_scan_id3_tags:
- ; Все теги обработали?
- mov eax,esi
- sub eax,[pMem]
- cmp eax,ebx
- jae loc_done_aiff
- cmp byte[esi],0
- je loc_done_aiff
- ; Проверить валидность названия тега
- xor ecx,ecx
- loc_check_id3_aiff:
- mov dl,byte[esi+ecx]
- cmp dl,'0'
- jb loc_done_aiff
- cmp dl,'9'
- jbe @f
- cmp dl,'A'
- jb loc_done_aiff
- cmp dl,'Z'
- ja loc_done_aiff
- @@:
- inc ecx
- cmp ecx,4
- jb loc_check_id3_aiff
- ; Album
- mov edi,album
- cmp dword [esi],'TALB'
- je @f
- ; Artist
- mov edi,artist
- cmp dword [esi],'TPE1'
- je @f
- ; Title
- mov edi,title
- cmp dword [esi],'TIT2'
- je @f
- ; Пропустить тег
- lodsd
- ; Размер данных
- lodsd
- bswap eax
- add esi,eax
- lodsw
- jmp loc_scan_id3_tags
- @@:
- lodsd
- ; Размер данных
- lodsd
- bswap eax
- mov ecx,eax
- ; Размер без учета байта типа кодировки
- dec ecx
- lodsw
- ; Тип кодировки строки
- lodsb
- or al,al
- jz loc_load_utf8
- loc_load_utf16:
- ; Пропустить BOM
- cmp word[esi],0xFEFF
- jne @f
- lodsw
- dec ecx
- dec ecx
- @@:
- ; Просто скопировать строку UTF-16
- rep movsb
- xor eax,eax
- stosw
- jmp loc_scan_id3_tags
- loc_load_utf8:
- ; UTF-8 -> юникод
- push ecx
- invoke MultiByteToWideChar,CP_UTF8,0,esi,ecx,0,0
- invoke MultiByteToWideChar,CP_UTF8,0,esi,-1,edi,eax
- pop ecx
- ; Следующий тег
- add esi,ecx
- jmp loc_scan_id3_tags
- loc_done_aiff:
- ; Данные собраны
- loc_free_aiff:
- ; Освободить память
- invoke GlobalUnlock,[hMem]
- loc_close_aiff:
- invoke CloseHandle,[desc]
Просмотров: 418 | Комментариев: 0
Метки: Assembler, мультимедиа
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Комментариeв нет
Добавить комментарий
Заполните форму для добавления комментария