Перейти к содержимому


Внимание!

Это форум по извлечению ресурсов из игр: музыки, звуков, текстур, 3D-моделей...
Перед поиском ответов на форуме, рекомендуется ознакомиться с основным сайтом EXTRACTOR.ru!
[ Прочтите внимательно - правила создания тем и ответа в них ]
Все вопросы по запуску игр задавайте в другом месте: Установка и запуск игр.


Фотография

MP3 - поиск сигнатур, получение размера и пр.


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 3

#1 Dr. No

Dr. No

    Ефрейтор

  • Пользователи
  • 5 сообщений
  • Пол:Мужчина
  • Город:Las Vegas

Отправлено 13 April 2013 - 17:22

Доброго времени суток! Очень давно интересовал вопрос поиска mp3 в архивах. По теме нарыл не много. Mp3 состоит из фреймов, в фрейме есть заголовок, в котором содержится всякая информация. Так вот, как из фрейма вытянуть размер mp3? Насколько я знаю, нужно подсчитать количество этих фреймов. Но как? Смотрел сорцы HyperRiper'a, но там очень плохой поиск mp3, половину не ищет, а если ищет, то фигово. Размер не совпадает и все такое. Есть у кого нибудь какие нить идеи/примеры?

Вот что я вытянул с кода рипера, но там фигня одна Изображение


program test;

{$APPTYPE CONSOLE}

uses
  Windows, SysUtils, Classes;

type
  TBuffer = array [0..3] of Byte;

  TOffsetsList = record
    Offset: Int64;
  end;

var
  DestFile: TFileStream;
  Buffer: TBuffer;
  PosBuf, FoundSize: Int64;
  MP3Ver: byte;
  MP3Layer: byte;
  MP3Padding: byte;
  MP3Rate: longword;
  MP3BitRate: longword;
  MP3FrameLen, MP3FrameSize: longword;
  MP3Frames: longword;
  buf3: array[1..3] of char;
  B: Byte;
  OffsetsList: array of TOffsetsList;
  i: Integer;

const
  BIT_RATE_TABLE: array [0..15] of Integer =
    (0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0);

var
  firstOffset, lastOffset: Int64;

begin
  PosBuf:= 0;
  DestFile:= TFileStream.Create('data.pak', fmOpenReadWrite and fmShareExclusive);

  repeat
    DestFile.Read(B, 1);
  until B = 255;

  DestFile.Seek((DestFile.Position-1), 0);
  firstOffset:= DestFile.Position;

  DestFile.Seek(firstOffset, 0);
  DestFile.Read(Buffer, 4);

  if (Buffer[0] = 255) and ((Buffer[1] and 224) = 224) then begin
    MP3Ver := Buffer[1] And 24;
    case MP3Ver of
   	24: MP3Ver := 10;
   	16: MP3Ver := 20;
   	8: exit;
    else
   	MP3Ver := 25;
    end;
    
    MP3Layer:= (4 - (Buffer [1] shr 1) and 3) and 3;
    MP3Padding:= ((Buffer [2] shr 1) and 1);

    MP3BitRate := BIT_RATE_TABLE[(Buffer[2] And 240) shr 4];
    MP3Rate := Buffer[2] And 12;

    if MP3Rate = 0 then MP3Rate := 44100;
    if MP3Rate = 4 then MP3Rate := 48000;
    if MP3Rate = 8 then MP3Rate := 32000;

    MP3FrameSize := (144000 * MP3BitRate) div MP3Rate + MP3Padding;
  end;

  repeat
    DestFile.Read(B, 1);
    if B = 255 then begin
      lastOffset:= (DestFile.Position - 1);
    end;
  until DestFile.Position >= DestFile.Size;

  Writeln(MP3FrameSize);
  Writeln(firstOffset, ' ', lastOffset);
end.


#2 -=CHE@TER=-

-=CHE@TER=-

    Полковник

  • Администраторы
  • 971 сообщений
  • Пол:Мужчина

Отправлено 14 April 2013 - 11:53

