scieee AI-readable full text Open interactive document viewer

Repositorio Institucional de Documentos

Abstract

El objetivo de este proyecto es diseñar un Estetoscopio con Cancelación de Ruido: un estetoscopio que eliminará todos los sonidos que no provienen del interior del cuerpo. El método empleado para alcanzar este objetivo requerirá de un sensor para capturar el sonido del cuerpo y otro para el sonido ambiente, después se realizará un procesado digital de la señal de forma que el sonido del primer sensor quedará limpio y en la salida por los auriculares sólo se podrá escuchar el sonido del corazón, pulmones... sin ninguna interferencia externa. Gil Vidal, Natanael; Martínez Gómez, Francisco Javier

Full text

ESTETOSCOPIO CON CANCELACIÓN DE RUIDO Realizado por: NATANAEL GIL VIDAL Dirigido por: Dr. FRANCISCO J. MARTÍNEZ GÓMEZ Director del Grupo de Vibroacústica Departamento de Ingeniería Mecánica Ingeniería Técnica Industrial Marzo 2011 Proyecto Fin de Carrera Este proyecto fue realizado en la Universidad de Glasgow (University of Glasgow) durante el curso 2009/2010 bajo la supervisi´on del Dr. Fernando Rodr´ıguez y la Prof. A. Catrina Bryce ´ Indice general 1. Objeto y alcance del proyecto 5 2. Antecedentes 7 2.1. M´edicos ................................ 7 2.2. T´ecnicos................................ 11 2.2.1. Se˜nales digitales . . . . . . . . . . . . . . . . . . . . . . . 11 2.2.2. DFT.............................. 12 2.2.3. Filtros............................. 15 2.2.4. Filtros adaptativos . . . . . . . . . . . . . . . . . . . . . . 16 3. Dise˜no e implementaci´on 18 3.1. Dise˜no e implementaci´on de un prototipo . . . . . . . . . . . . . 18 3.2. Implementaci´on de software . . . . . . . . . . . . . . . . . . . . . 22 3.2.1. Comaflotante......................... 22 3.2.2. Comafija ........................... 24 3.2.3. Pruebas............................ 26 3.3. Planteamiento de implementaci´on en Hardware . . . . . . . . . . 29 4. Conclusiones 33 A. Afecciones del coraz´on y pulmones 35 A.1.Fisiol´ogicas .............................. 37 A.1.1. Desdoblamiento del segundo ruido . . . . . . . . . . . . . 37 A.1.2. Soplo funcional . . . . . . . . . . . . . . . . . . . . . . . . 38 A.1.3. Zumbido venoso . . . . . . . . . . . . . . . . . . . . . . . 39 A.2.Sist´olicas ............................... 40 A.2.1. Estenosis a´ortica . . . . . . . . . . . . . . . . . . . . . . . 40 A.2.2. Prolapso mitral . . . . . . . . . . . . . . . . . . . . . . . . 41 A.2.3. Estenosis pulmonar . . . . . . . . . . . . . . . . . . . . . . 42 A.2.4. Comunicaci´on interventricular . . . . . . . . . . . . . . . . 43 A.2.5. Comunicaci´on interauricular . . . . . . . . . . . . . . . . . 44 A.3.Diast´olicas............................... 45 A.3.1. Insuficiencia a´ortica . . . . . . . . . . . . . . . . . . . . . 45 A.3.2. Estenosis mitral . . . . . . . . . . . . . . . . . . . . . . . 46 A.4. Roces, galopes y soplos continuos . . . . . . . . . . . . . . . . . . 47 A.4.1.Roces ............................. 47 A.4.2.Tercerruido.......................... 48 A.4.3.Cuartoruido ......................... 49 2 A.4.4. Ductus arterioso persistente . . . . . . . . . . . . . . . . . 50 A.5.Pulmones ............................... 51 A.5.1.Crepitantes .......................... 53 A.5.2.Sibilancias........................... 54 B. Formas de onda con filtros de distinta longitud 55 C. Respuestas del filtro con diferentes SNR 59 C.1.Formasdeonda............................ 59 C.2.Espectrogramas............................ 66 D. C´odigo 73 D.1.PrototipoMatlab........................... 73 D.2.SoftwareenC............................. 75 D.2.1.Comaflotante......................... 75 D.2.2.Comafija ........................... 78 D.3.VHDL................................. 81 D.3.1. Entidad y arquitectura . . . . . . . . . . . . . . . . . . . . 81 D.3.2. Banco de pruebas manual . . . . . . . . . . . . . . . . . . 85 D.3.3. Banco de pruebas autom´atico . . . . . . . . . . . . . . . . 93 D.4. Conversi´on Binario ←→ Texto ................... 96 D.4.1. Binario −→ Texto ...................... 96 D.4.2. Texto −→ Binario ...................... 98 Bibliograf´ıa 100 Anexo I 102 3 4 Cap´ıtulo 1 Objeto y alcance del proyecto A lo largo de la historia de la medicina se han ido desarrollando tecnolog´ıas que permiten profundizar cada vez m´as en el funcionamiento del cuerpo humano. Desde los simples alicates hasta las complej´ısimas tomograf´ıas por emisi´on de positrones pasando por las pr´otesis la tecnolog´ıa sanitaria ha ido siguiendo un desarrollo parejo a lo que las distintas ciencias han ido descubriendo. Un instrumento que se asocia inmediatamente a los profesionales de la salud es el estetoscopio (tambi´en llamado fonendoscopio), es quiz´as una de las herramientas m´as vers´atiles cuya idea es bastante simple: ayudar a escuchar los sonidos internos del cuerpo humano (o animal). A pesar de este sencillo concep- to, este producto tambi´en ha ido evolucionando y adaptando los conocimientos de otras ramas del conocimiento como es la electr´onica. Los primeros estetoscopios electr´onicos hac´ıan uso de electr´onica anal´ogica (bobinas, v´alvulas...) para amplificar el sonido y facilitar la escucha al facultativo. La aparici´on del mundo digital supuso toda una revoluci´on tecnolog´ıa, procesos anteriormente muy costosos se han ido abaratando y agilizando a pasos agigantados, ideas antes atrapadas en las mentes de sus creadores, han podido materializarse. Miniaturizaci´on, bajo consumos energ´etico, capacidad de manejo y procesamiento de grandes cantidades de datos... En esta nueva rama han ido apareciendo muchas nuevas disciplinas de las que, por supuesto, la medicina en general y los estetoscopios en particular se han podido ir nutriendo para llegar a lugares que antes eran impensables. El objetivo de este proyecto es utilizar esta rama de la ciencia para dise˜nar un estetoscopio que sea capaz de ofrecer un sonido m´as limpio de lo que puede ofrecer un fonendoscopio normal, y hacerlo sin perder las propiedades pr´acticas que caracterizan a esta herramienta (facilidad de uso, portabilidad, ligereza, robustez...). A la hora de realizar una auscultaci´on el principal problema que se encuentra el profesional es el ruido ambiente, para un examen ´optimo se requiere total silencio, algo que en la pr´actica es muy dif´ıcil por no decir imposible de conseguir. Al hablar de ruido ambiente en lo primero que se suele pensar es en el que interfiere directamente en el estetoscopio: se introduce por las ”olivas”, la 5 ”campana”, etc. y es el que tiene una soluci´on m´as f´acil: mejorar el aislamien- to ac´ustico. Pero este ruido tambi´en se introduce en el cuerpo que esta siendo auscultado y cuando el personal sanitario procede a escuchar los sonidos interiores, adem´as del coraz´on, pulmones, circulaci´on... se encuentra con los ruidos que ocurren en el ambiente. Lo peculiar de este ruido es que est´a modificado, el cuerpo act´ua como un filtro que hace que el proveniente del exterior que es capturado por el estetoscopio a trav´es del paciente sea distinto al que hay directamente en el exterior. En este proyecto se estudiar´an las t´ecnicas de procesamiento de la se˜nal necesarias para poder crear, mediante software, un filtro que se adapte a las distintas situaciones que se puedan presentar y que ofrezca robustez suficiente para, en caso de ser llevado a hardware, poder funcionar en unas condiciones en las que el uso de un estetoscopio com´un ser´ıa imposible. 6 Cap´ıtulo 2 Antecedentes Antes de comenzar a trabajar directamente en el proyecto necesitamos plantearnos qu´e es lo que queremos (es decir, qu´e esperar´ıa del producto un profesional de la medicina), c´omo lo queremos y c´omo podemos obtenerlo (la base tecnol´ogica que es necesaria para alcanzar nuestros objetivos). 2.1. M´edicos ”El estetoscopio es un dispositivo m´edico utilizado para la auscultaci´on, escuchar los sonidos internos de un cuerpo animal”[1] Normalmente es utilizado para escuchar el sonido del coraz´on y de los pulmones, pero a veces tambi´en pueden interesar los intestinos y la circulaci´on de la sangre. (a) Primeros estetoscopios [2] (b) Distintos modelos de estetoscopios antiguos [3] Figura 2.1: Estetoscopios 7 Antes de la invenci´on del estetoscopio, los doctores escuchaban el sonido del cuerpo directamente poniendo la oreja en el paciente, pero en 1816, Rene Theophile-Hyacinthe Laennec, que ten´ıa aprensi´on a tocar directamente los cuerpos, cogi´o una ”trompeta” de madera y descubri´o que era mucho mas f´acil escuchar los sonido mediante este m´etodo. Desde entonces este instrumento se ha ido refinando a lo largo del tiempo. No hubo ning´un desarrollo significativo en la siguiente d´ecada hasta que el Dr. Charles Williams dividi´o el instrumento en dos partes con una articulaci´on que permit´ıa que girara en diferentes ´angulos algo que permit´ıa al practicante mantener una postura m´as c´omoda, aplicar una presi´on menor sobre el paciente y la posibilidad de observar las pulsaciones en el cuello. Durante los siguientes 40 a˜nos no hubo muchos avances aparte de la creaci´on de un estetoscopio con dos campanas que iban cada una a una oreja. En 1926 Howard Sprague dise˜no la primera combinaci´on de campana y diafragma que se ha mantenido (de una forma bastante refinada) hasta nuestros d´ıas y no fue hasta 1940 cuando este mismo doctor (en conjunto con Maurice Rappaport) investig´o los principios f´ısicos del estetoscopio. La primera aparici´on de un estetoscopio electr´onico fue en 1961 desarrollado por Amplivox, debido a que usaba v´alvulas de vac´ıo ten´ıa un tama˜no y peso considerables por lo que su uso fue abandonado enseguida. La revoluci´on m´as grande vino con el Dr. David Littmann, que en ese mismo a˜no dise˜n´o un estetoscopio ligero con un s´olo tubo binaural. Este modelo se extendi´o r´apidamente y se convirti´o en el m´as popular debido a su ligereza, flexibilidad y excelentes propiedades ac´usticas. Desde entonces esta herramienta ha ido mejorando y creciendo tanto en calidad como en popularidad. [5] Figura 2.2: Partes de un estetoscopio [6] Hoy en d´ıa, los estetoscopios ac´usticos siguen siendo los m´as utilizados, el sonido es transmitido a trav´es de unos tubos llenos de aire, los estetoscopios 8 2.2.3. Filtros Figura 2.8: Filtro [8] El procesamiento de se˜nales est´a basado principalmente en lo que llamamos filtros, cogemos una se˜nal y la modificamos con un filtro. Dependiendo del resultado, algunos tipos comunes de filtros son paso bajo (la salida s´olo tendr´a las frecuencias bajas de la se˜nal de entrada), paso alto (s´olo dejar´a pasar frecuencias altas), paso banda (s´olo contendr´a ciertas frecuencias entre un l´ımite superior y otro inferior)... Otros tipos de filtros, clasificados por c´omo trabajan, son Finite Impulse Response (FIR, Respuesta finita al impulso) y Infinite Impulse Response filters (IIR, Respuesta infinita al impulso). Los filtros FIR son simples y estables mientras que los filtros IIR pueden ser m´as exactos pero tambi´en m´as inestables y pueden necesitar una gran carga de computaci´on. Aqu´ı s´olo pasar´e a explicar el primero que es el que se necesita en este proyecto. Filtros FIR Una de las principales propiedades de este tipo de filtros (tambi´en llamados no-recursivos) es que usa una cantidad limitada de datos, s´olo entradas pasadas y presentes. La operaci´on de este filtro es b´asicamente, multiplicar el valor de kmuestras por determinados coeficientes hy despu´es sumar los resultados. Figura 2.9: C´omo funciona un filtro FIR [8] y(n) = N−1 X k=0 h(k)x(n−k) (2.9) Mes el tama˜no del filtro, el n´umero de taps, cu´antos valores son usados. nes el ´ındice de salida. h(k) son los coeficientes del filtro, k es el ´ındice. xson los valores de entrada. 15 Esta operaci´on recibe el nombre de convoluci´on, y puede ser muy simplificada mediante DFT como se muestra en la ecuaci´on (2.10) y(n) = h(k)∗x(n)DF T * ) IDF T H(m)X(m) = Y(m) (2.10) Para dise˜nar un filtro de este tipo ”s´olo” necesitamos calcular los coeficientes, a grandes rasgos esto puede hacerse siguiendo los siguientes pasos: Definir cu´al va a ser la respuesta en el dominio frecuencial (para obtener un mejor resultado valoraremos el uso de ventanas). Convertir esa expresi´on al dominio temporal (IDFT) para obtener los coeficientes del filtro. Aplicar el filtro (convoluci´on). Tambi´en hay rutinas de software que permiten hacer todo este proceso de forma que la posibilidad de cometer errores desciende considerablemente. Toda la informaci´on explicada hasta este punto (Se˜nales digitales, DFT, filtros...) ha sido estudiada y aprendida de [8] 2.2.4. Filtros adaptativos Si las condiciones en las que fuera a trabajar nuestro producto fueran siempre las mismas, podr´ıamos utilizar el filtro anteriormente descrito, pero obviamente esto no es lo que va a ocurrir, por eso necesitamos algo que nos permita trabajar en condiciones cambiantes y no predecibles. Esto se hace a trav´es de filtros adaptativos, filtros que en vez de tener los par´ametros fijos, los ajustan ellos mismos. El filtro escogido para hacer este proyecto es el llamado Least Mean Squares (LMS) y se ha elegido por ser estable y simple por lo que no necesitamos mucho tiempo de computaci´on para obtener los resultados. Figura 2.10: Filtro LMS [9] 16 Este filtro es b´asicamente un filtro FIR con coeficientes cambiantes, cada vez que lo aplicamos tenemos que actualizarlos mediante un algoritmo. El algoritmo LMS es un algoritmo de gradiente estoc´astico (se adapta en base al error en el instante actual) que funciona como se explica a continuaci´on. ˆ h(n+ 1) = ˆ h(n) + µe ∗(n)x(n) (2.11) hson los coeficientes, ahora llamados weights. ees el ”error”; como se ve en la imagen, el sonido del estetoscopio menos nuestro sonido modificado. xes el sonido capturado por el micr´ofono ambiente. µes el tama˜no de paso, la ”velocidad” a la que el filtro encuentra los ”weights” ´optimos. Un valor mas alto ofrece m´as velocidad pero m´as imprecisi´on, un valor m´as bajo va m´as lento pero obtiene mejores resultados. El filtro LMS trata de minimizar las diferencias entre las dos entradas modificando una de ellas. Sin el sonido del coraz´on (interferencia), y con un filtro perfecto, la salida ser´ıa cero. Figura 2.11: Con altos valores de µel filtro estar´a m´as lejos del resultado deseado [10] Si µes muy elevado el sistema ser´a inestable, para reducir este problema se puede utilizar el algoritmo LMSnormalizado. h(n+ 1) = h(n) + µe ∗(n)x(n)/p (2.12) La ´unica diferencia con LMS es dividir la potencia de las muestras que est´an siendo utilizadas, siguiendo la notaci´on en la imagen 2.10 x2. 17 Cap´ıtulo 3 Dise˜no e implementaci´on En este apartado s´olo se adjuntar´an los extractos de las partes del c´odigo m´as significativo, para consultar el c´odigo completo dir´ıjase al ap´endice D. 3.1. Dise˜no e implementaci´on de un prototipo Esta es una idea general de lo que hay que hacer. Para la primera aproximaci´on pr´actica a un prototipo, se ha elegido GNU/Octave porque es un software libre que tiene una forma sencilla de trabajar con se˜nales digitales: matrices (en nuestro caso de orden nx1), procesamiento... [ dirty ,fs ] = wavread ( ’file1 . wav ’); [ noise ,fs ] = wavread ( ’file2 . wav ’); Lo primero de todo, necesitamos leer los archivos que queremos procesar, esto puede hacerse con el comando wavread, en mi caso estoy leyendo el audio 18 y tambi´en la frecuencia de muestreo, esto es porque por defecto GNU/Octave considera que esta frecuencia es 22kHz. u = noise (n : -1:n-M +1); Como el filtro est´a basado en un filtro FIR, nuestro vector de ”weights” debe tener los valores en un orden inverso por lo que nuestro siguiente paso ser´a rellenar el vector de esta forma. Octave permite hacer esto con un peque˜no ajuste en la funci´on utilizada para extraer parte de un vector: podemos indicar la direcci´on (y periodo) en la que los datos ser´an le´ıdos (por ejemplo, con 1 se leer´a de forma ”est´andar”, con 2 se leer´a cada dos valores, con −1 en orden inverso, etc.) Esto no es completamente necesario pero ayudara a simplificar las operaciones que hay que hacer m´as adelante. yn = w’ * u; %Applying filter e(n) = d(n) - yn; %Output p = (u’*u); w = w + (mu * u * e(n))/(p); %Normalized LMS Con GNU/Octave podemos aplicar filtros f´acilmente con la funci´on filter o con la funci´on convolution, pero en este caso he considerado apropiado utilizar algo que pueda ser portado m´as f´acilmente a otro lenguaje de programaci´on. Como ya tenemos preparados los valores, s´olo tenemos que multiplicar la traspuesta de la matriz de los weights por la que contiene las muestras de entrada y el resultado ser´a un n´umero escalar (estamos trabajando con matrices de orden 1xn). El siguiente paso ser´a calcular el error del filtro, y esto se hace simplemente encontrando la diferencia de la se˜nal que es captada directamente del cuerpo con la se˜nal procesada. Y por ´ultimo, antes de leer nuevos datos, necesitamos actualizar los coeficientes haciendo uso del algoritmo en cuesti´on, como Octave permite trabajar f´acilmente con matrices, simplemente tendr´ıamos que escribir la ecuaci´on (2.12), pero como en este proyecto s´olo vamos a trabajar con se˜nales reales, puede ser simplificado un poco m´as como vemos en (3.1). h(n+ 1) = h(n) + µe(n)x(n)/p (3.1) Como ya sabemos que valores elevados de µnos dan una r´apida aproximaci´on al resultado y valores m´as peque˜nos una aproximaci´on m´as exacta, la ´unica forma de tener un poco da cada es utilizar un valor de µvariable, al inicio, durante unas cuantas muestras, utilizaremos un valor bastante elevado (como estamos usando el algoritmo normalizado el filtro seguir´a siendo estable aunque µsea un n´umero grande) y despu´es lo cambiaremos por otro mas peque˜no. soundsc (e, fs ); Una vez que el archivo ha sido procesado, GNU/Octave nos permite escuchar el vector directamente, esto se hace a trav´es de la funci´on sound, tanto la lectura y escritura de archivos .wav se hace por defecto a 22kHz pero podemos indicarle nuestra propia frecuencia de muestreo. Otro comando interesante es la funci´on 19 soundcs que hace los mismo que la anterior pero reproduciendo el sonido al m´aximo volumen posible sin que llegue a distorsionar. Una vez que el prototipo ha sido dise˜nado y est´a funcionando correctamente con par´ametros aleatorios tenemos que elegirlos de forma que cumplan nuestros requisitos: µpuede ser un n´umero elevado porque estamos trabajando con el algoritmo normalizado NLMS por lo que voy a elegir primero un valor bastante alto, 0,5 que ser´a reducido despu´es de unos cuantos ciclos hasta alcanzar 0,01. El otro par´ametro clave en este tipo de filtro es el orden del filtro, necesitamos encontrar el equilibrio entre un buen desempe˜no y no demasiado coste de procesamiento (es el caso de un orden alto), por ello he comenzado las pruebas del filtro con valores elevados y luego los he ido bajando hasta que he encontrado un punto que me ha parecido adecuado, equilibrado. Para hacer las pruebas de este filtro primero he buscado algunas muestras de sonido de coraz´on [11]. Para el ruido he cogido diversos sonidos (ruido, m´usica, voces...) y los he mezclado juntos, esto ser´a el ruido ambiente. Por ´ultimo he filtrado este sonido con un filtro paso-bajo a 100Hz (despu´es de algo de investigaci´on he encontrado que esta es, m´as o menos, la frecuencia a la que el cuerpo humano adulto filtra los sonidos del exterior) y le he a˜nadido el sonido del coraz´on, este sera el sonido capturado del cuerpo por el estetoscopio. (a) El sonido antes de ser procesado (b) 32 taps (c) 16 taps Figura 3.1: Respuesta del prototipo a filtros de diferente orden. Se pueden encontrar el resto del ejemplos ap´endice B 20 Como podemos ver en la figura 3.1, 16 taps es muy bajo y 32 taps quiz´as podr´ıa ser reducido. He encontrado un buen equilibro utilizando 24 tpas; en la figura 3.3 podemos ver que la adaptaci´on es conseguida bastante r´apida, en menos de 250 muestras; los archivos de sonido est´an a una frecuencia de muestreo de 8kHZ por lo que esta adaptaci´on toma menos de 50ms. Figura 3.2: Respuesta del filtro con 24 taps Figura 3.3: Mirada m´as cercana a la respuesta del filtro a 24 taps 21 3.2. Implementaci´on de software El siguiente paso en el proyecto es implementar el prototipo como un software funcional que nos permita probar el algoritmo, el lenguaje escogido ha sido C, que puede ser utilizado en microprocesadores, por lo que si, en el futuro, queremos implementar este c´odigo directamente en hardware, no ser´an necesarios grandes cambios. Para tener una mejor comprensi´on y probar si el programa funciona correctamente, primero he utilizado coma flotante en las operaciones de mi aplicaci´on. 3.2.1. Coma flotante Una de las principales diferencias con el c´odigo de GNU/Octave es la forma de manejar los archivos .wav. En GNU/Octave cargamos el archivo completo en un vector, leemos los valores almacenados en esa estructura, despu´es de procesarlos los guardamos en un diferente vector y finalmente escribimos eso datos en un archivo (o lo reproducimos directamente). Si quisi´eramos hacer esto en C, necesitar´ıamos disponer de una gran cantidad de memoria disponible y otro problema es que la perspectiva para este c´odigo es que sea implementado en hardware para trabajar en el mundo real y en esta situaci´on s´olo tenemos acceso a muestras pasadas (si las vamos almacenando) y presentes, por ello tenemos que hacer algo que se asimile a c´omo funcionar´a el producto final: vamos a leer las muestras directamente de nuestro archivo y escribir el resultado directamente en otra. noiseFile = fopen (" file1 . wav " ," rb "); dirtyFile = fopen (" file2 . wav " ," rb "); outputFile = fopen (" output1 . wav " ," wb "); char buffer [44]; fread ( buffer , 1, 44 , noiseFile ); fwrite ( buffer , 1, 44 , outputFile ); fseek ( dirtyFile , 34 , SEEK_SET ); fread (& bs , 2, 1, dirtyFile ); Bs = bs / 8; fseek ( dirtyFile ,44 , SEEK_SET ); while (! feof ( dirtyFile )) { fread (& readInputBody , Bs , 1, dirtyFile ); fread (& readInputAmbience , Bs , 1, noiseFile ); ... C permite acceder a los archivos en modo binario mediante el proceso fopen, necesitamos indicar en los par´ametros si queremos acceder a este archivo en modo de lectura, escritura o ambos. Como estamos leyendo los archivos en modo binario necesitamos saber c´omo es el formato. Mirando las especificaciones vemos que los archivos .wav tienen un encabezado de 44 bytes. Este programa va a ser ejecutado en un ambiente controlado: nuestros dos archivos ser´an de la misma longitud, y por lo tanto, 22 la salida tambi´en tendr´a la misma longitud por lo que podemos utilizar el encabezado de cualquiera de los ficheros de entrada para crear el de salida. Dos valores importantes para nosotros en este c´odigo son la frecuencia de muestreo y el n´umero de bits por muestra, en este caso s´olo necesitamos leer el n´umero de bits por muestra (tenemos que saber d´onde empieza y acaba cada muestra). Podemos hacer f´acilmente en C con el comando fseek que mueve el puntero del fichero a determinado byte. Para leer bits se utiliza el comando fread, aparte del fichero que queremos leer y donde salvar la informaci´on le´ıda, necesitamos indicar el n´umero de bytes por bloque, y el n´umero de bloque para leer. Figura 3.4: Especificaciones del formato .wav El filtro no puede trabajar hasta que tiene suficientes valores, por eso las primeras muestras son simplemente almacenadas y copiadas en el fichero de salida, cuando el vector tiene suficientes datos, el filtro comienza a trabajar. Igual que en el c´odigo de GNU/Octave, tengo tres valores diferentes asignados aµ, para cambiarlos utilizo un contador que deja de trabajar cuando llega al tercer y ´ultimo valor de µ. Para almacenar nuestros valores muestreados necesitamos hacer uso de una estructura FIFO (First In First Out), esto es, que el primer valor que se introduce ser´a el primero en ser borrado. La primera idea fue crear y utilizar una cola, pero quiz´as eso complicar´ıa significativamente el c´odigo y no seria la soluci´on mas sencilla (s´olo es necesitada para una variable) por lo que he decidido utilizar simplemente un vector e ir moviendo todos los valores cada vez que se introduce nueva informaci´on. Este almacenaje se hace de forma inversa ya que es el vector que utilizaremos para los ”weights”. yn = 0; for (i = 0; i < ORDER ;i ++){ 23 yn += w[i]*u[i]; } En C no podemos manejar los vectores como matrices, por eso para aplicar el filtro (hacer la convoluci´on), necesitamos multiplicar cada uno de los valores de los vectores, como hemos preparado una de las estructuras anteriores de forma que se rellena inversamente, no hay ning´un problema en realizar esta operaci´on directamente sin pasos intermedios. e = calcBody - yn; if (e > 1) {e = 1;}; if (e < -1) {e = -1;}; Despu´es de obtener el error (nuestra salida) comprobamos que el resultado est´a dentro de unos l´ımites de trabajo, en caso de salirse, simplemente saturamos el valor, trabajando de esta forma siempre tenemos control sobre lo que est´a ocurriendo en el programa. power = power *( ORDER -1)/ ORDER + u[0] * u [0] /ORDER ; Como estamos utilizando el algoritmo LMS Normalizado necesitamos calcular la potencia de la parte de la se˜nal que estamos manejando, esto requiere bastante procesamiento, en cada iteraci´on se necesita multiplicar y sumar N veces (siendo Nel orden del filtro), una forma de relajar este requerimiento ser´ıa almacenar todos los valores que est´an siendo utilizados para trabajar con el filtro y en la siguiente iteraci´on sumar el nuevo y restar el mas viejo, pero esto requiere bastante memoria; la mejor elecci´on ser´ıa lo que recibe el nombre de media m´ovil. He estado tratando de implementar esto en mi c´odigo pero s´olo he obtenido resultados err´oneos, creo que la raz´on es que en este caso en concreto los valores son muy diferentes unos de otros por lo que la aproximaci´on no es v´alida. Como cuando se realiza el cambio a coma fija m´as adelante, esto no se necesita, he decidido dejar las operaciones en la forma ”te´orica” (multiplicando todos los valores uno por uno). for (i = 0; i < ORDER ;i ++){ w[i] = w[i] + e*mu*u[i]/ power ; } El siguiente paso es actualizar los ”weights”, necesitamos volver a iterar para sumar los t´erminos de los vectores. La ´ultima operaci´on antes de leer los siguientes valores de los archivos es escribir las salidas en el fichero de salida, se usa el proceso fwrite con los mismos par´ametros que se han utilizado anteriormente con fread. 3.2.2. Coma fija Como un paso m´as hacia la implementaci´on en hardware, en vez de utilizar coma flotante que es la forma m´as f´acil para hacer operaciones matem´aticas pero necesita una unidad de procesamiento de punto flotante para que sea eficiente (y 24 determinado a ser signed pero de distinto tama˜no, VHDL no permite hacer esto directamente, la forma de es convertir nuestro signed en un integer para finalmente convertir este ´ultimo en nuestro nuevo tipo signed. Figura 3.9: Funciones para la suma: estetoscopio +ruido =salida El ´unico problema con esta conversi´on es que estamos limitados a un m´aximo de 16 bit que es la m´axima longitud de un entero. function MultFix (b ,a: sample ) return sample is variable c: signed (4* RESOLUTION -1 downto 0) := ( others => ’0 ’); variable d: sample ; begin c:= to_signed ( to_integer (a) ,2* RESOLUTION ) * to_signed ( to_integer (b ),2* RESOLUTION ); c := shift_right (c, RESOLUTION ); if (c >= MAX_POS ) then d:=MAX_POS; elsif (c <= MAX_NEG ) then d:=MAX_NEG; else d:= to_signed ( to_integer (c), RESOLUTION ); end if; return d; end function MultFix ; Para la multiplicaci´on necesitamos hacer lo mismo otra vez, adem´as de desplazar el array para tener un resultado correcto en la parte decimal (en este caso ser´ıa el array completo). Banco de pruebas Como VHDL est´a preparado para dise˜no de hardware, para realizar una simulaci´on necesitamos preparar un banco de trabajo, otra pieza de c´odigo en la que escribiremos la entradas y salidas del sistema. variable linea : line ; file micFile : text open read_mode is " mic .dat "; readline ( micFile , linea ); read (linea , micData ); Para probar este sistema se necesita una gran cantidad de datos, no podemos ver si el sistema est´a funcionando correctamente simplemente leyendo unos cuantos valores, por eso la forma m´as f´acil de trabajar ser´ıa leer directamente el archivo .wav VHDL no permite esto pero permite leer arrays de caracteres de un fichero de texto. He creado dos peque˜nas aplicaciones en C (se pueden 31 ver en el anexo D.4 ) que transforman un archivo .wav en un fichero de texto (y viceversa). El formato de este archivo es una muestra por l´ınea, y cada muestra es en binario (unos y ceros). Ahora ya podemos realizar la simulaci´on, s´olo necesitamos transformar el archivo .wav utilizando wav2txt.c, despu´es ejecutar el programa VHDL que nos dar´a una salida en un fichero de texto que puede ser transformado a .wav de nuevo utilizando txt2wav.c para comprobar que el fichero est´a funcionando. 32 Cap´ıtulo 4 Conclusiones Los resultados conseguidos en este proyecto han sido bastante satisfactorios. Esta ha sido mi primera aproximaci´on al ”mundo de la se˜nal digital” y estoy agradablemente sorprendido del potencial de este ´area de la ingenier´ıa. Creo que el filtro est´a trabajando muy bien, con un algoritmo muy sencillo consigue resultados espectaculares en muy poco tiempo, suficiente para cumplir con los requisitos de dise˜no, no creo que la relaci´on entre los sonidos del cuerpo y las interferencias externas que se filtran sean tan exageradas como la que he estado utilizando en las muestras por lo que podr´ıa ser utilizado en situaciones reales. No he obtenido muchos resultados visibles y palpables pero definitivamente el realizar este proyecto ha merecido la pena. He necesitado aprender desde lo m´as b´asico sobre se˜nales digitales, procesamiento digital, filtros, lenguajes de programaci´on... obviamente no he podido profundizar mucho en cada una de las ´areas por la cantidad de tiempo que ser´ıa necesaria e incluso en algunos de ellas no tengo base suficiente para comprenderlas completamente. Futuro Basado en el trabajo realizado hasta ahora, se deja abierto el proyecto a una futura implementaci´on en hardware. Podr´ıa usarse un microcontrolador o un DSP para lo que se deber´ıa adaptar el c´odigo en C, y probablemente a˜nadir alguna optimizaci´on para alg´un tipo particular de hardware. Otro camino a seguir ser´ıa implementar la FPGA, esto s´ı que requerir´ıa m´as recursos y trabajo en el c´odigo ya que deber´ıa ser reescrito al estar preparado actualmente exclusivamente para simulaci´on. Tambi´en se podr´ıa desarrollar un software de procesamiento y gesti´on de los datos una vez capturados tales como visualizaci´on de los sonidos, posibilidad de enviar las muestras por medios digitales (sin tener que hacer que el paciente se tenga que desplazar), almacenaje de las muestras para un posterior an´alisis o comparaci´on, desarrollo de aplicaciones de detecci´on autom´atica, esto es, que bas´andose en una an´alisis inteligente de las muestras, sin intervenci´on del facultativo (excepto para posicionar el estetoscopio en las zonas correctas) se pudiera indicar qu´e afecciones podr´ıa estar padeciendo el paciente. 33 34 Ap´endice A Afecciones del coraz´on y pulmones Figura A.1: Partes del coraz´on [13] El coraz´on es el ´organo principal del aparato circulatorio. Anat´omicamente est´a subdividido en cuatro cavidades, dos derechas y dos izquierdas, separadas por un tabique medial. De manera que funcionalmente hablamos de dos bombas, que no comunican entre s´ı: el coraz´on derecho (que recibe sangre de los ´organos perif´ericos y la bombea a los pulmones) y el izquierdo (que recibe sangre oxigenada de los pulmones y la bombea de nuevo a los ´organos perif´ericos). Las dos cavidades superiores son llamadas aur´ıculas, y las cavidades inferiores se denominan ventr´ıculos. Cada aur´ıcula comunica con el ventr´ıculo que se encuentra por debajo mediante un orificio (orificio auriculoventricular), que puede estar cerrado por una v´alvula denominada tric´uspide en el lado derecho, y mitral en 35 el izquierdo. De los ventr´ıculos salen las arterias (Pulmonares en el derecho y Aorta en el izquierdo), y a las aur´ıculas afluyen las venas (cavas en la derecha, y pulmonares en la izquierda).El ´organo est´a contenido por dos hojas, una de ellas ´ıntimamente adherida (epicardio) y otra que se contin´ua con la primera y rodea completamente al coraz´on (pericardio propiamente dicho); entre las dos hojas, existe una cavidad virtual que permite los libres movimientos de la contracci´on card´ıaca. Recibe el nombre de ciclo card´ıaco el conjunto de acontecimientos que tienen lugar desde el inicio del latido card´ıaco, y que duran hasta el inicio del latido siguiente. Cada latido comienza con un potencial de acci´on espont´aneo iniciado en una estructura denominada N´odulo Sinusal, situado en la aur´ıcula derecha. Dicho potencial de acci´on viaja a trav´es de las dos aur´ıculas y del N´odulo Aur´ıculo Ventricular y el Haz de Hiss hacia los ventr´ıculos. En el N´odulo y el Haz se produce un retraso de una d´ecima de segundo, fundamental para que las aur´ıculas se contraigan antes que los ventr´ıculos, llen´andolos de esa forma. En la di´astole, los ventr´ıculos se llenan de sangre, y se contraen en la s´ıstole, expuls´andola hacia los vasos sangu´ıneos de todo el organismo. [12] Figura A.2: Espectrograma de una muestra de sonido de un coraz´on sano 36 A.1. Fisiol´ogicas A.1.1. Desdoblamiento del segundo ruido Figura A.3: Espectrograma de una muestra de sonido de un desdoblamiento del segundo ruido El desdoblamiento del segundo ruido puede ser debido a una causa fisiol´ogica: la respiraci´on. En la mayor´ıa de los adultos sanos, se puede escuchar un desdoblamiento del segundo ruido durante una inspiraci´on profunda. La raz´on de esto es que el segundo ruido del coraz´on es realmente la mezcla del cierre de dos v´alvulas distintas. Normalmente la v´alvula a´ortica se cierra antes que la pulmonar, pero est´an tan juntas que el sonido suena uniforme e instant´aneo. Al inspirar profundamente disminuye la presi´on intrator´acica lo que causa un incremento del retorno venoso, esto causa que la aur´ıcula y ventr´ıculos derechos se llenen un poco m´as de lo normal y que al ventr´ıculo le cueste un poco m´as de tiempo expulsar la sangre. Este retraso fuerza a la v´alvula pulmonar a mantenerse abierta un poco m´as de lo normal haciendo que la peque˜na diferencia anteriormente comentada se haga perceptible. En un paciente sano el sonido ir´a cambiando entre normal y desdoblado, si se escucha que hay un patr´on podr´ıa ser un desdoblamiento fijo lo cual no es un estado normal en el coraz´on. 37 A.1.2. Soplo funcional Figura A.4: Espectrograma de una muestra de sonido de un soplo funcional Un soplo card´ıaco se produce cuando hay un flujo de sangre anormalmente turbulento, esto puede ser causado por alguna patolog´ıa como alguna alteraci´on en una v´alvula card´ıaca por una anomal´ıa intercardiaca o extracardiaca. Se habla de soplo funcional cuando es causado principalmente por condiciones fisiol´ogicas fuera del coraz´on en vez de en el coraz´on mismo. 38 A.1.3. Zumbido venoso Figura A.5: Espectrograma de una muestra de sonido de un zumbido venoso Un zumbido venoso es un soplo continuo benigno. La sangre fluye hacia el cerebro a trav´es de las arterias car´otida y vertebral, el retorno lo hace por las venas yugulares. Este flujo puede hacer que las paredes de las venas vibren creando un zumbido. 39 A.2. Sist´olicas A.2.1. Estenosis a´ortica (a) Estenosis a´ortica temprana (b) Estenosis a´ortica tard´ıa Figura A.6: Espectrogramas de muestras de sonido de estenosis Uno de los soplos sist´olicos patol´ogicos m´as frecuente es debido a una estenosis a´ortica. En esta patolog´ıa la v´alvula a´ortica no se abre completamente disminuyendo, por lo tanto, el flujo desde el coraz´on. Conforme la v´alvula se va estrechando, la presi´on en el ventr´ıculo izquierdo va aumentando haciendo que ´este se vuelva m´as grueso y que a su vez disminuya el flujo sangu´ıneo. Conforme la presi´on sigue increment´andose la sangre puede quedarse en los pulmones habiendo dificultad para respirar. 40 A.4. Roces, galopes y soplos continuos A.4.1. Roces Figura A.13: Espectrograma de una muestra de sonido de un roce peric´ardico Normalmente las paredes interna y externa que componen el pericardio est´an lubricadas, pero la inflamaci´on del mismo hace que estas paredes rocen una con otra. Es un indicio de presencia de pericarditis (fibrinosa, compresiva...) pudiendo morir por taponamiento card´ıaco. 47 A.4.2. Tercer ruido Figura A.14: Espectrograma de una muestra de sonido de un tercer ruido Como su nombre indica es un sonido que se produce despu´es del primer y segundo sonidos normales en el coraz´on, ocurre al principio de la di´astole. Se cree que est´a causado por la oscilaci´on de la sangre entre las paredes de los ventr´ıculos iniciada por la entrada de fluido de la aur´ıcula. 48 A.4.3. Cuarto ruido Figura A.15: Espectrograma de una muestra de sonido de un cuarto ruido Es otro sonido extra que se produce despu´es del primer y segundo sonidos normales en el coraz´on, por definici´on ocurre inmediatamente antes del primero mientras la aur´ıcula se est´a contrayendo. Se piensa que est´a causado por rigidez en paredes de los ventr´ıculos que causan un flujo anormalmente turbulento cuando la aur´ıcula se contrae forzando a la sangre entrar. 49 A.4.4. Ductus arterioso persistente Figura A.16: Espectrograma de una muestra de sonido de un ductus arterioso persistente Es una enfermedad cong´enita del coraz´on donde el Ductus Arteriosus (el conducto situado en la parte inferior de la arteria aorta comunicando con la arteria pulmonar presente durante la etapa fetal y un breve periodo despu´es del nacimiento que previene excesos de presi´on en los pulmones) no se cierra despu´es del nacimiento, esto permite que una parte de la sangre oxigenada de la parte izquierda del coraz´on vuelva a los pulmones causando inflamaci´on de los pulmones y dificultades para respirar. 50 A.5. Pulmones Figura A.17: Pulmones [16] Cada c´elula del cuerpo necesita un suministro continuo de ox´ıgeno para producir energ´ıa y crecer, repararse y mantener sus funciones vitales. El aparato respiratorio es el encargado de aportar ese ox´ıgeno a los tejidos, y de eliminar el di´oxido de carbono. El sistema respiratorio incluye el diafragma y los m´usculos tor´acicos, la nariz y la boca, la faringe y la tr´aquea, el ´arbol bronquial y los pulmones, que constituyen el ´organo esencial del aparato respiratorio. El ox´ıgeno contenido en el aire que respiramos, entra al cuerpo a trav´es de la nariz (y/o la boca), atraviesa la faringe, llega a la tr´aquea que se divide en dos bronquios principales, los cuales llegan cada uno a un pulm´on. Los bronquios se ramifican en varias ocasiones formando bronquios m´as peque˜nos, que a su vez se vuelven a ramificar formando bronquiolos.. Despu´es de alrededor de 23 divisiones, los bronquiolos terminan en los conductos alveolares, al final de cada cual se encuentran c´umulos de alv´eolos (sacos alveolares). En ellos se lleva a cabo el intercambio gaseoso, que consiste en la difusi´on del O2yCO2entre la sangre y los alv´eolos. Anat´omicamente los pulmones presentan una hendidura profunda dirigida oblicuamente de arriba abajo y de atr´as adelante, llamada cisura oblicua, que es 51 (a) Partes del aparato respiratorio [14] (b) Partes de los pulmones [15] Figura A.18: Pulmones y aparato respiratorio ´unica en el pulm´on izquierdo, pero que se bifurca en el derecho, formando una segunda cisura llamada cisura horizontal. Estas cisuras dividen los pulmones en l´obulos , de manera que el pulm´on izquierdo comprende dos l´obulos (superior e inferior) mientras que el pulm´on derecho tiene tres (superior, medio e inferior. Ambos pulmones est´an recubiertos por dos hojas de pleura: la visceral, ´ıntimamente ligada al par´enquima pulmonar, y la parietal, con un espacio virtual entre ellas. Figura A.19: Espectrograma de una muestra de sonido de respiraci´on normal 52 A.5.1. Crepitantes Figura A.20: Espectrograma de una muestra de sonido de crepitaciones Es crepitante es un sonido que suele deberse a la aparici´on de secreciones en los bronquiolos o alv´eolos. Es un bastante caracter´ıstico ya que se asemejan al sonido de nieve siendo comprimida (al pisarla por ejemplo) o al roce del pelo (frotar un mech´on de pelo al lado de la oreja). Una de las causas es un fallo s´ubito en el lado izquierdo del coraz´on provoca la acumulaci´on de l´ıquido en los alv´eolos produciendo este sonido. 53 A.5.2. Sibilancias Figura A.21: Espectrograma de una muestra de sonido de sibilancias Es el sonido que hace el aire al pasar por unas v´ıas respiratorias congestionadas, como un silbido. Son frecuentemente debidas a obstrucciones en los conductos bronquiales tor´acicos m´as peque˜nos aunque tambi´en pueden ser de v´ıas mayores o por problemas en las cuerdas vocales. 54 Ap´endice B Formas de onda con filtros de distinta longitud Figura B.1: Filtro de 16 taps 55 Figura B.2: Filtro de 24 taps Figura B.3: Filtro de 32 taps 56 Figura C.8: SNR de -2dB Figura C.9: SNR de 3dB 63 Figura C.10: SNR de 8dB Figura C.11: SNR de 13dB 64 Figura C.12: SNR de 18dB Figura C.13: SNR de 23dB 65 C.2. Espectrogramas Figura C.14: S´olo coraz´on Figura C.15: SNR de -32dB 66 Figura C.16: SNR de -27dB Figura C.17: SNR de -22dB 67 Figura C.18: SNR de -17dB Figura C.19: SNR de -12dB 68 Figura C.20: SNR de -7dB Figura C.21: SNR de -2dB 69 Figura C.22: SNR de 3dB Figura C.23: SNR de 8dB 70 Figura C.24: SNR de 13dB Figura C.25: SNR de 18dB 71 Figura C.26: SNR de 23dB 72 44 outputFile = fopen("salidafixed.wav","wb"); 45 46 //The two files need to have the same header 47 48 char buffer [44]; 49 fread(buffer, 1, 44, aa); //Duplicating header 50 fwrite(buffer, 1, 44, outputFile); 51 52 fseek(aa, 34, SEEK SET); 53 fread(&Bs, 2, 1, aa); //Bits per sample 54 Bs /= 8; //Bytes per sample 55 56 fseek(dirtyFile,44,SEEK SET); 57 fseek(noiseFile,44,SEEK SET); 58 59 w[ORDER-1]=0; //Inicialize weights 60 61 n1=0; 62 n2=0; 63 64 while (!feof(dirtyFile)) { 65 66 starting: 67 fread(&readInputBody, Bs, 1, dirtyFile); //Read one sample of the file 68 fread(&readInputAmbience, Bs, 1, noiseFile); 69 70 calcBody = readInputBody; 71 72 calcAmbience=readInputAmbience; 73 74 while (n1<ORDER-1) { 75 fwrite(&readInputBody, Bs , 1, outputFile); 76 u[ORDER-n1-2] = calcAmbience; 77 w[n1]=0; 78 n1++; 79 goto starting; //Wait until we have enough data to start the filter 80 } 81 82 for (i=ORDER-1; i>0;i--){ 83 u[i] = u[i-1]; 84 } 85 u[0]=calcAmbience; 86 87 yn = 0; // Apply filter 88 for (i = 0; i<ORDER;i++){ 89 short int temp; 90 temp= MultFix(w[i],u[i]); 91 yn = AddFix(yn,temp); 79 92 } 93 94 e = AddFix(calcBody,-yn); // Error, output 95 96 for (i = 0; i<ORDER;i++){ // Update of the weights 97 short int temp; 98 temp = MultFix(e,MU); 99 temp = MultFix(temp,u[i]); 100 w[i] = AddFix(w[i],temp); 101 } 102 103 writeOutput = e; 104 105 fwrite(&writeOutput, Bs, 1, outputFile); // Write the output in the file 106 107 } 108 109 fcloseall(); 110 111 return 0; 112 } 80 D.3. VHDL D.3.1. Entidad y arquitectura 01 library IEEE; 02 use IEEE.STD LOGIC 1164.ALL; 03 --use IEEE.STD LOGIC ARITH.ALL; 04 --use IEEE.STD LOGIC SIGNED.ALL; 05 use IEEE.NUMERIC STD.ALL; 06 07 entity Filter is 08 Port ( 09 Micro : in std logic vector(15 downto 0); 10 Estetoscopio : in std logic vector(15 downto 0); 11 Salida : out std logic vector (15 downto 0); 12 clk: in std logic; 13 rst: in std logic 14 ); 15 end Filter; 16 17 architecture Behavioral of Filter is 18 19 constant ORDER: integer := 32; 20 constant MU: integer := 32; 21 constant RESOLUTION: integer := 16; 22 constant MAX POS: signed := "0111111111111111"; 23 constant MAX NEG: signed := "1000000000000000"; 24 25 subtype sample is signed (RESOLUTION-1 downto 0); 26 type bit16 is array (0 to ORDER-1) of sample; 27 28 signal Mic : std logic vector(RESOLUTION-1 downto 0); 29 signal Cuerpo : std logic vector(RESOLUTION-1 downto 0); 30 signal u sig: bit16; 31 signal w sig: bit16; 32 signal n1 sig:integer; 33 signal empezando sig:boolean; 34 35 begin 36 37 Mic <= Micro; 38 Cuerpo <= Estetoscopio; 39 40 accion: process (rst, clk) 41 42 variable empezando: boolean; 43 variable calcAmbience: sample := (others => ’0’); 44 variable calcBody: sample := (others => ’0’); 45 variable output: sample := (others => ’0’); 81 46 variable u: bit16; 47 variable w: bit16; 48 variable e: sample := (others => ’0’); 49 variable yn: sample := (others => ’0’); 50 variable temp: sample := (others => ’0’); 51 variable i: integer; 52 variable n1: integer; 53 variable n2: integer; 54 55 function AddFix (b,a:sample) return sample is --Add two fixed point values 56 variable c: signed (2*RESOLUTION-1 downto 0) := (others => ’0’); 57 variable d: sample; 58 begin 59 c := to signed(to integer(a),2*RESOLUTION)+to signed(to integer(b),2*RESOLUTION); --I need to adapt the length to check overflow 60 if (c>=MAX POS) then 61 d:=MAX POS; 62 elsif (c<=MAX NEG) then 63 d := MAX NEG; 64 else 65 d:= to signed(to integer(c),RESOLUTION); 66 end if; 67 return d; 68 end function AddFix; 69 70 function MultFix (b,a:sample) return sample is --Multiply to fixed point values 71 variable c: signed (4*RESOLUTION-1 downto 0):= (others => ’0’); 72 variable d: sample; 73 74 begin 75 c:= to signed(to integer(a),2*RESOLUTION)*to signed(to integer(b),2*RESOLUTION); --Need to adapt the length to check overflow 76 c := shift right (c,RESOLUTION); 77 if (c>=MAX POS) then 78 d:=MAX POS; 79 elsif (c<=MAX NEG) then 80 d:=MAX NEG; 81 else 82 d:= to signed(to integer(c),RESOLUTION); 83 end if; 84 return d; 85 end function MultFix; 86 87 begin 88 if (rst=’0’)then 89 w(ORDER-1):= (others => ’0’); --Inicialize weights 90 n1 sig<=0; 91 empezando sig <= true; 82 92 Salida <= (others => ’0’); 93 94 elsif (rising edge(clk)) then 95 96 calcAmbience:=signed(mic); --Take te values of the signal to work with them as variables 97 calcBody := signed(cuerpo); 98 u := u sig; 99 w := w sig; 100 empezando := empezando sig; 101 102 if (empezando) then 103 n1:=n1 sig; 104 w(n1):=(others => ’0’); --Keep inizialiting w 105 u(ORDER-n1-2) := calcAmbience; 106 n1 := n1+1; 107 if (n1=ORDER-1)then 108 empezando := false; 109 w(n1):=(others => ’0’); 110 end if; 111 empezando sig<= empezando; 112 n1 sig <= n1; 113 Salida <= (others => ’0’); 114 115 else 116 117 for iin ORDER-1 downto 1loop 118 u(i) := u(i-1); --Move the array to add new data 119 end loop; 120 u(0):= calcAmbience; 121 122 yn:= (others => ’0’); --Apply the filter 123 for iin 0to ORDER-1 loop 124 temp:=MultFix(w(i),u(i)); 125 yn:= AddFix(yn,temp); 126 end loop; 127 128 e := AddFix(calcBody,-yn); -- Error 129 130 for iin 0to ORDER-1 loop -- Update weights 131 temp := MultFix(e,to signed(MU,RESOLUTION)); 132 temp := MultFix(temp,u(i)); 133 w(i) := AddFix(w(i),temp); 134 end loop; 135 136 Salida <= std logic vector(e); --Write the new value in the signal. 137 138 end if; 139 83 140 w sig <= w; 141 u sig <= u; 142 143 end if; 144 145 end process accion; 146 147 end Behavioral; 84 D.3.2. Banco de pruebas manual Para hacer las pruebas, en un primer momento, se introducen los datos manualmente, en una versi´on posterior el programa los capturar´a autom´aticamente de un fichero de texto. 01 LIBRARY ieee; 02 USE ieee.std logic 1164.ALL; 03 04 05 ENTITY banco manual IS 06 END banco manual; 07 08 ARCHITECTURE behavior OF banco manual IS 09 10 11 COMPONENT Filter 12 PORT( 13 Micro : IN std logic vector(7 downto 0); 14 Estetoscopio : IN std logic vector(7 downto 0); 15 Salida : OUT std logic vector(7 downto 0); 16 clk : IN std logic; 17 rst : IN std logic 18 ); 19 END COMPONENT; 20 21 22 --Inputs 23 signal Micro : std logic vector(7 downto 0) := (others => ’0’); 24 signal Estetoscopio : std logic vector(7 downto 0) := (others => ’0’); 25 signal clk : std logic := ’0’; 26 signal rst : std logic := ’0’; 27 28 --Outputs 29 signal Salida : std logic vector(7 downto 0); 30 31 -- Clock period definitions 32 constant clk period : time := 1 us; 33 34 BEGIN 35 36 -- Instantiate the Unit Under Test (UUT) 37 uut: Filter PORT MAP ( 38 Micro => Micro, 39 Estetoscopio => Estetoscopio, 40 Salida => Salida, 41 clk => clk, 42 rst => rst 43 ); 85 44 45 -- Clock process definitions 46 clk process :process 47 begin 48 clk <= ’0’; 49 wait for clk period/2; 50 clk <= ’1’; 51 wait for clk period/2; 52 end process; 53 54 55 -- Stimulus process 56 stim proc: process 57 begin 58 -- hold reset . 59 rst <= ’0’; 60 wait for 1 us; 61 rst <= ’1’; 62 63 64 Estetoscopio <= "10010110"; 65 Micro <= "10101001"; 66 wait for 1 us; 67 68 Estetoscopio <= "10100110"; 69 Micro <= "10100101"; 70 wait for 1 us; 71 72 Estetoscopio <= "01011010"; 73 Micro <= "11100101"; 74 wait for 1 us; 75 76 Estetoscopio <= "00010111"; 77 Micro <= "11001010"; 78 wait for 1 us; 79 80 Estetoscopio <= "00001100"; 81 Micro <= "11100010"; 82 wait for 1 us; 83 Estetoscopio <= "10010110"; 84 Micro <= "10101001"; 85 wait for 1 us; 86 87 Estetoscopio <= "10100110"; 88 Micro <= "10100101"; 89 wait for 1 us; 90 91 Estetoscopio <= "01011010"; 92 Micro <= "11100101"; 93 wait for 1 us; 86 94 95 Estetoscopio <= "00010111"; 96 Micro <= "11001010"; 97 wait for 1 us; 98 99 Estetoscopio <= "00001100"; 100 Micro <= "11100010"; 101 wait for 1 us; 102 Estetoscopio <= "10010110"; 103 Micro <= "10101001"; 104 wait for 1 us; 105 106 Estetoscopio <= "10100110"; 107 Micro <= "10100101"; 108 wait for 1 us; 109 110 Estetoscopio <= "01011010"; 111 Micro <= "11100101"; 112 wait for 1 us; 113 114 Estetoscopio <= "00010111"; 115 Micro <= "11001010"; 116 wait for 1 us; 117 118 Estetoscopio <= "00001100"; 119 Micro <= "11100010"; 120 wait for 1 us; 121 Estetoscopio <= "10010110"; 122 Micro <= "10101001"; 123 wait for 1 us; 124 125 Estetoscopio <= "10100110"; 126 Micro <= "10100101"; 127 wait for 1 us; 128 129 Estetoscopio <= "01011010"; 130 Micro <= "11100101"; 131 wait for 1 us; 132 133 Estetoscopio <= "00010111"; 134 Micro <= "11001010"; 135 wait for 1 us; 136 137 Estetoscopio <= "00001100"; 138 Micro <= "11100010"; 139 wait for 1 us; 140 Estetoscopio <= "10010110"; 141 Micro <= "10101001"; 142 wait for 1 us; 143 87 144 Estetoscopio <= "10100110"; 145 Micro <= "10100101"; 146 wait for 1 us; 147 148 Estetoscopio <= "01011010"; 149 Micro <= "11100101"; 150 wait for 1 us; 151 152 Estetoscopio <= "00010111"; 153 Micro <= "11001010"; 154 wait for 1 us; 155 156 Estetoscopio <= "00001100"; 157 Micro <= "11100010"; 158 wait for 1 us; 159 Estetoscopio <= "10010110"; 160 Micro <= "10101001"; 161 wait for 1 us; 162 163 Estetoscopio <= "10100110"; 164 Micro <= "10100101"; 165 wait for 1 us; 166 167 Estetoscopio <= "01011010"; 168 Micro <= "11100101"; 169 wait for 1 us; 170 171 Estetoscopio <= "00010111"; 172 Micro <= "11001010"; 173 wait for 1 us; 174 175 Estetoscopio <= "00001100"; 176 Micro <= "11100010"; 177 wait for 1 us; 178 Estetoscopio <= "10010110"; 179 Micro <= "10101001"; 180 wait for 1 us; 181 182 Estetoscopio <= "10100110"; 183 Micro <= "10100101"; 184 wait for 1 us; 185 186 Estetoscopio <= "01011010"; 187 Micro <= "11100101"; 188 wait for 1 us; 189 190 Estetoscopio <= "00010111"; 191 Micro <= "11001010"; 192 wait for 1 us; 193 88 95 wait; 96 end process; 97 98 END; 95 D.4. Conversi´on Binario ←→ Texto D.4.1. Binario −→ Texto 01 #include "stdio.h" 02 #include "math.h" 03 #include "string.h" 04 #include "stdlib.h" 05 06 void dec2bin(unsigned short int decimal, char *salida) { 07 unsigned short int remain; 08 char temp[16]; 09 int i; 10 11 for (i = 0; i<16; i++){ 12 remain = decimal % 2; 13 decimal = decimal / 2; 14 temp[i] = remain + ’0’; 15 } 16 17 for(i = 0; i<16;i++){ 18 salida[i]=temp[16-1-i]; 19 } 20 21 } 22 23 int main() 24 { 25 short int buffer; 26 char binary[16]; 27 short int bs, Bs; 28 FILE *wavFile, *txtFile; 29 30 wavFile = fopen("ambiente2.wav","rb"); 31 txtFile = fopen("a.dat","wb"); 32 33 fseek(wavFile, 34, SEEK SET); 34 fread(&bs, 2, 1, wavFile); //Bits per sample 35 Bs = bs / 8; //Bytes per sample 36 37 fseek(wavFile,44,SEEK SET); 38 39 while (!feof(wavFile)) { 40 41 fread(&buffer, Bs, 1, wavFile); //Read sample from wav file 42 43 dec2bin(buffer,binary); //Convert to ascii char array 44 96 45 fprintf(txtFile," %s\n",binary); //write line in text file 46 47 } 48 49 fcloseall(); 50 51 return 0; 52 } 97 D.4.2. Texto −→ Binario 01 #include "stdio.h" 02 #include "math.h" 03 #include "string.h" 04 #include "stdlib.h" 05 06 int main() 07 { 08 09 unsigned char buffer[16]; 10 unsigned short int binario[16]; 11 unsigned short int entero; 12 13 int i; 14 short int bs, Bs; 15 FILE *txtFile, *jokerFile, *wavFile; 16 17 txtFile = fopen("salida.dat","rb"); 18 jokerFile = fopen("cuerpo1.wav","rb"); 19 wavFile = fopen("procesado.wav","wb"); 20 21 unsigned char bufferdup [44]; 22 fread(bufferdup, 1, 44, jokerFile); //Duplicate headers 23 fwrite(bufferdup, 1, 44, wavFile); 24 25 fseek(jokerFile, 34, SEEK SET); 26 fread(&bs, 2, 1, jokerFile); //Bits per sample 27 Bs = bs / 8; //Bytes per sample 28 29 while (!feof(txtFile)) { 30 31 fscanf(txtFile," %s",buffer); //Read line 32 33 entero=0; //convert to integer 34 for (i=0; i<16;i++){ 35 entero+= ((int)buffer[i]-(int)’0’)*(1<<(16-i)); 36 } 37 38 fwrite(&entero, Bs, 1, wavFile); //write value in wav file 39 40 } 41 42 fcloseall(); 43 44 return 0; 45 } 98 99 Bibliograf´ıa [1] Wikipedia, ”Stethoscope”http://en.wikipedia.org/wiki/Stethoscope [2] Meyers Konversations-Lexikon (1885-90). Public Domain. [3] Maw and Sons, Book of Illustrations, (1869). Public Domain. [4] Howard Hughes Medical Institute, History of Stethoscopes and Sphygmomanometers, http://www.hhmi.org/biointeractive/museum/exhibit98/ content/b6_17info.html [5] History of Stethoscopes, https://www.standris.com/education_ history.cfm [6] Atlas de Ruidos respiratorios, http://escuela.med.puc.cl/Publ/ AtlasRuidos/introduccion.html [7] ”Chris”, The Auscultation Assistant, http://www.med.ucla.edu/wilkes/ intro.html [8] Richard G. Lyons, Understanding Digital Signal Processing, Second Edition, Prentice Hall,2004 [9] Modificado de: Wikipedia, http://en.wikipedia.org/wiki/File:Lms_ filter.png [10] Wikipedia, http://en.wikipedia.org/wiki/File:Gradient_descent. png [11] The free sound project, ”greyseraphim”http://www.freesound.org/ samplesViewSingle.php?id=21409 [12] John E. may. Guyton y Hall, Compendio de Fisiolog´ıa m´edica, 11aed. Madrid, Elsevier, 2007 [13] Fauci et al.Harrison, Principios de Medicina Interna, Vol.2 17aed. Madrid, MaGrawHill, 2009 [14] Una introducci´on a las enfermedades pulmonares ocupacionales, American Lung Association, New York, Macmillan, 1979 [15] R.Putz, R.Pabst, Atlas de anatom´ıa humana Sobotta: volumen 2, 21aed, Madrid, Panamericana, 2000 [16] J.M Prieto Valtue˜na, Exploraci´on cl´ınica pr´actica, 26aed.Barcelona, Elsevier, 2005 100 101 Anexo I Informe original presentado en la Universidad de Glasgow (University of Glasgow) 102