15 de diciembre de 2008

Reproduccion MP3 en Java

Bueno, a quien no se le ha ocurrido tratar de reproducir sonido en Java, o tratar de construir un reproductor MP3 en este lenguaje tan popular

Lo que vamos a aprender es muy sencillo, solo basta con usar una libreria llamada BasicPlayer, sobre la cual lograremos reproducir archivos mp3 y de otras extensiones ademas de una manera sencilla.

Para ir al tutorial sigamos este enlace

Fuente: http://my.opera.com/jalvarezborja/blog/(Mi blog de programacion)

24 de noviembre de 2008

Personalizar Iconos en un JTree


A mas de uno se le habra ocurrido crear un JTree con la necesidad de cambiar los iconos por defecto con los que viene el arbol. Lastimosamente el IDE Netbeans (con el que trabajo frecuentemente) no nos permite hacer mucho (tal igual como lo que pasa con los JTable). En pocas palabras, necesitamos recordar nuestros conceptos de Herencia e Interfaces.


En mi caso particular, me planteo desarrollar un programa de mensajería instantanea (IM), el modelo que presentan los JTree y los arboles en general es muy adecuado para agrupar contactos por estado, por grupo, etc. y decidi usarlo en el proyecto que me encontraba desarrollando. Un aproximado podria ser el siguiente:

Figura 1: Modelo de JTree a crear


Donde, los iconos de contacto1 y contacto2 deben ser de un color distinto al de contacto3 y contacto4, el grupo conectados y no conectados deben tener un mismo icono y bueno, el icono de la raiz no tiene importancia.


CONCEPTOS PREVIOS:


Cuando un JTree necesita pintar los datos que contiene, esta llama a otra para obtener detalles de este dibujado. Esta clase a la que llama se denomina DefaultTreeCellRenderer y proporciona informacion de cada hoja, del icono de cada nodo dentro del arbol.


La clase DefaultTreeCellRenderer implementa a su vez la interfaz TreeCellRenderer , la cual, haciendo uso del metodo getTreeCellRendererComponent devuelve toda la informacion necesaria para dibujar un arbol y sus nodos.


El JTree, en su método getCellRenderer() nos devuelve la clase que está usando para saber cómo dibujar los datos. Con su método setCellRenderer() podríamos pasarle una clase hecha a nuestra medida. Haciendo uso de estos métodos, nosotros podemos redefinir los iconos en el arbol (aunque de una forma muy limitada), haciendo uso de los métodos:



  • setLeafIcon() para cambiar el icono de los nodos hoja (nodos sin hijos).

  • setOpenIcon() para cambiar el icono de los nodos con hijos que están desplegados (sus hijos son visibles).

  • setClosedIcon() para cambiar el icono de los nodos con hijos que están cerrados (los hijos no son visibles).


Sin embargo, esta solucion no permite distinguir entre los hijos de tal o cual padre dentro del arbol (para el caso de los hijos del nodo "Conectados" y los hijos del nodo "No Conectados").


Con todo lo que hemos descrito solo nos quedan dos cosas por hacer: Crear una clase que implemente la interfaz TreeCellRenderer (lo cual implica la construccion completa del metodo getTreeCellRendererComponent, lo cual no es muy adecuado) o crear una clase que herede de la superClase DefaultTreeCellRenderer y sobre la cual hariamos solo algunas modificaciones finales para lograr lo que buscamos.


Asumimos que ya tenemos en el proyecto un objeto instancia de JTree, la cual se denomina "arbol". Lo que haremos es modificar los datos que contiene por defecto para colocar los que en realidad necesitamos para nuestro proposito. Esto lo hacemos con el método remodelarArbol()






public void remodelarArbol(){

//DefaultTreeCellRenderer dt = (DefaultTreeCellRenderer)arbol.getCellRenderer();

DefaultTreeModel def = (DefaultTreeModel)arbol.getModel();

DefaultMutableTreeNode contactos = new DefaultMutableTreeNode("Contactos");

DefaultMutableTreeNode conectados = new DefaultMutableTreeNode("Conectados");

DefaultMutableTreeNode noconectados = new DefaultMutableTreeNode("No Conectados");

DefaultMutableTreeNode c1 = new DefaultMutableTreeNode("Contacto 1");

DefaultMutableTreeNode c2 = new DefaultMutableTreeNode("Contacto 2");

DefaultMutableTreeNode nc1 = new DefaultMutableTreeNode("Contacto 3");

DefaultMutableTreeNode nc2 = new DefaultMutableTreeNode("Contacto 4");

conectados.add(c1);

conectados.add(c2);

noconectados.add(nc1);

noconectados.add(nc2);

contactos.add(conectados);

contactos.add(noconectados);

def.setRoot(contactos);

arbol.setModel(def);

arbol.setCellRenderer(new RendererArbol());//añadimos nuevo renderer

}

Si nos fijamos en la ultima linea, añadimos a nuestro arbol remodelado una nueva clase que se encargará de su dibujado. Esta clase la tenemos que crear y ajustar a nuestras necesidades.



import javax.swing.tree.*;

import javax.swing.*;

import java.awt.*;



/**

*

* @author Jhon Anthony Alvarez Borja

*/

public class RendererArbol extends DefaultTreeCellRenderer{



/** Creates a new instance of RendererArbol */

ImageIcon conectados;

ImageIcon noConectados;

public RendererArbol() {

conectados = new ImageIcon("src/Resources/Pack MSN/Enligne.png");

noConectados = new ImageIcon("src/Resources/Pack MSN/Horsligne.png");

}



public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus)

{

super.getTreeCellRendererComponent(tree,value,selected,expanded,leaf,row,hasFocus);

String val = value.toString();

ImageIcon i;

DefaultMutableTreeNode nodo = (DefaultMutableTreeNode)value;

if(val.compareTo("Conectados")!=0 && val.compareTo("No Conectados")!=0 && val.compareTo("Contactos")!=0){

TreeNode t = nodo.getParent();

if(t!=null){

if(t.toString().compareTo("Conectados")==0){

setIcon(conectados);

}else if(t.toString().compareTo("No Conectados")==0){

setIcon(noConectados);

}

}

}

return this;

}

}






Lo que hacemos en esta clase es implementar el metodo getTreeCellRendererComponent modificando solo lo que nos interesa
lo cual es en este caso los íconos para los usuarios conectados y no conectados. Al hacer uso de la palabra reservada y el metodo super.getTreeCellRendererComponent lo que hacemos es llamar al método original de la clase y lineas abajo, colocamos las modificaciones que queremos hacer al momento de mostrar un determinado nodo en funcion de nuestras necesidades. En este caso basta con identificar el nombre de cada nodo padre, y de acuerdo a ello colocamos el icono correspondiente a conectado o no conectado.

Espero les sea de ayuda este pequeño tutorial. Aca les dejo el codigo fuente




Fuentes:

12 de noviembre de 2008

AUDIO DIGITAL


Actualmente, el avance de la tecnología computacional ha permitido la digitalizacion de la información, entre la que tambien encontramos al sonido. Esta evolucion en el sonido ha implicado la mejora notoria en la calidad de sonido en equipos de alta fidelidad (Hi-Fi), sin embargo el cambio delo analogico a lo digital ha provocado una serie de problemas diversos, los cuales han sido corregidos en su gran mayoria. He aquí una introducción y algunos conceptos indispensables para los interesados en procesamiento de señales y aficionados al audio digital.

En el procesamiento de señales es común encontrar este término, y muchas veces incluso confundido por la mayoría de las personas. En esta sección trataremos de despejar algunas dudas respecto a este término para profundizar mas adelante en el desarrollo de temas más complejos.