MP3 Frame Header
1) Ищешь в сканируемом файле WORD, у которого первые 11 бит зажжены.
2) Далее предполагаешь, что это начало MP3 фрейма и читаешь остальные данные из заголовка.
3) Проверяешь прочитанные данные на корректность, если они некорректны - переходишь к пункту 1.
4) Если заголовок нормальный, то вычисляешь из него размер фрейма и пропускаешь его (размер фрейма может быть нефиксированный!).
5) Снова читаешь данные и проверяешь на корректность (т.е. убеждаешься что попал на начало следующего фрейма), и так пока не прочитал что-то левое - значит MP3 закончился.

Есть способ быстрее:
1) Находишь начало MP3 файла.
2) Отрубаешь всё, до этого смещения.
3) Загружаешь получившийся MP3 с куском мусора в хвосте через mp3DirectCut (бесплатная программа - Google.com в помощь) и сохраняешь файл - сохраняется только MP3, а всё лишнее на конце отрубается.

#3 Dr. No

Dr. No

    Ефрейтор

  • Пользователи
  • 5 сообщений
  • Пол:Мужчина
  • Город:Las Vegas

Отправлено 14 April 2013 - 12:20

MP3 Frame Header
1) Ищешь в сканируемом файле WORD, у которого первые 11 бит зажжены.
2) Далее предполагаешь, что это начало MP3 фрейма и читаешь остальные данные из заголовка.
3) Проверяешь прочитанные данные на корректность, если они некорректны - переходишь к пункту 1.
4) Если заголовок нормальный, то вычисляешь из него размер фрейма и пропускаешь его (размер фрейма может быть нефиксированный!).
5) Снова читаешь данные и проверяешь на корректность (т.е. убеждаешься что попал на начало следующего фрейма), и так пока не прочитал что-то левое - значит MP3 закончился.

Есть способ быстрее:
1) Находишь начало MP3 файла.
2) Отрубаешь всё, до этого смещения.
3) Загружаешь получившийся MP3 с куском мусора в хвосте через mp3DirectCut (бесплатная программа - Google.com в помощь) и сохраняешь файл - сохраняется только MP3, а всё лишнее на конце отрубается.

Можно запороться на самом первом. Что именно искать, 255 аля $FF? И как проверить, зажжены биты или нет? Читать остальные данные это круто, но нужно из них еще получить информацию о количестве и размере фреймов. Второй способ отпадает, т.к. файл может быть размером в 10 Гб, а mp3 там только в начале, загружать 10 Гб в память - плохая затея ))

#4 -=CHE@TER=-

-=CHE@TER=-

    Полковник

  • Администраторы
  • 971 сообщений
  • Пол:Мужчина

Отправлено 14 April 2013 - 20:12

Можно запороться на самом первом. Что именно искать, 255 аля $FF? И как проверить, зажжены биты или нет? Читать остальные данные это круто, но нужно из них еще получить информацию о количестве и размере фреймов. Второй способ отпадает, т.к. файл может быть размером в 10 Гб, а mp3 там только в начале, загружать 10 Гб в память - плохая затея ))

Искать нужно WORD (2 байта) у которого первые 11 бит зажжены (т.е. единички).
1 байт = 8 бит, 11 бит - это два байта (8 бит + 3 бита у второго):
76543210 76543210
11111111 11100000

11111111b = FFh (255d)
11100000b = E0h (224d)
(b - binary (двоичная), h - hex (шестнадцетеричная), d - dec (десятичная) системы)
А теперь смотри программу, что ты привёл выше. Там это есть.
Размер фрейма нужно высчитывать из прочитанного заголовка (там, например, может быть выравнивание, а может и не быть, можеть быть контрольная сумма, а может отсутствовать и т.д.) и переходить к следующему и так пока первые два байта удовлетворяют маске FFE0h (что такое битовая маска знаем?) и корректным данным в заголовке. MP3 нигде не содержит количество фреймов, нужно тупо читать, пока они есть и правильные. Ссылку на структуру MP3 я привёл выше, вот даже лучше ссылка - смотри там подраздел "How to calculate frame length" (Как подсчитать длину фрейма) MPEG Audio Frame Header.

Что касается файла в 10 Гб, где MP3 только в начале - находишь начало MP3, отступаешь 50 Мб и записываешь получившийся кусок на диск. С 50 Mб, думаю, проблем не должно быть?