?? monkey.pas
字號(hào):
{ *************************************************************************** }
{ }
{ Audio Tools Library (Freeware) }
{ Class TMonkey - for manipulating with Monkey's Audio file information }
{ }
{ Uses: }
{ - Class TID3v1 }
{ - Class TID3v2 }
{ - Class TAPEtag }
{ }
{ Copyright (c) 2001,2002 by Jurgen Faul }
{ E-mail: jfaul@gmx.de }
{ http://jfaul.de/atl }
{ }
{ Version 1.2 (21 April 2002) }
{ - Class TID3v2: support for ID3v2 tags }
{ - Class TAPEtag: support for APE tags }
{ }
{ Version 1.1 (11 September 2001) }
{ - Added property Samples }
{ - Removed WAV header information }
{ }
{ Version 1.0 (7 September 2001) }
{ - Support for Monkey's Audio files }
{ - Class TID3v1: reading & writing support for ID3v1.x tags }
{ }
{ *************************************************************************** }
unit Monkey;
interface
uses
Classes, SysUtils, ID3v1, ID3v2, APEtag;
const
{ Compression level codes }
MONKEY_COMPRESSION_FAST = 1000; { Fast (poor) }
MONKEY_COMPRESSION_NORMAL = 2000; { Normal (good) }
MONKEY_COMPRESSION_HIGH = 3000; { High (very good) }
MONKEY_COMPRESSION_EXTRA_HIGH = 4000; { Extra high (best) }
{ Compression level names }
MONKEY_COMPRESSION: array [0..4] of string =
('Unknown', 'Fast', 'Normal', 'High', 'Extra High');
{ Format flags }
MONKEY_FLAG_8_BIT = 1; { Audio 8-bit }
MONKEY_FLAG_CRC = 2; { New CRC32 error detection }
MONKEY_FLAG_PEAK_LEVEL = 4; { Peak level stored }
MONKEY_FLAG_24_BIT = 8; { Audio 24-bit }
MONKEY_FLAG_SEEK_ELEMENTS = 16; { Number of seek elements stored }
MONKEY_FLAG_WAV_NOT_STORED = 32; { WAV header not stored }
{ Channel mode names }
MONKEY_MODE: array [0..2] of string =
('Unknown', 'Mono', 'Stereo');
type
{ Real structure of Monkey's Audio header }
MonkeyHeader = record
ID: array [1..4] of Char; { Always "MAC " }
VersionID: Word; { Version number * 1000 (3.91 = 3910) }
CompressionID: Word; { Compression level code }
Flags: Word; { Any format flags }
Channels: Word; { Number of channels }
SampleRate: Integer; { Sample rate (hz) }
HeaderBytes: Integer; { Header length (without header ID) }
TerminatingBytes: Integer; { Extended data }
Frames: Integer; { Number of frames in the file }
FinalSamples: Integer; { Number of samples in the final frame }
PeakLevel: Integer; { Peak level (if stored) }
SeekElements: Integer; { Number of seek elements (if stored) }
end;
{ Class TMonkey }
TMonkey = class(TObject)
private
{ Private declarations }
FFileLength: Integer;
FHeader: MonkeyHeader;
FID3v1: TID3v1;
FID3v2: TID3v2;
FAPEtag: TAPEtag;
procedure FResetData;
function FGetValid: Boolean;
function FGetVersion: string;
function FGetCompression: string;
function FGetBits: Byte;
function FGetChannelMode: string;
function FGetPeak: Double;
function FGetSamplesPerFrame: Integer;
function FGetSamples: Integer;
function FGetDuration: Double;
function FGetRatio: Double;
public
{ Public declarations }
constructor Create; { Create object }
destructor Destroy; override; { Destroy object }
function ReadFromFile(const FileName: string): Boolean; { Load header }
property FileLength: Integer read FFileLength; { File length (bytes) }
property Header: MonkeyHeader read FHeader; { Monkey's Audio header }
property ID3v1: TID3v1 read FID3v1; { ID3v1 tag data }
property ID3v2: TID3v2 read FID3v2; { ID3v2 tag data }
property APEtag: TAPEtag read FAPEtag; { APE tag data }
property Valid: Boolean read FGetValid; { True if header valid }
property Version: string read FGetVersion; { Encoder version }
property Compression: string read FGetCompression; { Compression level }
property Bits: Byte read FGetBits; { Bits per sample }
property ChannelMode: string read FGetChannelMode; { Channel mode }
property Peak: Double read FGetPeak; { Peak level ratio (%) }
property Samples: Integer read FGetSamples; { Number of samples }
property Duration: Double read FGetDuration; { Duration (seconds) }
property Ratio: Double read FGetRatio; { Compression ratio (%) }
end;
implementation
{ ********************** Private functions & procedures ********************* }
procedure TMonkey.FResetData;
begin
{ Reset data }
FFileLength := 0;
FillChar(FHeader, SizeOf(FHeader), 0);
FID3v1.ResetData;
FID3v2.ResetData;
FAPEtag.ResetData;
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetValid: Boolean;
begin
{ Check for right Monkey's Audio file data }
Result :=
(FHeader.ID = 'MAC ') and
(FHeader.SampleRate > 0) and
(FHeader.Channels > 0);
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetVersion: string;
begin
{ Get encoder version }
if FHeader.VersionID = 0 then Result := ''
else Str(FHeader.VersionID / 1000 : 4 : 2, Result);
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetCompression: string;
begin
{ Get compression level }
Result := MONKEY_COMPRESSION[FHeader.CompressionID div 1000];
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetBits: Byte;
begin
{ Get number of bits per sample }
if FGetValid then
begin
Result := 16;
if FHeader.Flags and MONKEY_FLAG_8_BIT > 0 then Result := 8;
if FHeader.Flags and MONKEY_FLAG_24_BIT > 0 then Result := 24;
end
else
Result := 0;
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetChannelMode: string;
begin
{ Get channel mode }
Result := MONKEY_MODE[FHeader.Channels];
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetPeak: Double;
begin
{ Get peak level ratio }
if (FGetValid) and (FHeader.Flags and MONKEY_FLAG_PEAK_LEVEL > 0) then
case FGetBits of
16: Result := FHeader.PeakLevel / 32768 * 100;
24: Result := FHeader.PeakLevel / 8388608 * 100;
else Result := FHeader.PeakLevel / 128 * 100;
end
else
Result := 0;
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetSamplesPerFrame: Integer;
begin
{ Get number of samples in a frame }
if FGetValid then
if (FHeader.VersionID >= 3900) or
((FHeader.VersionID >= 3800) and
(FHeader.CompressionID = MONKEY_COMPRESSION_EXTRA_HIGH)) then
Result := 73728
else
Result := 9216
else
Result := 0;
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetSamples: Integer;
begin
{ Get number of samples }
if FGetValid then
Result := (FHeader.Frames - 1) * FGetSamplesPerFrame + FHeader.FinalSamples
else
Result := 0;
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetDuration: Double;
begin
{ Get song duration }
if FGetValid then Result := FGetSamples / FHeader.SampleRate
else Result := 0;
end;
{ --------------------------------------------------------------------------- }
function TMonkey.FGetRatio: Double;
begin
{ Get compression ratio }
if FGetValid then
Result := FFileLength /
(FGetSamples * FHeader.Channels * FGetBits / 8 + 44) * 100
else
Result := 0;
end;
{ ********************** Public functions & procedures ********************** }
constructor TMonkey.Create;
begin
{ Create object }
inherited;
FID3v1 := TID3v1.Create;
FID3v2 := TID3v2.Create;
FAPEtag := TAPEtag.Create;
FResetData;
end;
{ --------------------------------------------------------------------------- }
destructor TMonkey.Destroy;
begin
{ Destroy object }
FID3v1.Free;
FID3v2.Free;
FAPEtag.Free;
inherited;
end;
{ --------------------------------------------------------------------------- }
function TMonkey.ReadFromFile(const FileName: string): Boolean;
var
SourceFile: file;
begin
try
{ Reset data and search for file tag }
FResetData;
if (not FID3v1.ReadFromFile(FileName)) or
(not FID3v2.ReadFromFile(FileName)) or
(not FAPEtag.ReadFromFile(FileName)) then raise Exception.Create('');
{ Set read-access, open file and get file length }
AssignFile(SourceFile, FileName);
FileMode := 0;
Reset(SourceFile, 1);
FFileLength := FileSize(SourceFile);
{ Read Monkey's Audio header data }
Seek(SourceFile, ID3v2.Size);
BlockRead(SourceFile, FHeader, SizeOf(FHeader));
if FHeader.Flags and MONKEY_FLAG_PEAK_LEVEL = 0 then
FHeader.PeakLevel := 0;
if FHeader.Flags and MONKEY_FLAG_SEEK_ELEMENTS = 0 then
FHeader.SeekElements := 0;
CloseFile(SourceFile);
Result := true;
except
FResetData;
Result := false;
end;
end;
end.
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -