PDA

Ver la versión completa : [Ayuda] Necesito ayuda matemático-software



Drumpi
27/02/2010, 20:20
Hola a todos:

No sabía dónde poner esto, porque no tenemos un hilo de programación... aunque esto es algo a medio camino entre matemáticas, programación y cacharreo vario.
No encuentro información por ningún lado, más allá de la teoría fundamental.

Os pongo en situación: estoy haciendo un programa de reconocimiento de palabras, a través de la voz. Ya he buscado mucha información acerca del tema, pero no es el problema.
El caso es que quiero hacer mi propia investigación, así que me he diseñado mi propio programa de análisis (más que nada, porque luego me tocará pasarlo a C) y estoy intentando obtener la transformada de Fourier de un archivo de sonido que yo mismo he creado, con una señal sinusoidal.
El algoritmo que uso es el clásico Radix-2 para cálculo de la FFT. Hasta aquí bien, pero en los libros no explica qué datos son los que se obtienen. He entendido que la FFT calcula la transformada de Fourier Discreta, por lo que nos devolvería un vector de valores que se repiten cada 2pi.

Pero una vez obtenido los valores y calculado su módulo, no sé cómo obtener el valor de frecuencia al que corresponde cada delta.
Es más, supuestamente, con la señal seno, debería obtener un único valor delta, y obtengo varios valores, que por su distribución, corresponde a una señal sinusoidal y a sus armónicos. E idénticos resultados con otra señal que corresponde a dos señales sinusoidales sumadas, de distinta frecuencia.

A ver si alguno de vosotros, que hayais trabajado con DSPs, señales y demás me hecha una mano con esto, que ya tengo hasta pesadillas con ello :S
Gracias.

FlipFlopX
27/02/2010, 20:35
Drumpi cada vez que se nombra la palabra DSP andas tu por ahí metido, eres un poco masoquilla jeje. Con un seno de una única frecuencia debes obtener una delta en esa frecuencia, no debes obtener armónicos, ya si es una suma de 2 frecuencias, pues los armónicos de la intermodulación y demás..Mírate aunque supongo que lo habrás hecho el "Signals and Systems" de Oppenheim, y sino dimelo que yo tengo unos apuntes muy majos (y sufridos) sobre todo lo que quieras saber sobre señales. Saludillos

Logann
27/02/2010, 20:54
Para ver rapidamente que es una (F)FT: http://home.fuse.net/clymer/graphs/fourier.html

Para lo que tu quieres hacer lo mas interesante es dividir tu señal en ventanas, (ventana hamilton por ejemplo) y ver como evoluciona la frecuencia durante el tiempo en una palabra.


Recuerda que tienes que hacer el modulo de la parte real e imaginaria.

Drumpi
28/02/2010, 01:38
Drumpi cada vez que se nombra la palabra DSP andas tu por ahí metido, eres un poco masoquilla jeje. Con un seno de una única frecuencia debes obtener una delta en esa frecuencia, no debes obtener armónicos, ya si es una suma de 2 frecuencias, pues los armónicos de la intermodulación y demás..Mírate aunque supongo que lo habrás hecho el "Signals and Systems" de Oppenheim, y sino dimelo que yo tengo unos apuntes muy majos (y sufridos) sobre todo lo que quieras saber sobre señales. Saludillos

Masoca no, que me han "prestado" una Beagle y tengo que hacerlo funcionar :D:D:D
Obviamente, el Oppenheim, o "la Biblia de Señales y Sistemas" es una gran fuente, pero como hasta el martes no tengo acceso a una biblioteca para consultarlo, me tengo que conformar con internet,
Y en todos los sitios que busco me dicen lo mismo: qué es la FFT, cómo se obtiene de las fórmulas matemáticas y en algunos casos, el código en C++. Pero no me dicen qué son los resultados, cómo sé a qué frecuencia se debe cada delta...


Para ver rapidamente que es una (F)FT: http://home.fuse.net/clymer/graphs/fourier.html

Para lo que tu quieres hacer lo mas interesante es dividir tu señal en ventanas, (ventana hamilton por ejemplo) y ver como evoluciona la frecuencia durante el tiempo en una palabra.


Recuerda que tienes que hacer el modulo de la parte real e imaginaria.

¿Ventana de Hamilton o de Hanning? de momento estoy tomando 1024 muestras seguidas de la señal, modifico el inicio a mano, y vuelvo a calcular (lo estoy haciendo en PC y para probar, de momento la eficiencia no es problema). Hasta que no sepa identificar una única frecuencia es mejor no hacer nada más serio.

