⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unadspdlibpipes.pas

📁 Voice Commnucation Components for Delphi
💻 PAS
📖 第 1 页 / 共 2 页
字号:
    // simply pass data through
    result := len;
    onNewData(data, result, self);
  end;
end;

// --  --
function unaDSPDLibWavePipe.isActive(): bool;
begin
  // inherited will return false, since "device" is nil
  //
  result := f_active;
end;


{ unavclDSPDLibMultiBand }

// --  --
procedure unavclDSPDLibMultiBand.AfterConstruction();
begin
  inherited;
  //
  freqAssignMode := unafam_powerOf2;
  numBands := c_defNumBands;
end;

// --  --
function unavclDSPDLibMultiBand.allocateNBuf(n: uint): pFloatArray;
begin
  result := malloc(n * sizeOf(dspl_float));
end;

// --  --
function unavclDSPDLibMultiBand.applyDeviceFormat(const format: WAVEFORMATEX; isSrc: bool): bool;
begin
  // apply format on automation
  result := inherited applyDeviceFormat(format, isSrc);
  //
  if (result) then
    checkFreqMode();
end;

// --  --
procedure unavclDSPDLibMultiBand.checkFreqMode();
var
  i: int;
  frq:  pFloatArray;
  max: dspl_float;
  f: dspl_float;
  n: uint;
begin
  case (f_freqAssignMode) of

    unafam_manual: begin
      // not much to care about
      //
      // just make sure we have freq buffer large enough to hold the bands,
      // and adjust the size of freq buffer as necessary
      frequency[getNumFreq() - 1] := frequency[getNumFreq() - 1];
    end;

    unafam_powerOf2: begin
      //
      n := getNumFreq();
      if ((0 < n) and (0 < pcmFormat.nSamplesPerSec)) then begin
	//
	max := pcmFormat.nSamplesPerSec / 2.75625;
	frq := allocateNBuf(n);
	try
	  for i := 1 to n do begin
	    //
	    f := max / (1 shl (int(n) - i));
	    frq[i - 1] := f / pcmFormat.nSamplesPerSec;
	  end;
	  //
	  automation.dspl_obj_setc(dsplObj, DSPL_PID or DSPL_P_FRQ, pdspl_float(frq), n);
	finally
	  mrealloc(frq);
	end;
	//
      end;	// 0 < n
    end;

  end;	// case
end;

// --  --
procedure unavclDSPDLibMultiBand.doSetNumBands(value: uint);
begin
  if (f_numBands <> value) then begin
    //
    f_numBands := value;
    //
    automation.dspl_obj_seti(dsplObj, DSPL_PID or DSPL_P_OTHER, numBands);           // set number of bands
    //
    checkFreqMode();
  end;
end;

// --  --
function unavclDSPDLibMultiBand.getFreq(band: uint): dspl_float;
var
  chunk: pdspl_chunk;
begin
  chunk := automation.root.getc(dsplObj, DSPL_PID or DSPL_P_FRQ);
  if ((nil <> chunk) and (int(band) < chunk.r_len)) then
    result := pFloatArray(chunk.r_fp)[band] * pcmFormat.nSamplesPerSec
  else
    result := 0.0;
end;

// --  --
function unavclDSPDLibMultiBand.getNumFreq(): int;
begin
  result := numBands;
end;

// --  --
procedure unavclDSPDLibMultiBand.setFreq(band: uint; const value: dspl_float);
var
  i: int;
  fbuf: pFloatArray;
  chunk: pdspl_chunk;
  n: uint;