La frecuencia de muestreo viene a ser el número de muestras por unidad de tiempo que se toman de una señal continua (analógica) para poder producir una señal discreta (digital), durante el proceso necesario para transformarla de analógica a digital.

La frecuencia de muestreo, como todas las frecuencias, se expresa en Hz (hercios o ciclos por segundo).

Obviamente, la transformación de una onda analógica a digital ocasiona la perdida de información, pero matemáticamente es demostrable la reconstrucción completa de una onda bajo el Teorema de muestreo de Nyquist-Shannon.

TEOREMA DE NYQUIST - SHANNON

Según este teorema, para poder reconstruir con exactitud la forma de una onda, es necesario que la frecuencia de muestreo sea siempre el doble de la frecuencia a muestrear. Atendiendo al margen audible de los humanos, que va desde los 20 Hz hasta los 20 kHz, es necesario que la frecuencia de muestreo sea como mínimo de 40 000 muestras por segundo. Por otro lado, cada bit de una muestra de audio añade 6 dB de margen dinámico (margen que hay entre el nivel de referencia y el ruido de fondo de un determinado sistema, medido en decibelios), por lo que con 8 bits obtendríamos 48 dB, con 16 bits 96 dB y con 24 bits 144 dB. Ahora, como el margen dinámico útil es aproximadamente 110 dB ( sin llegar al umbral del dolor ) y el de los sistemas analógicos de cinta magnética de unos 72 dB, pareció en principio que codificar a 16 bits era una buena alternativa.

La alta tasa de muestreo de otro formato de audio de reciente aparición, el SACD o Super Audio CD, es una consecuencia del uso de una tecnología denominada modulación Sigma-Delta (Direct Stream Digital). Si bien la tasa de muestreo es 64 veces la del CD-Audio, es necesario tener presente que se trata de una cuantificación de 1 bit (en lugar de los 16 empleados en el CD-Audio) y basado en técnicas de Noise Shaping (modelado de ruido). No es posible, por tanto, establecer comparaciones superficiales con el PCM de CD-Audio, ya que en este caso la relación señal-ruido no es constante respecto de la frecuencia (en CD-Audio el ruido de cuantificación es independiente de la frecuencia y sólo depende de los intervalos de amplitud empleados en el proceso de cuantificación, es decir, de unos 98,09 dB constantes para los 16 bits de este estándar CD-Audio en todo el espectro útil).

Un SACD puede registrar y reproducir señales con componentes de hasta 33 kHz con una relación señal-ruido equivalente al de un CD-Audio (aunque 33 kHz está casi una octava por encima del máximo audible y, por tanto, una ventaja sobre el CD-Audio de dudosa utilidad) y mantener una relación señal-ruido de aproximadamente 122 dB para el espectro audible (un potencial, el equivalente aproximado a 20 bits,3 también de dudosa utilidad práctica como formato final de usuario). Entre las ventajas objetivas de estos formatos recientes (DVD-Audio y SACD) se encuentra el potencial multicanal (registro de más de dos canales) y la capacidad para el empleo de técnicas de protección de copia (algo de extraordinario interés para las compañías discográficas). Ninguna prueba doble-ciego realizada en condiciones controladas ha probado que existan diferencias audibles entre estos formatos denominados de "alta resolución"


ALIASING

Todo lo explicado anteriormente es correcto, sin embargo existen sonidos que el oído humano no puede escuchar (aquellos armónicos que se generan más allá de los 20 000 Hz). Cuando digitalizamos una onda con tales armónicos presentes, según Nyquist, se produce el fenómeno de aliasing, el cual convierte esas frecuencias no audibles y las cuales no las percibimos en frecuencias que si lo son y que no se encuentran presentes en el sonido original.

