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.
Aggiungi un commento