La libreria crt del Pascal fornisce alcune funzioni interessanti per far emettere suoni a determinate frequenze.
Innanzitutto, bisogna precisare che per includere la libreria interessata è necessario l’enunciato
uses crt;
Le funzioni necessarie al nostro scopo sono:
sound(hz);
nosound;
delay(time);
La funzione sound fa emettere alla macchina un suono alla frequenza specificata tra parentesi. Per cambiare nota è sufficiente invocare nuovamente la funzione, specificando una frequenza diversa. Per fermare il suono bisogna invocare nosound.
Per far durare la nota per un tempo ragionevole, il programmatore deve ritardare la successiva occorrenza di sound(hz) o di nosound. Per fare questo si usa in genere delay(time), in cui time è una variabile di tipo word (il cui valore è compreso tra 0 e 65535) e corrisponde a multipli di 1 millisecondo (dipende dalla macchina). Purtroppo, questa funzione non è supportata dai processori veloci dell’ultima generazione, che rendono necessario l’utilizzo di altre funzioni. Questo aspetto rende dunque il programma poco portabile.

Dopo quanto detto, siamo arrivati a capire come far generare al computer dei suoni. Il seguente frammento di programma farà generare tre suoni in sequenza, di durate diverse:
sound(262); delay(400);
sound (330); delay(400);
sound (392); delay(400);
sound (524); delay(400);
nosound;

Riporto qui di seguito la tabella con le frequenze (e relativa formula) delle note dell’ottava centrale:

Nota        Frequenza    Formula
Do        262        440 * [2 ^ (1/12)] ^ (-9)
Do#/Reb    277        440 * [2 ^ (1/12)] ^ (-8)
Re        294        440 * [2 ^ (1/12)] ^ (-7)
Re#/Mib    311        440 * [2 ^ (1/12)] ^ (-6)
Mi        330        440 * [2 ^ (1/12)] ^ (-5)
Fa        349        440 * [2 ^ (1/12)] ^ (-4)
Fa#/Solb    370        440 * [2 ^ (1/12)] ^ (-3)
Sol        392        440 * [2 ^ (1/12)] ^ (-2)
Sol#/Lab    415        440 * [2 ^ (1/12)] ^ (-1)
La        440        440 * [2 ^ (1/12)] ^ 0
La#/Sib    466        440 * [2 ^ (1/12)] ^ 1
Si        494        440 * [2 ^ (1/12)] ^ 2

Per ottenere le note delle altre ottave, è sufficiente raddoppiare, triplicare, ecc., o, viceversa, dimezzare, ridurre a un terzo, ecc. le frequenza indicate nella tabella.

Possiamo però rendere il programma meglio strutturato, avvalendoci delle formule specifiche per ottenere le note relative.
Operativamente, si può procedere nel modo seguente. Le funzioni “potenza” e “radice” sono le medesime che ho inserito nella sezione “Tips” del sito; ciò su cui bisogna focalizzare l’attenzione è la procedura “nota”.
program generazione_suoni;
uses crt;

(*calcola la n-esima potenza di a*)
function potenza(a:real;n:integer):real;
var
   i:integer;
   x:real;
begin
   x:=1;
   if n<>0 then
      for i:=1 to abs(n) do
         x:=x*a;
   if n<0 then
      x:=1/x;
   potenza:=x;
end;

(*calcola la n-esima radice di a*)
function radice(a:real;n:integer):real;
const
   precisione_max=5;
   radice_max=100;
var
   i,precisione:integer;
   x:real;
begin
   x:=0;
   for precisione:=0 downto -precisione_max do
   begin
      for i:=0 to 9 do
         if potenza(x+potenza(10,precisione)*i,n) > a then break;
      dec(i);
      x:=x+potenza(10,precisione)*i;
   end;
   radice:=x;
end;

(*emette la nota desiderata*)
procedure nota(n:integer);
begin
   sound(round(440*(potenza(radice(2,12),n))));
end;

begin
   nota(-9); delay(400);
   nota(-5); delay(400);
   nota(-2); delay(400);
   nota(3);  delay(400);
   nosound;
   readln;
end.

La procedura “nota” riceve come argomento un numero intero, che corrisponde all’esponente della formula utilizzata per generare la nota relativa. La funzione round è necessaria in quanto il risultato della formula è un numero reale, mentre la funzione sound riceve come argomento un numero intero.