Blog. Just Blog

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

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Парсинг метаданных 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. Код для парсинга метаданных будет следующим:
  1.         ; Открыть файл для чтения
  2.         invoke  CreateFile,sample,GENERIC_READ,\
  3.                 FILE_SHARE_READ,0,OPEN_EXISTING,0,0
  4.         mov     [desc],eax
  5.  
  6.         ; Прочитать заголовок файла
  7.         invoke  _lread,[desc],buff,12
  8.  
  9.         ; Проверить корректность файла
  10.         mov     eax,dword[buff]
  11.         or      eax,20202020h
  12.         cmp     eax,'form'
  13.         jne     loc_close_aiff
  14.         mov     eax,dword[buff+8]
  15.         or      eax,20202020h
  16.         ; Учесть оба формата
  17.         cmp     eax,'aiff'
  18.         je      loc_chk_section_aiff
  19.         cmp     eax,'aifc'
  20.         jne     loc_close_aiff
  21. loc_chk_section_aiff:
  22.         ; Прочитать заголовок секции
  23.         invoke  _lread,[desc],buff,8
  24.         cmp     eax,-1
  25.         je      loc_close_aiff
  26.         cmp     eax,8
  27.         jne     loc_close_aiff
  28.  
  29.         ; Название секции
  30.         mov     eax,dword [buff]
  31.         ; Перевести в нижний регистр
  32.         or      eax,20202020h
  33.         ; Метаданные в секции ID3?
  34.         cmp     eax,'id3 '
  35.         je      loc_read_id3
  36.  
  37.         ; Перейти к следующей секции
  38.         mov     eax,dword [buff+4]
  39.         bswap   eax
  40.         ; Учесть выравнивание секции
  41.         inc     eax
  42.         and     eax,0FFFFFFFEh
  43.  
  44.         invoke  _llseek,[desc],eax,FILE_CURRENT
  45.         ; Весь файл обработали?
  46.         cmp     eax,-1
  47.         jne     loc_chk_section_aiff
  48.         jmp     loc_close_aiff
  49.  
  50. loc_read_id3:
  51.         ;----------------------------------------------
  52.         ; Обработка секции ID3
  53.         ;----------------------------------------------
  54.         ; Выделить память под метаданные
  55.         mov     ebx,dword [buff+4]
  56.         bswap   ebx
  57.         invoke  GlobalAlloc,GMEM_ZEROINIT,ebx
  58.         mov     [hMem],eax
  59.         invoke  GlobalLock,[hMem]
  60.         mov     [pMem],eax
  61.  
  62.         ; Прочитать метаданные
  63.         invoke  _lread,[desc],[pMem],ebx
  64.  
  65.         mov     esi,[pMem]
  66.         ; ID3v2.3
  67.         cmp     dword [esi],0x03334449
  68.         je      @f
  69.         ; ID3v2.4
  70.         cmp     dword [esi],0x04334449
  71.         jne     loc_free_aiff
  72. @@:
  73.         add     esi,10
  74. loc_scan_id3_tags:
  75.         ; Все теги обработали?
  76.         mov     eax,esi
  77.         sub     eax,[pMem]
  78.         cmp     eax,ebx
  79.         jae     loc_done_aiff
  80.         cmp     byte[esi],0
  81.         je      loc_done_aiff
  82.  
  83.         ; Проверить валидность названия тега
  84.         xor     ecx,ecx
  85. loc_check_id3_aiff:
  86.         mov     dl,byte[esi+ecx]
  87.         cmp     dl,'0'
  88.         jb      loc_done_aiff
  89.         cmp     dl,'9'
  90.         jbe     @f
  91.         cmp     dl,'A'
  92.         jb      loc_done_aiff
  93.         cmp     dl,'Z'
  94.         ja      loc_done_aiff
  95. @@:
  96.         inc     ecx
  97.         cmp     ecx,4
  98.         jb      loc_check_id3_aiff
  99.  
  100.         ; Album
  101.         mov     edi,album
  102.         cmp     dword [esi],'TALB'
  103.         je      @f
  104.         ; Artist
  105.         mov     edi,artist
  106.         cmp     dword [esi],'TPE1'
  107.         je      @f
  108.         ; Title
  109.         mov     edi,title
  110.         cmp     dword [esi],'TIT2'
  111.         je      @f
  112.  
  113.         ; Пропустить тег
  114.         lodsd
  115.         ; Размер данных
  116.         lodsd
  117.         bswap   eax
  118.         add     esi,eax
  119.         lodsw
  120.         jmp     loc_scan_id3_tags
  121. @@:
  122.         lodsd
  123.         ; Размер данных
  124.         lodsd
  125.         bswap   eax
  126.         mov     ecx,eax
  127.         ; Размер без учета байта типа кодировки
  128.         dec     ecx
  129.         lodsw
  130.         ; Тип кодировки строки
  131.         lodsb
  132.         or      al,al
  133.         jz      loc_load_utf8
  134. loc_load_utf16:
  135.         ; Пропустить BOM
  136.         cmp     word[esi],0xFEFF
  137.         jne     @f
  138.         lodsw
  139.         dec     ecx
  140.         dec     ecx
  141. @@:
  142.         ; Просто скопировать строку UTF-16
  143.         rep     movsb
  144.         xor     eax,eax
  145.         stosw
  146.         jmp     loc_scan_id3_tags
  147.  
  148. loc_load_utf8:
  149.         ; UTF-8 -> юникод
  150.         push    ecx
  151.         invoke  MultiByteToWideChar,CP_UTF8,0,esi,ecx,0,0
  152.         invoke  MultiByteToWideChar,CP_UTF8,0,esi,-1,edi,eax
  153.         pop     ecx
  154.         ; Следующий тег
  155.         add     esi,ecx
  156.         jmp     loc_scan_id3_tags
  157.  
  158. loc_done_aiff:
  159.         ; Данные собраны
  160.  
  161. loc_free_aiff:
  162.         ; Освободить память
  163.         invoke  GlobalUnlock,[hMem]
  164. loc_close_aiff:
  165.         invoke  CloseHandle,[desc]
В приложении пример программы с исходным текстом, которая парсит метаданные из AIFF-файла и выводит их. Тестовый сэмпл находится здесь, я не стал включать его в архив из-за большого размера.

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

AIFF.Metadata.Demo.zip (3,052 bytes)


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

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
Комментариeв нет

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

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

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