%!

  
% A modified efficient digital sinewave algorithm
% =====================================
% Don Lancaster and Synergetics www.tinaja.com

% Some ultra compact low end digital sinewave generators
% were described in Column 10 of https://www.tinaja.com/glib/hackar1.pdf

% It appears that better performance and lower distortion can be
% had by making the initial triangle approximation look more like
% a true cosine wave. This can be done by adding adjustments to a
% simple clipping. At a penalty of only a few bytes extra.

% This example creates a 55 amplitue 44 frequency 8 modified triangle
% height sinewave usable by a low end microprocessor. Verified.

% This file is http://www.tinaja.com/psutils/nusine53.psl It is normally
% run by sending the file to Distiller by way of command line //acrodist /F.
% It should also be GhostScript or Google Drive compatible.

% The companion demo is http://www.tinaja.com/psutils/nusine53.pdf

% It appears that dozens of similar low distortion sinewaves of
% different amplitudes are possible.

% Development services available via don@tinaja.com.


% ///////// (A) WEB FRIENDLY COLOR UTILITIES /////////////

% tintmat is a self-generating list of 216 triple color values

/webtintmat [
0 1 5 { /a exch store
0 1 5 { /b exch store
0 1 5 { 5 div b 5 div a 5 div
}for
} for
} for
] def


% setwebtint accepts a color number 0 to 215 and then
% sets the PostScript color generator for later use...

/setwebtint { abs cvi 216 cvi mod     % restrict range
webtintmat exch 3 mul 3 getinterval   % get values from table
aload pop setrgbcolor} def            % and set them

% The blocks are arranged as red to the right, green
% up in order of increasing blue.

% Some "pure color" sequences are

% red:        0    1    2    3    4    5
% orange:     0    7    8   15   16   23  (sort of)
% yellow:     0    7   14   21   28   35
% green:      0    6   12   18   24   30
% aqua:       0   42   84  126  168  210
% blue:       0   36   72  108  144  180
% magenta:    0   37   74  111  148  185
% purple      0   73   73  110  147  183  (sort of)
% gray        0   43   86  129  172  215

% ////////////// GONZO EXCERPTS //////////////////

/setgrid { /blocksize exch def translate    % simplified
           blocksize dup scale} def


% repeats [ proc distance trips] xrpt

/xrpt{gsave aload pop /trips exch def /dist exch def /rproc exch def
trips { gsave rproc grestore dist 0 translate } repeat grestore} def

/yrpt{gsave aload pop /trips exch def /dist exch def /rproc exch def
trips { gsave rproc grestore 0 dist translate } repeat grestore} def


% mergestr merges the two top stack strings into one top stack string

/mergestr {2 copy length exch length add string dup dup 4 3 roll
4 index length exch putinterval 3 1 roll exch 0 exch putinterval} def


/showgrid {gsave /vblocks exch def /hblocks exch def
thingridlines setlinewidth
[{0 0 moveto 0 vblocks rlineto stroke} 1
hblocks 1 add] xrpt
[{0 0 moveto hblocks 0 rlineto stroke} 1
vblocks 1 add] yrpt
fatterborder { gsave newpath 0 0.96 blocksize div 
dtransform round idtransform 
setlinewidth pop 2 setlinecap
0 0 moveto hblocks 0 rlineto 0 vblocks rlineto 
hblocks neg 0 rlineto closepath stroke grestore} if
fat5 { gsave newpath 0 0.48 blocksize div dtransform round
idtransform setlinewidth pop mark {5 0 moveto 0 vblocks rlineto
stroke} 5 hblocks 5 div cvi] xrpt mark {0 5 moveto hblocks 0 rlineto
stroke} 5 vblocks 5 div cvi] yrpt grestore} if
fatter10 { gsave newpath 0 0.96 blocksize div 
dtransform round idtransform setlinewidth pop 
mark {10 0 moveto 0 vblocks rlineto stroke} 10
hblocks 10 div cvi] xrpt mark {0 10 moveto hblocks 0 rlineto stroke} 10
vblocks 10 div cvi] yrpt grestore} if
grestore} def

/fatterborder {true  } store
/fat5 {false} store
/fatter10 { false} store
/thingridlines {0} store


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%



%%%%%%%%%%%%%%%%%%% adjusted sinewave %%%%%%%%%%%%%
 
/sizegoal 55 store   % height of sinewave  
/steps 44 store      % steps per cycle
/plothi 8 store      % height of modified cosine triangle