Cito un ejemplo no mío pero muy didáctico: Lo que ocurre cuando vemos la rueda de un carro en una película, aunque el carro va hacia adelante nosotros vemos que los aros de la rueda van en sentido inverso. No hay concordancia entre el periodo de rotación de la rueda y la frecuencia de muestreo del cine (que es de 24 frames/sec). Para evitar este tipo de problemas se tiene que añadir un filtro de paso bajo de corte por encima de la frecuencia que se corresponda con la mitad de frecuencia de muestreo. Este tipo de filtro es conocido como “filtro anti-aliasing”. Para este problema, en los CD’s de audio se estandarizó que la frecuencia de muestreo sea de 44.1 kHz para poder utilizar filtros con una pendiente desde los 22.050 kHz.


FRECUENCIAS TIPICAS DE MUESTREO


Las investigaciones en esta rama continuan, los sistemas de audio tienden a tener mayor capacidad de mustreo y mayor resolucion, asimismo los medios para almacenar esa informacion avanzan a la misma velocidad, con costes mas asequibles a los usuarios.

Continuaremos proximamente con aplicaciones DSP en ondas de audio, espero les haya motivado con esta introduccion a este inmenso campo de procesamiento de señales.

Fuentes:

[1] Los males del audio digital. Jitter, aliasing, errores de cuantización

[2] http://es.wikipedia.org/wiki/Frecuencia_de_muestreo


24 de septiembre de 2008

Algoritmo de Esqueletizacion de Pavlidis


En ocasiones, debido a la gran cantidad de información que presenta una imagen, resulta conveniente trabajar solo con las características más importantes de la imagen a procesar. Para el caso particular de reconocimiento óptico de caracteres las características más importantes se encuentran representadas en el esqueleto del caracter.

Entendemos por Esqueletización a una transformación que busca reducir la cantidad de datos o simplificar la forma del objeto, con el fin de encontrar características útiles en algoritmos de reconocimiento y clasificación.


El algoritmo de esqueletizacion de Pavlidis se basa en la idea de que los pixeles esqueletales son solo aquellos pixels que presentan alguna similaridad con alguna de las plantillas que se muestran a continuación:


En las plantillas del inciso A, al menos un píxel de los grupos etiquetados como A o B debe ser diferente de cero. Los píxeles marcados con el valor de 2 son píxeles esqueletales.

En la plantilla del inciso B, al menos un píxel marcado con debe ser diferente de cero. Si ambos píxeles etiquetados con C son diferentes de cero, entonces los píxeles etiquetados con CA o pueden tener cualquier valor. De otra manera, al menos un miembro de cada par marcados con BA y deben ser diferentes de cero


En base a esta teoría y atendiendo a dificultades en los resultados con el algoritmo antes mencionado, planteo una solución alternativa, la cual se basa en las rotaciones de las plantillas que muestro a continuacion:

Según lo cual, las cuatro rotaciones en 90º de cada una de las plantillas deben ser comparadas con cada uno de los 4-vecinos de cada pixel de la imagen. Los 4-vecinos de un pixel en una vecindad de 3x3 se denota bajo el siguiente esquema:
Y los que son necesarios a considerarse en el algoritmo de pavlidis y en ste algoritmo son los pixels 0,2,4,6.


Algoritmo
% Entrada: Imagen binarizada imBin normalizada (0 = negro, 1 = blanco)
% Salida: Imagen Esqueletizada normalizada (0=negro, 1=blanco)

REMAIN = 1; % se usa para denotar la existencia de pixeles esqueletales
SKEL = 0; % se fija a cierta cuando alguna vecindad de un pixel es similar a
% alguna de las plantillas existentes en P
CONVERTIR IMBIN A CEROS Y UNOS Y ALMACENARLA EN IMG
nf = NUMERO DE FILAS DE MATRIZ img
nc = NUMERO DE COLUMNAS DE MATRIZ img
d = 1 % columnas que no se evalúan por ser la plantilla de 3 x 3
MIENTRAS REMAIN = 1
REMAIN = 0;
PARA k=1 hasta 4 % los indices de los vecinos de un determinado punto
% se recorre toda la imagen
PARA i=1+d hasta nf-d
PARA j=1+d hasta nc-d
SI P TIENE EL VALOR DE 1 Y SI J-VECINO TIENE EL VALOR DE CERO
SKEL = 0
SI VECINDAD DE P CONCUERDA CON ALGUNA PLANTILLA, SKEL SE ACTUALIZA A 1
SI SKEL == 1 ENTONCES % si la plantilla concuerda con la matriz
img(i,j) = 2;
EN CASO CONTRARIO
img(i,j) = 3;
REMAIN = 1;
FIN SI
FIN SI
FIN PARA
FIN PARA
REEMPLAZAR TODOS LOS PIXELS CON VALOR “3” POR “0”
FIN PARA
FIN MIENTRAS % fin del algoritmo



