uses crt,dos;
const voclast:Byte=0;           {letzter Wert}
      trigger=5;                {Empfindlichkeit}
      fertig:Boolean=false;     {fertig ?}
var   oldint8:Pointer;          {alter IRQ 0 Handler}
      Voc:Pointer;              {Zeiger auf Sample-Daten im Speicher}
      VocFile:File;             {Voc-Datei}
      timwert,                  {Wert fr Timer-Chip}
      vocpos,                   {aktueller Offset in Voc-File}
      voclen,                   {L„nge des Voc-Files}
      Hz:Word;                  {Sample-Frequenz}

Procedure Play;interrupt;assembler;
{spielt Voc im Interrupt ab}
asm
  mov dx,61h                    {Inhalt des Controll Ports lesen}
  in al,dx
  mov cl,al                     {und in cl sichern}
  les di,voc                    {es:di mit Zeiger auf Sample-Daten laden}
  inc vocpos                    {Position um 1 weiter}
  mov ax,vocpos                 {in ax laden}
  add di,ax                     {und auf Speicher-Offset addieren}
  cmp ax,voclen                 {bereits Sample-Ende erreicht ?}
  jne @ok                       {ja,}
  mov fertig,1                  {dann flag setzen}
@ok:
  mov al,es:[di]                {sonst Wert holen}
  mov bl,al                     {in bl sichern}
  sub al,voclast                {Differenz zum letzten Wert bilden}
  mov voclast,bl                {und Wert als letzten Wert vermerken}
  cmp al,trigger                {Abstand gr”áer als Ansprechschwelle ?}
  jg @set                       {dann Speaker auf high setzen}
  cmp al,-trigger               {Abstand kleiner als negative Ansprechschw. ?}
  jg @ende                      {nein, dann fertig}
  mov al,cl                     {alten Inhalt d. Control-Ports}
  and al,not 2                  {Bit 1 l”schen}
  out dx,al                     {und schreiben}
  jmp @ende                     {fertig}
@set:
  mov al,cl                     {alten Inhalt d. Control-Ports}
  or al,2                       {Bit 1 setzen}
  out dx,al                     {und schreiben}
@ende:
  pushf                         {alten Handler aufrufen}
  call [oldint8]
End;

begin
  Assign(VocFile,'rythm.voc');  {File ”ffnen}
  Reset(VocFile,1);             {Zurcksetzen}
  Voclen:=FileSize(VocFile);    {L„nge ermitteln}
  GetMem(Voc,Voclen);           {entsprechend Speicher allokieren}
  BlockRead(VocFile,Voc^,FileSize(VocFile));
                                {Voc-File einlesen (max. 64kB)}
  Close(VocFile);               {und schlieáen}
  Hz:=1000000 div               {Sample-Frequenz aus Datei ermitteln}
    (256-Byte(Ptr(Seg(Voc^),Ofs(Voc^)+$1f)^));

  GetIntVec($8,OldInt8);        {Vektor IRQ 0 sichern}
  SetIntVec($8,@Play);          {IRQ 0 auf Handler verbiegen}

   timwert := 1193180 DIV Hz;   {aus Sampling-Frequenz Timer-Start berechn.}
  Port[$43]:=$36;               {diesen auf Z„hler 0 programmieren}
   Port[$40]:=Lo(timwert);
   Port[$40]:=Hi(timwert);

  Repeat Until KeyPressed or fertig;  {warten, bis Ende oder Taste}

  SetIntVec($8,OldInt8);        {Vektor wieder herstellen}
  Port[$43]:=$36;               {Timer zurcksetzen}
   Port[$40]:=0;                {(18,2 Hz)}
   Port[$40]:=0;
End.
