X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fengine%2Fe_soundfile_mp3.pas;h=65b47e60e68e6176a2c8a97ef00904219184bdb3;hb=df21c986515fa0a93a10afbd789341894fcfe68d;hp=5f60a864bb726d8ed1a1ac9507e8e54de746301d;hpb=a4b97dbff3c995c7dda7fcfd5fc61e0aa19e7547;p=d2df-sdl.git diff --git a/src/engine/e_soundfile_mp3.pas b/src/engine/e_soundfile_mp3.pas index 5f60a86..65b47e6 100644 --- a/src/engine/e_soundfile_mp3.pas +++ b/src/engine/e_soundfile_mp3.pas @@ -2,8 +2,7 @@ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. + * the Free Software Foundation, version 3 of the License ONLY. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -44,13 +43,9 @@ type TMP3LoaderFactory = class (TSoundLoaderFactory) public - constructor Create(); - destructor Destroy(); override; function MatchHeader(Data: Pointer; Len: LongWord): Boolean; override; function MatchExtension(FName: string): Boolean; override; function GetLoader(): TSoundLoader; override; - private - FMPG: pmpg123_handle; // tester context end; implementation @@ -89,49 +84,43 @@ end; (* TMP3LoaderFactory *) -constructor TMP3LoaderFactory.Create(); -begin - FMPG := mpg123_new(nil, nil); - if FMPG <> nil then - mpg123_replace_reader_handle(FMPG, streamRead, streamLSeek, nil); -end; - -destructor TMP3LoaderFactory.Destroy(); -begin - if FMPG <> nil then mpg123_delete(FMPG); -end; function TMP3LoaderFactory.MatchHeader(Data: Pointer; Len: LongWord): Boolean; var - ID3: array [0..9] of Byte; - HeaderLen: LongInt; - S: TSFSMemoryStreamRO; - Info: mpg123_frameinfo; + P: PByte; + N: LongInt; begin Result := False; - if Len < 10 then Exit; + if Len < 10 then Exit; // way too short even without an ID3 + + P := PByte(Data); - // try and check for an ID3 header - Move(Data^, ID3, 10); - if (ID3[0] = Ord('I')) and (ID3[1] = Ord('D')) and (ID3[2] = Ord('3')) then + // try to check for an ID3v2 header + if ((P+0)^ = $49) and ((P+1)^ = $44) and ((P+2)^ = $33) then // 'ID3' begin - HeaderLen := ID3[9] + (ID3[8] shl 7) + (ID3[7] shl 14) + (ID3[6] shl 21); - Result := Len > (HeaderLen + 10); + N := (P+9)^ + ((P+8)^ shl 7) + ((P+7)^ shl 14) + ((P+6)^ shl 21); + Result := Len > (N + 10); if Result then Exit; end; - // if there isn't one, employ heavier shit - if FMPG = nil then Exit; - - S := TSFSMemoryStreamRO.Create(Data, Len); - - if mpg123_open_handle(FMPG, S) = MPG123_OK then + // try to read the frame sync word, bits 0-10 should be 1 + if ((P+0)^ = $FF) and (((P+1)^ and $E0) = $E0) then begin - Result := mpg123_info(FMPG, @Info) = MPG123_OK; - mpg123_close(FMPG); + // bits 11-12: mpeg version, can't be 01 + if (((P+1)^ and $10) = 0) and (((P+1)^ and $08) = $08) then + Exit; + // bits 13-14: layer: can't be 00 + if ((P+1)^ and $06) = 0 then + Exit; + // bits 16-19: bitrate index: can't be 1111 or 0000 + if (((P+2)^ and $F0) = 0) or (((P+2)^ and $F0) = $F0) then + Exit; + // bits 20-21: samplerate index: can't be 11 + if ((P+2)^ and $0C) = $0C then + Exit; + // this is probably an MP3 then + Result := True; end; - - S.Destroy(); end; function TMP3LoaderFactory.MatchExtension(FName: string): Boolean; @@ -151,7 +140,8 @@ end; function TMP3Loader.LoadStream(Stream: TStream; SStreaming: Boolean): Boolean; var - SRate, SEnc, SChans: LongInt; + SRate: clong; + SEnc, SChans: LongInt; begin FMPG := mpg123_new(nil, nil); if FMPG = nil then @@ -231,7 +221,7 @@ begin Result := LoadStream(S, SStreaming); except on E: Exception do - e_LogWritefln('ModPlug: ERROR: could not read file `%s`: %s', [FName, E.Message]); + e_LogWritefln('MPG123: ERROR: could not read file `%s`: %s', [FName, E.Message]); end; if not Result and (S <> nil) then @@ -254,9 +244,10 @@ begin Got := 0; if FMPG = nil then Exit; Ret := mpg123_read(FMPG, Buf, Len, @Got); - if FLooping and (Ret = MPG123_DONE) then - mpg123_seek(FMPG, 0, 0); // loop - Result := Got; + if FLooping and ((Ret = MPG123_DONE) or (Got = 0)) then + Ret := mpg123_seek(FMPG, 0, 0); // loop + if Ret = MPG123_OK then + Result := Got; end; function TMP3Loader.GetAll(var OutPtr: Pointer): LongWord;