351 lines
9.5 KiB
ObjectPascal
351 lines
9.5 KiB
ObjectPascal
(*
|
|
this file is a part of audio components suite v 2.3.
|
|
copyright (c) 2002-2005 andrei borovsky. all rights reserved.
|
|
see the license file for more details.
|
|
you can contact me at mail@z0m3ie.de
|
|
*)
|
|
|
|
{
|
|
$Log: acs_lame.pas,v $
|
|
Revision 1.5 2006/07/04 17:12:45 z0m3ie
|
|
ACS 2.4 alt wiederhergestellt (unterschiedliche Sampleformate ...)
|
|
|
|
Revision 1.2 2006/01/01 18:46:40 z0m3ie
|
|
*** empty log message ***
|
|
|
|
Revision 1.1 2005/12/19 18:36:38 z0m3ie
|
|
*** empty log message ***
|
|
|
|
Revision 1.6 2005/12/18 17:01:54 z0m3ie
|
|
delphi compatibility
|
|
|
|
Revision 1.5 2005/12/04 16:54:34 z0m3ie
|
|
All classes are renamed, Style TACS... than T... to avoid conflicts with other components (eg TMixer is TACSMixer now)
|
|
|
|
Revision 1.4 2005/11/28 21:57:24 z0m3ie
|
|
mostly FileOut fixes
|
|
moved PBuffer to PBuffer8
|
|
set all to dynamically Buffering
|
|
|
|
Revision 1.3 2005/11/28 19:10:14 z0m3ie
|
|
*** empty log message ***
|
|
|
|
Revision 1.2 2005/09/13 04:04:50 z0m3ie
|
|
First release without Components for Fileformats
|
|
only TFileIn and TFileOut are Visible
|
|
|
|
Revision 1.1 2005/09/12 22:04:52 z0m3ie
|
|
modified structure again, fileformats are now in an sperat folder.
|
|
all File In/Out classes are capsulated from TFileIn and TFileOut
|
|
|
|
Revision 1.2 2005/08/22 20:17:01 z0m3ie
|
|
changed Headers to log
|
|
changed mail adress
|
|
|
|
}
|
|
|
|
unit acs_lame;
|
|
|
|
{$ifdef fpc}
|
|
{$mode delphi}
|
|
{$endif}
|
|
|
|
interface
|
|
|
|
uses
|
|
ACS_File,Classes, SysUtils, ACS_Classes, lame,
|
|
{$IFDEF LINUX}
|
|
baseunix;
|
|
{$ENDIF}
|
|
|
|
{$IFDEF WINDOWS}
|
|
Windows;
|
|
{$ENDIF}
|
|
|
|
type
|
|
|
|
TMP3Quality = (ql0, ql1, ql2, ql3, ql4, ql5,
|
|
ql6, ql7, ql8, ql9);
|
|
|
|
TMP3Mode = (STEREO = 0,
|
|
JOINT_STEREO,
|
|
DUAL_CHANNEL, // LAME doesn't supports this!
|
|
MONO);
|
|
|
|
TMP3SampleRate = (srDefault, sr32kHz, sr41kHz, sr48kHz);
|
|
|
|
TMP3BitRate = (br8, br16, br24, br32, br40, br48, br56, br64, br80, br96,
|
|
br112, br128, br144, br160, br192, br224, br256, br320);
|
|
|
|
BOOL = Boolean;
|
|
|
|
TMP3Out = class(TACSCustomFileOut)
|
|
private
|
|
FBitRate : TMP3BitRate;
|
|
_plgf : PLame_global_flags;
|
|
mp3buf : PByte;
|
|
mp3buf_size : Integer;
|
|
FTitle : String;
|
|
FArtist : String;
|
|
FAlbum : String;
|
|
FYear : String;
|
|
FTrack : String;
|
|
FComment : String;
|
|
FGenre : String;
|
|
FCopyright: BOOL;
|
|
FOriginal: BOOL;
|
|
FEnableVBR: BOOL;
|
|
FWriteVBRHeader: BOOL;
|
|
FCRC: BOOL;
|
|
FVBRQuality: TMP3Quality;
|
|
FVBRMinBitrate: integer;
|
|
FVBRMaxBitrate: integer;
|
|
FQuality: TMP3Quality;
|
|
FMode: TMP3Mode;
|
|
FSampleRate: TMP3SampleRate;
|
|
protected
|
|
procedure Done; override;
|
|
function DoOutput(Abort : Boolean):Boolean; override;
|
|
procedure Prepare; override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
published
|
|
property BitRate : TMP3BitRate read FBitRate write FBitRate stored True;
|
|
property Id3TagTitle : String read FTitle write FTitle;
|
|
property Id3TagArtist : String read FArtist write FArtist;
|
|
property Id3TagAlbum : String read FAlbum write FAlbum;
|
|
property Id3TagYear : String read FYear write FYear;
|
|
property Id3TagTrack : String read FTrack write FTrack;
|
|
property Id3TagComment : String read FComment write FComment;
|
|
property Id3TagGenre : String read FGenre write FGenre;
|
|
property Quality : TMP3Quality read FQuality write FQuality default ql5;
|
|
|
|
property SampleRate : TMP3SampleRate read FSampleRate write FSampleRate default srDefault;
|
|
property Mode : TMP3Mode read FMode write FMode default STEREO;
|
|
|
|
//Extras
|
|
property CRC : BOOL read FCRC write FCRC default false;
|
|
property Copyright : BOOL read FCopyright write FCopyright default false;
|
|
property Original : BOOL read FOriginal write FOriginal default true;
|
|
|
|
//VBR encoding
|
|
property WriteVBRHeader : BOOL read FWriteVBRHeader write FWriteVBRHeader default false;
|
|
property EnableVBR : BOOL read FEnableVBR write FEnableVBR default false;
|
|
property VBRQuality : TMP3Quality read FVBRQuality write FVBRQuality default ql5;
|
|
property VBRMinBitrate : integer read FVBRMinBitrate write FVBRMinBitrate default 128;
|
|
property VBRMaxBitrate : integer read FVBRMaxBitrate write FVBRMaxBitrate default 192;
|
|
end;
|
|
|
|
implementation
|
|
|
|
constructor TMP3Out.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
LoadLAME;
|
|
FBitRate := br128;
|
|
|
|
FBufferSize := $4000;
|
|
FQuality := ql5;
|
|
FSampleRate := srDefault;
|
|
FMode := STEREO;
|
|
FCRC := false;
|
|
FCopyright := false;
|
|
FOriginal := true;
|
|
|
|
FWriteVBRHeader := false;
|
|
FEnableVBR := false;
|
|
FVBRQuality := ql5;
|
|
FVBRMinBitrate := 128;
|
|
FVBRMaxBitrate := 192;
|
|
|
|
if not (csDesigning in ComponentState) then
|
|
if not LameLoaded then
|
|
raise EACSException.Create(LAME_PATH + ' library could not be loaded.');
|
|
end;
|
|
|
|
destructor TMP3Out.Destroy;
|
|
begin
|
|
UnloadLAME;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TMP3Out.Prepare;
|
|
var
|
|
samples, br, tbr, sr, ql : Integer;
|
|
begin
|
|
GetMem(FBuffer,FBufferSize);
|
|
if not FStreamAssigned then
|
|
begin
|
|
if FFileName = '' then raise EACSException.Create('File name is not assigned.');
|
|
FStream := TFileStream.Create(FFileName, fmCreate or fmShareExclusive, FAccessMask);
|
|
end;
|
|
FInput.Init;
|
|
_plgf := lame_init;
|
|
if FInput.Size > 0 then
|
|
samples := FInput.Size div ((Finput.BitsPerSample shr 3)*Finput.Channels);
|
|
lame_set_num_samples(_plgf, samples);
|
|
lame_set_in_samplerate(_plgf, Finput.SampleRate);
|
|
lame_set_num_channels(_plgf, 2); // not Finput.Channels see the note below
|
|
case FBitRate of
|
|
br8 : br := 8;
|
|
br16 : br := 16;
|
|
br24 : br := 24;
|
|
br32 : br := 32;
|
|
br40 : br := 40;
|
|
br48 : br := 48;
|
|
br56 : br := 56;
|
|
br64 : br := 64;
|
|
br80 : br := 80;
|
|
br96 : br := 96;
|
|
br112 : br := 112;
|
|
br128 : br := 128;
|
|
br144 : br := 144;
|
|
br160 : br := 160;
|
|
br192 : br := 192;
|
|
br224 : br := 224;
|
|
br256 : br := 256;
|
|
br320 : br := 320;
|
|
end;
|
|
case FSampleRate of
|
|
srDefault: sr := 0;
|
|
sr32kHz: sr := 32000;
|
|
sr41kHz: sr := 41000;
|
|
sr48kHz: sr := 48000;
|
|
end;
|
|
lame_set_out_samplerate(_plgf,sr);
|
|
{ lame_set_mode(_plgf, Integer(FMode));
|
|
if FCopyright then
|
|
lame_set_copyright(_plgf,1)
|
|
else
|
|
lame_set_copyright(_plgf,0);
|
|
if FOriginal then
|
|
lame_set_original(_plgf,1)
|
|
else
|
|
lame_set_original(_plgf,0);
|
|
if FCRC then
|
|
lame_set_error_protection(_plgf,1)
|
|
else
|
|
lame_set_error_protection(_plgf,0);
|
|
|
|
if not EnableVBR then
|
|
begin
|
|
lame_set_brate(_plgf, br);
|
|
case FQuality of
|
|
ql0: ql:=0;
|
|
ql1: ql:=1;
|
|
ql2: ql:=2;
|
|
ql3: ql:=3;
|
|
ql4: ql:=4;
|
|
ql5: ql:=5;
|
|
ql6: ql:=6;
|
|
ql7: ql:=7;
|
|
ql8: ql:=8;
|
|
ql9: ql:=9;
|
|
end;
|
|
lame_set_quality(_plgf,ql);
|
|
end
|
|
else
|
|
begin
|
|
if FWriteVBRHeader then
|
|
lame_set_bWriteVbrTag(_plgf,1);
|
|
lame_set_VBR(_plgf,2);
|
|
case FVBRQuality of
|
|
ql0: ql:=0;
|
|
ql1: ql:=1;
|
|
ql2: ql:=2;
|
|
ql3: ql:=3;
|
|
ql4: ql:=4;
|
|
ql5: ql:=5;
|
|
ql6: ql:=6;
|
|
ql7: ql:=7;
|
|
ql8: ql:=8;
|
|
ql9: ql:=9;
|
|
end;
|
|
lame_set_VBR_q(_plgf,ql);
|
|
if FVBRMinBitrate > FVBRMaxBitrate then
|
|
begin
|
|
tbr := FVBRMinBitrate;
|
|
FVBRMinBitrate := FVBRMaxBitrate;
|
|
FVBRMinBitrate := tbr;
|
|
end;
|
|
lame_set_VBR_min_bitrate_kbps(_plgf,FVBRMinBitrate);
|
|
lame_set_VBR_max_bitrate_kbps(_plgf,FVBRMaxBitrate);
|
|
end;
|
|
}
|
|
lame_init_params(_plgf);
|
|
mp3buf_size := (FBufferSize shr 1) + (FBufferSize shr 3) + 7200;
|
|
GetMem(mp3buf, mp3buf_size);
|
|
end;
|
|
|
|
procedure TMP3Out.Done;
|
|
var
|
|
res : Integer;
|
|
begin
|
|
id3tag_init(_plgf);
|
|
id3tag_set_title(_plgf, PChar(FTitle));
|
|
id3tag_set_artist(_plgf, PChar(FArtist));
|
|
id3tag_set_album(_plgf, PChar(FAlbum));
|
|
id3tag_set_year(_plgf, PChar(FYear));
|
|
id3tag_set_track(_plgf, PChar(FTrack));
|
|
id3tag_set_comment(_plgf, PChar(FComment));
|
|
id3tag_set_genre(_plgf, PChar(FGenre));
|
|
res := lame_encode_flush(_plgf, mp3buf, mp3buf_size);
|
|
FStream.Write(mp3buf^, res);
|
|
if not FStreamAssigned then FStream.Free;
|
|
lame_close(_plgf);
|
|
FreeMem(mp3buf);
|
|
FInput.Flush;
|
|
FreeMem(FBuffer);
|
|
end;
|
|
|
|
function TMP3Out.DoOutput(Abort : Boolean):Boolean;
|
|
var
|
|
Len, res, ns : Integer;
|
|
begin
|
|
// No exceptions Here
|
|
Result := True;
|
|
if not CanOutput then Exit;
|
|
if Abort then
|
|
begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
while InputLock do;
|
|
InputLock := True;
|
|
Len := Finput.GetData(@FBuffer, FBufferSize);
|
|
InputLock := False;
|
|
if Len <> 0 then
|
|
begin
|
|
if FInput.Channels = 2 then
|
|
begin
|
|
ns := Len shr 2;
|
|
res := lame_encode_buffer_interleaved(_plgf, @FBuffer, ns, mp3buf, mp3buf_size);
|
|
end else
|
|
begin
|
|
(* If the input stream is mono we turn it into stereo here.
|
|
This is the way to bypass some pour performance on mono streams,
|
|
maybe not the best way, but for a while ...*)
|
|
ns := Len shr 1;
|
|
res := lame_encode_buffer(_plgf, @FBuffer, @FBuffer, ns, mp3buf, mp3buf_size);
|
|
end;
|
|
if res < 0 then
|
|
begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
FStream.Write(mp3buf^, res);
|
|
end else
|
|
begin
|
|
Result := False;
|
|
Exit;
|
|
end;
|
|
end;
|
|
|
|
initialization
|
|
|
|
FileFormats.Add('mp3','Mpeg Layer III',TMP3Out);
|
|
|
|
|
|
end.
|