script "Saw generator" language "pascal";

{
Saw generator through additive synthesis for Edison
(06) gol
}


// slow version
procedure GenSaw(Freq,Phase,Vol:Single);
var   n,x,c,m,x1,x2:Integer;
      s:Double;
      d,d2,p,f,Nyquist:Double;
Begin
if EditorSample.Length<=0 then EditorSample.Length:=Round(EditorSample.MSToSamples(1000));
Editor.GetSelectionS(x1,x2);

if Freq<10 then Freq:=10;
d:=Pi*2/EditorSample.SampleRate;
p:=Phase*Pi*2;
Nyquist:=EditorSample.SampleRate*0.5;
Vol:=Vol*0.5;

for n:=x1 to x2 do 
  Begin
  x:=n-x1;
  if x mod 10000=0 then ProgressMsg('正在处理',x,x2-x1);
    
  f:=Freq;
  s:=0;
  d2:=(n-x1)*d+p;
  m:=1;
  while f<Nyquist do
    Begin
    s:=s+Sin(d2*f)/m;
    f:=f+Freq;
    m:=m+1;
    End;  
  s:=s*Vol;  
  
  for c:=0 to EditorSample.NumChans-1 do
    EditorSample.SetSampleAt(n,c,s);
  End;
End;


// fast version
procedure GenSaw_Fast(Freq,Phase,Vol:Single);
var   n,m,x1,x2:Integer;
      f,Nyquist:Double;
      TempSample:TSample;
Begin
if EditorSample.Length<=0 then EditorSample.Length:=Round(EditorSample.MSToSamples(1000));
Editor.GetSelectionS(x1,x2);
EditorSample.SilenceFromTo(x1,x2);

TempSample:=TSample.Create;
TempSample.Length:=x2-x1+1;
TempSample.NumChans:=1;
TempSample.SampleRate:=EditorSample.SampleRate;

if Freq<10 then Freq:=10;
Nyquist:=EditorSample.SampleRate*0.5;
Vol:=Vol*0.5;

f:=Freq;
m:=1;
n:=Round(Nyquist/Freq);
while f<Nyquist do
  Begin
  ProgressMsg('正在处理 '+IntToStr(Round(f))+'Hz 正弦',m,n);
      
  TempSample.SineFromTo(0,x2-x1,f,Phase*m,Vol/m);
  EditorSample.PasteFromTo(TempSample,x1,x2,2);
  f:=f+Freq;
  m:=m+1;
  End;  
  
TempSample.Free;  
End;


var Form:TScriptDialog;

Begin
Form:=CreateScriptDialog('锯齿波发生器','一个频段受限制的锯齿波发生器。');
Form.AddInputKnob('基本频率(Hz)',500,10,5000);
Form.AddInput('相位',0);
Form.AddInput('音量',1);
if Form.Execute then GenSaw_Fast(Form.GetInputValue('基本频率(Hz)'),Form.GetInputValue('相位'),Form.GetInputValue('音量'));
Form.Free;
End.
