unit tgen;

interface

uses
	LibV;

function  toneInit(fr,a:vector_p):vboolean;
//	stdcall;external 'tgen.dll' name '_toneInit@8';
procedure toneGenerate(float_out:vec_t_array_p;num_samples:u32_t);
//	stdcall;external 'tgen.dll' name '_toneGenerate@8';

implementation

const
  SAMPLING_RATE	= 44100;
  MAXTONES	=	256;

var
  num_tones : u32_t;
  phase : array[0..MAXTONES] of vec_t;
  dph : array[0..MAXTONES] of vec_t;
  amp : array[0..MAXTONES] of vec_t;
  freq : array[0..MAXTONES] of vec_t;

function toneInit(fr,a:vector_p):vboolean;
var
 c : u32_t;
begin
  Result := False;
	if (fr^.size <> a^.size) or (fr^.size > MAXTONES) then
    Exit;
	num_tones := fr^.size;
	memCopy(@freq,fr^.elements,num_tones * sizeof(vec_t));
	memCopy(@amp,a^.elements,num_tones * sizeof(vec_t));
	memZero(@phase,num_tones * sizeof(vec_t));
	for c:=0 to num_tones-1 do
		dph[c] := M_2PI * freq[c] / SAMPLING_RATE;
	Result := True;
end;

function fmod(x:double):double;stdcall;external 'msvcrt.dll';

procedure toneGenerate(float_out:vec_t_array_p;num_samples:u32_t);
var
	s,c,l,t : u32_t;
	f,sv : vec_t;
const
  m_2p : vec_t = M_2PI;
begin
  l := num_samples-1;
  t := num_tones-1;
	for s:=0 to l do
  begin
		sv := 0;
		for c:=0 to t do
    begin
      asm
        mov eax, c
        mov edx, offset phase
        fld m_2p
        fld dword ptr phase[eax * 4]
        fprem
        fld dword ptr dph[eax * 4]
        faddp
        fst dword ptr phase[eax * 4]
        fsin
        fld dword ptr amp[eax * 4]
        fmulp
        fstp f
        ffree st(0)
      end;
      sv := sv + f;
		end;
		if sv < -1 then
			sv := -1
		else
			if sv > 1 then
				sv := 1;
		float_out^[s] := sv;
	end;
end;

end.
