Blog. Just Blog

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

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

Пиратил тут очередную партию музыкальных новинок и один из альбомов оказался в невиданном ранее формате с расширением ".opus". Естественно, первым желанием было не послушать, а поковыряться во внутренностях файлов. Как оказалось, аудиокодек Opus это детище тех же разработчиков, которые до этого выпустили кодек OGG. Несомненно, алгоритмы кодирования звукового потока отличаются, а вот сама внутренняя структура файла практически в точности повторяет разобранный ранее формат OGG. В том числе и способ хранения метаданных, которые меня интересуют.

Все особенности работы с форматом OGG я описал в статье по приведенной выше ссылке, дублировать информацию не буду. Отличие заключается только в том, что сигнатура блока метаданных - это восьмибайтная строка "OpusTags", в остальном все без изменений. Код для парсинга метаданных Opus-файлов будет примерно следующим:
  1.         invoke  CreateFile,sample,GENERIC_READ,FILE_SHARE_READ,0,\
  2.                 OPEN_EXISTING,0,0
  3.         mov     [desc],eax
  4. loc_read:
  5.         ; Прочитать заголовок страницы
  6.         invoke  _lread,[desc],buff,sizeof.OGG_PAGE_HEADER
  7.  
  8.         ; Проверить корректность страницы
  9.         mov     esi,buff
  10.         cmp     [esi+OGG_PAGE_HEADER.dMagic],'OggS'
  11.         jne     loc_close
  12.  
  13.         ; Количество сегментов в странице
  14.         movzx   ebx,[esi+OGG_PAGE_HEADER.bSegnemts]
  15.  
  16.         ; Прочитать таблицу размеров сегментов
  17.         invoke  _lread,[desc],tTable,ebx
  18.  
  19.         ; Подсчитать длину всех сегментов
  20.         mov     ecx,ebx
  21.         mov     esi,tTable
  22.         xor     ebx,ebx
  23. @@:
  24.         lodsb
  25.         movzx   eax,al
  26.         add     ebx,eax
  27.         loop    @b
  28.  
  29.         ; Метаданные записаны в страницу 1
  30.         mov     esi,buff
  31.         cmp     [esi+OGG_PAGE_HEADER.dPage],1
  32.         jne     loc_skip
  33.  
  34.         ; Выделить память под метаданные
  35.         invoke  GlobalAlloc,GMEM_ZEROINIT,ebx
  36.         mov     [hMem],eax
  37.         invoke  GlobalLock,[hMem]
  38.         mov     [pMem],eax
  39.  
  40.         ; Прочитать метаданные
  41.         invoke  _lread,[desc],[pMem],ebx
  42.  
  43.         ; Сигнатура блока метаданных
  44.         mov     esi,[pMem]
  45.         cmp     dword [esi],'Opus'
  46.         jne     loc_free
  47.         cmp     dword [esi+4],'Tags'
  48.         jne     loc_free
  49.  
  50.         ; Пропустить сигнатуру
  51.         add     esi,8
  52.         ; Длина строки названия кодировщика
  53.         add     esi,dword[esi]
  54.         add     esi,4
  55.         ; Количество тегов
  56.         mov     ebx,dword[esi]
  57.         add     esi,4
  58.  
  59.         ; Метаданных нет
  60.         or      ebx,ebx
  61.         jz      loc_free
  62. loc_get_tags:
  63.         push    ebx
  64.  
  65.         ; Размер тега
  66.         mov     ecx,dword[esi]
  67.         add     esi,4
  68.  
  69.         ; Первые 4 символа названия тега
  70.         mov     eax,[esi]
  71.         ; Перевести в нижний регистр
  72.         or      eax,20202020h
  73.         mov     ebx,title
  74.         cmp     eax,'titl'
  75.         je      @f
  76.         mov     ebx,artist
  77.         cmp     eax,'arti'
  78.         je      @f
  79.         mov     ebx,album
  80.         cmp     eax,'albu'
  81.         je      @f
  82.  
  83.         ; Пропустить тег
  84.         add     esi,ecx
  85.         jmp     loc_next_tag
  86. @@:
  87.         ; Найти символ-разделитель
  88.         mov     al,'='
  89.         mov     edi,esi
  90.         repne   scasb
  91.         ; Передвинуть указатель на значение тега
  92.         mov     esi,edi
  93.         ; Разделитель не нашелся, битые данные
  94.         or      ecx,ecx
  95.         jz      loc_next_tag
  96.  
  97.         ; UTF-8 -> юникод
  98.         push    ecx
  99.         invoke  MultiByteToWideChar,CP_UTF8,0,edi,ecx,0,0
  100.         invoke  MultiByteToWideChar,CP_UTF8,0,edi,-1,ebx,eax
  101.         pop     ecx
  102.         ; Перейти к следующему тегу
  103.         add     esi,ecx
  104. loc_next_tag:
  105.         pop     ebx
  106.         ; Все теги обработали?
  107.         sub     ebx,1
  108.         jnz     loc_get_tags
  109.  
  110.         ...
  111.         ; artist -> наименование исполнителя
  112.         ; album -> название альбома
  113.         ; title -> название трека
  114.         ...
  115.  
  116. loc_free:
  117.         ; Освободить память
  118.         invoke  GlobalUnlock,[hMem]
  119.  
  120.         jmp     loc_close
  121. loc_skip:
  122.         ; Перейти к следующей странице
  123.         invoke  _llseek,[desc],ebx,FILE_CURRENT
  124.         cmp     eax,-1
  125.         je      loc_close
  126.         jmp     loc_read
  127. loc_close:
  128.         invoke  CloseHandle,[desc]
В приложении пример программы с исходным текстом, которая парсит метаданные из Opus-файла и выводит их.

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

Opus.Metadata.Demo.zip (459,299 bytes)


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

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

Комментарии

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

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

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

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