AudioImage.pas
上传用户:wanyu_2000
上传日期:2021-02-21
资源大小:527k
文件大小:20k
源码类别:

DVD

开发平台:

Delphi

  1. {-----------------------------------------------------------------------------
  2.  Unit Name: AudioImage
  3.  Author:    Paul Fisher / Andrew Semack
  4.  Purpose:   to create a CD image of audio wave files
  5.  History:
  6. -----------------------------------------------------------------------------}
  7. unit AudioImage;
  8. interface
  9. uses
  10.   CustomImage, Windows, Contnrs,dialogs, SysUtils, Messages, Classes, mmSystem,
  11.     WaveUtils,MP3Convert;
  12. type
  13.   TCDTrack = class(TMemoryStream)      //TMemoryStream
  14.   private
  15.     fDirty: Boolean;
  16.     fValid: Boolean;
  17.     fMpeg : Boolean;
  18.     fDataSize: DWORD;
  19.     fDataOffset: DWORD;
  20.     fData: Pointer;
  21.     fWaveFormat: PWaveFormatEx;
  22.     fOnChange: TNotifyEvent;
  23.     FTrackFileName: string;
  24.     FTrackName: string;
  25.     FSectorSize: Integer;
  26.     FSectorCount: Integer;
  27.     function GetValid: Boolean;
  28.     function GetData: Pointer;
  29.     function GetDataSize: DWORD;
  30.     function GetDataOffset: DWORD;
  31.     function GetLength: DWORD;
  32.     function GetBitRate: DWORD;
  33.     function GetPeakLevel: Integer;
  34.     function GetPCMFormat: TPCMFormat;
  35.     function GetWaveFormat: PWaveFormatEx;
  36.     function GetAudioFormat: string;
  37.     procedure SetSectorSize(Sector: Integer);
  38.   protected
  39.     function Realloc(var NewCapacity: Longint): Pointer; override;
  40.     function UpdateDetails: Boolean; virtual;
  41.     function MSecToByte(MSec: DWORD): DWORD;
  42.     procedure DoChange;
  43.     property Dirty: Boolean read fDirty;
  44.     function ConvertTo(const pTargetWaveFormat: PWaveFormatEx): Boolean;    
  45.   public
  46.     constructor Create; virtual;
  47.     destructor Destroy; override;
  48.     function Equals(Track: TCDTrack): Boolean;
  49.     function SameFormat(Track: TCDTrack): Boolean;
  50.     procedure Crop;
  51.     function Invert: Boolean;
  52.     function ChangeVolume(Percent: Integer): Boolean;
  53.     function ConvertToPCM(TargetFormat: TPCMFormat): Boolean;
  54.     function MP3Convert(FromMP3toPCM : Boolean): Boolean;
  55.     function ConvertToMP3(TargetFormat: TPCMFormat): Boolean;
  56.     function ConvertFromMP3(TargetFormat: TPCMFormat): Boolean;
  57.     function Delete(Pos: DWORD; Len: DWORD): Boolean;
  58.     function Insert(Pos: DWORD; Wave: TCDTrack): Boolean;
  59.     function InsertSilence(Pos: DWORD; Len: DWORD): Boolean;
  60.     function Write(const Buffer; Count: Longint): Longint; override;
  61.     property TrackName: string read FTrackName write FTrackName;
  62.     property TrackFileName: string read FTrackFileName write FTrackFileName;
  63.     property Valid: Boolean read GetValid;
  64.     property Data: Pointer read GetData;
  65.     property DataSize: DWORD read GetDataSize;
  66.     property DataOffset: DWORD read GetDataOffset;
  67.     property PCMFormat: TPCMFormat read GetPCMFormat;
  68.     property WaveFormat: PWaveFormatEx read GetWaveFormat;
  69.     property AudioFormat: string read GetAudioFormat;
  70.     property Length: DWORD read GetLength; // in milliseconds
  71.     property BitRate: DWORD read GetBitRate; // in kbps
  72.     property PeakLevel: Integer read GetPeakLevel; // in percent
  73.     property OnChange: TNotifyEvent read fOnChange write fOnChange;
  74.     property SectorCount: integer read FSectorCount;
  75.     property SectorSize: integer write SetSectorSize;
  76.   end;
  77.   // TTrack item
  78.   TCDTrackItem = class
  79.   private
  80.     FName: string;
  81.     FCDTrack: TCDTrack;
  82.     FTag: Integer;
  83.     FWavFileName : String;
  84.     FSongTitle : String;     //TITLE "How Precious"
  85.     FPreGap : Integer;
  86.     FPostGap : Integer;
  87.     FTrackIndex : Integer;
  88.     //procedure ReadData(Stream: TStream);
  89.     //procedure WriteData(Stream: TStream);
  90.   protected
  91.     function GetDisplayName: string;
  92.   public
  93.     constructor Create;
  94.     destructor Destroy; override;
  95.     procedure LoadWaveFile(Filename: string);
  96.     procedure SaveWaveFile(Filename: string);
  97.   published
  98.     property WavFileName : String read FWavFileName write FWavFileName;
  99.     property CDTrack: TCDTrack read FCDTrack write FCDTrack;
  100.     property Name: string read fName write fName;
  101.     property DisplayName: string read GetDisplayName;
  102.     property SongTitle : String read FSongTitle write FSongTitle;
  103.     //cue file stuff
  104.     property TrackIndex : Integer read FTrackIndex write FTrackIndex default 0;
  105.     property PreGap : Integer read FPreGap write FPreGap default 0;
  106.     property PostGap : Integer read FPostGap write FPostGap default 0;
  107.     property Tag: Integer read fTag write fTag default 0;
  108.   end;
  109.   PCDTrackItem = ^TCDTrackItem;
  110. type
  111.   TAudioImage = class(TCustomImage)
  112.   private
  113.     FTrackList: TClassList;
  114.     FLastError: string;
  115.     FCUESheet : TStringlist;
  116.     FPerformer : String;
  117.     FSongwriter : String;
  118.     function GetItem(Index: Integer): TCDTrackItem;
  119.     procedure SetItem(Index: Integer; Value: TCDTrackItem);
  120.   protected
  121.     procedure EmptyTrackList;
  122.     procedure CreateCUEFile(TrackID : Integer);
  123.     function GetCUESheet : TStringlist;
  124.   public
  125.     constructor Create;
  126.     destructor Destroy; override;
  127.     function GetLastError: string;
  128.     function Add: TCDTrackItem;
  129.     function Insert(Index: Integer): TCDTrackItem;
  130.     function TrackCount: Integer;
  131.     procedure ClearAllTracks;
  132.     property CUESheet : TStringlist read GetCUESheet;
  133.     property Performer : String read FPerformer write FPerformer;
  134.     property Songwriter : String read FSongwriter write FSongwriter;
  135.     property Tracks[Index: Integer]: TCDTrackItem read GetItem write SetItem;
  136.       default;
  137.   end;
  138. implementation
  139. uses covertfuncs;
  140. { TCDTrack }
  141. constructor TCDTrack.Create;
  142. begin
  143.   inherited Create;
  144.   fDirty := False;
  145.   fWaveFormat := nil;
  146. end;
  147. destructor TCDTrack.Destroy;
  148. begin
  149.   if Assigned(fWaveFormat) then
  150.     FreeMem(fWaveFormat);
  151.   inherited Destroy;
  152. end;
  153. procedure TCDTrack.SetSectorSize(Sector: Integer);
  154. var
  155.   DataSize: Integer;
  156. begin
  157.   FSectorSize := Sector;
  158.   DataSize := GetDataSize;
  159.   if (DataSize mod FSectorSize) > 0 then
  160.     FSectorCount := (DataSize div FSectorSize) + 1
  161.   else // bigger so add on a full sector!
  162.     FSectorCount := (DataSize div FSectorSize);
  163. end;
  164. function TCDTrack.Realloc(var NewCapacity: Integer): Pointer;
  165. begin
  166.   Result := inherited Realloc(NewCapacity);
  167.   if not Dirty then
  168.     DoChange;
  169. end;
  170. function TCDTrack.Write(const Buffer; Count: Integer): Longint;
  171. begin
  172.   Result := inherited Write(Buffer, Count);
  173.   if not Dirty then
  174.     DoChange;
  175. end;
  176. procedure TCDTrack.DoChange;
  177. begin
  178.   fDirty := True;
  179.   if Assigned(fOnChange) then
  180.     fOnChange(Self);
  181. end;
  182. function TCDTrack.MSecToByte(MSec: DWORD): DWORD;
  183. begin
  184.   with fWaveFormat^ do
  185.     Result := MulDiv(nAvgBytesPerSec, MSec, 1000)
  186.       and ($FFFFFFFF shl (nChannels * wBitsPerSample div 16));
  187. end;
  188. function TCDTrack.UpdateDetails: Boolean;
  189. begin
  190.   if fDirty then
  191.   begin
  192.     fValid := False;
  193.     fDirty := False;
  194.     fMpeg := False;
  195.     if Assigned(fWaveFormat) then
  196.     begin
  197.       FreeMem(fWaveFormat);
  198.       fWaveFormat := nil;
  199.     end;
  200.     if GetStreamWaveAudioInfo(Self, fWaveFormat, fDataSize, fDataOffset) then
  201.     begin
  202.       fData := Pointer(DWORD(Memory) + fDataOffset);
  203.       fValid := True;
  204.     end;
  205.     if fValid = False then
  206.     if GetStreamWaveAudioInfo(Self, fWaveFormat, fDataSize, fDataOffset) then
  207.     begin
  208.       fMpeg := True;
  209.     end;
  210.   end;
  211.   Result := fValid;
  212. end;
  213. function TCDTrack.GetAudioFormat: string;
  214. begin
  215.   if UpdateDetails then
  216.     Result := GetWaveAudioFormat(fWaveFormat)
  217.   else
  218.     Result := '';
  219. end;
  220. function TCDTrack.GetBitRate: DWORD;
  221. begin
  222.   if UpdateDetails then
  223.     Result := GetWaveAudioBitRate(fWaveFormat)
  224.   else
  225.     Result := 0;
  226. end;
  227. function TCDTrack.GetPeakLevel: Integer;
  228. begin
  229.   if PCMFormat <> nonePCM then
  230.     Result := GetWaveAudioPeakLevel(fData, fDataSize, fWaveFormat.wBitsPerSample)
  231.   else
  232.     Result := -1;
  233. end;
  234. function TCDTrack.GetLength: DWORD;
  235. begin
  236.   if UpdateDetails then
  237.     Result := GetWaveAudioLength(fWaveFormat, fDataSize)
  238.   else
  239.     Result := 0;
  240. end;
  241. function TCDTrack.GetData: Pointer;
  242. begin
  243.   if UpdateDetails then
  244.     Result := fData
  245.   else
  246.     Result := nil;
  247. end;
  248. function TCDTrack.GetDataSize: DWORD;
  249. begin
  250.   if UpdateDetails then
  251.     Result := fDataSize
  252.   else
  253.     Result := 0;
  254. end;
  255. function TCDTrack.GetDataOffset: DWORD;
  256. begin
  257.   if UpdateDetails then
  258.     Result := fDataOffset
  259.   else
  260.     Result := 0;
  261. end;
  262. function TCDTrack.GetValid: Boolean;
  263. begin
  264.   Result := UpdateDetails;
  265. end;
  266. function TCDTrack.GetPCMFormat: TPCMFormat;
  267. begin
  268.   if UpdateDetails then
  269.     Result := GetPCMAudioFormat(fWaveFormat)
  270.   else
  271.     Result := nonePCM;
  272. end;
  273. function TCDTrack.GetWaveFormat: PWaveFormatEx;
  274. begin
  275.   if UpdateDetails then
  276.     Result := fWaveFormat
  277.   else
  278.     Result := nil;
  279. end;
  280. function TCDTrack.Equals(Track: TCDTrack): Boolean;
  281. begin
  282.   if Valid = Track.Valid then
  283.     if fValid and Track.fValid then
  284.       Result :=
  285.         (fDataSize = Track.fDataSize) and
  286.         (fWaveFormat^.cbSize = Track.fWaveFormat^.cbSize) and
  287.         CompareMem(fWaveFormat, Track.fWaveFormat,
  288.         SizeOf(TWaveFormatEx) + fWaveFormat^.cbSize) and
  289.         CompareMem(fData, Track.fData, fDataSize)
  290.     else
  291.       Result :=
  292.         (Size = Track.Size) and
  293.         CompareMem(Memory, Track.Memory, Size)
  294.   else
  295.     Result := False;
  296. end;
  297. function TCDTrack.SameFormat(Track: TCDTrack): Boolean;
  298. begin
  299.   if Valid and Track.Valid then
  300.     Result :=
  301.       (fWaveFormat^.cbSize = Track.fWaveFormat^.cbSize) and
  302.       CompareMem(fWaveFormat, Track.fWaveFormat,
  303.       SizeOf(TWaveFormatEx) + fWaveFormat^.cbSize)
  304.   else
  305.     Result := False;
  306. end;
  307. procedure TCDTrack.Crop;
  308. begin
  309.   Size := DataOffset + DataSize;
  310. end;
  311. function TCDTrack.Invert: Boolean;
  312. begin
  313.   Result := False;
  314.   if PCMFormat <> nonePCM then
  315.   begin
  316.     InvertWaveAudio(fData, fDataSize, fWaveFormat.wBitsPerSample);
  317.     Result := True;
  318.   end;
  319. end;
  320. function TCDTrack.ChangeVolume(Percent: Integer): Boolean;
  321. begin
  322.   Result := False;
  323.   if PCMFormat <> nonePCM then
  324.   begin
  325.     ChangeWaveAudioVolume(fData, fDataSize, fWaveFormat.wBitsPerSample,
  326.       Percent);
  327.     Result := True;
  328.   end;
  329. end;
  330. function TCDTrack.ConvertTo(const pTargetWaveFormat: PWaveFormatEx): Boolean;
  331. var
  332.   NewData: Pointer;
  333.   NewDataSize: DWORD;
  334.   ckInfo, ckData: TMMCKInfo;
  335.   mmIO: HMMIO;
  336. begin
  337.   Result := False;
  338.   if Valid then
  339.   begin
  340.     if (fWaveFormat.cbSize <> pTargetWaveFormat^.cbSize) or
  341.       not CompareMem(fWaveFormat, pTargetWaveFormat, SizeOf(TWaveFormatEx) +
  342.         fWaveFormat.cbSize) then
  343.     begin
  344.       if ConvertWaveFormat(fWaveFormat, fData, fDataSize, pTargetWaveFormat,
  345.         NewData, NewDataSize) then
  346.       try
  347.         mmIO := CreateStreamWaveAudio(Self, pTargetWaveFormat, ckInfo, ckData);
  348.         try
  349.           mmioWrite(mmIO, NewData, NewDataSize);
  350.         finally
  351.           CloseWaveAudio(mmio, ckInfo, ckData);
  352.         end;
  353.         Result := True;
  354.       finally
  355.         ReallocMem(NewData, 0);
  356.       end;
  357.     end
  358.     else
  359.       Result := True;
  360.   end;
  361. end;
  362. function TCDTrack.ConvertToPCM(TargetFormat: TPCMFormat): Boolean;
  363. var
  364.   NewWaveFormat: TWaveFormatEx;
  365. begin
  366.   Result := False;
  367.   if TargetFormat <> nonePCM then
  368.   begin
  369.     SetPCMAudioFormatS(@NewWaveFormat, TargetFormat);
  370.     Result := ConvertTo(@NewWaveFormat);
  371.   end;
  372. end;
  373. function TCDTrack.MP3Convert(FromMP3toPCM : Boolean): Boolean;
  374. var
  375.   NewData: Pointer;
  376.   NewDataSize: DWORD;
  377.   Converter : TMP3Convertor;
  378.   HasConverted : Boolean;
  379. begin
  380.   Result := False;
  381.   UpdateDetails;
  382.   NewDataSize := 0;
  383.   Converter := TMP3Convertor.Create(nil);
  384.   try
  385.   if FromMP3toPCM = False then
  386.      HasConverted := Converter.ConvertToMP3Format(self.Memory,fDataSize,NewData,NewDataSize)
  387.       else
  388.       HasConverted := Converter.ConvertFromMP3Format(self.Memory,fDataSize,NewData,NewDataSize);
  389.       showmessage(Converter.LastError);
  390.         try
  391.           if HasConverted = True then
  392.           begin
  393.             self.Clear;
  394.             self.Seek(soFromBeginning,0);
  395.             self.Write(Newdata^,NewDataSize);
  396.             Result := True;
  397.           end;
  398.         finally
  399.           if NewDataSize <> 0 then ReallocMem(NewData, 0);
  400.         end;
  401.    finally
  402.     Converter.Free;
  403.    end;
  404. end;
  405. function TCDTrack.ConvertToMP3(TargetFormat: TPCMFormat): Boolean;
  406. var
  407.   NewWaveFormat: TWaveFormatEx;
  408. begin
  409.   Result := False;
  410.   if TargetFormat <> nonePCM then
  411.   begin
  412.     SetPCMAudioFormatS(@NewWaveFormat, TargetFormat);
  413.     Result := MP3Convert(False);
  414.     UpdateDetails;
  415.   end;
  416. end;
  417. function TCDTrack.ConvertFromMP3(TargetFormat: TPCMFormat): Boolean;
  418. var
  419.   NewWaveFormat: TWaveFormatEx;
  420. begin
  421.   Result := False;
  422.   if TargetFormat <> nonePCM then
  423.   begin
  424.     SetPCMAudioFormatS(@NewWaveFormat, TargetFormat);
  425.     Result := MP3Convert(True);
  426.     UpdateDetails;
  427.   end;
  428. end;
  429. function TCDTrack.Delete(Pos, Len: DWORD): Boolean;
  430. var
  431.   Index: DWORD;
  432.   NewWave: TCDTrack;
  433.   ckInfo, ckData: TMMCKInfo;
  434.   mmIO: HMMIO;
  435. begin
  436.   Result := False;
  437.   if Valid and (Len > 0) and (Pos < Length) then
  438.   begin
  439.     NewWave := TCDTrack.Create;
  440.     try
  441.       mmIO := CreateStreamWaveAudio(NewWave, fWaveFormat, ckInfo, ckData);
  442.       try
  443.         Index := MSecToByte(Pos);
  444.         if Index > fDataSize then
  445.           Index := fDataSize;
  446.         if Index > 0 then
  447.           mmioWrite(mmIO, fData, Index);
  448.         Inc(Index, MSecToByte(Len));
  449.         if Index < fDataSize then
  450.           mmioWrite(mmIO, Pointer(DWORD(fData) + Index), fDataSize - Index);
  451.       finally
  452.         CloseWaveAudio(mmio, ckInfo, ckData);
  453.       end;
  454.       LoadFromStream(NewWave);
  455.       Result := True;
  456.     finally
  457.       NewWave.Free;
  458.     end;
  459.   end;
  460. end;
  461. function TCDTrack.Insert(Pos: DWORD; Wave: TCDTrack): Boolean;
  462. var
  463.   Index: DWORD;
  464.   NewWave: TCDTrack;
  465.   ckInfo, ckData: TMMCKInfo;
  466.   mmIO: HMMIO;
  467. begin
  468.   Result := False;
  469.   if SameFormat(Wave) then
  470.   begin
  471.     NewWave := TCDTrack.Create;
  472.     try
  473.       mmIO := CreateStreamWaveAudio(NewWave, fWaveFormat, ckInfo, ckData);
  474.       try
  475.         Index := MSecToByte(Pos);
  476.         if Index > fDataSize then
  477.           Index := fDataSize;
  478.         if Index > 0 then
  479.           mmioWrite(mmIO, fData, Index);
  480.         mmioWrite(mmIO, Wave.fData, Wave.fDataSize);
  481.         if Index < fDataSize then
  482.           mmioWrite(mmIO, Pointer(DWORD(fData) + Index), fDataSize - Index);
  483.       finally
  484.         CloseWaveAudio(mmio, ckInfo, ckData);
  485.       end;
  486.       LoadFromStream(NewWave);
  487.       Result := True;
  488.     finally
  489.       NewWave.Free;
  490.     end;
  491.   end;
  492. end;
  493. function TCDTrack.InsertSilence(Pos, Len: DWORD): Boolean;
  494. var
  495.   Index: DWORD;
  496.   SilenceBytes: DWORD;
  497.   Silence: Byte;
  498.   NewWave: TCDTrack;
  499.   ckInfo, ckData: TMMCKInfo;
  500.   mmIO: HMMIO;
  501. begin
  502.   Result := False;
  503.   if (PCMFormat <> nonePCM) and (Len > 0) then
  504.   begin
  505.     NewWave := TCDTrack.Create;
  506.     try
  507.       mmIO := CreateStreamWaveAudio(NewWave, fWaveFormat, ckInfo, ckData);
  508.       try
  509.         Index := MSecToByte(Pos);
  510.         if Index > fDataSize then
  511.           Index := fDataSize;
  512.         if Index > 0 then
  513.           mmioWrite(mmIO, fData, Index);
  514.         if fWaveFormat.wBitsPerSample = 8 then
  515.           Silence := 128
  516.         else
  517.           Silence := 0;
  518.         SilenceBytes := MSecToByte(Len);
  519.         while SilenceBytes > 0 do
  520.         begin
  521.           mmioWrite(mmIO, PChar(@Silence), 1);
  522.           Dec(SilenceBytes);
  523.         end;
  524.         if Index < fDataSize then
  525.           mmioWrite(mmIO, Pointer(DWORD(fData) + Index), fDataSize - Index);
  526.       finally
  527.         CloseWaveAudio(mmio, ckInfo, ckData);
  528.       end;
  529.       LoadFromStream(NewWave);
  530.       Result := True;
  531.     finally
  532.       NewWave.Free;
  533.     end;
  534.   end;
  535. end;
  536. // CDTracks
  537. constructor TCDTrackItem.Create;
  538. begin
  539.   inherited Create;
  540.   FCDTrack := TCDTrack.Create;
  541. end;
  542. destructor TCDTrackItem.Destroy;
  543. begin
  544.   FCDTrack.Free;
  545.   inherited Destroy;
  546. end;
  547. procedure TCDTrackItem.LoadWaveFile(Filename: string);
  548. begin
  549.   if FileExists(Filename) then
  550.   begin
  551.     CDTrack.LoadFromFile(Filename);
  552.     CDTrack.TrackFileName := Filename;
  553.     CDTrack.TrackName := ExtractFileName(Filename);
  554.     SongTitle := CDTrack.TrackName;
  555.     WavFileName := Filename;
  556.     CDTrack.UpdateDetails;
  557.   end
  558.   else
  559.     CDTrack.Clear;
  560. end;
  561. procedure TCDTrackItem.SaveWaveFile(Filename: string);
  562. begin
  563.   CDTrack.SaveToFile(Filename);
  564.   CDTrack.TrackFileName := Filename;
  565.   CDTrack.TrackName := ExtractFileName(Filename);
  566. end;
  567. {procedure TCDTrackItem.ReadData(Stream: TStream);
  568. begin
  569.    CDTrack.LoadFromStream(Stream);
  570. end;
  571. procedure TCDTrackItem.WriteData(Stream: TStream);
  572. begin
  573.    CDTrack.SaveToStream(Stream);
  574. end;
  575. }
  576. function TCDTrackItem.GetDisplayName: string;
  577. var
  578.   WaveInfo: string;
  579. begin
  580.   if (CDTrack <> nil) and (CDTrack.Size <> 0) then
  581.   begin
  582.     if CDTrack.Valid then
  583.       WaveInfo := CDTrack.AudioFormat + ', ' +
  584.         IntToStr(CDTrack.BitRate) + ' kbps, ' +
  585.         MS2Str(CDTrack.Length, msAh) + ' sec.'
  586.     else
  587.       WaveInfo := 'Invalid Content';
  588.   end
  589.   else
  590.     WaveInfo := 'Empty Wave File';
  591.   Result := Name + ' (' + WaveInfo + ')';
  592. end;
  593. { TAudioImage }
  594. constructor TAudioImage.Create;
  595. begin
  596.   inherited Create;
  597.   FTrackList := TClassList.Create;
  598.   FCUESheet := TStringList.Create;
  599.   ImageType := ITAudioImage;
  600. end;
  601. destructor TAudioImage.Destroy;
  602. begin
  603.   EmptyTrackList;
  604.   FCUESheet.Free;
  605.   FTrackList.Free;
  606.   inherited Destroy;
  607. end;
  608. procedure TAudioImage.EmptyTrackList;
  609. var
  610.   Index: Integer;
  611. begin
  612.   try
  613.     for Index := 0 to (FTrackList.Count - 1) do
  614.       TCDTrackItem(FTrackList.Items[Index]).Destroy;
  615.   finally
  616.     FTrackList.Clear;
  617.   end;
  618. end;
  619. procedure TAudioImage.ClearAllTracks;
  620. begin
  621.   EmptyTrackList;
  622. end;
  623. function TAudioImage.GetLastError: string;
  624. begin
  625.   Result := FLastError;
  626. end;
  627. function TAudioImage.TrackCount: Integer;
  628. begin
  629.   Result := FTrackList.Count;
  630. end;
  631. function TAudioImage.Add: TCDTrackItem;
  632. var
  633.   NewTrackItem: TCDTrackItem;
  634. begin
  635.   Result := nil;
  636.   try
  637.     NewTrackItem := TCDTrackItem.Create;
  638.     FTrackList.Add(TClass(NewTrackItem));
  639.     Result := NewTrackItem;
  640.   except
  641.     on e: exception do
  642.       FLastError := e.Message;
  643.   end;
  644. end;
  645. function TAudioImage.Insert(Index: Integer): TCDTrackItem;
  646. var
  647.   Track: TCDTrackItem;
  648. begin
  649.   Result := nil;
  650.   try
  651.     if Index <= (FTrackList.Count - 1) then
  652.     begin
  653.       Track := TCDTrackItem.Create;
  654.       FTrackList.Insert(Index, TClass(Track));
  655.       Result := Track;
  656.     end
  657.     else
  658.       FLastError := 'Insert Index Too Large!';
  659.   except
  660.     on e: exception do
  661.       FLastError := e.Message;
  662.   end;
  663. end;
  664. function TAudioImage.GetItem(Index: Integer): TCDTrackItem;
  665. var
  666.   Track: TCDTrackItem;
  667. begin
  668.   Result := nil;
  669.   try
  670.     if Index <= (FTrackList.Count - 1) then
  671.     begin
  672.       Track := TCDTrackItem(FTrackList.Items[Index]);
  673.       result := Track;
  674.     end
  675.     else
  676.       FLastError := 'Item Index Too Large!';
  677.   except
  678.     on e: exception do
  679.       FLastError := e.Message
  680.   end;
  681. end;
  682. procedure TAudioImage.SetItem(Index: Integer; Value: TCDTrackItem);
  683. var
  684.   Track: TCDTrackItem;
  685. begin
  686.   if Index <= (FTrackList.Count - 1) then
  687.   begin
  688.     try // remove the track
  689.       Track := TCDTrackItem(FTrackList.Items[Index]);
  690.       Track.Destroy;
  691.     except
  692.       on e: exception do
  693.         FLastError := e.Message
  694.     end;
  695.     try
  696.       FTrackList.Insert(Index, TClass(Value));
  697.     except
  698.       on e: exception do
  699.         FLastError := e.Message;
  700.     end;
  701.   end
  702.   else
  703.     FLastError := 'Item Index Too Large!';
  704. end;
  705. procedure TAudioImage.CreateCUEFile(TrackID : Integer);
  706. var
  707.   Gap: integer;
  708.   k : string;
  709. begin
  710.   FCUESheet.Add(' TITLE "'+Tracks[trackid].SongTitle+'"');
  711.   FCUESheet.Add(' PERFORMER "'+Performer+'"');
  712.   FCUESheet.Add(' SONGWRITER "'+Songwriter+'"');
  713.   FCUESheet.Add('');
  714.   FCUESheet.Add('FILE "' + Tracks[trackid].CDTrack.TrackFileName + '" WAVE');
  715.   k := Format('%02.02d', [TrackID + 1]);
  716.   FCUESheet.Add('  TRACK ' + k + ' AUDIO');
  717.   Gap := Tracks[trackid].PreGap;
  718.   if (TrackID <> 0) then
  719.       FCUESheet.Add('    PREGAP ' + LBA2HMSF(Gap));
  720.   Gap := Tracks[trackid].TrackIndex;
  721.   FCUESheet.Add('    INDEX 01 ' + LBA2HMSF(Gap));
  722.   Gap := Tracks[trackid].PostGap;
  723.   FCUESheet.Add('    POSTGAP ' + LBA2HMSF(Gap));
  724. end;
  725. function TAudioImage.GetCUESheet : TStringlist;
  726. var
  727.    Index : Integer;
  728. begin
  729.   FCUESheet.Clear;
  730.   For Index := 0 to Self.TrackCount -1 do
  731.    CreateCUEFile(Index);
  732.   FCUESheet.SaveToFile('C:BurnCUE.cue');
  733.   Result := FCUESheet;
  734. end;
  735. end.