MMDSCptr.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:38k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {========================================================================}
  2. {=                (c) 1995-98 SwiftSoft Ronald Dittrich                 =}
  3. {========================================================================}
  4. {=                          All Rights Reserved                         =}
  5. {========================================================================}
  6. {=  D 01099 Dresden             = Fax.: +49 (0)351-8037944              =}
  7. {=  Loewenstr.7a                = info@swiftsoft.de                     =}
  8. {========================================================================}
  9. {=  Actual versions on http://www.swiftsoft.de/mmtools.html             =}
  10. {========================================================================}
  11. {=  This code is for reference purposes only and may not be copied or   =}
  12. {=  distributed in any format electronic or otherwise except one copy   =}
  13. {=  for backup purposes.                                                =}
  14. {=                                                                      =}
  15. {=  No Delphi Component Kit or Component individually or in a collection=}
  16. {=  subclassed or otherwise from the code in this unit, or associated   =}
  17. {=  .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed     =}
  18. {=  without express permission from SwiftSoft.                          =}
  19. {=                                                                      =}
  20. {=  For more licence informations please refer to the associated        =}
  21. {=  HelpFile.                                                           =}
  22. {========================================================================}
  23. {=  $Date: 04.09.98 - 22:15:16 $                                        =}
  24. {========================================================================}
  25. unit MMDSCptr;
  26. {$I COMPILER.INC}
  27. {.$DEFINE _MMDEBUG}
  28. interface
  29. uses
  30.   Windows,
  31.   SysUtils,
  32.   Messages,
  33.   Classes,
  34.   Controls,
  35.   Dialogs,
  36.   MMSystem,
  37.   MMRegs,        { Should be after MMSystem }
  38.   MMUtils,
  39.   MMObj,
  40.   MMDSPObj,
  41.   MMOLE2,
  42.   MMDSound,
  43.   MMD3DTyp,
  44.   MM3D,
  45.   MMWave,
  46.   MMPCMSup,
  47.   MMACMDlg,
  48.   MMWaveIO,
  49.   MMDSMix
  50.   {$IFDEF _MMDEBUG}
  51.   ,MMDebug
  52.   {$ENDIF}
  53.   ;
  54. const
  55.   NOTIFICATIONTHREAD_TIMEOUT = INFINITE;
  56. type
  57.   EMMDSCaptureError = class(Exception);
  58.   TMMDSCapture = class;
  59.   TMMDSCaptureBuffer = class;
  60.   {----------------------------------------------------------------------------}
  61.   TMMDSCaptureBufferNotifyThread = class(TMMThreadEx)
  62.   private
  63.     FBuffer          : TMMDSCaptureBuffer;
  64.     FSystemEvent,
  65.     FBufferStopEvent : THandle;
  66.     FSyncing         : Boolean;
  67.     procedure DoBufferStop;
  68.   protected
  69.     procedure Execute; override;
  70.   public
  71.     constructor Create(ABuffer: TMMDSCaptureBuffer);
  72.     destructor Destroy; override;
  73.   end;
  74.   {----------------------------------------------------------------------------}
  75.   TMMDSCaptureBuffer = class(TMMObject)
  76.   private
  77.     FOwned           : Boolean;
  78.     FCaptureBuffer   : IDirectSoundCaptureBuffer;
  79.     FNotify          : IDirectSoundNotify;
  80.     FCapture         : TMMDSCapture;
  81.     FNotifyThread    : TMMDSCaptureBufferNotifyThread;
  82.     FName            : string;
  83.     FMemory          : TMemoryStream;
  84.     FBufferLength    : Longint;
  85.     FFormat          : PWaveFormatEx;
  86.     FResetPosition   : Boolean;
  87.     FCapturing       : Boolean;
  88.     FBufferStopEvent : THandle;
  89.     FOnBufferStop,
  90.     FOnRelease       : TNotifyEvent;
  91.     FCBOrigin,                      // Origin of capture buffer in the whole stream
  92.     FCBSize,                        // buffer size
  93.     FCBDataPosition  : Integer;     // bytes processed
  94.     function  GetPosition: Longint;
  95.     function  GetReadPosition: Longint;
  96.     function  GetCapturing: Boolean;
  97.     function  GetCaptureLength: Longint;
  98.     procedure SetFormat(Value: PWaveFormatEx);
  99.     function  GetCaps: TDSCBCAPS;
  100.     procedure SetCaptureBuffer(Value: IDirectSoundCaptureBuffer);
  101.     function  IsThereNewData: Boolean;
  102.   protected
  103.     procedure Capture;
  104.     procedure Stop;
  105.     procedure ReleaseBuffer;
  106.     procedure FreeBuffer;
  107.     procedure CopyData;
  108.     property  DirectSoundCaptureBuffer: IDirectSoundCaptureBuffer read FCaptureBuffer write SetCaptureBuffer;
  109.     property  DirectSoundNotify: IDirectSoundNotify read FNotify;
  110.   public
  111.     constructor Create(Size: Longint; Format: PWaveFormatEx); virtual;
  112.     destructor  Destroy; override;
  113.     property OnBufferStop: TNotifyEvent read FOnBufferStop write FOnBufferStop;
  114.     property OnRelease: TNotifyEvent read FOnRelease write FOnRelease;
  115.     property Caps: TDSCBCAPS read GetCaps;
  116.     property Name: string read FName;
  117.     property Memory: TMemoryStream read FMemory;
  118.     property PWaveFormat: PWaveFormatEx read FFormat write SetFormat;
  119.     property BufferLength: Longint read FBufferLength write FBufferLength;
  120.     property CaptureLength: Longint read GetCaptureLength;
  121.     property Capturing: Boolean read GetCapturing;
  122.     property Position: Longint read GetPosition;
  123.     property ResetPosition: Boolean read FResetPosition write FResetPosition;
  124.   end;
  125.   {----------------------------------------------------------------------------}
  126.   TMMDSCaptureCaps = class(TMMObject)
  127.   private
  128.     FChannels: Integer;
  129.     FFormats : Integer;
  130.     function  GetHasFormat(Index: Integer): Boolean;
  131.     procedure SetHasFormat(Index: Integer; Value: Boolean);
  132.     procedure SetIntDummy(Value: Integer);
  133.   protected
  134.     procedure SetCaps(const Caps: TDSCCAPS);
  135.   public
  136.     property Formats: Integer read FFormats;
  137.   published
  138.     property Channels: Integer read FChannels write SetIntDummy;
  139.     property Has11025Mono8bit: Boolean index 0 read GetHasFormat write SetHasFormat;
  140.     property Has11025Mono16bit: Boolean index 1 read GetHasFormat write SetHasFormat;
  141.     property Has11025Stereo8bit: Boolean index 2 read GetHasFormat write SetHasFormat;
  142.     property Has11025Stereo16bit: Boolean index 3 read GetHasFormat write SetHasFormat;
  143.     property Has22050Mono8bit: Boolean index 4 read GetHasFormat write SetHasFormat;
  144.     property Has22050Mono16bit: Boolean index 5 read GetHasFormat write SetHasFormat;
  145.     property Has22050Stereo8bit: Boolean index 6 read GetHasFormat write SetHasFormat;
  146.     property Has22050Stereo16bit: Boolean index 7 read GetHasFormat write SetHasFormat;
  147.     property Has44100Mono8bit: Boolean index 8 read GetHasFormat write SetHasFormat;
  148.     property Has44100Mono16bit: Boolean index 9 read GetHasFormat write SetHasFormat;
  149.     property Has44100Stereo8bit: Boolean index 10 read GetHasFormat write SetHasFormat;
  150.     property Has44100Stereo16bit: Boolean index 11 read GetHasFormat write SetHasFormat;
  151.   end;
  152.   TMMDSBufferEvent = procedure(Sender: TObject; Buffer: TMMDSCaptureBuffer) of object;
  153.   {----------------------------------------------------------------------------}
  154.   TMMDSCapture = class(TMMNonVisualComponent)
  155.   private
  156.     DirectCapture   : IDirectSoundCapture;
  157.     FDevices        : TList;
  158.     FDeviceID       : TMMDeviceID;
  159.     FProductName    : String;
  160.     FBuffers        : TList;
  161.     FCaps           : TMMDSCaptureCaps;
  162.     FOnBufferStop   : TMMDSBufferEvent;
  163.     procedure SetCaps(Value: TMMDSCaptureCaps);
  164.     function  GetCaps: TMMDSCaptureCaps;
  165.     function  GetNumDevs: integer;
  166.     function  GetDevices(Index: integer): PDSDRIVERDESC;
  167.     procedure SetDeviceID(DeviceID: TMMDeviceID);
  168.     procedure SetProductName(const Value: String);
  169.     function  GetBuffer(Index: integer): TMMDSCaptureBuffer;
  170.     function  GetBufferName(const Name: string): TMMDSCaptureBuffer;
  171.     function  GetBufferCount: integer;
  172.     procedure SetupBuffer(var Name: string; Buffer: TMMDSCaptureBuffer);
  173.     procedure ClearBuffer(Buffer: TMMDSCaptureBuffer);
  174.     function  FindFreeName(const Name: String): String;
  175.     function  GetOpened: Boolean;
  176.   protected
  177.     procedure BufferStop(Buffer: TMMDSCaptureBuffer); dynamic;
  178.   public
  179.     constructor Create(AOwner: TComponent); override;
  180.     destructor  Destroy; override;
  181.     procedure Open;
  182.     procedure Close;
  183.     function  AddBuffer(var Name: string; BufferLength: Longint; Format: PWaveFormatEx): TMMDSCaptureBuffer;
  184.     procedure RemoveBuffer(Buffer: TMMDSCaptureBuffer);
  185.     procedure CaptureBuffer(Buffer: TMMDSCaptureBuffer);
  186.     procedure StopBuffer(Buffer: TMMDSCaptureBuffer);
  187.     procedure UpdateData(Buffer: TMMDSCaptureBuffer);
  188.     procedure FreeBuffers;
  189.     property  Buffer[Index: integer]: TMMDSCaptureBuffer read GetBuffer;
  190.     property  BufferByName[const Name: string]: TMMDSCaptureBuffer read GetBufferName;
  191.     property  BufferCount: integer read GetBufferCount;
  192.     property  NumDevs: integer read GetNumDevs;
  193.     property  Devices[Index: integer]: PDSDRIVERDESC read GetDevices;
  194.     property  Opened: Boolean read GetOpened;
  195.   published
  196.     property  OnBufferStop: TMMDSBufferEvent read FOnBufferStop write FOnBufferStop;
  197.     property  CaptureCaps: TMMDSCaptureCaps read GetCaps write SetCaps;
  198.     property  DeviceID: TMMDeviceID read FDeviceID write SetDeviceID default 0;
  199.     property  ProductName: String read FProductName write SetProductName stored False;
  200.   end;
  201.   {----------------------------------------------------------------------------}
  202.   TMMDSCaptureChannel = class(TMMDSPComponent)
  203.   private
  204.     FCaptureBuffer : TMMDSCaptureBuffer;
  205.     FCapture       : TMMDSCapture;
  206.     FOnCaptureStop : TNotifyEvent;
  207.     function  GetInputFormat: string;
  208.     procedure SetInputFormat(aValue: string);
  209.     function  GetPosition: Longint;
  210.     procedure SetReset(aValue: Boolean);
  211.     function  GetReset: Boolean;
  212.     function  GetCapturing: Boolean;
  213.     function  GetBufferLength: Longint;
  214.     procedure SetBufferLength(Value: Longint);
  215.     function  GetCaptureLength: Longint;
  216.     procedure BufferStop(Sender: TObject);
  217.   protected
  218.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  219.     procedure SetPWaveFormat(aValue: PWaveFormatEx); override;
  220.     procedure DefineProperties(Filer: TFiler); override;
  221.     procedure ReadData(Stream: TStream); virtual;
  222.     procedure WriteData(Stream: TStream); virtual;
  223.   public
  224.     constructor Create(AOwner: TComponent); override;
  225.     destructor  Destroy; override;
  226.     procedure GetVUMeter(var LeftValue, RightValue, BothValue: integer; Interval: integer);
  227.     procedure SaveFormatInRegistry(RootKey: HKEY; Localkey, Field: string);
  228.     procedure LoadFormatFromRegistry(RootKey: HKEY; Localkey, Field: string);
  229.     function  SelectFormat: Boolean;
  230.     procedure SetPCMFormat(Mode: TMMMode; Bits: TMMBits; SampleRate: Longint);
  231.     procedure Reset;
  232.     procedure Init;
  233.     procedure Capture;
  234.     procedure Stop;
  235.     function SaveToRAWFile(FName: TFileName): Boolean;
  236.     function SaveToWaveFile(FName: TFileName): Boolean;
  237.     property PWaveFormat;
  238.     property CaptureBuffer: TMMDSCaptureBuffer read FCaptureBuffer;
  239.     property Position: Longint read GetPosition;
  240.     property CaptureLength: Longint read GetCaptureLength;
  241.     property Capturing: Boolean read GetCapturing;
  242.   published
  243.     property OnCaptureStop: TNotifyEvent read FOnCaptureStop write FOnCaptureStop;
  244.     property CaptureObject: TMMDSCapture read FCapture write FCapture;
  245.     property BufferLength: Longint read GetBufferLength write SetBufferLength;
  246.     property InputFormat: string read GetInputFormat write SetInputFormat stored False;
  247.     property ResetPosition: Boolean read GetReset write SetReset default True;
  248.   end;
  249. implementation
  250. {$IFDEF DELPHI3} resourcestring{$ELSE} const {$ENDIF}
  251.   SLockFailed = 'DirectSoundCaptureBuffer Lock failed';
  252.   SCannotConvertWave = 'Unable to convert sound data';
  253. procedure DSCheckAvailable;
  254. begin
  255.   if _WinNT3_ then
  256.     raise EMMDSCaptureError.Create(LoadResStr(IDS_DSNOTSUPPORTED));
  257.   if not LoadDSoundDLL then
  258.     raise EMMDSCaptureError.Create(LoadResStr(IDS_DLLERROR) + ' DSOUND.DLL...');
  259. end;
  260. {== TMMDSCapture ==============================================================}
  261. constructor TMMDSCapture.Create(AOwner: TComponent);
  262. begin
  263.   inherited Create(AOwner);
  264.   DSCheckAvailable;
  265.   FBuffers := TList.Create;
  266.   FCaps := TMMDSCaptureCaps.Create;
  267.   FDevices := TList.Create;
  268.   if Assigned(DirectSoundCaptureEnumerate) then
  269.      DirectSoundCaptureEnumerate(DriverEnumerate, FDevices);
  270.   SetDeviceID(0);
  271.   ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
  272.   if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
  273. end;
  274. {-- TMMDSCapture --------------------------------------------------------------}
  275. destructor TMMDSCapture.Destroy;
  276. begin
  277.   Close;
  278.   FCaps.Free;
  279.   FBuffers.Free;
  280.   FreeDriverList(FDevices);
  281.   FDevices.Free;
  282.   inherited Destroy;
  283. end;
  284. {-- TMMDSCapture --------------------------------------------------------------}
  285. procedure TMMDSCapture.BufferStop(Buffer: TMMDSCaptureBuffer);
  286. begin
  287.    UpdateData(Buffer);
  288.    if Assigned(FOnBufferStop) then FOnBufferStop(Self, Buffer);
  289.    if Assigned(Buffer.FOnBufferStop) then Buffer.FOnBufferStop(Buffer);
  290. end;
  291. {-- TMMDSCapture --------------------------------------------------------------}
  292. function TMMDSCapture.GetDevices(Index: integer): PDSDRIVERDESC;
  293. begin
  294.   Result := PDSDRIVERDESC(FDevices.Items[Index])
  295. end;
  296. {-- TMMDSCapture --------------------------------------------------------------}
  297. procedure TMMDSCapture.SetProductName(const Value: String);
  298. begin
  299. end;
  300. {-- TMMDSCapture --------------------------------------------------------------}
  301. function TMMDSCapture.GetNumDevs: integer;
  302. begin
  303.   Result := FDevices.Count;
  304. end;
  305. {-- TMMDSCapture --------------------------------------------------------------}
  306. procedure TMMDSCapture.SetDeviceID(DeviceID: TMMDeviceID);
  307. begin
  308.   if (DirectCapture <> nil) then
  309.     raise EMMDSCaptureError.Create(LoadResStr(IDS_PROPERTYOPEN));
  310.   if (NumDevs > 0) and (DeviceID >= 0) and (DeviceID < NumDevs) then
  311.   begin
  312.     GetCaps;
  313.     FProductName := Devices[DeviceID]^.Description;
  314.     FDeviceID := DeviceID;
  315.   end
  316.   else
  317.   begin
  318.     FProductName := LoadResStr(IDS_DSNODEVICE);
  319.     FDeviceID := InvalidID;
  320.   end;
  321. end;
  322. {-- TMMDSCapture --------------------------------------------------------------}
  323. procedure TMMDSCapture.Open;
  324. begin
  325.   if LoadDSoundDLL and (DirectCapture = nil) then
  326.   begin
  327.     if (DeviceID = InvalidID) then
  328.       raise EMMDSCaptureError.Create(LoadResStr(IDS_INVALIDDEVICEID));
  329.     try
  330.       DSCheck(DirectSoundCaptureCreate(Devices[FDeviceID]^.lpGUID, DirectCapture, nil));
  331.     except
  332.       Close;
  333.       raise;
  334.     end;
  335.   end;
  336. end;
  337. {-- TMMDSCapture --------------------------------------------------------------}
  338. function TMMDSCapture.GetOpened: Boolean;
  339. begin
  340.   Result := DirectCapture <> nil;
  341. end;
  342. {-- TMMDSCapture --------------------------------------------------------------}
  343. procedure TMMDSCapture.Close;
  344. begin
  345.   FreeBuffers;
  346.   if (DirectCapture <> nil) then
  347.   begin
  348.     DirectCapture.Release;
  349.     DirectCapture := nil;
  350.   end;
  351. end;
  352. {-- TMMDSCapture --------------------------------------------------------------}
  353. procedure TMMDSCapture.SetCaps(Value: TMMDSCaptureCaps);
  354. begin
  355. end;
  356. {-- TMMDSCapture --------------------------------------------------------------}
  357. function TMMDSCapture.GetCaps: TMMDSCaptureCaps;
  358. var
  359.   Caps: TDSCCAPS;
  360. begin
  361.   ZeroMemory(@Caps, SizeOf(Caps));
  362.   Caps.dwSize := SizeOf(Caps);
  363.   if (DeviceID <> InvalidID) then
  364.   begin
  365.     if not Opened then
  366.     begin
  367.       Open;
  368.       try
  369.         DirectCapture.GetCaps(Caps);
  370.       finally
  371.         Close;
  372.       end;
  373.     end
  374.     else
  375.       DirectCapture.GetCaps(Caps);
  376.   end;
  377.   FCaps.SetCaps(Caps);
  378.   Result := FCaps;
  379. end;
  380. {-- TMMDSCapture --------------------------------------------------------------}
  381. function TMMDSCapture.GetBuffer(Index: integer): TMMDSCaptureBuffer;
  382. begin
  383.   Result := TMMDSCaptureBuffer(FBuffers[Index])
  384. end;
  385. {-- TMMDSCapture --------------------------------------------------------------}
  386. function TMMDSCapture.GetBufferName(const Name: string): TMMDSCaptureBuffer;
  387. var
  388.   i: integer;
  389. begin
  390.   for i := 0 to FBuffers.Count-1 do
  391.   begin
  392.     Result := FBuffers[i];
  393.     if Result.Name = Name then
  394.       exit;
  395.   end;
  396.   Result := nil;
  397. end;
  398. {-- TMMDSCapture --------------------------------------------------------------}
  399. function TMMDSCapture.FindFreeName(const Name: String): String;
  400. var
  401.   i: integer;
  402. begin
  403.   if (BufferByName[Name] <> nil) or (Name = '') then
  404.   begin
  405.     i := 0;
  406.     repeat
  407.       Inc(i);
  408.       Result := Name + IntToStr(i);
  409.     until BufferByName[Result] = nil;
  410.   end else
  411.     Result := Name;
  412. end;
  413. {-- TMMDSCapture --------------------------------------------------------------}
  414. function TMMDSCapture.GetBufferCount: integer;
  415. begin
  416.   Result := FBuffers.Count;
  417. end;
  418. {-- TMMDSCapture --------------------------------------------------------------}
  419. procedure TMMDSCapture.SetupBuffer(var Name: string; Buffer: TMMDSCaptureBuffer);
  420. var
  421.   BufferDesc: TDSCBUFFERDESC;
  422.   BufferInterface: IDirectSoundCaptureBuffer;
  423. begin
  424.   if (Buffer = nil) or (Buffer.PWaveFormat = nil) then exit;
  425.   Name := FindFreeName(Name);
  426.   Buffer.FName := Name;
  427.   ZeroMemory(@BufferDesc, SizeOf(BufferDesc));
  428.   with BufferDesc do
  429.   begin
  430.     dwSize := SizeOf(BufferDesc);
  431.     dwFlags := 0;
  432.     dwBufferBytes := Buffer.BufferLength;
  433.     lpwfxFormat := Buffer.PWaveFormat;
  434.    end;
  435.   Buffer.DirectSoundCaptureBuffer := nil;
  436.   DSCheck(DirectCapture.CreateCaptureBuffer(BufferDesc,BufferInterface, nil));
  437.   Buffer.DirectSoundCaptureBuffer := BufferInterface;
  438.   Buffer.FCapture := Self;
  439.   FBuffers.Add(Buffer);
  440. end;
  441. {-- TMMDSCapture --------------------------------------------------------------}
  442. function TMMDSCapture.AddBuffer(var Name: string; BufferLength: Longint; Format: PWaveFormatEx): TMMDSCaptureBuffer;
  443. begin
  444.   Result := TMMDSCaptureBuffer.Create(BufferLength, Format);
  445.   try
  446.     SetupBuffer(Name, Result);
  447.   except
  448.     Result.Free;
  449.     raise;
  450.   end;
  451. end;
  452. {-- TMMDSCapture --------------------------------------------------------------}
  453. procedure TMMDSCapture.FreeBuffers;
  454. begin
  455.   while BufferCount > 0 do RemoveBuffer(Buffer[0]);
  456. end;
  457. {-- TMMDSCapture --------------------------------------------------------------}
  458. procedure TMMDSCapture.ClearBuffer(Buffer: TMMDSCaptureBuffer);
  459. var
  460.   i: integer;
  461. begin
  462.   i := FBuffers.IndexOf(Buffer);
  463.   if i >= 0 then
  464.   begin
  465.     StopBuffer(Buffer);
  466.     Buffer.ReleaseBuffer;
  467.     FBuffers.Delete(i);
  468.     FBuffers.Pack;
  469.   end;
  470. end;
  471. {-- TMMDSCapture --------------------------------------------------------------}
  472. procedure TMMDSCapture.RemoveBuffer(Buffer: TMMDSCaptureBuffer);
  473. begin
  474.   ClearBuffer(Buffer);
  475.   Buffer.FreeBuffer;
  476. end;
  477. {-- TMMDSCapture --------------------------------------------------------------}
  478. procedure TMMDSCapture.CaptureBuffer(Buffer: TMMDSCaptureBuffer);
  479. begin
  480.   if (Buffer <> nil) and (Buffer.DirectSoundCaptureBuffer <> nil) then
  481.       Buffer.Capture;
  482. end;
  483. {-- TMMDSCapture --------------------------------------------------------------}
  484. procedure TMMDSCapture.StopBuffer(Buffer: TMMDSCaptureBuffer);
  485. begin
  486.   if (Buffer <> nil) and (Buffer.DirectSoundCaptureBuffer <> nil) then
  487.       Buffer.Stop;
  488. end;
  489. {-- TMMDSCapture --------------------------------------------------------------}
  490. procedure TMMDSCapture.UpdateData(Buffer: TMMDSCaptureBuffer);
  491. begin
  492.    Buffer.CopyData
  493. end;
  494. {== TMMDSCaptureCaps ==========================================================}
  495. procedure TMMDSCaptureCaps.SetIntDummy(Value: Integer);
  496. begin
  497. end;
  498. {-- TMMDSCaptureCaps ----------------------------------------------------------}
  499. function TMMDSCaptureCaps.GetHasFormat(Index: Integer): Boolean;
  500. begin
  501.   Result := FFormats and (1 shl Index) <> 0
  502. end;
  503. {-- TMMDSCaptureCaps ----------------------------------------------------------}
  504. procedure TMMDSCaptureCaps.SetHasFormat(Index: Integer; Value: Boolean);
  505. begin
  506. end;
  507. {-- TMMDSCaptureCaps ----------------------------------------------------------}
  508. procedure TMMDSCaptureCaps.SetCaps(const Caps: TDSCCAPS);
  509. begin
  510.   FFormats := Caps.dwFormats;
  511.   FChannels := Caps.dwChannels;
  512. end;
  513. const
  514.   LoopFlags: array[Boolean] of Integer = (0, DSCBSTART_LOOPING);
  515. {== TMMDSCaptureBuffer ========================================================}
  516. constructor TMMDSCaptureBuffer.Create(Size: Longint; Format: PWaveFormatEx);
  517. begin
  518.    inherited Create;
  519.    FMemory := TMemoryStream.Create;
  520.    FBufferLength := Size;
  521.    FFormat       := wioCopyWaveFormat(Format);
  522.    FResetPosition:= True;
  523. end;
  524. {-- TMMDSCaptureBuffer --------------------------------------------------------}
  525. destructor TMMDSCaptureBuffer.Destroy;
  526. begin
  527.   ReleaseBuffer;
  528.   FMemory.Free;
  529.   GlobalFreeMem(Pointer(FFormat));
  530.   inherited Destroy;
  531. end;
  532. {-- TMMDSCaptureBuffer --------------------------------------------------------}
  533. procedure TMMDSCaptureBuffer.SetFormat(Value: PWaveFormatEx);
  534. begin
  535.    GlobalFreeMem(Pointer(FFormat));
  536.    FFormat := wioCopyWaveFormat(Value);
  537. end;
  538. {-- TMMDSCaptureBuffer --------------------------------------------------------}
  539. function TMMDSCaptureBuffer.GetCaptureLength: Longint;
  540. begin
  541.    Result := FMemory.Size
  542. end;
  543. {-- TMMDSCaptureBuffer --------------------------------------------------------}
  544. procedure TMMDSCaptureBuffer.SetCaptureBuffer(Value: IDirectSoundCaptureBuffer);
  545. var
  546.   Caps: TDSCBCAPS;
  547.   Positions: array[0..2] of TDSBPOSITIONNOTIFY;
  548. begin
  549.   ReleaseBuffer;
  550.   FCaptureBuffer := Value;
  551.   if Value <> nil then
  552.   begin
  553.     if FCaptureBuffer.QueryInterface(IID_IDirectSoundNotify, FNotify) = S_OK then
  554.     begin
  555.       ZeroMemory(@Caps, SizeOf(Caps));
  556.       Caps.dwSize := SizeOf(Caps);
  557.       FCaptureBuffer.GetCaps(Caps);
  558.       FCBSize := Caps.dwBufferBytes;
  559.       FBufferStopEvent := CreateEvent(nil, False, False, nil);
  560.       Positions[0].dwOffset := DSBPN_OFFSETSTOP;
  561.       Positions[0].hEventNotify := FBufferStopEvent;
  562.       FNotify.SetNotificationPositions(1, @Positions);
  563.       FNotifyThread := TMMDSCaptureBufferNotifyThread.Create(Self);
  564.     end;
  565.   end;
  566. end;
  567. {-- TMMDSCaptureBuffer --------------------------------------------------------}
  568. function TMMDSCaptureBuffer.GetPosition: Longint;
  569. var
  570.    aResult: DWORD;
  571. begin
  572.   if (FCaptureBuffer <> nil) then
  573.   begin
  574.     FCaptureBuffer.GetCurrentPosition(aResult, DWORD(nil^));
  575.     Result := aResult;
  576.   end
  577.   else
  578.     Result := 0;
  579. end;
  580. {-- TMMDSCaptureBuffer --------------------------------------------------------}
  581. function TMMDSCaptureBuffer.GetReadPosition: Longint;
  582. var
  583.    aResult: DWORD;
  584. begin
  585.   if (FCaptureBuffer <> nil) then
  586.   begin
  587.      FCaptureBuffer.GetCurrentPosition(DWORD(nil^), aResult);
  588.      Result := aResult;
  589.   end
  590.   else Result := 0;
  591. end;
  592. {-- TMMDSCaptureBuffer --------------------------------------------------------}
  593. function TMMDSCaptureBuffer.GetCapturing: Boolean;
  594. var
  595.   Status: DWORD;
  596. begin
  597.   if FCaptureBuffer <> nil then
  598.   begin
  599.     FCaptureBuffer.GetStatus(Status);
  600.     Result := Status and DSCBSTATUS_CAPTURING <> 0;
  601.   end
  602.   else
  603.     Result := False;
  604. end;
  605. {-- TMMDSCaptureBuffer --------------------------------------------------------}
  606. function TMMDSCaptureBuffer.GetCaps: TDSCBCAPS;
  607. begin
  608.   ZeroMemory(@Result, SizeOf(Result));
  609.   Result.dwSize := SizeOf(Result);
  610.   if FCaptureBuffer <> nil then
  611.      FCaptureBuffer.GetCaps(Result);
  612. end;
  613. {-- TMMDSCaptureBuffer --------------------------------------------------------}
  614. procedure TMMDSCaptureBuffer.Capture;
  615. begin
  616.   if FCaptureBuffer <> nil then
  617.   begin
  618.     if not Capturing then
  619.     begin
  620.       FCBOrigin := 0;
  621.       FCBDataPosition := GetPosition;
  622.       if FResetPosition then Memory.Clear;
  623.     end;
  624.     FCaptureBuffer.Start(LoopFlags[False]);
  625.     FCapturing := True;
  626.   end;
  627. end;
  628. {-- TMMDSCaptureBuffer --------------------------------------------------------}
  629. procedure TMMDSCaptureBuffer.Stop;
  630. begin
  631.   if FCaptureBuffer <> nil then
  632.   begin
  633.     FCapturing := False;
  634.     FCaptureBuffer.Stop;
  635.   end;
  636. end;
  637. {-- TMMDSCaptureBuffer --------------------------------------------------------}
  638. procedure TMMDSCaptureBuffer.ReleaseBuffer;
  639. begin
  640.   if FCaptureBuffer <> nil then
  641.   begin
  642.     FCaptureBuffer.Release;
  643.     FCaptureBuffer := nil;
  644.     if Assigned(FNotify) then
  645.     begin
  646.       with FNotifyThread do
  647.       begin
  648.         Terminate;
  649.         SetEvent(FSystemEvent);
  650.         if FSyncing then FreeOnTerminate := True else Free;
  651.       end;
  652.       FNotifyThread := nil;
  653.       FNotify.Release;
  654.       FNotify := nil;
  655.       CloseHandle(FBufferStopEvent);
  656.       FBufferStopEvent := 0;
  657.     end;
  658.     if Assigned(FOnRelease) then
  659.        FOnRelease(Self);
  660.   end;
  661. end;
  662. {-- TMMDSCaptureBuffer --------------------------------------------------------}
  663. procedure TMMDSCaptureBuffer.FreeBuffer;
  664. begin
  665.   ReleaseBuffer;
  666.   if not FOwned then Free;
  667. end;
  668. {-- TMMDSCaptureBuffer --------------------------------------------------------}
  669. function TMMDSCaptureBuffer.IsThereNewData: Boolean;
  670. begin
  671.   Result := FCBOrigin + GetPosition > FCBDataPosition
  672. end;
  673. {$DEFINE ACCUMULATE}
  674. {-- TMMDSCaptureBuffer --------------------------------------------------------}
  675. procedure TMMDSCaptureBuffer.CopyData;
  676. var
  677.   p1, p2: Pointer;
  678.   l1, l2: DWORD;
  679.   CaptureCursor,
  680. {$IFDEF ACCUMULATE}
  681.   bl2,
  682. {$ENDIF}
  683.   bp1, bl1: DWORD;
  684. begin
  685.   if not IsThereNewData then
  686.     exit;
  687.   DSCheck(FCaptureBuffer.GetCurrentPosition(DWORD(nil^), CaptureCursor));
  688.   if FCBDataPosition < FCBOrigin then
  689.   begin
  690.     bp1 := FCBDataPosition - (FCBOrigin - FCBSize);
  691.     bl1 := FCBSize - bp1;
  692. {$IFDEF ACCUMULATE}
  693.     bl2 := CaptureCursor;
  694. {$ENDIF}
  695.   end else
  696.   begin
  697.     bp1 := FCBDataPosition - FCBOrigin;
  698.     bl1 := CaptureCursor - bp1;
  699. {$IFDEF ACCUMULATE}
  700.     bl2 := 0;
  701. {$ENDIF}
  702.   end;
  703. {$IFDEF _MMDEBUG}
  704.     DB_FormatLn(0, 'Locking capture buffer from %d to %d and %d to %d',
  705.       [bp1, bp1 + bl1, 0, {$IFDEF ACCUMULATE}bl2{$ELSE}0{$ENDIF}]);
  706. {$ENDIF}
  707.   try
  708.     with Memory do
  709. {$IFDEF ACCUMULATE}
  710.       Position := Size;
  711. {$ELSE}
  712.       if bp1 = 0 then Clear else Position := Size;
  713. {$ENDIF}
  714.     DSCheck(FCaptureBuffer.Lock(bp1, bl1, p1, l1, p2, l2, 0));
  715.     Memory.Write(p1^, l1);
  716.     if l2 > 0 then Memory.Write(p2^, l2);
  717.     DSCheck(FCaptureBuffer.Unlock(p1, l1, p2, l2));
  718. {$IFDEF ACCUMULATE}
  719.     if bl2 > 0 then
  720.     begin
  721.        DSCheck(FCaptureBuffer.Lock(0, bl2, p1, l1, p2, l2, 0));
  722.        Memory.Write(p1^, l1);
  723.        if l2 > 0 then Memory.Write(p2^, l2);
  724.        DSCheck(FCaptureBuffer.Unlock(p1, l1, p2, l2));
  725.     end;
  726. {$ENDIF}
  727. {$IFDEF ACCUMULATE}
  728.     Inc(FCBDataPosition, bl1 + bl2);
  729. {$ELSE}
  730.     Inc(FCBDataPosition, bl1);
  731. {$ENDIF}
  732.   except
  733.     ReleaseBuffer;
  734.     raise EMMDSCaptureError.Create(SLockFailed);
  735.   end;
  736. end;
  737. {== TMMDSCaptureBufferNotifyThread ============================================}
  738. constructor TMMDSCaptureBufferNotifyThread.Create(ABuffer: TMMDSCaptureBuffer);
  739. begin
  740.   inherited Create(False);
  741.   FBuffer := ABuffer;
  742.   FSystemEvent := CreateEvent(nil, False, False, nil);
  743. end;
  744. {-- TMMDSCaptureBufferNotifyThread --------------------------------------------}
  745. destructor TMMDSCaptureBufferNotifyThread.Destroy;
  746. begin
  747.   CloseHandle(FSystemEvent);
  748.   inherited;
  749. end;
  750. {-- TMMDSCaptureBufferNotifyThread --------------------------------------------}
  751. procedure TMMDSCaptureBufferNotifyThread.Execute;
  752. var
  753.   HandleCount: Integer;
  754. begin
  755.   while not Terminated do
  756.   begin
  757.     if FBuffer.DirectSoundCaptureBuffer <> nil then
  758.     begin
  759.       FBufferStopEvent := FBuffer.FBufferStopEvent;
  760.       HandleCount := 2;
  761.     end
  762.     else
  763.       HandleCount := 1;
  764. {$IFDEF _MMDEBUG}
  765.     if HandleCount = 1
  766.       then DB_FormatLn(0, 'Thread: Waiting for system event %d', [FSystemEvent])
  767.       else DB_FormatLn(0, 'Thread: Waiting for system event %d and stop event %d', [FSystemEvent, FBufferStopEvent]);
  768. {$ENDIF}
  769.     case WaitForMultipleObjects(HandleCount, @FSystemEvent, False,
  770.          NOTIFICATIONTHREAD_TIMEOUT) - WAIT_OBJECT_0 of
  771.       0: {$IFDEF _MMDEBUG}
  772.          DB_FormatLn(0, 'Thread: System event fired', [0])
  773.          {$ENDIF}
  774.          ;
  775.       1: {$IFDEF _MMDEBUG}
  776.          begin
  777.            DB_FormatLn(0, 'Thread: Stop event, synchronizing...', [0]);
  778.          {$ENDIF}
  779.            Synchronize(DoBufferStop);
  780.          {$IFDEF _MMDEBUG}
  781.          end;
  782.          {$ENDIF}
  783.     end;
  784.   end;
  785. end;
  786. {-- TMMDSCaptureBufferNotifyThread --------------------------------------------}
  787. procedure TMMDSCaptureBufferNotifyThread.DoBufferStop;
  788. begin
  789.   FSyncing := True;
  790.   try
  791.      { detecting full loop by CursorPos }
  792.     with FBuffer do
  793.     if (GetPosition = 0) then Inc(FCBOrigin, FCBSize);
  794.     if Assigned(FBuffer.FCapture) then
  795.        FBuffer.FCapture.BufferStop(FBuffer);
  796.   finally
  797.     FSyncing := False;
  798.   end;
  799. end;
  800. {== TMMDSCaptureChannel =======================================================}
  801. constructor TMMDSCaptureChannel.Create(AOwner: TComponent);
  802. begin
  803.   inherited Create(AOwner);
  804.   DSCheckAvailable;
  805.   FCaptureBuffer := TMMDSCaptureBuffer.Create(100000,nil);
  806.   FCaptureBuffer.FOnBufferStop := BufferStop;
  807.   FCaptureBuffer.FOwned := True;
  808.   SetPCMFormat(mMono, b8Bit, 11025);
  809.    ErrorCode := ComponentRegistered(InitCode, Self, ClassName);
  810.    if (ErrorCode <> 0) then RegisterFailed(InitCode, Self , ClassName);
  811. end;
  812. {-- TMMDSCaptureChannel -------------------------------------------------------}
  813. destructor TMMDSCaptureChannel.Destroy;
  814. begin
  815.   if FCapture <> nil then FCapture.Close;
  816.   FCaptureBuffer.Free;
  817.   inherited Destroy;
  818. end;
  819. {-- TMMDSCaptureChannel -------------------------------------------------------}
  820. procedure TMMDSCaptureChannel.Notification(AComponent: TComponent; Operation: TOperation);
  821. begin
  822.   inherited Notification(AComponent, Operation);
  823.   if (Operation = opRemove) and (AComponent = FCapture) then
  824.     FCapture := Nil;
  825. end;
  826. {-- TMMDSCaptureChannel -------------------------------------------------------}
  827. procedure TMMDSCaptureChannel.BufferStop(Sender: TObject);
  828. begin
  829.   if Assigned(FOnCaptureStop) then FOnCaptureStop(Self);
  830.   if FCaptureBuffer.GetPosition = 0 then
  831.      FCapture.RemoveBuffer(FCaptureBuffer);
  832. end;
  833. {-- TMMDSCaptureChannel -------------------------------------------------------}
  834. procedure TMMDSCaptureChannel.Init;
  835. var
  836.   AName: string;
  837. begin
  838.   if (FCapture <> nil) and (BufferLength > 0) then
  839.   with FCapture do
  840.   begin
  841.      if (FCaptureBuffer.DirectSoundCaptureBuffer = nil) then
  842.      begin
  843.         FCapture.Open;
  844.         SetupBuffer(AName, FCaptureBuffer);
  845.      end;
  846.   end;
  847. end;
  848. {-- TMMDSCaptureChannel -------------------------------------------------------}
  849. procedure TMMDSCaptureChannel.Reset;
  850. begin
  851.   if Assigned(FCaptureBuffer) then
  852.      FCapture.RemoveBuffer(FCaptureBuffer);
  853. end;
  854. {-- TMMDSCaptureChannel -------------------------------------------------------}
  855. procedure TMMDSCaptureChannel.Capture;
  856. begin
  857.   Init;
  858.   if FCapture <> nil then
  859.      FCapture.CaptureBuffer(FCaptureBuffer);
  860. end;
  861. {-- TMMDSCaptureChannel -------------------------------------------------------}
  862. procedure TMMDSCaptureChannel.Stop;
  863. begin
  864.   if FCapture <> nil then
  865.      FCapture.StopBuffer(FCaptureBuffer);
  866. end;
  867. {-- TMMDSCaptureChannel -------------------------------------------------------}
  868. function TMMDSCaptureChannel.GetPosition: Longint;
  869. begin
  870.   Result := FCaptureBuffer.GetPosition
  871. end;
  872. {-- TMMDSCaptureChannel -------------------------------------------------------}
  873. procedure TMMDSCaptureChannel.SetPWaveFormat(aValue: PWaveFormatEx);
  874. begin
  875.    FCaptureBuffer.PWaveFormat := aValue;
  876.    inherited;
  877. end;
  878. {-- TMMDSCaptureChannel -------------------------------------------------------}
  879. function TMMDSCaptureChannel.GetBufferLength: Longint;
  880. begin
  881.    Result := FCaptureBuffer.BufferLength;
  882. end;
  883. {-- TMMDSCaptureChannel -------------------------------------------------------}
  884. procedure TMMDSCaptureChannel.SetBufferLength(Value: Longint);
  885. begin
  886.    FCaptureBuffer.BufferLength := Value;
  887. end;
  888. {-- TMMDSCaptureChannel -------------------------------------------------------}
  889. function TMMDSCaptureChannel.GetCaptureLength: Longint;
  890. begin
  891.    Result := FCaptureBuffer.CaptureLength;
  892. end;
  893. {-- TMMDSCaptureChannel -------------------------------------------------------}
  894. function TMMDSCaptureChannel.GetCapturing: Boolean;
  895. begin
  896.   Result := FCaptureBuffer.Capturing
  897. end;
  898. {-- TMMDSCaptureChannel -------------------------------------------------------}
  899. procedure TMMDSCaptureChannel.SetReset(aValue: Boolean);
  900. begin
  901.    FCaptureBuffer.ResetPosition := aValue;
  902. end;
  903. {-- TMMDSCaptureChannel -------------------------------------------------------}
  904. function TMMDSCaptureChannel.GetReset: Boolean;
  905. begin
  906.    Result := FCaptureBuffer.ResetPosition;
  907. end;
  908. {-- TMMDSCaptureChannel -------------------------------------------------------}
  909. procedure TMMDSCaptureChannel.ReadData(Stream: TStream);
  910. var
  911.    Buf: PChar;
  912. begin
  913.    Buf := GlobalAllocMem(Stream.Size);
  914.    try
  915.       Stream.ReadBuffer(Buf^,Stream.Size);
  916.       PWaveFormat := Pointer(Buf);
  917.    finally
  918.       GlobalFreeMem(Pointer(Buf));
  919.    end;
  920. end;
  921. {-- TMMDSCaptureChannel -------------------------------------------------------}
  922. procedure TMMDSCaptureChannel.WriteData(Stream: TStream);
  923. begin
  924.    if (PWaveFormat <> nil) then
  925.        Stream.WriteBuffer(PWaveFormat^,wioSizeOfWaveFormat(PWaveFormat));
  926. end;
  927. {-- TMMDSCaptureChannel -------------------------------------------------------}
  928. procedure TMMDSCaptureChannel.DefineProperties(Filer: TFiler);
  929. begin
  930.    inherited DefineProperties(Filer);
  931.    Filer.DefineBinaryProperty('WaveFormatEx', ReadData, WriteData, PWaveFormat <> nil);
  932. end;
  933. {-- TMMDSCaptureChannel -------------------------------------------------------}
  934. procedure TMMDSCaptureChannel.SetPCMFormat(Mode: TMMMode; Bits: TMMBits; SampleRate: Longint);
  935. var
  936.    wfx: TWaveFormatEx;
  937. begin
  938.    pcmBuildWaveHeader(@wfx, (Ord(Bits)+1)*8, Ord(Mode)+1, SampleRate);
  939.    PWaveFormat := @wfx;
  940. end;
  941. {-- TMMDSCaptureChannel -------------------------------------------------------}
  942. function TMMDSCaptureChannel.SelectFormat: Boolean;
  943. var
  944.    ACM: TMMACM;
  945. begin
  946.    ACM := TMMACM.Create(nil);
  947.    try
  948.       ACM.EnumFormats := efRestrict;
  949.       Result := ACM.ChooseFormat(PWaveFormat,'Select Format');
  950.       if Result then
  951.          PWaveFormat := ACM.PWaveFormat;
  952.    finally
  953.       ACM.Free;
  954.    end;
  955. end;
  956. {-- TMMDSCaptureChannel -------------------------------------------------------}
  957. function TMMDSCaptureChannel.GetInputFormat: string;
  958. var
  959.    FormatTag, Format: string;
  960. begin
  961.    Result := 'Unknown';
  962.    if (PWaveFormat <> nil) and
  963.       acmGetFormatDescription(PWaveFormat, FormatTag, Format) then
  964.       Result := FormatTag+' '+Format;
  965. end;
  966. {-- TMMDSCaptureChannel -------------------------------------------------------}
  967. procedure TMMDSCaptureChannel.SetInputFormat(aValue: string);
  968. begin
  969.    MessageDlg('This is a read-only property, please use SelectFormat.',
  970.               mtInformation,[mbOK],0);
  971. end;
  972. {-- TMMDSCaptureChannel -------------------------------------------------------}
  973. procedure TMMDSCaptureChannel.SaveFormatInRegistry(RootKey: HKEY; Localkey, Field: string);
  974. begin
  975.    if (PWaveFormat <> nil) then
  976.        SaveInRegistryBinary(RootKey,LocalKey,Field,PWaveFormat^,wioSizeOfWaveFormat(PWaveFormat));
  977. end;
  978. {-- TMMDSCaptureChannel -------------------------------------------------------}
  979. procedure TMMDSCaptureChannel.LoadFormatFromRegistry(RootKey: HKEY; Localkey, Field: string);
  980. var
  981.    wfx: array[0..1024] of Char;
  982. begin
  983.    if GetFromRegistryBinary(RootKey,LocalKey,Field,wfx,sizeOf(wfx)) > 0 then
  984.       PWaveFormat := @wfx;
  985. end;
  986. {-- TMMDSCaptureChannel -------------------------------------------------------}
  987. function TMMDSCaptureChannel.SaveToRAWFile(FName: TFileName): Boolean;
  988. begin
  989.   Result := False;
  990.   if (CaptureLength > 0) then
  991.   try
  992.      FCaptureBuffer.Memory.SaveToFile(FName);
  993.      Result := True
  994.   except
  995.   end;
  996. end;
  997. {-- TMMDSCaptureChannel -------------------------------------------------------}
  998. function TMMDSCaptureChannel.SaveToWaveFile(FName: TFileName): Boolean;
  999. var
  1000.    lpwio: PWaveIOCB;
  1001. begin
  1002.    Result := False;
  1003.    if (CaptureLength > 0) then
  1004.    begin
  1005.       if (wioCreateFileInfo(lpwio, PWaveFormat) = 0) and (lpwio <> nil) then
  1006.       try
  1007.          if wioWriteFileInfo(lpwio, PChar(FName)) = 0 then
  1008.          try
  1009.             Result := wioWaveWriteData(lpwio, FCaptureBuffer.Memory.Memory, CaptureLength) = CaptureLength;
  1010.          finally
  1011.             wioWaveClose(lpwio);
  1012.          end;
  1013.       finally
  1014.          wioFreeFileInfo(lpwio);
  1015.       end;
  1016.    end;
  1017. end;
  1018. {-- TMMDSCaptureChannel -------------------------------------------------------}
  1019. procedure TMMDSCaptureChannel.GetVUMeter(var LeftValue, RightValue, BothValue: integer; Interval: integer);
  1020. var
  1021.    nBytes,dwPos: DWORD;
  1022.    PeakLeft,PeakRight: Smallint;
  1023.    wfx: TWaveFormatEx;
  1024.    p1,p2: Pointer;
  1025.    l1,l2: DWORD;
  1026. begin
  1027.    LeftValue  := 0;
  1028.    RightValue := 0;
  1029.    BothValue  := 0;
  1030.    if Capturing and (PWaveFormat^.wFormatTag = WAVE_FORMAT_PCM) then
  1031.    begin
  1032.       FCaptureBuffer.DirectSoundCaptureBuffer.GetFormat(@wfx, SizeOf(wfx), DWORD(nil^));
  1033.       nBytes := wioTimeToBytes(@wfx,Interval);
  1034.       dwPos := FCaptureBuffer.GetReadPosition;
  1035.       if (dwPos - nBytes > 0) then
  1036.       begin
  1037.          if FCaptureBuffer.DirectSoundCaptureBuffer.Lock(dwPos-nBytes,nBytes, p1, l1, p2, l2, 0) <> 0 then
  1038.             exit;
  1039.          if (l1 >= nBytes) then
  1040.          begin
  1041.             pcmFindPeak(@wfx,p1,nBytes, PeakLeft, PeakRight);
  1042.             if (wfx.wBitsPerSample = 8) then
  1043.             begin
  1044.                PeakLeft := (PeakLeft-128)*255;
  1045.                PeakRight:= (PeakRight-128)*255;
  1046.             end;
  1047.             LeftValue := abs(PeakLeft);
  1048.             RightValue := abs(PeakRight);
  1049.             BothValue := (LeftValue + RightValue) div 2;
  1050.          end;
  1051.          FCaptureBuffer.DirectSoundCaptureBuffer.Unlock(p1, l1, p2, l2);
  1052.       end;
  1053.    end;
  1054. end;
  1055. end.