Si quereis os puedo subir el código que he hecho, con los recursos y todo listo para usar. Lo estoy haciendo con Bennu (necesitaba un entorno gráfico que se programase en minutos) pero creo que se entiende fácilmente, no se requiere conocimientos del lenguaje para usarlo/verlo, más allá de unas nociones de C y doble-clic :D:D:D.

Segata Sanshiro
28/02/2010, 02:14
Supongamos que la señal es de N muestras. Su TF es de periodo 2pi y variable continua w, al ser la TF de una secuencia discreta. Su DFT está compuesta de N muestras tomadas de forma equiespaciada, entre 0 y 2pi, de la TF. No sé si habrá diferencias significativas entre el espectro de la FFT y el de la DFT pero imagino que no, ya que la primera en teoría es un caso particular de la segunda cuando se dan ciertas condiciones sobre la longitud de las secuencias.

(Editado para mejorar la redacción y escrito de memorieta xD).

Drumpi
28/02/2010, 14:33
Supongamos que la señal es de N muestras. Su TF es de periodo 2pi y variable continua w, al ser la TF de una secuencia discreta. Su DFT está compuesta de N muestras tomadas de forma equiespaciada, entre 0 y 2pi, de la TF. No sé si habrá diferencias significativas entre el espectro de la FFT y el de la DFT pero imagino que no, ya que la primera en teoría es un caso particular de la segunda cuando se dan ciertas condiciones sobre la longitud de las secuencias.

(Editado para mejorar la redacción y escrito de memorieta xD).

Muy bien, aprobado... aunque no has dicho nada nuevo que no haya leido ya :D
Bueno, en serio, me extraña esta frase:
"ya que la primera en teoría es un caso particular de la segunda cuando se dan ciertas condiciones sobre la longitud de las secuencias."
¿Eso exactamente que quiere decir?

Por otro lado, he estado revisando el código del enlace que me ha pasado Logann, así, por encima, y parece ser que es el mismo código (salvando las distancias) que he empleado yo, así que voy a tener que revisar mi código. No se de java, pero creo que lo entiendo ^^U

Segata Sanshiro
28/02/2010, 15:25
Dices que realizas la transformada del seno, y en vez de salirte dos deltas como esperabas, te salen un par de sincs. Esto es a causa del intervalo de observación finito. Es decir, las dos deltas que esperabas salen cuando haces la TF de una señal sinusoidal infinita en el tiempo. Sin embargo, cuando haces la DFT, la haces de una señal con un número de muestras limitado (en tu caso, 1024), porque no tienes en el disco duro espacio para guardar una señal infinita.

Si haces la prueba, verás que a senos de igual frecuencia, cuantas más muestras tomes, más se parecerá la DFT a dos deltas. Si realizas la DFT de cuatro o cinco periodos del seno, aparecerán un par de sincs con lóbulos anchos. Si la realizas de mil periodos, verás como los lóbulos de las sinc se han estrechado mucho, intentando parecerse a deltas.

Salen sincs porque una señal sinusoidal que no es infinta en el tiempo, se puede ver como el resultado de multiplicar un seno infinito por una ventana (un pulso rectangular que vale 1 durante un tiempo limitado y 0 en el resto); eso en frecuencia equivale a convolucionar la transformada del seno ideal infinito (dos deltas en f0 y -f0) por la transformada del pulso (una sinc).

Con lo que te dije en el anterior post, puedes ir deshaciendo los pasos que se toman hasta tener la DFT, y averiguar a qué frecuencia "corresponde" cada delta, aunque si no lo pienso durante un buen rato (o saco los resúmenes del Oppenheim xD), no sabría decirte las operaciones exactas.

Sobre lo que comenté de la DFT y la FFT, la FFT es una forma eficiente de calcular la DFT, pero producen exactamente los mismos resultados. No me expliqué bien con lo de las longitudes, y puede que incluso no sea cierto dependiendo de los algoritmos, no estoy seguro.

jduranmaster
28/02/2010, 15:52
Como veo ka luego lo tienes ke pasar a C (o C++) lo mismo esto de aki te sirve:

http://members.fortunecity.com/saul8/proyectos/fft/fft.htm

Drumpi
28/02/2010, 16:55
Salen sincs porque una señal sinusoidal que no es infinta en el tiempo, se puede ver como el resultado de multiplicar un seno infinito por una ventana (un pulso rectangular que vale 1 durante un tiempo limitado y 0 en el resto); eso en frecuencia equivale a convolucionar la transformada del seno ideal infinito (dos deltas en f0 y -f0) por la transformada del pulso (una sinc).

