
(*

Incorrect Music

Andreja Andric, January 2007.

Duration: 37 seconds

Compile this program with a 16 bit pascal compiler (like Borland Turbo Pascal 7), 
and run it this way: 
incmusic > incmusic.wav
to obtain stereo recording of Incorrect Music

Note #1: this program contains a programming error (rnd function can return negative
values, while throughout the program it is assumed that its value is always positive). 
When I discovered and corrected the error, I noticed that the musical result was far 
less impressive. Therefore in the final version I retained the error in code. 
That was very cool.

Note #2: although the program uses a linear congruent random generator, it always 
produces the same music piece, because the starting seed is fixed to 7 (magickal number).
If you change the seed and recompile the program it might generate a different music
piece, but it is not guaranteed to work at all, due to the above described error.

*)

program IncorrectMusic;

var 
   i, j, current_amplitude, a, b, upper_limit, lower_limit, seed, aa, cc:integer;
   rise, regular:boolean;

procedure writeheader;
const 
   header:array[1..44] of integer=
(82, 73, 70, 70, 44, 0, 100, 0, 87, 65, 86, 69, 102, 109, 116, 32, 16, 0, 0, 0, 
1, 0, 2, 0, 68, 172, 0, 0, 16, 177, 2, 0, 4, 0, 16, 0, 100, 97, 116, 97, 0, 0, 100, 0);
var
   i:integer;
begin
   for i:=1 to 44 do write(chr(header[i]));
end;

function rnd(limit:integer):integer;
begin
   seed:=seed*aa+cc;
   rnd:=seed mod limit;
end;

begin
   seed:=7; a:=6; upper_limit:=32000; lower_limit:=-32000; current_amplitude:=0; 
   rise:=true; regular:=true; aa:=5377; cc:=13849;
   writeheader;
   for i:=1 to 16384 do
   begin
      for j:=1 to 200 do
      begin
         b:=5+(a mod 10);
         if regular then b:=a else b:=rnd(b);
         write(chr(current_amplitude div 256));
         write(chr(current_amplitude mod 256));
         if rise 
         then current_amplitude:=current_amplitude+b 
         else current_amplitude:=current_amplitude-b;
         if rise and (current_amplitude>upper_limit) then rise:=false;
         if not rise and (current_amplitude<lower_limit) then rise:=true;
      end;
      if(rnd(191)=7) then a:=6+rnd(30);
      if(rnd(171)=7) then upper_limit:=100+10000*rnd(30);
      if(rnd(181)=7) then lower_limit:=-100-10000*rnd(30);
      if(rnd(161)=7) then regular:=not regular;
      if(i mod 5000 = 0) then cc:=cc-100;
   end;
end.
