unit acs_mpeg; {$ifdef fpc} {$mode delphi} {$endif} interface uses Classes, SysUtils,ACS_file,ACS_classes, smpeg; type TMPEGIn = class(TACSCustomFileIn) private _M : Pointer; protected procedure OpenFile; override; procedure CloseFile; override; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; function GetData(Buffer : Pointer; BufferSize : Integer): Integer; override; procedure Init; override; end; implementation constructor TMPEGIn.Create; begin inherited Create(AOwner); BufferSize := $2000; end; destructor TMPEGIn.Destroy; begin inherited Destroy; end; procedure TMPEGIn.Init; begin inherited Init; SMPEG_play(_M); end; procedure TMPEGIn.OpenFile; var info : SMPEG_info; spec : SDL_AudioSpec; begin if FOpened = 0 then begin (* the next call is needed just to make sure the SDL library is loaded *) _M := SMPEG_new(PChar(FFileName), info, 1); SMPEG_delete(_M); FValid := True; _M := SMPEG_new(PChar(FFileName), info, 0); if info.has_audio <> 1 then begin FValid := False; Exit; end; FTime := Round(info.total_time); SMPEG_wantedSpec(_M, spec); FSR := spec.freq; FBPS := 16; FChan := spec.channels; FSize := FTime*2*FChan*FSR; end; Inc(FOpened); end; procedure TMPEGIn.CloseFile; begin if FOpened = 1 then begin if SMPEG_status(_M) = SMPEG_PLAYING then SMPEG_stop(_M); SMPEG_delete(_M); end; if FOpened > 0 then Dec(FOpened); end; function TMPEGIn.GetData(Buffer : Pointer; BufferSize : Integer): Integer; var l, offs : Integer; tmp : Single; begin if not Busy then raise EACSException.Create('The Stream is not opened'); if BufStart > BufEnd then begin if FOffset <> 0 then begin offs := Round((FOffset/100)*FSize); FPosition := FPosition + offs; if FPosition < 0 then FPosition := 0 else if FPosition > FSize then FPosition := FSize; if FOffset < 0 then begin SMPEG_rewind(_M); SMPEG_play(_M); tmp := (FPosition/FSize)*FTime; SMPEG_skip(_M, tmp); end; tmp := (FOffset/100)*FTime; SMPEG_skip(_M, tmp); FOffset := 0; end; BufStart := 1; FillChar(FBuffer, BufferSize, 0); l := Buffersize; l := SMPEG_playAudio(_M, @FBuffer[BufEnd + 1], BufferSize - BufEnd); if l = 0 then begin if FLoop then begin Flush; Init; SMPEG_rewind(_M); SMPEG_play(_M); FPosition := 0; l := SMPEG_playAudio(_M, @FBuffer[BufEnd + 1], BufferSize - BufEnd); end else begin Result := 0; Exit; end; end; BufEnd := l; end; if BufferSize < (BufEnd - BufStart + 1) then Result := BufferSize else Result := BufEnd - BufStart + 1; Move(FBuffer[BufStart], Buffer^, Result); Inc(BufStart, Result); Inc(FPosition, Result); end; initialization LoadMPEGLibrary; if LibsmpegLoaded then begin FileFormats.Add('mp3','Mpeg Audio Layer III',TMPEGIn); FileFormats.Add('mp2','Mpeg Audio Layer II',TMPEGIn); FileFormats.Add('mpeg','Mpeg Audio',TMPEGIn); end; finalization UnLoadMPEGLibrary; end.