/adjustcos {     % details here will vary with other amplitudes!


{
dup 5 ge {1 sub} if
dup -5 le {1 add} if

dup 6 eq {pop 5} if
dup -6 eq {pop -5} if

} pop

dup 8 eq {pop 7} if
dup -8 eq {pop -7} if

 dup 9 ge {pop 8} if
 dup -9 le {pop -8} if

 

  } store


10 250 translate
1 setlinewidth 
1 setlinejoin
1 setlinecap

%%%%%%%%%%%%%%%%%%%%% cos channel  %%%%%%%%%%%%%

% Calculate a 48 step low distortion digital sinewave…

/size sizegoal def % set zero to peak size 
/speed 0 def % initialize speed
/cycles 6 store % number of full cycles


0 size moveto

1    1 steps cycles mul { % start a for loop

 /val exch store % save position

 /speed speed size 0 gt {-1}{+1} % start the algorithm
 ifelse add store




 /size size speed adjustcos add store % finish the algorithm


 % use your sinewave here

  1 0 rlineto val size lineto   % for actual
  % val size lineto   % smoothed

 } for % complete loop

212 setwebtint 1 setlinewidth stroke 



%%%%%%%%%%%%%%%%%%%%%%% sin channel %%%%%%%%%%%%%%%%%%%%%%%%%

 -1 0 moveto

/size sizegoal def % set zero to peak size
/speed 0 def % initialize speed




1 1 steps cycles mul { % start a for loop

 /val exch store % save position

 /speed speed size 0 gt {-1}{+1} % start the algorithm
 ifelse add store


    

 /size size speed adjustcos
add store % finish the algorithm


 % use your sinewave here

%  1 0 rlineto val speed adjustcos lineto 
 val speed adjustcos lineto


 } for % complete loop

30 setwebtint 1 setlinewidth stroke 








%%%%%%%%%%%%%%  real comparison sinewave %%%%%%%%%%%%%%%

/phase 0  store
/trim 1 store   % should be one after debug

0 0 moveto
0 1 steps cycles mul {/pos exch store 
pos trim mul phase add 

pos 360 mul steps div sin 
plothi mul neg  

2 copy == (    ) print ==              

lineto
} for


0 setwebtint 0 setlinewidth stroke


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


gsave 0 0 moveto 
0 setlinewidth 600 0 rlineto 212 setwebtint stroke grestore  % baseline

gsave 0 sizegoal  moveto 
0 setlinewidth 600 0 rlineto 212 setwebtint stroke grestore  % baseline

gsave 0 sizegoal neg moveto 
0 setlinewidth 600 0 rlineto 212 setwebtint stroke grestore  % baseline


gsave 0 5  moveto 
0 setlinewidth 600 0 rlineto 5 setwebtint stroke grestore  % red 5

gsave 0 10  moveto 
0 setlinewidth 600 0 rlineto 5 setwebtint stroke grestore  % red 10





%%%%%%%%%%%%%%%%%%%%%%%  grid boxes %%%%%%%%%%%%%%%%%%%%%

4 1 12 {/ruleuh exch store               % upper h grid
68 ruleuh moveto 20 
0 rlineto          
0 setwebtint 0 setlinewidth stroke
} for 

93 4 moveto                               % upper v grid
0 1 20 {/ruleuv exch store
68 ruleuv add  4 moveto 
0 8 rlineto 
0 setwebtint stroke
} for


showpage

% EOF

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Catalog:

% 23-36-4:
%   filename matches amplitude
%   text matches data
%   no dc offset
%   cos fit all green
%   unity trim
%   3 cosine pair adjustment
%   delta  ( no previous )

% 39-40-6:
%   filename matches amplitude
%   text matches data
%   no dc offset
%   cos fit all green
%   unity trim
%   3 cos pair adjustment
%   delta 40-36 = 14

% 55-44-8:
%   filename matches amplitude
%   text matches data
%   no dc offset
%   cos fit all green 
%   unity trim
%   2 cos pair adjustment
%   delta55-39 = 16

% 76-48-10:   
%   filename matches amplitude
%   text matches data
%   no dc offset
%   cos fit all green 
%   unity trim
%   3 cos pair adjustment
%   delta 76-55 = 21

% 98-52-12:  
%   filename matches amplitude
%   text matches data
%   no dc offset
%   cos fit all green 
%   unity trim
%   2 cos pair adjustment
%   delta 98-76 = 22

% 118-56-14 still has problems