Автор: -=CHE@TER=- Apr 25 2009, 15:40
Помнится http://www.forum.ctpax-x.org/index.php?showtopic=172.
Вот, сделал сам, т.к. все эти тупые программы как надо не умеют в виду врождённой кривизны рук разработчиков.
В общем на альбомчике из 19 композиций, у которых ID3v2 был приписан Winamp'ом 2.81 после обработки удалось съэкономить чуть более 18 Кб.
В общем см. документацию по ссылке в коде программы.
Никакие флаги, версии и прочие вещи не проверяются - так что на некоторых файлах может работать некорректно - проверяйте результат перед удалением оригинала!
Выкидывается асболютно всё, кроме описанных в коде тэгов.
Для удобства просмотра в HEX-редакторах выравнивается по 16-ти байтной границе (хотя и не обязательно).
To Do List:
- всякие копирайты, справка и нормальные сообщения об ошибках
- сделать проверки на "неожиданный конец файла" и прочие непредвиденные случаи (сейчас считается, что все файлы нормальные - т.е. нет такого, что в середине ID3v2 файл закончился)
- сохранение оригинальной даты создания/изменения/модификации файла
- возможность оставлять непустые блоки (обложки, URL и т.д.) - пустыми же считаются блоки, у которых размер данных 0, либо размер данных 1, но этот байт с данными равен 0x00 (пустая строчка).
- возможность указания кодировки для конвертирования текста в тэгах (UTF8->CP1251, UNICODE->CP1251 и т.д.)
- не создавать новый файл, если ничего не стрипнулось
CODE
Program mp3strip;
{$APPTYPE CONSOLE}
Type
TFrameHdr = Packed Record
Name: Array[0..3] Of Char;
Size: Integer;
Encoding: Byte;
Flags: Word;
End;
TID3 = Packed Record
ID3: Array[0..2] Of Char;
Version: Word;
Flags: Byte;
Size: Integer;
End;
Const ID3_ALLOW = 'TRCKTIT2COMMTALBTYERTCONTPE1';
// http://www.id3.org/id3v2.3.0
{
TRCK - track number
TIT2 - song title
COMM - comments
TABL - album name
TYER - year
TCON - genre
TPE1 - artist
}
Function IsAllowedTag(const T: String): Boolean;
Begin
result:=((Pos(T, ID3_ALLOW)-1) Mod 4 = 0);
End;
Function swap32(Const dw: longword): longword; Assembler;
Asm
bswap eax
End;
Function ID3_7BIT(X: Integer): Integer;
Var I: Byte;
Begin
result:=0;
For I:=0 To 3 Do
Begin
X:=X ShL 1;
result:=result ShL 8;
result:=result + ((X And $FF) ShR 1);
X:=X ShR 8;
End;
End;
Var
Fl, F: File;
H: TFrameHdr;
M: TID3;
P: Pointer;
Begin
WriteLn('ID3v2 strip');
WriteLn;
If ParamCount = 0 Then Exit;
AssignFile(Fl, ParamStr(1));
{$I-}
FileMode:=0;
Reset(Fl, 1);
FileMode:=2;
{$I+}
If IOResult<>0 Then
Begin
WriteLn('Can''t open input file.');
Exit;
End;
BlockRead(Fl, M, SizeOf(M));
If M.ID3 <> 'ID3' Then
Begin
WriteLn('Input don''t have ID3v2 tag.');
CloseFile(Fl);
Exit;
End;
AssignFile(F, '_' + ParamStr(1));
ReWrite(F, 1);
BlockWrite(F, M, SizeOf(M));
Repeat
BlockRead(Fl, H, SizeOf(H));
M.Size:=swap32(H.Size) - 1;
// If H.Name[0] <> #0 Then WriteLn(H.Name, ' - ', M.Size);
If IsAllowedTag(H.Name) Then
Begin
BlockWrite(F, H, SizeOf(H));
GetMem(P, M.Size);
BlockRead(Fl, P^, M.Size);
BlockWrite(F, P^, M.Size);
FreeMem(P, M.Size);
End
Else
Seek(Fl, FilePos(Fl) + M.Size);
Until H.Name[0] = #0;
// padding with zeros
While FileSize(F) Mod 16 <> 0 Do BlockWrite(F, H, 1);
// fix padding size
M.Size:=ID3_7BIT(FileSize(F) - SizeOf(M));
Seek(F, 0);
BlockWrite(F, M, SizeOf(M));
Seek(F, FileSize(F));
Seek(Fl, FilePos(Fl) - SizeOf(H));
While H.Name[0] <> #$FF Do BlockRead(Fl, H, 1);
Seek(Fl, FilePos(Fl) - 1);
H.Size:=FileSize(Fl)-FilePos(Fl);
GetMem(P, H.Size);
BlockRead(Fl, P^, H.Size);
BlockWrite(F, P^, H.Size);
FreeMem(P, H.Size);
CloseFile(F);
CloseFile(Fl);
End.