Aca les dejo la implementación del algoritmo de pavlidis, con una ligera modificación hecha por mi parte para Adelgazamiento de Imágenes. El trabajo fue desarrollado en el curso de Procesamiento de Imágenes, un curso de Pre-grado de la carrera de Informática en la Universidad Nacional de Trujillo. El codigo esta hecho en matlab y se encuentra documentado.

Consultas en bases de datos de Imagenes

Las soluciones computacionales actuales a necesidades de información de ciertas empresas necesitan almacenar y recuperar información propia para poder desempeñar sus actividades diarias tales como retiros y depósitos en caso de bancos, consulta de precios y facturación en caso de un centro comercial, y un sinfín de actividades que requieren siempre una base de datos (o bases de datos) para su funcionamiento. Dependiendo de las necesidades de información de la empresa y su manipulación es que se escoge entre distintos tipos de bases de datos la que más se adecúe a una solución en particular y con esta se satisfacen las necesidades de información de las aplicaciones.

Existen aplicaciones que manipulan información multimedia o imágenes, como los servicios de información satelitales en los que es necesaria la ubicación directa de la imagen, para este tipo de necesidades existe un tipo de base de datos denominado “Base de datos de Imágenes”, en el cual el índice o llave es una imagen(a diferencia de las bases de datos convencionales en las que contábamos con un ID de tipo cadena o numérico), por lo que nos daremos cuenta de que el tipo de consultas en este tipo de bases de datos es muy distinto al que nosotros conocemos en las bases de datos convencionales.

Todo esto nos lleva a pensar en un factor importantísimo en toda aplicación (como lo vendría a ser el propio manejador de la base de datos): “La Eficiencia”. Imaginemos una base de datos de imágenes en las que se quiera recuperar todas las imágenes que posean un rectángulo en el extremo izquierdo, y que se encuentren entre un rango de tono de gris determinado. ¿Será eficiente la respuesta de la base de datos en una base con unos cien mil registros? Obviamente el factor eficiencia está asociado directamente al intérprete de consultas de la base de datos que, como reitero es muy distinto al de una base de datos convencional.

En este paper lo que se pretende es brindar una visión global del tratamiento de bases de datos de imágenes haciendo hincapié en las consultas en este tipo de bases de datos por lo importante de ellas en la recuperación de información en este tipo de bases de datos.


21 de septiembre de 2008

Conexiones a Bases de Datos en C#

En la actualidad, el acceso a datos por parte de nuestros programas de escritorio es algo indispensable, y el uso de bases de datos dan fe de ello, tanto en el trabajo como en la vida universitaria de cualquier estudiante de computación y afines.

En vista de ello, y ya que actualmente me encuentro estudiando C#, me animé a incursionar más en el mundo del software propietario y aprovechar las herramientas y tecnologías que proveen.


ADO.NET es una colección de clases, interfaces, estructuras y tipos enumerados que permiten acceder a los datos almacenados en una base de datos desde la plataforma .NET. Si bien se puede considerar una versión mejorada de ADO, no comparte con éste su jerarquía de clases.

