📄 u_dspdet_main.pas
字号:
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 + -