begin
  if (int(band) < getNumFreq()) then begin
    //
    chunk := automation.root.getc(dsplObj, DSPL_PID or DSPL_P_FRQ);
    if ((nil <> chunk) and (int(band) < chunk.r_len)) then begin
      //
      pFloatArray(chunk.r_fp)[band] := value / pcmFormat.nSamplesPerSec;
      //
      // assuming the chunk will not be re-allocated
      automation.dspl_obj_setc(dsplObj, DSPL_PID or DSPL_P_FRQ, chunk.r_fp, getNumFreq()); // we also make sure number of bands is properly specified
    end
    else begin
      //
      // must allocate a larger chunk
      n := getNumFreq();
      fbuf := allocateNBuf(n);
      if (0 < n) then begin
	//
	try
	  for i := 0 to n - 1 do begin
	    //
	    if (i = int(band)) then
	      fbuf[i] := value  / pcmFormat.nSamplesPerSec	//
	    else
	      if (i < chunk.r_len) then
		fbuf[i] := pFloatArray(chunk.r_fp)[i]	// take old values we have in the chunk
	      else
		fbuf[i] := 0.0;	// zero the rest
	    //
	  end;
	  //
	  automation.dspl_obj_setc(dsplObj, DSPL_PID or DSPL_P_FRQ, pdspl_float(fbuf), getNumFreq());
	finally
	  mrealloc(fbuf);
	end;
      end;
    end;
    //
  end;
end;

// --  --
procedure unavclDSPDLibMultiBand.setNumBands(value: uint);
begin
  doSetNumBands(value);
end;


{ TunavclDSPDLibEQ }

// --  --
constructor TunavclDSPDLibEQ.create(owner: tComponent);
begin
  inherited;	// creates automation
  //
  f_dsplObj := automation.dspl_objNew(DSPL_OID or DSPL_EQMB);
end;

// --  --
procedure TunavclDSPDLibEQ.doSetNumBands(value: uint);
begin
  inherited;
  //
  // just make sure we have gain buffer large enough to hold the numBands
  // and adjust the size of gain buffer if necessary
  gain[numBands - 1] := gain[numBands - 1];
end;

// --  --
function TunavclDSPDLibEQ.getGain(band: uint): dspl_float;
var
  chunk: pdspl_chunk;
begin
  chunk := automation.root.getc(dsplObj, DSPL_PID or DSPL_P_GAIN);
  if ((nil <> chunk) and (int(band) < chunk.r_len)) then
    result := v2db(pFloatArray(chunk.r_fp)[band])
  else
    result := 0.0;
end;

// --  --
procedure TunavclDSPDLibEQ.setGain(band: uint; const value: dspl_float);
var
  i: int;
  gbuf: pFloatArray;
  chunk: pdspl_chunk;
begin
  if (band < numBands) then begin
    //
    chunk := automation.root.getc(dsplObj, DSPL_PID or DSPL_P_GAIN);
    if ((nil <> chunk) and (int(band) < chunk.r_len)) then begin
      //
      pFloatArray(chunk.r_fp)[band] := db2v(value);
      //
      // assuming the chunk will not be re-allocated
      automation.dspl_obj_setc(dsplObj, DSPL_PID or DSPL_P_GAIN, chunk.r_fp, numBands);
    end
    else begin
      //
      // must allocate a larger chunk
      gbuf := allocateNBuf(numBands);
      if (0 < numBands) then begin
	try
	  for i := 0 to numBands - 1 do begin
	    //
	    if (i = int(band)) then
	      gbuf[i] := db2v(value)
	    else
	      if (i < chunk.r_len) then
		gbuf[i] := pFloatArray(chunk.r_fp)[i]	// take old values we have in the chunk
	      else
		gbuf[i] := db2v(0.0);	// zero the rest
	    //
	  end;
	  //
	  automation.dspl_obj_setc(dsplObj, DSPL_PID or DSPL_P_GAIN, pdspl_float(gbuf), numBands);
	finally
	  mrealloc(gbuf);
	end;
      end;
      //
    end;
  end;
end;


{ TunavclDSPDLibMBSP }

// --  --
procedure TunavclDSPDLibMBSP.AfterConstruction();
begin
  inherited;
  //
  processDataInPlace := false;	// assign default value
end;

// --  --
procedure TunavclDSPDLibMBSP.BeforeDestruction();
var
  c: uint;
begin
  inherited;
  //
  for c := low(f_localFBuf) to high(f_localFBuf) do begin
    //
    f_localFBufSize[c] := 0;
    mrealloc(f_localFBuf[c]);
  end;  
end;

// --  --
function TunavclDSPDLibMBSP.convertOutFloat2PCM(out buf: pointer): int;
var
  p, b, c: uint;
  s: uint;
  nSamples: uint;
  outBuf: pdspl_float;
  f: dspl_float;
  //
  pcmBits: uint;	// local copy of pcmFormat.wBitsPerSample
  pcmChannels: uint;