DO .NET usa XML. De hecho, los conjuntos de datos se almacenan internamente en XML, en vez de almacenarse en binario como sucedía en ADO. Al estar los datos almacenados en XML, se simplifica el acceso a los datos a través de HTTP (algo que ocasiona problemas en ADO si los datos tienen que pasar cortafuegos). Por otro lado, se simplifica la comunicación entre aplicaciones al ser XML un formato estándar.

Con ADO .NET se puede acceder a los datos de dos formas distintas:

  • Acceso conectado: Acceso sólo de lectura con cursores unidireccionales ("firehose cursors"). La aplicación realiza una consulta y lee los datos conforme los va procesando con la ayuda de un objeto DataReader.
  • Acceso desconectado: La aplicación ejecuta la consulta y almacena los resultados de la misma para procesarlos después accediendo a un objeto de tipo DataSet. De esta forma, se minimiza el tiempo que permanece abierta la conexión con la base de datos.

Al proporcionar conjuntos de datos de forma desconectada, se utilizan mejor los recursos de los servidores y se pueden construir sistemas más escalables que con ADO (que mantenía abierta la conexión con la base de datos la mayor parte del tiempo). Este enfoque resulta más adecuado en sistemas distribuidos como Internet.

Ahora vamos a ver unos cuantos códigos de ejemplo de conexiones de base de datos en C#.

Si tenemos una base de datos en SQL Server (aunque funciona para cualquier base que se encuentre registrada previamente en el DSN de usuario), de nombre “ModeladorSQL” en el DSN de Usuario y con nombre del servidor = “HOME” (el nombre del computador), el código de una conexión será de la siguiente manera:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;

namespace WindowsApplication1
{
class ejemplo1
{
SqlConnection conexion;

public ejemplo1()
{

inicializarConexionBD();
consultaBD();
cerrarConexionBD();
}

private void cerrarConexionBD()
{
conexion.Close();
}

private void inicializarConexionBD()
{
conexion = new SqlConnection("Server=HOME;Database=ModeladorSQL;Integrated Security=True");
conexion.Open();
}

private void consultaBD()
{
SqlDataReader dr;
SqlCommand comm = new SqlCommand("Select nombre from Tipo_Atributo",conexion);
dr = comm.ExecuteReader();
while(dr.Read())
{
Console.WriteLine(dr.GetString(0));

}
}
}
}


La sencilla aplicación busca reportar la primera columna del resultado de la consulta, la cual devuelve todos los atributos “nombre” de la tabla “Tipo_Atributo”

Otra forma de obtener el mismo resultado, pero de una manera más elaborada es la siguiente, solo reemplazamos el procedimiento consultaBD por el que se muestra a continuacion:


private void consultaBD()

{
DataSet d = new DataSet();
SqlCommand com = new SqlCommand("Select nombre from Tipo_Atributo",conexion);
SqlDataAdapter sda = new SqlDataAdapter();
sda.SelectCommand = com;
sda.Fill(d);
DataTable data = d.Tables[0];
foreach (DataRow dr in data.Rows)
{
int i;
for (i = 0; i < data.Columns.Count; i++)
{
Console.WriteLine(dr[i].ToString());
}
}
}


En el ejemplo anterior hacemos uso de un objeto de tipo DataSet,una caché de memoria interna de datos recuperados desde un origen de datos. Este tipo de estructura permite almacenar más de una tabla dentro de ella. Para hacer uso de ella en las consultas, es necesario declarar un SqlDataAdapter, el cual llenará los datos de la consulta dentro de ella, en una nueva tabla.

ODBC.NET es un componente complementario del Kit de desarrollo de software (SDK) de Microsoft .NET Framework. Proporciona acceso a los controladores ODBC nativos de la misma manera que el proveedor de datos de OLE DB .NET proporciona acceso a los proveedores de OLE DB nativos. Aunque el proveedor de datos de ODBC .NET está pensado para trabajar con todos los controladores ODBC compatibles, sólo se ha probado con los siguientes:

  • Controlador ODBC de Microsoft SQL
  • Controlador ODBC de Microsoft para Oracle
  • Controlador ODBC de Microsoft Jet

