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

📄 unadspdlib.pas

📁 Voice Commnucation Components for Delphi
💻 PAS
📖 第 1 页 / 共 5 页
字号:
  gr_env := 1;
  nsot := 0;
  //
  inherited create(DSPL_OID or DSPL_DYNPROC);
end;

// --  --
function unaDspDL_DynProc.process(nSamples: dspl_int): dspl_result;
var
  in_chunk: pdspl_chunk;
  out_chunk: pdspl_chunk;
  sc_chunk: pdspl_chunk;
  ina: pdspl_float;
  //sc: pdspl_float;
  outa: pdspl_float;
  out_len: dspl_int;
  valid: dspl_result;
  attack_samples: dspl_float;
  release_samples: dspl_float;
  aratio: dspl_float;
  bratio: dspl_float;
  ld: pdspl_float;
  theta: dspl_double;
  oth: bool;
  gain: dspl_double;
  gr: dspl_double;
  t: int;
begin
  in_chunk := getc(DSPL_PID or DSPL_P_IN or DSPL_DYNPROC_IN);
  out_chunk := getc(DSPL_PID or DSPL_P_OUT);
  sc_chunk := getc(DSPL_PID or DSPL_P_IN or DSPL_DYNPROC_SC);
  //
  result := DSPL_SUCCESS;
  //
  if (nil = sc_chunk.r_fp) then
    sc_chunk := in_chunk
  else
    if (in_chunk.r_len <> sc_chunk.r_len) then
      result := DSPL_FAILURE;
  //
  if (DSPL_SUCCESS = result) then begin
    //
    ina := in_chunk.r_fp;
    //sc := sc_chunk.r_fp;
    outa := out_chunk.r_fp;
    //
    out_len := out_chunk.r_len;
    if ((out_len <> in_chunk.r_len) or (out_len < nSamples)) then
      result := DSPL_FAILURE
    else begin
      //
      if (f_modified) then begin
	//
	if (ld_buffer_size < out_len) then begin
	  //
	  ld_buffer_size := out_len;
	  mrealloc(ld_buffer, sizeOf(ld_buffer^) * ld_buffer_size);
	end;
	//
	valid := true;
	//
	valid := valid and level_detector.setf(DSPL_PID or DSPL_P_ATTACK,  getf(DSPL_PID or DSPL_P_ATTACK  or DSPL_LD));
	valid := valid and level_detector.setf(DSPL_PID or DSPL_P_RELEASE, getf(DSPL_PID or DSPL_P_RELEASE or DSPL_LD));
	valid := valid and level_detector.setf(DSPL_PID or DSPL_P_OTHER,   getf(DSPL_PID or DSPL_P_OTHER   or DSPL_LD));
	//
	valid := valid and level_detector.seti(DSPL_PID or DSPL_P_TYPE, geti(DSPL_PID or DSPL_P_TYPE or DSPL_LD));
	valid := valid and level_detector.setc(DSPL_PID or DSPL_P_IN,   sc_chunk.r_fp, sc_chunk.r_len);
	valid := valid and level_detector.setc(DSPL_PID or DSPL_P_OUT,  ld_buffer, out_len);
	//
	if (not valid) then
	  result := DSPL_FAILURE
	else begin
	  //
	  attack_samples := 0.5 * getf(DSPL_PID or DSPL_P_ATTACK);
	  release_samples := 0.5 * getf(DSPL_PID or DSPL_P_RELEASE);
	  //
	  if ((attack_samples < 0) or (release_samples < 0)) then
	    result := DSPL_FAILURE
	  else begin
	    //
	    alpha := attack_samples / (attack_samples + 2.0);
	    beta := exp(-1.0 / (release_samples + 1.0));
	    //
	    aratio := getf(DSPL_PID or DSPL_P_RATIO or DSPL_DYNPROC_ABOVE);
	    bratio := getf(DSPL_PID or DSPL_P_RATIO or DSPL_DYNPROC_BELOW);
	    //
	    if ((aratio < 0.02) or (bratio < 0.02)) then
	      result := DSPL_FAILURE
	    else begin
	      //
	      aratio_inv := 1.0 / aratio;
	      bratio_inv := 1.0 / bratio;
	      //
	      if (aratio_inv < 1e-3) then aratio_inv := 0.0;
	      if (bratio_inv < 1e-3) then bratio_inv := 0.0;
	      //
	      th := getf(DSPL_PID or DSPL_P_THRESHOLD);
	      try
		ascale := getf(DSPL_PID or DSPL_P_GAIN or DSPL_DYNPROC_ABOVE) * pow(th, 1.0 - aratio_inv);
	      except
		ascale := db2v(60.0);
	      end;
	      //
	      try
		bscale := getf(DSPL_PID or DSPL_P_GAIN or DSPL_DYNPROC_BELOW) * pow(th, 1.0 - bratio_inv);
	      except
		bscale := db2v(60.0);
	      end;
	      //
	    end;
	  end;
	end;  
      end;	// if (modified) ...
      //
      if (DSPL_SUCCESS = result) then begin
	//
	level_detector.process(nSamples);
	//
	ld := ld_buffer;
	nsot := 0;
	//
	for t := 0 to nSamples -1 do begin
	  //
	  oth := (ld^ >= th);
	  //
	  if (oth) then
	    gain := ascale * pow(ld^, aratio_inv)
	  else
	    gain := bscale * pow(ld^, bratio_inv);
	  //
	  if (oth) then
	    gr := ascale * pow(ld^, aratio_inv - 1)
	  else
	    gr := bscale * pow(ld^, bratio_inv - 1);
	  //
	  if (gr < db2v(-127.0)) then gr := 0;
	  if (gr > db2v(127.0))  then gr := db2v(120.0);
	  //
	  if (gain > gain_env) then
	    theta := alpha
	  else
	    theta := beta;
	  //  
	  if (gain_env > th) then
	    inc(nsot);
	  //
	  gain_env := gain_env * theta;
	  gain_env := gain_env + gain * (1.0 - theta);
	  //
	  gr_env := gr_env * theta;
	  gr_env := gr_env + gr * (1.0 - theta);
	  //
	  outa^ := gr_env * ina^;
	  //
	  inc(ina);
	  inc(outa);
	  inc(ld);
	end;
	//
	seti(DSPL_PID or DSPL_P_OTHER, nsot);
	//
	f_modified := false;
      end;
    end;
  end;
