154 lines
3.4 KiB
ObjectPascal
154 lines
3.4 KiB
ObjectPascal
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.
|
|
|