Version:0.9 StartHTML:0000000105 EndHTML:0000045764 StartFragment:0000000152 EndFragment:0000045730
/******************************************************/
/*************** Isidro Pastor Jorda ******************/
/******************************************************/
/****************** Telematica ************************/
/******************** FPII ****************************/
/****************** Practica 5 ************************/
/******************************************************/
#include "Pasaje.h"
#include <fstream.h>
#include <string>
#include <windows.h> // uso de la funcion beep para reproducir la musica
const float frec[2][13]={
{262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494, 0},
{523, 554, 587, 622, 659, 698, 740, 784, 831, 880, 932, 988, 0} };
const float dura[5]={1.0, 2.0, 4.0, 0.5,0.25};
const int tiempobase = 1000 ; //Equivale a 1s como tiempo base
/*****************************************************************************
* Funcion: IntroNota
* Descripcion: Introduce una nota de tipo Valor en el objeto que hace la llamada
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* n E Dato que queremos introducir en el pasaje
*
*
*
* Valor devuelto:
* No devuelve nada
*****************************************************************************/
void Pasaje::IntroNota(Valor n)
{
while ( !(lst.FinalLista()) ) // Solo introducimos nota en un pasaje luego siempre lo haremos al final
lst.Avanzar();
lst.Insertar(n); // Una vez situados al final insertamos la nota
};
/*****************************************************************************
* Funcion: EliminarNota
* Descripcion: elimina una nota de tipo Valor en el objeto que hace la llamada
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* idno E id de la nota que queremos eliminar del pasaje
*
*
*
* Valor devuelto:
* True si se ha podido eliminar, false en caso contrario
*****************************************************************************/
bool Pasaje::EliminarNota(int idno)
{
bool ok;
ok = BuscarIdNota(idno);
if (ok) // Posicionamos el punto de interes en la nota que queremos eliminar
lst.Eliminar(); // y la eliminamos
else
cerr << " El identificador de nota introducido no se encuentra en el pasaje/melodia\n";
return (ok);
};
/*****************************************************************************
* Funcion: Visualizar
* Descripcion: Muestra por pantalla los elementos del objeto que hace la llamada
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
*
*
*
*
* Valor devuelto:
* No devuelve nada
*****************************************************************************/
void Pasaje::Visualizar()
{
Valor aux;
lst.IrAInicio();
lst.Consulta(aux);
cout << " IDNOTA OCTAVA NOTA DURACION \n" ;
while ( !(lst.FinalLista()) )
{
cout << " " << aux.iden << " "; // Mostramos primero el id de nota
if (aux.nota == Tiponota(12) ) // Si la nota es un silencimo mostraremos una S
cout << " S ";
else
cout << " " << int(aux.octava) + 1 << " " ; // Si no es silencio entonces mostramos la octava
switch ( int(aux.nota) ) // Para estar seguros de que tenemos un entero lo explicitamos aunque no es necesario
{
case 0:
cout << "Do ";
break;
case 1:
cout << "Do# ";
break;
case 2:
cout << "Re ";
break;
case 3:
cout << "Re# ";
break;
case 4:
cout << "Mi ";
break;
case 5:
cout << "Fa ";
break;
case 6:
cout << "Fa# ";
break;
case 7:
cout << "Sol ";
break;
case 8:
cout << "Sol# ";
break;
case 9:
cout << "La ";
break;
case 10:
cout << "La# ";
break;
case 11:
cout << "Si ";
break;
case 12:
cout << " ";
break;
default:
cout << " ";
break;
};
switch ( int(aux.duracion) ) // y despues de mostrar la nota mostramos la duracion de la misma
{
case 0:
cout << " ne ";
break;
case 1:
cout << " bl ";
break;
case 2:
cout << " re ";
break;
case 3:
cout << " co ";
break;
case 4:
cout << " sc ";
break;
default:
cout << " ";
break;
};
cout << endl;
lst.Avanzar(); // Avanzamos el punto de interes una posicion en la lista
lst.Consulta(aux); // y volvemos a consultar el dato siguiente
} // while
};
/*****************************************************************************
* Funcion: LimpiarPasaje
* Descripcion: Elimina todos los elementos del objeto que hace la llamada
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
*
*
*
*
* Valor devuelto:
* No devuelve nada
*****************************************************************************/
void Pasaje::LimpiarPasaje()
{
lst.IrAInicio(); // Vamos al inicio del pasaje
while(!lst.ListaVacia()) // y empezamos a borrar todo hasta que tengamos una lista vacia
lst.Eliminar();
};
/*****************************************************************************
* Funcion: Tocar
* Descripcion: Reproduce mediante el PCSpeaker los datos del objeto que hace la llamada
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
*
*
*
*
* Valor devuelto:
* No devuelve nada
*****************************************************************************/
void Pasaje::Tocar()
{
Valor aux;
lst.IrAInicio(); // Reproduciremos empezando desde el principio
while( !lst.FinalLista() )
{
lst.Consulta(aux); // consultamos el dato y llamamos a la funcion beep para reproducirlo por el pcspeaker
Beep(int(frec[aux.octava][aux.nota]), int(tiempobase * dura[aux.duracion]));
lst.Avanzar(); // despues de tocar la nota avanzamos a la siguiente el punto de interes
}
};
/*****************************************************************************
* Funcion: TocarAlreves
* Descripcion: Reproduce en orden inverso mediante el PCSpeaker los datos del
* objeto que hace la llamada
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
*
*
*
*
* Valor devuelto:
* No devuelve nada
*****************************************************************************/
void Pasaje::TocarAlreves()
{
Valor aux;
if (!lst.ListaVacia()) // si la lista no esta vacia
{
lst.IrAFinal(); // nos situamos al final de la lista
while ( !lst.PrincipioLista() ) // y hasta que no estemos en el principio
{
lst.Consulta(aux); // consultaremos el dato, lo reproduciremos ....
Beep(int(frec[aux.octava][aux.nota]), int(tiempobase * dura[aux.duracion]));
lst.Retroceder(); // y situaremos el punto de interes en la nota anterior de la lista
}
lst.Consulta(aux); // Consultamos y tocamos el primer elemento de la lista
Beep(int(frec[aux.octava][aux.nota]), int(tiempobase * dura[aux.duracion]));
}
};
/*****************************************************************************
* Funcion: IntroPasaje
* Descripcion: Introduce un objeto pasaje en otro delante de una determinada
* posicion modificando el id de la nota introducida para evitar
* repeticiones de id dentro de la nueva melodia
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* pas E Objeto cuyos elementos queremos introducir
* idno E Posicion de la nota delante de la que queremos introducir los datos
* idnota E/S contador de id de notas del programa principal
*
*
*
* Valor devuelto:
* No devuelve nada
*****************************************************************************/
bool Pasaje::IntroPasaje(Pasaje pas, int idno, int & idnota) //Añade en una cierta posición
{
bool ok;
Valor aux;
if (idno == 0) // Si pasamos idno = 0 queremos insertar al principio de la melodia
{
lst.IrAInicio();
cout << " Insertando el pasaje al inicio de la melodia ... \n";
ok = true;
}
else
{
if (idno == -1) // si le introducimos un -1 entendemos que queremos insertar al final
{
ok = true;
while ( !(lst.FinalLista()))
lst.Avanzar();
}
else // en caso de no ser ni 0 ni -1 buscamos el id de nota correspondiente
{
if (!BuscarIdNota(idno)) // si no encontramos ese id de nota daremos un error
{
cerr << " Error, no se ha encontrado ese id de nota\n";
ok = false;
}
else // si se ha encontrado entonces tendremos ya situado nuestro punto de interes
ok = true;
} // else
} // else
if (ok) // si todo ha ido bien en la busqueda del id nota tendremos el pto de interes bien situado
{
pas.lst.IrAInicio(); // nos situamos en el principio de la lista que vamos a introducir
while( !(pas.lst.FinalLista()) ) // y repetiremos la operacion hasta completar toda la lista
{
pas.lst.Consulta(aux); // consultaremos un dato y lo almacenaremos en aux
aux.iden = idnota; // modificamos el id de nota de ese aux para asegurarnos que es UNICO
lst.Insertar(aux); // Insertamos la nota en la melodia, objeto que hace la llamada a la funcion
pas.lst.Avanzar(); // Avanzamos una posicion en la lista para seguir introduciendo la siguiente nota
idnota++;
}
}
return (ok); // si todo ha ido bien devolveremos true, false en caso contrario
};
/*****************************************************************************
* Funcion: EliminarPasaje
* Descripcion: Elimina del objeto que hace la llamada, y a partir de una nota
* pasada como dato a la funcion, un determinado numero de notas.
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* n E Numero de notas a eliminar
* idno E Posicion de la nota a partir de la cual queremos eliminar
*
*
*
* Valor devuelto:
* No devuelve nada
*****************************************************************************/
bool Pasaje::EliminarPasaje(int idno, int n)
{
int i;
bool ok;
ok = BuscarIdNota(idno); // buscamos el id nota a partir del que queremos eliminar
if (ok) // si lo encontramos empezaremos a borrar elementos
{
for( i=0; i<n; i++) // empezando por ese id de nota y hasta un total de n elementos
lst.Eliminar();
};
return (ok);
};
/*****************************************************************************
* Funcion: BuscarIdNota
* Descripcion: Posiciona el punto de interes sobre una determinada nota
*
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* idno E id de la nota donde queremos posicionar el punto de interes
*
*
*
* Valor devuelto:
* No devuelve nada
*****************************************************************************/
bool Pasaje::BuscarIdNota(int idno)
{
bool ok;
Valor aux;
if (idno == 0)
cerr << " El id nota 0 esta reservado para indicar el principio de un pasaje/melodia\n";
else // si no es el idnota reservado para el inicio del pasaje
{
lst.Consulta(aux); // Consultaremos el dato donde esta ahora el pto de interes por si fuera ese
if(aux.iden == idno) // si tenemos suerte y lo es entonces ya hemos terminado
ok = true;
else // en caso contrario debemos empezar a buscar desde el principio del pasaje
{
lst.IrAInicio(); // Nos situamos al principio del pasaje
lst.Consulta(aux); // y consultamos el primer dato
while(aux.iden != idno && !lst.FinalLista() ) // repetiremos lo siguiente hasta encontrarlo o llegar al final
{
lst.Avanzar(); // Avanzaremos
lst.Consulta(aux); // y consultaremos el siguiente elemento que se compara en el while
};
if (lst.FinalLista()) // si hemos salido del while por llegar al final de la lista
ok = false; // entonces no habremos encontrado el elemento buscado
else
ok = true; // en caso contrario hemos salido por haber encontrado el elemento
}
}
return(ok);
};
/*****************************************************************************
* Funcion: GrabarMelodia
* Descripcion: Graba los datos del objeto que hace la llamada en un fichero de texto
* cuyo nombre se pasa como un parametro a la funcion junto con el
* titulo de ese pasaje que se incluira a titulo informativo dentro
* del fichero de texto para una mejor distincion de la melodia.
*
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* fichero E string con el nombre del fichero que queremos grabar
* titulo E Titulo de la melodia que vamos a grabar
*
*
* Valor devuelto:
* True si se ha grabado con exito el fichero, false en caso contrario
*****************************************************************************/
bool Pasaje::GrabarMelodia(string fichero, string titulo)
{
ofstream f;
Valor aux;
bool ok;
ok = true;
f.open(fichero.c_str());
if (!f)
{
cerr << " Error creando el fichero " << fichero << endl;
ok = false;
}
else
{
f << ".Titulo: " << titulo << " Fichero datos musicales by Isidro Pastor & Noemi Ruth Moya" << endl;
lst.IrAInicio(); // Si hemos abierto el fichero correctamente vamos al inicio del pasaje
while ( !(lst.FinalLista()) )
{
lst.Consulta(aux); // Consultamos el dato y lo almacenamos en aux
f << aux.octava << " " ; // grabamos en el fichero la octava correspondiente a la nota
switch (aux.nota) // y la nota de la que se trata en modo texto
{
case 0:
f << "Do ";
break;
case 1:
f << "Do# ";
break;
case 2:
f << "Re ";
break;
case 3:
f << "Re# ";
break;
case 4:
f << "Mi ";
break;
case 5:
f << "Fa ";
break;
case 6:
f << "Fa# ";
break;
case 7:
f << "Sol ";
break;
case 8:
f << "Sol# ";
break;
case 9:
f << "La ";
break;
case 10:
f << "La# ";
break;
case 11:
f << "Si ";
break;
case 12:
f << ". ";
break;
default:
f << ". ";
break;
};
switch (aux.duracion) // seguida de la duracion
{
case 0:
f << "ne";
break;
case 1:
f << "bl";
break;
case 2:
f << "re";
break;
case 3:
f << "co";
break;
case 4:
f << "sc";
break;
default:
f << ".";
break;
};
f << endl; // terminaremos la introduccion de cada nota con un salto de linea
lst.Avanzar(); // y avanzaremos el punto de interes para leer el siguiente dato y grabarlo
} // while
} // else
return (ok);
};
/*****************************************************************************
* Funcion: LeerMelodia
* Descripcion: Lee los datos de un fichero de texto con el formato reconocido
* por el programa y carga esos datos en el objeto que hace la
* llamada.
*
*
*
*
* Parametros:
*
* Nombre E/S Descripcion
* ------ ----- -----------
* fichero E string con el nombre del fichero que queremos cargar
* idnota E/S contador para el id de las notas
*
*
* Valor devuelto:
* True si se ha podido cargar correctamente el fichero, false en caso contrario
*****************************************************************************/
bool Pasaje::LeerMelodia(string fichero,int & idnota)
{
ifstream f;
string aux, aux2;
Valor notaaux;
int leer;
bool ok;
ok = true;
int total = 0; //numero total de notas cargadas desde el fichero
int idaux = idnota; // idnota inicial antes de introducir cualquier otra nota del fichero
lst.IrAFinal(); // Nos situamos siempre al final de la lista para introducir el pasaje
lst.Avanzar(); // y avanzamos una vez para introducir despues del ultimo elemento
f.open(fichero.c_str());
if (!f)
{
cerr << " Error abriendo el fichero " << fichero << endl;
ok = false;
}
else
{
getline(f, aux);
/****************************************************************************
* Definiremos como estructura de nuestro fichero que comience por un punto *
* de esta forma podremos, al menos en un principio, determinar si el *
* fichero al que estamos intentando acceder tiene un formato inteligible *
* por nuestro programa, en caso contrario mostrara que el formato del *
* fichero no es interpretable por el programa y abortara la carga del *
* archivo *
****************************************************************************/
if ( aux[0] == '.') // Comprobamos que el primer caracter leido del fichero es un punto
{
f >> leer >> aux >> aux2;
while(!f.eof() && ok)
{
notaaux.octava = Tipooctava(leer);
notaaux.iden = idnota;
switch ( int(aux[0]) ) // Comprobaremos el indice entero que tiene la primera letra de la nota
{
case 68: // caso en que la primera letra es una D
if ( aux.find('#') != -1)
notaaux.nota = do_s;
else
notaaux.nota = do_;
break;
case 70: // caso en que la primera letra es una F
if ( aux.find('#') != -1)
notaaux.nota = fa_s;
else
notaaux.nota = fa;
break;
case 76: // caso en que la primera letra es una L
if ( aux.find('#') != -1)
notaaux.nota = la_s;
else
notaaux.nota = la;
break;
case 77: // caso en que la primera letra es una M
notaaux.nota = mi;
break;
case 82: // caso en que la primera letra es una R
if ( aux.find('#') != -1)
notaaux.nota = re_s;
else
notaaux.nota = re;
break;
case 83: // caso en que la primera letra es una S
if (aux != "Si")
{
if ( aux.find('#') != -1)
notaaux.nota = sol_s;
else
notaaux.nota = sol;
}
else
notaaux.nota = si;
break;
case 46: // caso que la letra sea un punto tendremos una pausa
notaaux.nota = pausa;
break;
default:
cerr << " Error cargando nota, Formato irreconocible\n";
ok = false;
break;
};// switch
switch (int (aux2[0])) // comprobamos la primera letra del string de duracion
{
case 110: // si es una "n" sera una negra
notaaux.duracion = negra;
break;
case 98: // si es una "b" sera una blanca
notaaux.duracion = blanca;
break;
case 114: // si es una "r" sera una redonda
notaaux.duracion = redonda;
break;
case 99: // si es una "c" sera una corchea
notaaux.duracion = corchea;
break;
case 115: // si es una "s" sera una semicorchea
notaaux.duracion = semicorchea;
break;
default: // si no es ninguna de las anteriores letras hay error
cerr << " Error cargando duracion, Formato irreconocible\n";
ok = false;
break;
};// switch
if(ok) // si todo ha ido bien podremos introducir en la lista y seguir adelante
{
idnota++; // aumentaremos el id nota si hemos introducido la nota bien
total++; // incrementamos el contador total de notas introducidas desde fichero
lst.Insertar(notaaux); // y finalmente insertamos la nota en nuestro pasaje
f >> leer >> aux >> aux2; // leemos la siguiente linea del fichero fuente de datos
}
} // while
} //if
else
cerr << " El formato del fichero de notas no es correcto, no se puede cargar la melodia\n";
f.close();
}// else
/**********************************************************************
* Si se produjeron errores durante la carga del fichero, tendremos *
* una carga parcial en memoria del fichero hasta el momento donde *
* se produjo el error, y logicamente no queremos que esto ocurra *
* por lo tanto borraremos del pasaje a partir del idnota inicial *
* con el que se entra en la funcion almacenado en idaux, tantas *
* notas como hayamos leido satisfactoriamente del fichero, dato que *
* hemos ido almacenando en la variable total, por lo que al final *
* si tenemos errores no se notara modificacion alguna en la melodia *
* donde ibamos a cargar el fichero en caso de tener esta melodia *
* otros elementos ya cargados y reestablecemos el idnota inicial del *
* programa para no desperdiciar id's de notas no usados *
**********************************************************************/
if (!ok)
{
EliminarPasaje(idaux, total); // eliminamos las notas cargadas desde fichero
idnota = idaux; // restauramos el indice de id al valor inicial antes de la llamada a la funcion
}
return (ok);
};