end;


{ unaDspDL_SpeechProc }

// --  --
procedure unaDspDL_SpeechProc.AfterConstruction();
begin
  setc(DSPL_PID or DSPL_P_IN or 0, nil, 0);
  setc(DSPL_PID or DSPL_P_OUT or 0, nil, 0);
  //
  setf(DSPL_PID or DSPL_P_THRESHOLD or 0, db2v(-36.0));
  setc(DSPL_PID or DSPL_P_THRESHOLD or 0, nil, 0);
  //
  setf(DSPL_PID or DSPL_P_NFRQ or DSPL_SPEECHPROC_SAMPLE_RATE, DSPL_DEFAULT_SAMPLE_FRQ);
  //
  setf(DSPL_PID or DSPL_P_NFRQ or DSPL_SPEECHPROC_DEESSER,  2000.0);
  setf(DSPL_PID or DSPL_P_NFRQ or DSPL_SPEECHPROC_ENHANCER, 5000.0);
  setf(DSPL_PID or DSPL_P_Q    or DSPL_SPEECHPROC_ENHANCER, 0.4);
  setf(DSPL_PID or DSPL_P_NFRQ or DSPL_SPEECHPROC_LOWCUT,   300.0);
  //
  setf(DSPL_PID or DSPL_P_GAIN or 0,                         db2v(+6.0));
  setf(DSPL_PID or DSPL_P_GAIN or DSPL_SPEECHPROC_CEIL or 0, db2v(-0.5));
  //
  // number of samples over threshold
  seti(DSPL_PID or DSPL_P_OTHER or 0, 0);
  //
  inherited;
end;

// --  --
procedure unaDspDL_SpeechProc.BeforeDestruction();
begin
  inherited;
  //
  mrealloc(acca);
  mrealloc(accb);
  mrealloc(la_in);
  mrealloc(la_buf);
  mrealloc(hp_out);
  //
  freeAndNil(hp);
  freeAndNil(enh);
  //
  freeAndNil(agc);
  freeAndNil(comp);
  freeAndNil(ng);
  freeAndNil(lim);
  freeAndNil(ds);
end;

// --  --
constructor unaDspDL_SpeechProc.create();
begin
  {$IFDEF DEBUG }
  f_nameFull := c_DSPL_OBJNAMES_FULL[DSPL_SPEECHPROC];
  f_nameShort := c_DSPL_OBJNAMES_SHORT[DSPL_SPEECHPROC];
  {$ENDIF }
  //
  hp := unaDspDL_EQ2B.create();
  enh := unaDspDL_EQ2B.create();
  //
  agc := unaDspDL_DynProc.create();
  comp := unaDspDL_DynProc.create();
  ng := unaDspDL_DynProc.create();
  lim := unaDspDL_DynProc.create();
  ds := unaDspDL_DynProc.create();
  //
  acca := nil;
  accb := nil;
  hp_out := nil;
  la_buf := nil;
  la_in := nil;
  //
  la_size := 0;
  la_pos := 0;
  //
  inherited create(DSPL_OID or DSPL_SPEECHPROC);
end;

// --  --
function unaDspDL_SpeechProc.process(nSamples: dspl_int): dspl_result;
const
  look_ahead: dspl_float = 0.005;
  att_ratio: dspl_double = 0.125;
var
  in_chunk: pdspl_chunk;
  out_chunk: pdspl_chunk;
  th_chunk: pdspl_chunk;
  //
  ina: pdspl_float;
  outa: pdspl_float;
  la: pdspl_float;
  ill: pdspl_float;
  acc: pdspl_float;
  hpp: pdspl_float;
  //
  out_len: dspl_int;
  sample_rate: dspl_float;
  noise_level: dspl_float;
  gap: dspl_double;
  agc_th: dspl_float;
  agc_gain: dspl_float;
  //
  i: int;
  s: dspl_float;
  slope: dspl_double;
