#include <iostream.h>
#include <dos.h>
#include <conio.h>
#include <stdlib.h>
#include <graphics.h>
#include <process.h>
#include <ctype.h>
#include <string.h>
#include <fstream.h>
#ifdef __cplusplus
#define __CPPARGS ...
#else
#define __CPPARGS
#endif
void sonido(int frecuencia);
void nsonido();
void interrupt (*antint9)(__CPPARGS);
void interrupt nuevaint9(__CPPARGS);
void interrupt (*antint8)(__CPPARGS);
void interrupt demonioreloj(__CPPARGS);
class teclapiano{
int x1,y1,x2,y2;
unsigned char numnota,sostenido;
public:
teclapiano() { }
void meterdatos(int h1,int k1,int h2,int k2, int nn)
{
x1=h1;
y1=k1;
x2=h2;
y2=k2;
numnota=nn;
sostenido=0;
}
void dibujatecla();
void desactivatecla();
void activatecla(unsigned char &sost);
};
class piano {
unsigned char actual;
teclapiano *pteclas;
public:
piano();
~piano()
{
delete [] pteclas;
}
void pulsatecla(int numtecla,unsigned char &sost);
void despulsa();
void tocar(unsigned char numoctava,unsigned char activo,int nota, unsigned char numnota, unsigned char sost);
};
piano mipiano;
static const unsigned A=880,AS=923,B=988,C=1047,CS=1109,D=1175,DS=1245,
E=1329,F=1397,FS=1480,G=1568,GS=1661;
class nota {
public:
int frecuencia,duracion;
unsigned char numnota,numoctava,sost;
};
class melodia {
nota *pnotas;
unsigned char activo;
int notactual, numnotas;
public:
melodia()
{
pnotas=0;
activo=0;
numnotas=0;
notactual=0;
}
void crearnotas(int totalnotas)
{
numnotas=totalnotas;
pnotas=new nota [numnotas];
notactual=0;
activo=0;
}
void llenarnota(int indice, int frec, float dur, unsigned char noct, unsigned char nn,unsigned char sostenido);
void activar()
{
activo=1;
mipiano.pulsatecla(pnotas[notactual].numoctava*7+pnotas[notactual].numnota,pnotas[notactual].sost);
sonido(pnotas[notactual].frecuencia);
}
void decduracion();
unsigned char devestado()
{
return activo;
}
int devduractual()
{
return pnotas[notactual].duracion;
}
};
void melodia::llenarnota(int indice, int frec, float dur, unsigned char noct, unsigned char nn, unsigned char sostenido)
{
if(noct==5)
pnotas[indice].frecuencia=frec;
else
{
if(noct<5)
pnotas[indice].frecuencia=frec/(1<<(5-noct));
else if(noct>5)
pnotas[indice].frecuencia=frec*(1<<(noct-5));
}
pnotas[indice].duracion=(int) (dur*18.2);
pnotas[indice].numnota=nn;
pnotas[indice].numoctava=noct;
pnotas[indice].sost=sostenido;
}
void melodia::decduracion()
{
pnotas[notactual].duracion--;
if(!(pnotas[notactual].duracion))
{
notactual++;
if(notactual==numnotas)
{
activo=0;
notactual=0;
nsonido();
mipiano.despulsa();
delete [] pnotas;
}
else
{
mipiano.despulsa();
mipiano.pulsatecla(pnotas[notactual].numoctava*7+pnotas[notactual].numnota,pnotas[notactual].sost);
sonido(pnotas[notactual].frecuencia);
}
}
}
void teclapiano::dibujatecla()
{
char cad[2]=" \0";
cad[0]=numnota+0x41;
bar(x1+1,y1+1,x2-1,y2-1);
rectangle(x1,y1,x2,y2);
if(numnota!=1 && numnota!=4)
{
setfillstyle(SOLID_FILL,BLACK);
bar(x2-((x2-x1)/2),y1,x2,y1+(y2-y1)/2);
setfillstyle(SOLID_FILL,WHITE);
}
outtextxy(x2-10,y2-10,cad);
}
void teclapiano::activatecla(unsigned char &sost)
{
struct linesettingstype lineinfo;
getlinesettings(&lineinfo);
sostenido=sost;
setlinestyle(SOLID_LINE,0,3);
if(!sostenido)
{
line(x1+2,y1+1,x1+2,y2-1);
line(x1+1,y2-2,x2-1,y2-2);
}
else
{
setcolor(LIGHTGRAY);
line((x1+(x2-x1)/2+1),y1+1,x1+(x2-x1)/2+1,y1+(y2-y1)/2-1);
line(x1+(x2-x1)/2,y1+(y2-y1)/2-1,x2-1,y1+(y2-y1)/2-1);
setcolor(BLACK);
}
setlinestyle(lineinfo.linestyle,lineinfo.upattern,lineinfo.thickness);
}
void teclapiano::desactivatecla()
{
struct linesettingstype lineinfo;
getlinesettings(&lineinfo);
setlinestyle(SOLID_LINE,0,3);
if(!sostenido)
{
setcolor(WHITE);
line(x1+2,y1+1,x1+2,y2-1);
line(x1+1,y2-2,x2-1,y2-2);
setcolor(BLACK);
}
else
{
line(x1+(x2-x1)/2+1,y1+1,x1+(x2-x1)/2+1,y1+(y2-y1)/2-1);
line(x1+(x2-x1)/2,y1+(y2-y1)/2-1,x2-1,y1+(y2-y1)/2-1);
}
setlinestyle(lineinfo.linestyle,lineinfo.upattern,lineinfo.thickness);
}
piano::piano()
{
int controlador=DETECT, modo;
if(registerbgidriver(EGAVGA_driver)<0)
{
cout<<"Error de gr ficos";
getch();
exit(1);
}
initgraph(&controlador, &modo,"");
if(graphresult()!=grOk)
{
cout<<"Error de gr ficos";
getch();
exit(1);
}
unsigned char i,j;
int xn=getmaxx(), yn=getmaxy(), cotay1=yn/5.0;
actual=0;
pteclas=new teclapiano[57]; if(!pteclas)
{
closegraph();
cout<<"Insuficiente memoria...";
getch();
exit(1);
}
char titulo[]="Piano Expo FI 99";
char creditos[]="Autor: Ariel Medina V.";
outtextxy(xn/2-strlen(titulo)*8/2,0,titulo);
outtextxy(xn-strlen(creditos)*8,yn-10,creditos);
setcolor(BLACK);
for(i=0; i<21; i++)
{
pteclas[i].meterdatos((xn/23.0)*(i+1),cotay1,(xn/23.0)*(i+2),cotay1*2-10,i%7);
pteclas[i].dibujatecla();
}
for(i=0, j=21; i<21; i++, j++)
{
pteclas[j].meterdatos((xn/23.0)*(i+1),cotay1*2,(xn/23.0)*(i+2),cotay1*3-10,i%7);
pteclas[j].dibujatecla();
}
for(i=0, j=42; i<15; i++, j++)
{
pteclas[j].meterdatos((xn/23.0)*(i+4),cotay1*3,(xn/23.0)*(i+5),cotay1*4-10,i%7);
pteclas[j].dibujatecla();
}
}
void piano::pulsatecla(int numtecla,unsigned char &sost)
{
actual=numtecla;
pteclas[actual].activatecla(sost);
}
void piano::despulsa()
{
pteclas[actual].desactivatecla();
}
void piano::tocar(unsigned char numoctava,unsigned char activo,int nota, unsigned char numnota, unsigned char sost)
{
if(activo)
despulsa();
if(numoctava<8)
{
pulsatecla(numoctava*7+numnota,sost);
if(numoctava==5)
sonido(nota);
else
{
if(numoctava<5)
sonido(nota/(1<<(5-numoctava)));
else if(numoctava>5)
sonido(nota*(1<<(numoctava-5)));
}
}
else
if(!numnota)
{
pulsatecla(numoctava*7,sost);
sonido(nota*(1<<(numoctava-5)));
}
}
class notarchivo {
unsigned char numnota, numoctava, sost;
float duracion, frecuencia;
public:
~notarchivo()
{
if(ptrsig)
delete ptrsig;
}
notarchivo(unsigned char nn, float dur, unsigned char noct,unsigned char st, float frec)
{
ptrsig=0;
numnota=nn;
duracion=dur;
numoctava=noct;
sost=st;
frecuencia=frec;
}
void recuperadatos(unsigned char &nn, float &dur, unsigned char &noct, unsigned char &st, float &frec )
{
nn=numnota;
dur=duracion;
noct=numoctava;
st=sost;
frec=frecuencia;
}
notarchivo *ptrsig;
};
class listanotas {
notarchivo *ini, *fin;
int totalnotas;
void meternota(unsigned char nn, float dur, unsigned char noct,unsigned char st, float frec);
public:
listanotas() { ini=fin=0; totalnotas=0; }
~listanotas() { delete ini; }
int llenarlista(char *nomarchivo);
void volcarlista(melodia &pmelodia);
int extraercomponente(int &posicion, int tam, unsigned char *sdestino,unsigned char *sfuente);
};
void listanotas::meternota(unsigned char nn, float dur, unsigned char noct,unsigned char st, float frec)
{
notarchivo *temp;
temp=new notarchivo(nn,dur,noct,st,frec);
if(!temp)
{
closegraph();
cout<<"Error de asignaci˘n de memoria...";
if(ini) delete ini;
exit(1);
}
if(!ini)
{
ini=fin=temp;
}
else
{
fin->ptrsig=temp;
fin=temp;
}
totalnotas++;
}
int listanotas::extraercomponente(int &posicion, int tam, unsigned char *sdestino,unsigned char *sfuente)
{
unsigned char indice=0;
while(posicion<tam && sfuente[posicion]!=',' && indice<4 && sfuente[posicion]!='=')
{
if(!isspace(sfuente[posicion]))
{
sdestino[indice++]=sfuente[posicion];
}
posicion++;
}
if(indice==4 || posicion==tam)
return 1;
sdestino[indice]='\0';
if(sfuente[posicion]!='=')
posicion++;
return 0;
}
int listanotas::llenarlista(char *nomarchivo)
{
unsigned char c=' ', nom[3], *bufer, sdestino[20], componente[5], numoct=6;
int tamanio, i=0 ;
float dn=0.5, durnota=0.5;
ifstream flujoent(nomarchivo, ios::binary | ios:: in);
if(!flujoent)
{
return 1;
}
flujoent.seekg(0,ios::end);
tamanio=flujoent.tellg();
flujoent.seekg(0,ios::beg);
if(tamanio>4096)
return 2;
bufer=new unsigned char [tamanio];
flujoent.read(bufer,tamanio);
flujoent.close();
while(i<tamanio && isspace(c))
{
c=bufer[i++];
}
if(i<tamanio)
{
if(c=='[')
do
{
c=bufer[i++];
}while(c!=']' && i<tamanio);
while(i<tamanio)
{
if(!extraercomponente(i,tamanio,componente,bufer))
{
if(strcmp(componente,"DN"))
{
int no;
if(no=atoi(componente))
{
if(no>0 && no<10)
numoct=(unsigned char) no;
else
return 10;
}
else
{
if(strlen(componente)==1)
{
switch(componente[0])
{
case 'A':
meternota(0,durnota,numoct,0,A);
break;
case 'B':
meternota(1,durnota,numoct,0,B);
break;
case 'C':
meternota(2,durnota,numoct,0,C);
break;
case 'D':
meternota(3,durnota,numoct,0,D);
break;
case 'E':
meternota(4,durnota,numoct,0,E);
break;
case 'F':
meternota(5,durnota,numoct,0,F);
break;
case 'G':
meternota(6,durnota,numoct,0,G);
break;
case 'R':
durnota=dn*4;
break;
case 'N':
durnota=dn;
break;
}
}
else
{
if(strlen(componente)==2)
{
if(componente[1]=='S')
switch(componente[0])
{
case 'A':
meternota(0,durnota,numoct,1,AS);
break;
case 'C':
meternota(2,durnota,numoct,1,CS);
break;
case 'D':
meternota(3,durnota,numoct,1,DS);
break;
case 'F':
meternota(5,durnota,numoct,1,FS);
break;
case 'G':
meternota(6,durnota,numoct,1,GS);
break;
}
else
switch(componente[1])
{
case 'O':
durnota=dn/2;
break;
case 'C':
durnota=dn/4;
break;
case 'U':
durnota=dn/8;
break;
case 'F':
durnota=dn/16;
break;
case 'L':
durnota=dn*2;
break;
}
}
else
return 10;
}
}
}
else
{
i++;
if(!extraercomponente(i,tamanio,componente,bufer))
{
float temp;
if(temp=atof(componente))
dn=temp;
else
return 9;
}
else
return 8;
}
}
else
return 5;
}
}
else
return 4;
return 0;
}
void listanotas::volcarlista(melodia &pmelodia)
{
unsigned char numnota, numoctava, sostenido;
float durnota, frecuencia;
notarchivo *temp=ini;
int indice=0;
pmelodia.crearnotas(totalnotas);
while(temp)
{
temp->recuperadatos(numnota,durnota,numoctava,sostenido,frecuencia);
pmelodia.llenarnota(indice,(int) frecuencia,durnota,numoctava,numnota,sostenido);
temp=temp->ptrsig;
indice++;
}
delete ini;
}
melodia melodia1;
main()
{
unsigned char letra;
antint9=getvect(0x09);
setvect(0x09,nuevaint9);
do
{
letra=getch();
}while(letra!=0x1b);
setvect(0x09,antint9);
antint8=getvect(0x08);
listanotas milista;
milista.llenarlista("condor.pno");
milista.volcarlista(melodia1);
setvect(0x08,demonioreloj);
getch();
setvect(0x08,antint8);
nsonido();
closegraph();
return 0;
}
void interrupt nuevaint9(__CPPARGS)
{
unsigned char codigo=0;
static unsigned char activo=0, sost=0, noct=5;
codigo=inportb(0x60);
if(codigo<0x80)
switch(codigo)
{
case 0x1e:
if(codigo!=activo)
{
mipiano.tocar(noct,activo,sost?AS:A,0,sost);
activo=codigo;
}
break;
case 0x30:
if(codigo!=activo)
{
mipiano.tocar(noct,activo,B,1,0);
activo=codigo;
}
break;
case 0x2e:
if(codigo!=activo)
{
mipiano.tocar(noct,activo,sost?CS:C,2,sost);
activo=codigo;
}
break;
case 0x20:
if(codigo!=activo)
{
mipiano.tocar(noct,activo,sost?DS:D,3,sost);
activo=codigo;
}
break;
case 0x12:
if(codigo!=activo)
{
mipiano.tocar(noct,activo,E,4,0);
activo=codigo;
}
break;
case 0x21:
if(codigo!=activo)
{
mipiano.tocar(noct,activo,sost?FS:F,5,sost);
activo=codigo;
}
break;
case 0x22:
if(codigo!=activo)
{
mipiano.tocar(noct,activo,sost?GS:G,6,sost);
activo=codigo;
}
break;
case 0x1d:
noct=4; break;
case 0x38:
noct=6; break;
case 0x2a:
sost=1; break;
case 0x1f:
sost=1; break;
case 0x02:
noct=0; break;
case 0x03:
noct=1; break;
case 0x04:
noct=2; break;
case 0x05:
noct=3; break;
case 0x06:
noct=4; break;
case 0x07:
noct=5; break;
case 0x08:
noct=6; break;
case 0x09:
noct=7; break;
case 0x0a:
noct=8; break;
}
else
{
codigo-=0x80;
if(codigo==activo)
{
nsonido();
mipiano.despulsa();
activo=0;
}
else
{
if(codigo>0x01 && codigo<0x0b)
noct=5;
else
switch(codigo)
{
case 0x1d:
noct=5;
break;
case 0x38:
noct=5;
break;
case 0x2a:
sost=0;
break;
case 0x1f:
sost=0;
break;
}
}
}
antint9();
}
void interrupt demonioreloj(__CPPARGS)
{
if(melodia1.devestado())
{
melodia1.decduracion();
}
else if(melodia1.devduractual())
melodia1.activar();
antint8();
}
void sonido(int frecuencia)
{
int contador; unsigned char valorant;
contador=0x1234DD/frecuencia; outportb(0x43,0xb6); outportb(0x42,(unsigned char) (contador&0x00ff)); outportb(0x42,(unsigned char) (contador>>8)); valorant=inportb(0x61);
outportb(0x61,valorant | 3); }
void nsonido()
{
unsigned char valorant;
valorant=inportb(0x61);
outportb(0x61,valorant & 0xfc); }