unit AudioDTS;

interface

uses KOL, ATLCommon;

type TDTSAudioInfo = PAudioInfo;

function NewAudioDTS: TDTSAudioInfo;

implementation

uses ATLLib;

type TDTSHeader = packed record
       SignatureChunk: Cardinal;
       Buff: array[0..7] of Byte;
     end;

const
  _Channels: array [0..15] of Byte = (1, 2{dual mono}, 2{stereo}, 2{sum - difference}, 2{left and right total},
                                      3, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8);

  _Sample_Rate: array [0..15] of Integer = (0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, 12000, 24000, 48000, 0, 0 );

  _Bitrate: array [0..31] of Double = (32, 56, 64, 96, 112, 128, 192, 224, 256, 320, 384, 448, 512, 576, 640,
                                       768, 960, 1024, 1152, 1280, 1344, 1408, 1411.2, 1472, 1536, 1920, 2048,
                                       3072, 3840, 0{open}, 0{Variable}, 0{Loss-less});

  _SamplesPerBlock = 32;

type
  TAudioDTS = object(TAudioInfo)
  private
  end;

function AudioDTSReader(const AFileName: KOLstring; AudioInfo: TDTSAudioInfo): Boolean; forward;

function NewAudioDTS: TDTSAudioInfo;
begin
    New(Result, Create);
    with TAudioDTS(Result^) do begin
      FAudioVendor:= aDTS;
      FExistsProps:= [apSampleRate, apBitrate, apChannels, apBits, apDuration];
      FReader:= AudioDTSReader;
    end;
end;

function AudioDTSReader(const AFileName: KOLstring; AudioInfo: TDTSAudioInfo): Boolean;
var Source: PStream;
    tehWord: Word;
    Header: TDTSHeader;
    B: Byte;
begin
    with TAudioDTS(AudioInfo^) do begin
      Result := False;
      try
        ResetData;
        Source:= OpenFileRead(AFileName);
        try
          if (Source.Read(Header, SizeOf(TDTSHeader)) = SizeOf(TDTSHeader)) and
             (Header.SignatureChunk = $0180FE7F) then begin

            FFileSize:= Source.Size;
            FValid:= TRUE;

            if (Header.Buff[0] and $80 <> 0) and (((Header.Buff[0] and $7C) shr 2) + 1 <> 32) then Exit;

            B:= ((Header.Buff[3] and $0F) shl 2) or ((Header.Buff[4] and $C0) shr 6);
            if (B and $30) <> 0 then Exit;
            FChannels:= _Channels[B];

            FSampleRate:= _Sample_Rate[(Header.Buff[4] and $3C) shr 2];
            FBitrate:= Round(_Bitrate[((Header.Buff[4] and $03) shl 3) or ((Header.Buff[5] and $E0) shr 5)]);

            if FSampleRate = 0 then Exit;


  //          nbBlocks:= (((Header.Buff[0] and $01) shl 6) or ((Header.Buff[1] and $FC) shr 2)) + 1;
  //          frmsize:= (((Header.Buff[1] and $03) shl 12) or ((Header.Buff[2] and $FF) shl 4) or ((Header.Buff[3] and $F0) shl 4)) + 1;
  //          FBits:= 8 * Round(frmsize / (FChannels * DTS_SAMPLESPERBLOCK * nbBlocks));
            tehWord:= Header.Buff[7] or (Header.Buff[6] shl 8);
            case ((tehWord and $01C0) shr 6) of
              0..1: FBits:= 16;
              2..3: FBits:= 20;
              4..5: FBits:= 24;
              else FBits:= 16;
            end;

            FDuration := FFileSize / (FBitrate * 1000 / 8);
            Result := True;
          end;
        finally
          Source.free;
        end;
      except
      end;
    end;
end;

end.