begin
  in_chunk := getc(DSPL_PID or DSPL_P_IN);
  out_chunk := getc(DSPL_PID or DSPL_P_OUT);
  //
  th_chunk := getc(DSPL_PID or DSPL_P_THRESHOLD);
  //
  ina := in_chunk.r_fp;
  outa := out_chunk.r_fp;
  out_len := out_chunk.r_len;
  //
  result := DSPL_SUCCESS;
  if ((out_len <> in_chunk.r_len) or (out_len < nSamples)) then
    result := DSPL_FAILURE
  else begin
    //
    if (f_modified) then begin
      //
      if (buffer_length < out_len) then begin
	//
	buffer_length := out_len;
	//
	mrealloc(acca, sizeOf(acca^) * buffer_length);
	mrealloc(accb, sizeOf(accb^) * buffer_length);
	mrealloc(la_in, sizeOf(la_in^) * buffer_length);
	mrealloc(hp_out, sizeOf(hp_out^) * buffer_length);
      end;
      //
      // lookahead
      sample_rate := getf(DSPL_PID or DSPL_P_NFRQ or DSPL_SPEECHPROC_SAMPLE_RATE);
      if (la_size < floor(sample_rate * look_ahead)) then begin
	//
	la_size := floor(sample_rate * look_ahead);
	la_pos := 0;
	mrealloc(la_buf, sizeOf(la_buf^) * la_size);
	//
	for i := 0 to la_size - 1 do
	  pFloatArray(la_buf)[i] := 0.0;
      end;
      //
      // AGC Setup
      agc.seti(DSPL_PID or DSPL_P_TYPE    or DSPL_LD, DSPL_LD_PEAK);
      agc.setf(DSPL_PID or DSPL_P_ATTACK  or DSPL_LD, 0.001 * sample_rate);
      agc.setf(DSPL_PID or DSPL_P_RELEASE or DSPL_LD, 1.0 * sample_rate);
      agc.setf(DSPL_PID or DSPL_P_OTHER   or DSPL_LD, 0.5 * sample_rate);
      //
      agc.setf(DSPL_PID or DSPL_P_ATTACK , 0.01 * sample_rate);
      agc.setf(DSPL_PID or DSPL_P_RELEASE, 0.05 * sample_rate);
      //
      enh.seti(DSPL_PID or DSPL_P_TYPE or DSPL_EQ2B_BAND1, DSPL_BIQ_PEAK);
      enh.setf(DSPL_PID or DSPL_P_GAIN or DSPL_EQ2B_BAND1, db2v(+6.0));
      enh.setf(DSPL_PID or DSPL_P_FRQ  or DSPL_EQ2B_BAND1, getf(DSPL_PID or DSPL_P_NFRQ or DSPL_SPEECHPROC_ENHANCER) / sample_rate);
      enh.setf(DSPL_PID or DSPL_P_Q    or DSPL_EQ2B_BAND1, getf(DSPL_PID or DSPL_P_Q    or DSPL_SPEECHPROC_ENHANCER));
      //
      slope := pow(2.0, -0.5);
      //
      enh.seti(DSPL_PID or DSPL_P_TYPE or DSPL_EQ2B_BAND2, DSPL_BIQ_HP);
      enh.setf(DSPL_PID or DSPL_P_FRQ  or DSPL_EQ2B_BAND2, getf(DSPL_PID or DSPL_P_NFRQ or DSPL_SPEECHPROC_LOWCUT) / sample_rate);
      enh.setf(DSPL_PID or DSPL_P_Q    or DSPL_EQ2B_BAND2, slope);
      //
      hp.seti(DSPL_PID or DSPL_P_TYPE or DSPL_EQ2B_BAND2, DSPL_BIQ_HP);
      hp.setf(DSPL_PID or DSPL_P_FRQ  or DSPL_EQ2B_BAND2, getf(DSPL_PID or DSPL_P_NFRQ or DSPL_SPEECHPROC_DEESSER) / sample_rate);
      hp.setf(DSPL_PID or DSPL_P_Q    or DSPL_EQ2B_BAND2, slope / 2.0);
      //
      ds.seti(DSPL_PID or DSPL_P_TYPE    or DSPL_LD, DSPL_LD_RMS);
      ds.setf(DSPL_PID or DSPL_P_ATTACK  or DSPL_LD, 0.001 * sample_rate);
      ds.setf(DSPL_PID or DSPL_P_RELEASE or DSPL_LD, 0.001 * sample_rate);
      //
      ds.setf(DSPL_PID or DSPL_P_ATTACK , 0.005 * sample_rate);
      ds.setf(DSPL_PID or DSPL_P_RELEASE, 0.050 * sample_rate);
      //
      ds.setf(DSPL_PID or DSPL_P_THRESHOLD, db2v(-20.0));
      ds.setf(DSPL_PID or DSPL_P_RATIO or DSPL_DYNPROC_ABOVE, 100.0);
      ds.setf(DSPL_PID or DSPL_P_RATIO or DSPL_DYNPROC_BELOW, 1.0);
      ds.setf(DSPL_PID or DSPL_P_GAIN  or DSPL_DYNPROC_ABOVE, db2v(3.0));
      ds.setf(DSPL_PID or DSPL_P_GAIN  or DSPL_DYNPROC_BELOW, db2v(3.0));
      //
      comp.seti(DSPL_PID or DSPL_P_TYPE    or DSPL_LD, DSPL_LD_RMS);
      comp.setf(DSPL_PID or DSPL_P_ATTACK  or DSPL_LD, 0.001 * sample_rate);
      comp.setf(DSPL_PID or DSPL_P_RELEASE or DSPL_LD, 0.005 * sample_rate);
      //
      comp.setf(DSPL_PID or DSPL_P_ATTACK , 0.005 * sample_rate);
      comp.setf(DSPL_PID or DSPL_P_RELEASE, 0.050 * sample_rate);
      //
      comp.setf(DSPL_PID or DSPL_P_THRESHOLD, db2v(-12.0));
      comp.setf(DSPL_PID or DSPL_P_RATIO or DSPL_DYNPROC_ABOVE, 4.0);
      comp.setf(DSPL_PID or DSPL_P_RATIO or DSPL_DYNPROC_BELOW, 1.0);
      comp.setf(DSPL_PID or DSPL_P_GAIN  or DSPL_DYNPROC_ABOVE, getf(DSPL_PID or DSPL_P_GAIN));
      comp.setf(DSPL_PID or DSPL_P_GAIN  or DSPL_DYNPROC_BELOW, getf(DSPL_PID or DSPL_P_GAIN));
      //
      ng.seti(DSPL_PID or DSPL_P_TYPE    or DSPL_LD, DSPL_LD_PEAK);
      ng.setf(DSPL_PID or DSPL_P_ATTACK  or DSPL_LD, 0.001 * sample_rate);
      ng.setf(DSPL_PID or DSPL_P_RELEASE or DSPL_LD, 0.001 * sample_rate);
      ng.setf(DSPL_PID or DSPL_P_OTHER   or DSPL_LD, 0.001 * sample_rate);
      //
      ng.setf(DSPL_PID or DSPL_P_ATTACK , 0.005 * sample_rate);
      ng.setf(DSPL_PID or DSPL_P_RELEASE, 0.300 * sample_rate);
      //
      ng.setf(DSPL_PID or DSPL_P_RATIO or DSPL_DYNPROC_ABOVE, 1.0);
      ng.setf(DSPL_PID or DSPL_P_RATIO or DSPL_DYNPROC_BELOW, 0.05);
      ng.setf(DSPL_PID or DSPL_P_GAIN  or DSPL_DYNPROC_ABOVE, db2v(0.0));
      ng.setf(DSPL_PID or DSPL_P_GAIN  or DSPL_DYNPROC_BELOW, db2v(0.0));
      //
      lim.seti(DSPL_PID or DSPL_P_TYPE    or DSPL_LD, DSPL_LD_PEAK);
      lim.setf(DSPL_PID or DSPL_P_ATTACK  or DSPL_LD, 0.000 * sample_rate);
      lim.setf(DSPL_PID or DSPL_P_RELEASE or DSPL_LD, 0.001 * sample_rate);
      lim.setf(DSPL_PID or DSPL_P_OTHER   or DSPL_LD, 0.005 * sample_rate);
      //
      lim.setf(DSPL_PID or DSPL_P_ATTACK , 0.000 * sample_rate);
      lim.setf(DSPL_PID or DSPL_P_RELEASE, 0.050 * sample_rate);
      //
      lim.setf(DSPL_PID or DSPL_P_THRESHOLD, getf(DSPL_PID or DSPL_P_GAIN or DSPL_SPEECHPROC_CEIL));
      lim.setf(DSPL_PID or DSPL_P_RATIO or DSPL_DYNPROC_ABOVE, 100.0);
      lim.setf(DSPL_PID or DSPL_P_RATIO or DSPL_DYNPROC_BELOW, 1.0);
      lim.setf(DSPL_PID or DSPL_P_GAIN  or DSPL_DYNPROC_ABOVE, db2v(0.0));
      lim.setf(DSPL_PID or DSPL_P_GAIN  or DSPL_DYNPROC_BELOW, db2v(0.0));
      //
      agc.setc(DSPL_PID or DSPL_P_IN,  la_in, out_len);
      agc.setc(DSPL_PID or DSPL_P_OUT, acca , out_len);
      //
      enh.setc(DSPL_PID or DSPL_P_IN,  acca, out_len);
      enh.setc(DSPL_PID or DSPL_P_OUT, accb, out_len);
      //
      hp.setc(DSPL_PID or DSPL_P_IN,  accb  , out_len);
      hp.setc(DSPL_PID or DSPL_P_OUT, hp_out, out_len);
      //
      ds.setc(DSPL_PID or DSPL_P_IN,  hp_out, out_len);
      ds.setc(DSPL_PID or DSPL_P_OUT, accb  , out_len);
      //
      ng.setc(DSPL_PID or DSPL_P_IN,  acca, out_len);
      ng.setc(DSPL_PID or DSPL_P_OUT, accb, out_len);
      ng.setc(DSPL_PID or DSPL_P_IN or DSPL_DYNPROC_SC, ina, out_len);
      //
      comp.setc(DSPL_PID or DSPL_P_IN,  accb, out_len);
      comp.setc(DSPL_PID or DSPL_P_OUT, acca, out_len);
      //
      lim.setc(DSPL_PID or DSPL_P_IN,  acca, out_len);
      lim.setc(DSPL_PID or DSPL_P_OUT, outa, out_len);
      //
    end;	// if (modified) ...
    //
    if ((nil <> th_chunk.r_fp) or f_modified) then begin
      //
      if (nil <> th_chunk.r_fp) then
	noise_level := th_chunk.r_fp^
      else
	noise_level := getf(DSPL_PID or DSPL_P_THRESHOLD);
      //
      if (noise_level > db2v(-18.0)) then
	noise_level := db2v(-18.0)
      else
	if (noise_level < db2v(-127.0)) then
	  noise_level := db2v(-127.0);
      //
      gap := pow(db2v(-12.0) / noise_level, att_ratio);
      //
      agc_th := noise_level * gap;
      agc_gain := db2v(-12.0) / agc_th;
      //
      agc.setf(DSPL_PID or DSPL_P_THRESHOLD, agc_th);
      agc.setf(DSPL_PID or DSPL_P_RATIO or DSPL_DYNPROC_ABOVE, 8.0);
      agc.setf(DSPL_PID or DSPL_P_RATIO or DSPL_DYNPROC_BELOW, att_ratio);
      agc.setf(DSPL_PID or DSPL_P_GAIN  or DSPL_DYNPROC_ABOVE, agc_gain);
      agc.setf(DSPL_PID or DSPL_P_GAIN  or DSPL_DYNPROC_BELOW, agc_gain);
      //
      ng.setf(DSPL_PID or DSPL_P_THRESHOLD, noise_level);
      //
    end;	// if (chunk or modified) ...
    //
    la := la_in;
    ill := ina;
    //
    i := nSamples;
    while (i > 0) do begin
      //
      dec(i);
      //
      s := pFloatArray(la_buf)[la_pos];
      pFloatArray(la_buf)[la_pos] := ill^;
      inc(la_pos);
      //
      if (la_pos >= la_size) then
	la_pos := 0;
      //
      la^ := s;
      //
      inc(la);
      inc(ill);
    end;
    //
    agc.process(nSamples);
    enh.process(nSamples);
    hp.process(nSamples);
    //
    acc := acca;
    hpp := hp_out;
    //
    i := nSamples;
    while (i > 0) do begin
      //
      dec(i);
      //
      acc^ := acc^ - hpp^;
      inc(acc);
      inc(hpp);
    end;
    //
    ds.process(nSamples);
    //
    acc := acca;
    hpp := accb;
    //
    i := nSamples;
    while (i > 0) do begin
      //
      dec(i);
      //
      acc^ := acc^ + hpp^;
      //
      inc(acc);
      inc(hpp);
    end;
    //
    ng.process(nSamples);
    comp.process(nSamples);
    lim.process(nSamples);
    //
    seti(DSPL_PID or DSPL_P_OTHER, ng.geti(DSPL_PID or DSPL_P_OTHER));
    //
    f_modified := false;
  end;
end;


⌨️ 快捷键说明

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