Sí, algo más o menos así he leido, que existen esos efectos laterales, pero eso no se aprecia en la web hecha en java. Voy a mirármelo más tranquilamente, si no, tendré que buscar una forma de "deconvolucionar" la señal :S


Como veo ka luego lo tienes ke pasar a C (o C++) lo mismo esto de aki te sirve:

http://members.fortunecity.com/saul8/proyectos/fft/fft.htm

Sí, ya tenía la librería de la fftw en mi punto de mira, pero descarté su uso porque desde la beagle no puedo "ver" los resultados (no he conseguido ver nada por la salida de video, y para esto voy a trabajar sólo con la consola de comandos, viendo los datos directamente por la minicom).


Por si quereis ver lo que llevo hecho, lo teneis aqui (http://drumpi.se32.com/cosas/prueba.rar).
Su funcionamiento es muy sencillo: basta con ejecutar el seasee.bat para hacerlo funcionar. En el entorno se puede mover cada gráfica usando el ratón y el botón derecho, y en las gráficas de las señales de onda (de los ficheros WAV) se puede uno desplazar a lo largo de toda la señal usando el botón central, y a cada segundo que se mantenga pulsado se actualiza su gráfica de la FFT. Para salir se debe pulsar ESC y después F5 (es un método que uso por el tema de debug).
Se pueden cargar más señales desde la consola de debug que aparece con alt+c, escribiendo RUN NUEVO_WAV("fichero.wav"), y volviendo a pulsar alt+c. Si la gráfica está encima de todas, en dicha consola, escribiendo RUN CALCULATE_FFT(LIST_GRAFICAS) (tal cual, sin cambiar nada) se crea lagráfica de la FFT.
También se puede hacer modificando el fichero SEASEE.PRG. Creo que el código del programa es muy sencillo de entender.
Incluyo tres archivos sonoros generados por código: una señal constante, un seno (que se carga por defecto) y la suma de dos senos, aparte de otros sonidos que usaré más adelante para el estudio.

Está hecho en Bennu, pero no hace falta instalar nada para echarlo a andar, ni tan siquiera para compilar (ya lo hace el .bat)
Espero que os guste ;)

jduranmaster
28/02/2010, 17:03
Está hecho en Bennu, pero no hace falta instalar nada para echarlo a andar, ni tan siquiera para compilar (ya lo hace el .bat)
Espero que os guste ;)

oks lo voy a probar haber ke tal..... hecho en Bennu????, dios no me digas ke lo vas a portar a la Wiz????? jejeje

Drumpi
28/02/2010, 18:30
oks lo voy a probar haber ke tal..... hecho en Bennu????, dios no me digas ke lo vas a portar a la Wiz????? jejeje

Vale, lo acabo de volver a subir, me he dado cuenta que he cometido un error al inicializar uno de los bucles. Ahora sí sale algo que cuadra más, se ve el módulo de la sinc, pero aun me falla porque tras cada actualización, crece la gráfica (creo que tiene algo que ver con que seno y coseno devuelven un valor int en milésimas de grado). Pero es raro, dado que todos los valores son reescritos en cada "actualización", debería salir la misma gráfica siempre.

El código está basado en este:
http://cnx.org/content/m12016/latest/

¿Pasarlo a WIZ? Si funciona, dado que va a funcionar en la Beagle, se portará a Pandora...
Y después haré un módulo en C para Bennu, por lo que sí, debería funcionar en PC, WIZ y hasta GP2X si le van los micrófonos USB :lol: ... si consigo un rendimiento óptimo, porque aun no se lo rápido que va ^^U

jduranmaster
28/02/2010, 18:40
ok me vuelvo a bajar el programa desde el enlace anterior.......

Drumpi
03/03/2010, 19:08
Bueno, estoy de vuelta, porque he resuelto un par de dudas... y un par de bugs:

Resulta que lo que se obtiene en la gráfica son las amplitudes de las frecuencias, yendo estas desde 0Hz (componente continua) hasta la velocidad de muestreo (44100Hz).
Así que, para testear más a fondo, he tomado sólo 64 muestras, y estoy repasando el código usando valores reales (lo que es un coñazo). He comprobado que hacía mal la copia de datos al buffer para hacer las cuentas, y que un par de variables eran de un tipo incorrecto. Lo he modificado y ahora la gráfica es estable, ya no cambia y tiende al infinito como hacía antes...

Pero sigue sin ir bien.
En fin, estoy intentando volverlo a subir, pero no se qué pasa que la conexión hoy va fatal.

El enlace es el mismo.