

  procedure CheckHr(hr: HRESULT; n: WideString);
  begin
    if hr <> DS_OK then Die('%0() returned %1', [n, DSErrorString(hr)]);
  end;


  constructor TDirectXSoundMan.Create;
  var
    hr: HRESULT;
    i: integer;
    bd: TDSBufferDesc;
    wf: TWaveFormatEx;
  begin
    try
      resampleFreq:= Config.Int['sound','directsound_force_resample'];
      InitDirectSound;
//      AddLog('DirectSound: ')
      hr:= DirectSoundCreate8(NIL, f_device, NIL);  CheckHr(hr, 'DirectSoundCreate8');
//      DirectSoundDevice.GetCaps(
      if MotherState.DebugMode then AddLog('  Default device created.');
(* there is no need for this.
      hr:=DirectSoundDevice.SetCooperativeLevel(WindowManager.WindowHandle, DSSCL_PRIORITY);
      CheckHr(hr, 'DirectSoundDevice.SetCooperativeLevel');
      if MotherState.DebugMode then AddLog('  Cooperative level set to DSSCL_PRIORITY.');*)


      hr:= f_device.SetCooperativeLevel(WindowManager.WindowHandle, DSSCL_NORMAL);
      CheckHr(hr, 'IDirectSound8.SetCooperativeLevel');
      if MotherState.DebugMode then AddLog('  Cooperative level set to DSSCL_NORMAL.');

      //Creating the stereo buffers for tripl buffering.
      with wf do begin
        wFormatTag:= 1; //WAVE_FORMAT_PCM;       { format type }
        nChannels:= 2;        { number of channels (i.e. mono, stereo, etc.) }
        nSamplesPerSec:= 44100;  { sample rate }
        nAvgBytesPerSec:= 44100 * 4; { for buffer estimation }
        nBlockAlign:= 4;      { block size of data }
        wBitsPerSample:= 16;   { number of bits per sample of mono data }
        cbSize:=0;           { the count in bytes of the size of }
      end;
      with bd do begin
        dwSize:= sizeof(TDSBufferDesc);
        dwFlags:= 0;  //specify hardware?
        dwBufferBytes:= snd_buffer_size*4;
        dwReserved:= 0;
        lpwfxFormat:= @wf;
//        guid3DAlgorithm:=
      end;
      for i:=0 to snd_buffers - 1 do begin
        hr:= f_device.CreateSoundBuffer(bd, f_buffer[i], NIL);
        CheckHr(hr, 'IDirectSound8.CreateSoundBuffer');
      end;

      //Play the intro sound;
      TestGong;
    except
      Die(MI_ERROR_SOUND_INIT);
    end;
    AddLog('DirectSound 8 initialized.');
  end;


  destructor TDirectXSoundMan.Destroy;
  var i: integer;
  begin
    f_b_buffer:= nil; //takes care of calling Release(). Pascal syntax is strange here.
    for i:=0 to snd_buffers - 1 do f_buffer[i]:= nil;
    DirectSoundDevice:= nil;
    CloseDirectSound;
  end;


  procedure TDirectXSoundMan.SetVolume(volume: float);
  begin

  end;

  procedure TDirectXSoundMan.NewData(begins: TDateTime; samples, rate: integer; data: pointer);
  var
    bd: TDSBufferDesc;
  begin
    if f_muted then Enable;

   //lock the next buffer
   //fill the next buffer
   //unlock the next buffer

   //get current buffer playing position and calculate the next buffer start position
   //stop current buffer
   //start the next buffer

   //cycle the current buffer id

    f_GotNewData:= Yes;
  end;

  procedure TDirectXSoundMan.PlaySound(samples, rate: integer; data: pointer);
  var
    bd: TDSBufferDesc;
    hr: HResult;
    wf: TWaveFormatEx;
    p1, p2: pointer;
    b1, b2: dword;
    dst_samples: integer;
i: integer;
  begin
    dst_samples:= samples;
    try
      if Assigned(f_b_buffer) then begin
        hr:= f_b_buffer.Stop; CheckHr(hr, 'IDirectSoundBuffer.Stop');
        f_b_buffer:= nil;
      end;
      with wf do begin
        wFormatTag:= 1; //WAVE_FORMAT_PCM;       { format type }
        nChannels:= 1;        { number of channels (i.e. mono, stereo, etc.) }
        if resampleFreq > 0 then begin
          nSamplesPerSec:= resampleFreq;
          nAvgBytesPerSec:= resampleFreq * 2;
          dst_samples:= Trunc((1.0 * samples * resampleFreq) / rate);
        end else begin
          nSamplesPerSec:= rate;  { sample rate }
          nAvgBytesPerSec:= rate * 2; { for buffer estimation }
        end;
        nBlockAlign:=2;      { block size of data }
        wBitsPerSample:= 16;   { number of bits per sample of mono data }
        cbSize:=0;           { the count in bytes of the size of }
      end;
      with bd do begin
        dwSize:= sizeof(TDSBufferDesc);
        dwFlags:=  {DSBCAPS_CTRLDEFAULT or} DSBCAPS_LOCDEFER;
        dwBufferBytes:= dst_samples*2;
        dwReserved:= 0;
        lpwfxFormat:= @wf;
//        guid3DAlgorithm:=
      end;
      hr:= f_device.CreateSoundBuffer(bd, f_b_buffer, NIL);    CheckHr(hr, 'IDirectSound8.CreateSoundBuffer');
      hr:= f_b_buffer.Lock(0, 0, @p1, @b1, @p2, @b2, DSBLOCK_ENTIREBUFFER);  CheckHr(hr, 'IDirectSoundBuffer.Lock');
      if resampleFreq > 0
        then _Resample(data, p1, samples, min(b1 div 2, dst_samples))
        else Move(data^, p1^, min(b1, samples*2));
//for i:=0 to dst_samples - 1 do AddLog('-- %0',[SmallInt((p1 + i*2)^)]);
      hr:= f_b_buffer.Unlock(p1, b1, p2, b2); CheckHr(hr, 'IDirectSoundBuffer.Unlock');
      hr:= f_b_buffer.Play(0, 100, DSBPLAY_LOCSOFTWARE); CheckHr(hr, 'IDirectSoundBuffer.Play');
    except
      AddLog('TDirectXSoundMan.PlaySound() failed: '#10#13'  %0', [StopDying()]);
    end;
  end;

  procedure TDirectXSoundMan.Cycle;
  begin
    if not f_GotNewData then begin
      //stop the current buffer if there weren't any new data in one second or if (MotherState.ModuleState <> msLoaded)
    end;
    f_GotNewData:= No;
  end;

  procedure TDirectXSoundMan.Disable;
  begin
    if f_muted then Exit;

  end;

  procedure TDirectXSoundMan.Enable;
  begin
    if not f_muted then Exit;

  end;