Las conexiones, sin embargo son bastante similares a las hechas usando ADO.NET, aunque no con la potencialidad de esta ultima. Veamos un ejemplo:

Asumiendo que la base de datos se encuentra en SQL Server 2000, que el servidor se llama “HOME” y que la base de datos, en orígenes de datos se encuentra registrada como “modeladorSQL”.

using System;
using System.Data;
using System.Data.Odbc;

namespace WindowsApplication1
{
class ejemplo2
{
OdbcConnection conexion;

public ejemplo2()
{
inicializarConexionBD_ODBC();
consulta_ODBC();
cerrarConexionBD();
}

private void cerrarConexionBD()
{
conexion.Close();
}

private void inicializarConexionBD_ODBC()
{
conexion = new OdbcConnection("Driver={SQL Server};Server=HOME;Database=modeladorSQL;IntegratedSecurity=True");
conexion.Open();
}

private void consulta_ODBC()
{
OdbcCommand comm;
comm = new OdbcCommand("Select nombre from Tipo_Atributo", conexion);
OdbcDataReader reader = comm.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(reader.GetString(0));
}
}
}
}

Esta es una forma sencilla de conectar una base de datos, sin embargo podemos hacerlo de una manera más elaborada:

private void consulta_ODBC()
{
OdbcCommand comm;
DataSet d = new DataSet();
comm = new OdbcCommand("Select nombre from Tipo_Atributo",conexion);
OdbcDataAdapter da = new OdbcDataAdapter();
da.SelectCommand = comm;
da.Fill(d);
DataTable data = d.Tables[0];
foreach (DataRow dr in data.Rows)
{
for (int i = 0; i < data.Columns.Count; i++)
{
Console.WriteLine(dr[i].ToString());
}
}
}


Vemos que trabaja con estructuras similares a ADO.NET, como objetos DataView, OdbcDataAdapter muy similar a SqlDataAdapter. Depende de gustos, de la aplicación y del gestor de base de datos a utilizar. Hay que tener en cuenta que en ODBC especificamos el driver a utilizar para la base de datos correspondiente, algo que no se ve en ADO.NET.. en fin..

Espero que les sea de utilidad . Saludos

Fuentes:

http://support.microsoft.com/kb/310988/es
http://msdn.microsoft.com/es-es/library/system.data.dataset(VS.80).aspx
http://elvex.ugr.es/decsai/csharp/databases/index.xml

30 de agosto de 2008

Tecnicas de Construccion de Programas - Material

Como uds sabran, un curso de técnicas de construccion de programas en el III ciclo de Informática es fundamental, aca les dejo un material confeccionado por mi persona y el docente del curso en el semestre 2008-I para el curso de Tecnicas de Construcción de Programas dictado en la Universidad Nacional de Trujillo.
  • La primera unidad corresponde al manejo de archivos secuenciales en C++.
  • La segunda unidad corresponde a algoritmia elemental, eficiencia computacional y tecnicas de recurrencia
  • La ultima unidad referida basicamente a temas de algoritmia avanzada, como son los algoritmos avidos, backtraking

Espero les sean de utilidad estos materiales.


13 de agosto de 2008

Determinacion de pitch en una onda de habla

El lograr determinar con precisión el periodo de pitch(relacionado fuertemente con la frecuencia fundamental) es un tanto imprecisa, mucho mas en el analisis en el dominio del tiempo que en el del dominio de las frecuencias.

Lo que queremos encontrar es la forma de un periodo que se repita en la onda y aproximar el periodo de la misma. Hay varias formas de hacerlo, sin embargo propongo un método muy similar al planteado en la bibliografia, el cual es sin embargo ineficiente para propositos de analisis de ondas muy grandes, ademas de ser suceptible a ruido.

Les dejo el paper para que le echen un vistazo y puedan proporcionar mejoras al mismo.