begin
  result := 0;
  //
  pcmBits := pcmFormat.wBitsPerSample;
  pcmChannels := pcmFormat.nChannels;
  //
  // convert float samples to integer values (if we have to)
  if ((0 < pcmBits) and (0 < pcmChannels) and (0 < numBands)) then begin
    //
    // 1. calculate the resulting samples, taking passThrough in account
    //
    for c := 0 to pcmChannels - 1 do begin
      //
      for b := 0 to numBands - 1 do begin
	//
	automation.getMultiOutData(c, b, outBuf, nSamples);
	f_localRaw[c][b] := pFloatArray(outBuf);
	//
	if (1 > nSamples) then
	  continue;	// no out data in this channel/band?
	//
	if (f_localFBufSize[c] <> int(nSamples) * sizeOf(dspl_float)) then begin
	  //
	  f_localFBufSize[c] := nSamples * sizeOf(dspl_float);
	  mrealloc(f_localFBuf[c], f_localFBufSize[c]);
	end;
	//
	// sum up samples in this channel with current band
	for s := 0 to nSamples - 1 do begin
	  //
	  if (f_bandPT[b]) then
	    f := outBuf^
	  else
	    f := 0.0;	// this band is not included in result
	  //
	  if (0 = b) then
	    f_localFBuf[c][s] := f	// take samples from first band as a result
	  else
	    f_localFBuf[c][s] := f_localFBuf[c][s] + f;
	  //
	  inc(outBuf);
	end;
	//
      end;	// for all bands
      //
      // notify we have some samples ready
      if (assigned(f_onRawSamplesAvail)) then
	f_onRawSamplesAvail(self, nSamples, numBands, c, @f_localRaw[c]);
      //
    end;      // for all channels
    //
    // 2. convert result to output buffer
    //
    for c := 0 to pcmChannels - 1 do begin
      //
      nSamples := f_localFBufSize[c] div sizeOf(dspl_float);
      //
      result := nSamples * pcmChannels * (1 + (pcmBits - 1) shr 3);
      if (f_localBufSize < result) then begin
	//
	mrealloc(f_localBuf, result);
	f_localBufSize := result;
      end;
      //
      p := c;
      for s := 0 to nSamples - 1 do begin
	//
	f := f_localFBuf[c][s];
	if (f > 1.0) then
	  f := 1.0;
	//
	if (f < -1.0) then
	  f := -1.0;
	//
	case (pcmBits) of

	   8: pArray(f_localBuf)[p] 	    := trunc(f * $FF + $80);
	  16: pSmallIntArray(f_localBuf)[p] := trunc(f * $7FFF);
	  24: pInt32Array(f_localBuf)[p]    := trunc(f * $7FFFFF);
	  32: pFloatArray(f_localBuf)[p]    := f;

	end;
	//
	inc(p, pcmChannels);	// go to next sample in same channel
	//
      end;	  // for all samples
    end;      // for all channels
    //
    buf := f_localBuf;
    //
  end;	// 0 < channels
end;

// --  --
constructor TunavclDSPDLibMBSP.create(owner: tComponent);
var
  i: int;
begin
  inherited;	// creates automation
  //
  f_dsplObj := automation.dspl_objNew(DSPL_OID or DSPL_MBSP);
  //
  for i := low(f_bandPT) to high(f_bandPT) do
    f_bandPT[i] := true;
end;

// --  --
function TunavclDSPDLibMBSP.getNumFreq(): int;
begin
  result := numBands - 1;
end;

// --  --
function TunavclDSPDLibMBSP.getPT(band: uint): bool;
begin
  result := f_bandPT[band];
end;

// --  --
procedure TunavclDSPDLibMBSP.setPT(band: uint; value: bool);
begin
  f_bandPT[band] := value;
end;


//
// -- IDE --
//
procedure Register();
begin
  RegisterComponents('VC2.5 DSP', [
    TunavclDSPDLibEQ,
    TunavclDSPDLibMBSP
  ]);
end;

// -- unit globals --

initialization
  g_root := unaDspDLibRoot.create();

finalization
  freeAndNil(g_root);
end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -