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

📄 u_dspdet_main.pas

📁 Voice Commnucation Components for Delphi
💻 PAS
📖 第 1 页 / 共 2 页
字号:
      with (waveRiff.waveStream.dstFormat^) do begin
	//
	f_dsplAutoLD.setFormat(nSamplesPerSec, wBitsPerSample, nChannels);
	f_dsplAutoND.setFormat(nSamplesPerSec, wBitsPerSample, nChannels);
	waveOut.pcmFormat := waveRiff.waveStream.dstFormat;
	//
	f_dsplAutoND.dspl_obj_setf(f_dsplObjND, DSPL_PID or DSPL_P_NFRQ or DSPL_ND_SAMPLE_RATE, nSamplesPerSec);
	f_chNum := nChannels;
      end;
    end;
    //
    c_pb_file.visible := true;
    c_pb_file.max := waveRiff.waveStream.streamSize;
    //
    waveRiff.open();
  end
  else begin
    //
    // source is live recording
    //
    waveIn.deviceId := index2deviceId(c_cb_source);
    //
    f_dsplAutoLD.setFormat(waveIn.pcm_samplesPerSec, waveIn.pcm_bitsPerSample, waveIn.pcm_numChannels);
    f_dsplAutoND.setFormat(waveIn.pcm_samplesPerSec, waveIn.pcm_bitsPerSample, waveIn.pcm_numChannels);
    waveOut.pcmFormat := waveIn.pcmFormat;
    //
    f_dsplAutoND.dspl_obj_setf(f_dsplObjND, DSPL_PID or DSPL_P_NFRQ or DSPL_ND_SAMPLE_RATE, waveIn.pcm_samplesPerSec);
    f_chNum := waveIn.pcm_numChannels;
    //
    c_pb_file.visible := false;
    //
    waveIn.open();
  end;
  //
  c_timer_update.enabled := true;
  waveOut.open();	// force opening, since waveOut provider may be removed
end;

// --  --
procedure Tc_form_main.c_cb_loopClick(Sender: TObject);
begin
  waveRiff.loop := c_cb_loop.checked;
end;

// --  --
procedure Tc_form_main.c_button_stopClick(Sender: TObject);
begin
  c_button_start.enabled := true;
  c_button_stop.enabled := false;
  //
  c_timer_update.enabled := false;
  //
  waveIn.close();
  waveRiff.close();
  //
  c_sb_main.panels[1].text := 'Stopped. ' + c_sb_main.panels[1].text;
end;

// --  --
procedure Tc_form_main.c_timer_updateTimer(Sender: TObject);
begin
  c_sb_main.panels[1].text := 'Bytes processed: ' + int2str(f_totalBytes, 10, 3);
  //
  if (c_pb_file.visible) then
    c_pb_file.position := waveRiff.waveStream.streamPosition;
  //
  {$IFDEF DEBUG }
  c_sb_main.panels[0].text := 'Mem: ' + int2str(ams() shr 10, 10, 3) + ' KB';
  {$ENDIF }
  //
  if (f_streamDone) then
    c_button_stop.click();
  //
  f_ld_enabled := c_cb_LD_enable.checked;
  f_nd_enabled := c_cb_ND_enable.checked;
  f_passSignalOnly := c_cb_onlySignal.checked;
end;

// --  --
procedure Tc_form_main.c_cb_sourceChange(Sender: TObject);
var
  i: int;
begin
  i := c_cb_source.itemIndex;
  if ((0 <= i) and (pointer($666) = c_cb_source.items.objects[i])) then begin
    //
    if (c_od_file.execute()) then begin
      //
      c_label_fileName.caption := c_od_file.fileName;
    end;
    //
    c_pb_file.visible := fileExists(c_label_fileName.caption);
    c_label_fileName.visible := c_pb_file.visible;
    c_cb_loop.visible := c_pb_file.visible;
  end
  else begin
    //
    c_label_fileName.visible := false;
    c_pb_file.visible := false;
    c_cb_loop.visible := false;
  end;
end;

// --  --
procedure Tc_form_main.waveRiffStreamIsDone(sender: TObject);
begin
  f_streamDone := true;
end;

// --  --
procedure Tc_form_main.dataAvail(sender: unavclInOutPipe; data: Pointer; len: Cardinal);
var
  c: int;
  okLD: bool;
  okND: bool;
  fp: dspl_float;
  son, signalOverNoise: bool;
begin
  okLD := false;
  if (f_ld_enabled) then begin
    // pass chunk to LD
    f_dsplAutoLD.processChunk(data, len, -1, -1, false);	// not interested in output to be placed into data buffer
    okLD := true;
    //
    inc(f_totalBytes, len);
  end;
  //
  okND := false;
  if (f_nd_enabled) then begin
    // pass chunk to ND
    f_dsplAutoND.processChunk(data, len, -1, -1, false);	// not interested in output to be placed into data buffer
    okND := true;
    //
    inc(f_totalBytes, len);
  end;
  //
  // check if we have the output buffers
  if (not f_outBufValidLD or not f_outBufValidND) then begin
    //
    for c := 0 to f_chNum - 1 do begin
      //
      if (not f_outBufValidLD and okLD) then
	f_dsplAutoLD.getOutData(c, f_dsplOutBufLD[c], f_dsplOutBufLDSize[c]);
      //
      if (not f_outBufValidND and okND) then
	f_dsplAutoND.getOutData(c, f_dsplOutBufND[c], f_dsplOutBufNDSize[c]);
    end;
    //
    f_outBufValidLD := f_outBufValidLD or okLD;
    f_outBufValidND := f_outBufValidND or okLD;
  end;
  //
  if (f_ld_enabled) then begin
    //
    // display LD data on GUI
    for c := 0 to f_chNum - 1 do
      plotArray(c_pb_LD, c, f_dsplOutBufLD[c], f_dsplOutBufLDSize[c]);
  end;
  //
  if (f_nd_enabled) then begin
    //
    // display ND data on GUI
    for c := 0 to f_chNum - 1 do
      plotArray(c_pb_ND_main, c, f_dsplOutBufND[c], f_dsplOutBufNDSize[c]);
  end;
  //
  // check if we need to re-assign waveIn --> waveOut link
  if (f_passSignalOnly <> f_passSignalOnlyOld) then begin
    //
    f_passSignalOnlyOld := f_passSignalOnly;
    if (f_passSignalOnly) then begin
      //
      waveIn.consumer := nil;  	// disconnect waveOut from provider
      waveRiff.consumer := nil;
    end
    else begin
      //
      waveIn.consumer := waveOut;  	// restore provider/consumer links
      waveRiff.consumer := waveOut;
      //
      waveOut.open();
    end;
  end;
  //
  // check if we need to pass only non-noise signal
  if (f_ld_enabled and f_nd_enabled) then begin
    //
    signalOverNoise := false;
    //
    // display resulting graph
    if (f_dsplOutBufLDSize[0] = f_dsplOutBufNDSize[0]) then begin
      //
      for c := 0 to f_chNum - 1 do begin
	//
	if (DSPL_SUCCESS = f_dsplAutoND.dspl_obj_getf(f_dsplObjND, c, DSPL_PID or DSPL_P_OUT, fp)) then
	  plotResult(c_pb_ND_level, c, f_dsplOutBufLD[c], fp, f_dsplOutBufLDSize[0], son);
	//
	if (son) then 
	  signalOverNoise := true;	// at least in one channel
      end;
      //
    end
    else
      ; //should not be here
    //
    if (f_passSignalOnly and signalOverNoise) then
      waveOut.write(data, len)
    else
      ;	// signal level is lower than noise level, do not pass it
    //
  end;
end;

// --  --
function ScrollDCSane(DC: HDC; DX, DY: Integer; Scroll, Clip: PRect; Rgn: HRGN; Update: PRect): BOOL; stdcall; external user32 name 'ScrollDC';

// --  --
procedure Tc_form_main.plotArray(box: tPaintBox; channel: int; data: pdspl_float; len: uint);
const
  c_delta 	= 10;
var
  dc: hDC;
  s: int;
  x, dx: float;
  xi, yi, maxY: int;
  h: int;
  rect: tRect;
begin
  box.canvas.lock();
  try
    //
    dc := box.canvas.handle;
    //
    if (0 = channel) then
      ScrollDCSane(dc, -c_delta, 0, nil, nil, 0, nil);
    //
    if (0 < len) then begin
      //
      x := box.width;
      h := (box.height - 1) div f_chNum;
      //
      dx := -c_delta / len;
      maxY := 0;
      xi := box.width;
      //
      rect.Left := box.width - c_delta;
      rect.Top := channel * h;
      rect.Right := box.width;
      rect.Bottom := (channel + 1) * h;
      //
      FillRect(dc, rect, f_solidBG);
      //
      for s := 0 to len - 1 do begin
	//
	yi := round(data^ * h);
	if (maxY < yi) then
	  maxY := yi;
	//
	x := x + dx;
	inc(data);
	//
	if (round(x) <> xi) then begin
	  //
	  xi := round(x);
	  MoveToEx(dc, xi, (channel + 1) * h, nil);
	  LineTo  (dc, xi, (channel + 1) * h - maxY);
	  //
	  maxY := 0;
	end;
      end;
      //
    end;
  finally
    box.canvas.unlock();
  end;
end;

// --  --
procedure Tc_form_main.plotResult(box: tPaintBox; const channel: int; data: pdspl_float; ND: dspl_float; len: uint; out signalOverNoise: bool);
var
  s: int;
  w, h: int;
  maxS: dspl_float;
  dc: hDC;
  rect: tRect;
  spen: hPen;
begin
  box.canvas.lock();
  try
    //
    dc := box.canvas.handle;
    //
    if (0 = channel) then
      ScrollDCSane(dc, -1, 0, nil, nil, 0, nil);
    //
    w := box.width - 1;
    h := (box.height - 1) div f_chNum;
    //
    rect.Left := box.width - 1;
    rect.Top := channel * h;
    rect.Right := box.width;
    rect.Bottom := (channel + 1) * h;
    //
    FillRect(dc, rect, f_solidBG);
    //
    // calculate mean level of chunk
    maxS := 0.0;
    if ((0 < len) and (0 < f_chNum)) then begin
      //
      for s := 0 to len - 1 do begin
	//
	if (maxS < data^) then
	  maxS := data^;
	//
	inc(data);
      end;
    end;
    //
    spen := SelectObject(dc, f_penGreen);
    try
      if (maxS < ND) then begin
	//
	signalOverNoise := false;
	//
	SelectObject(dc, f_penBlue);
	MoveToEx(dc, w, (channel + 1) * h, nil);
	LineTo  (dc, w, (channel + 1) * h - round(ND * h));
	//
	SelectObject(dc, f_penRed);
	MoveToEx(dc, w, (channel + 1) * h, nil);
	LineTo  (dc, w, (channel + 1) * h - round(maxS * h));	// maxS
      end
      else begin
	//
	signalOverNoise := true;
	//
	//SelectObject(dc, f_penGreen);	// already selected
	MoveToEx(dc, w, (channel + 1) * h, nil);
	LineTo  (dc, w, (channel + 1) * h - round(maxS * h));
	//
	SelectObject(dc, f_penBlue);
	MoveToEx(dc, w, (channel + 1) * h, nil);
	LineTo  (dc, w, (channel + 1) * h - round(ND * h));	// ND
      end;
      //
    finally
      SelectObject(dc, spen);
    end;
    //
  finally
    box.canvas.unlock();
  end;
end;


end.

⌨️ 快捷键说明

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