Professional Documents
Culture Documents
rea de Teora de la Seal y Comunicaciones Departamento de Ingeniera Electrnica Escuela Superior de Ingenieros Universidad de Sevilla
NDICE
CAPTULO 1: INTRODUCCIN Y OBJETIVOS ...................................... 1 CAPTULO 2: HARDWARE Y SOFTWARE ............................................. 3 2.1. HARDWARE .............................................................................. 3 2.2. SOFTWARE ............................................................................... 5 2.3. PRUEBAS EN OTROS SISTEMAS ................................................ 9 2.4. ESTRUCTURA DEL PROGRAMA ................................................. 10 CAPTULO 3: DESARROLLO DE LA INTERFASE .................................. 14 3.1. USO DE DIRECTSHOW PARA EL CONTROL DE LA TARJETA......... 14 3.2. OTRAS CLASES PARA DECORACIN DE LA INTERFASE .............. 26 CAPTULO 4: ALGORITMO DE DETECCIN ....................................... 27 4.1. ALGORITMO DE CORRELACIN ................................................ 27 4.2. PARMETROS QUE INTERVIENEN EN EL PROCESO .................... 30 4.3. RUTINAS DESARROLLADAS ...................................................... 34 4.4. FASE DE PRUEBAS: RESULTADOS Y CONCLUSIONES ................. 38 4.5. DECISOR ................................................................................. 57 CAPTULO 5: MANUAL DE USUARIO .................................................. 61 5.1. INICIO DE LA APLICACIN ....................................................... 61 5.2. MENU ..................................................................................... 62 5.3. GRABACIN ............................................................................ 67 5.4. DETECCIN ............................................................................ 68 5.5. CONFIGURACIN DE PARMETROS .......................................... 70 CAPTULO 6: LNEAS FUTURAS DE INVESTIGACIN ........................ 73
-i-
ANEXOS ANEXO 1: POSIBLES PROBLEMAS DE LA APLICACIN ..................... 74 ANEXO 2: FORMATO DE LOS FICHEROS WAV ................................... 78 ANEXO 3: CDIGO FUENTE ............................................................... 79 A3.1. Clase CRadioApp ................................................................... 79 A3.2. Clase CRadioDlg .................................................................... 82 A3.3. Clase CArchivos..................................................................... 120 A3.4. Clase CDialosint .................................................................... 125 A3.5. Clase Configuracin .............................................................. 128 A3.6. Clase CButtonST (Clase CMemDC est includa en ButtonST.h) ........................................................................ 132 BIBLIOGRAFA ................................................................................. 147
- ii -
Lista de ilustraciones
Ilustracin 1: Caractersticas sistema utilizado............................................... 4 Ilustracin 2: WINTV_USB........................................................................... 4 Ilustracin 3: S.O. Windows XP.................................................................... 6 Ilustracin 4: Visual Studio 6.0..................................................................... 6 Ilustracin 5: DirectX 9.0a............................................................................ 7 Ilustracin 6: Grafo 1 en la aplicacin GraphEdit............................................ 8 Ilustracin 7: Grafo 2 en la aplicacin GraphEdit............................................ 8 Ilustracin 8: Estructura de datos capstuff................................................ 12 Ilustracin 9: Estructura de datos archivo_wav......................................... 13 Ilustracin 10: Grafo 1............................................................................... 15 Ilustracin 11: Grafo 2............................................................................... 15 Ilustracin 12: Formacin Grafo DirectShow................................................ 24 Ilustracin 13: Formacin Grafo DirectShow (2)........................................... 25 Ilustracin 14: Formacin Grafo DirectShow (3).......................................... 25 Ilustracin 15: Formacin Grafo DirectShow (4)........................................... 26 Ilustracin 16: Colas de correlacin cruzada................................................ 28 Ilustracin 17: Nmero de muestras........................................................... 31 Ilustracin 18: Tiempo de conmutacin FM -> TV........................................ 41 Ilustracin 19: Tiempo de conmutacin FM -> FM....................................... 42 Ilustracin 20: Diagrama de flujo del decisor............................................... 59 Ilustracin 21: Dilogo principal.................................................................. 61 Ilustracin 22: Men Archivos..................................................................... 63 Ilustracin 23: Dilogo Archivos.................................................................. 64 Ilustracin 24: Men Configurar.................................................................. 64 Ilustracin 25: Dilogo Sintonizador............................................................ 65 Ilustracin 26: Dilogo Configuracin.......................................................... 66 Ilustracin 27: Dilogo Versin................................................................... 67 Ilustracin 28: Dilogo guardar archivo .wav............................................... 68 Ilustracin 29: Muestra archivo frecuencias.cfg............................................ 68 Ilustracin 30: Muestra anuncio detectado.................................................. 69
- iii -
Ilustracin 31: Muestra fichero resultados................................................... 70 Ilustracin 32: Configuracin sonido del sistema.......................................... 71 Ilustracin 33: Mensaje de registro correcto................................................ 76 Ilustracin 34: Mensaje de error anuncio piloto............................................ 77
- iv -
Lista de tablas
Tabla 1: Caractersticas tcnicas tarjeta WinTV............................................ 5 Tabla 2: Sistemas donde se ha comprobado el correcto funcionamiento de la aplicacin.................................................................................................. 9 Tabla 3: Ejemplo nmero de muestras-frecuencia de muestreo.................... 31 Tabla 4: Tiempo de computacin-Tiempo de captura.................................. 39 Tabla 5: Prueba FM 125 mseg................................................................... 44 Tabla 6: Prueba FM 100 mseg................................................................... 45 Tabla 7: Prueba FM 90 mseg..................................................................... 46 Tabla 8: Prueba FM 80 mseg..................................................................... 47 Tabla 9: Prueba FM 75 mseg..................................................................... 48 Tabla 10: Prueba TV 125 mseg.................................................................. 50 Tabla 11: Prueba TV 100 mseg.................................................................. 51 Tabla 12: Prueba TV 90 mseg.................................................................... 52 Tabla 13: Prueba TV 80 mseg.................................................................... 53 Tabla 14: Prueba TV 75 mseg.................................................................... 54 Tabla 15: Prueba TV 70 mseg.................................................................... 55 Tabla 16: Formato de los ficheros .WAV..................................................... 78
-v-
-1-
cierto modo para disminuir en la medida de lo posible la excesiva carga computacional que implica el proceso. Est capacitada para trabajar con varios anuncios simultneamente y con varias sintonas de radio (o en su defecto canales de TV). Por lo tanto el objetivo es el desarrollo de una aplicacin que cumpla con los siguientes requisitos: Trabaje en tiempo real: Es el requisito principal y en torno a l gira el diseo de la aplicacin y las herramientas utilizadas para su desarrollo. Que sea eficiente computacionalmente: Cuanto ms eficiente sea la aplicacin se obtendrn mejores resultados y posibilitar el funcionamiento con un mayor nmero de anuncios y cadenas. Sencilla de cara al usuario final: Debe de ser sencilla de utilizar y con una interfaz amigable de cara al usuario. Flexible: Debe de ofrecer la posibilidad de cambiar los parmetros necesarios por parte del usuario final para un funcionamiento ms adecuado y preciso, orientado a una solucin particular. Portable: Debe de funcionar en todos los sistemas, y no debe de tener dependencia de la tarjeta capturadora. Para demostrar la portabilidad del sistema se ha comprobado el funcionamiento de la aplicacin en otros sistemas y los resultados son expuestos en el captulo 2.
-2-
2.1. HARDWARE.
2.1.1. SISTEMA.
El PC utilizado es un porttil de procesador INTEL CENTRINO a 1.4 GHz., con 512 MB de RAM DDR como refleja en la ilustracin 1. Es el sistema con el que se han realizado las pruebas y medidas de tiempos como los de computacin o conmutacin que son descritos en los apartados 4.4.1 y 4.4.2, respectivamente. Es muy importante la velocidad del micro en una aplicacin de tan elevado coste computacional como esta.
-3-
Se han realizado comprobaciones en otros sistemas con diferentes configuraciones para comprobar el correcto funcionamiento de la aplicacin, los resultados de esas pruebas y las conclusiones se exponen en el apartado 2.3.
Ilustracin 2: WINTV_USB.
-4-
2.2. SOTWARE.
2.2.1. SISTEMA OPERATIVO.
El sistema operativo utilizado ha sido el Windows XP Profesional (ilustracin 3).
-5-
Un posible problema de usar otro sistema operativo puede ser conseguir los controladores de la tarjeta para ese sistema operativo. An teniendo la tarjeta correctamente instalada en otro sistema operativo puede que no sea correcto el funcionamiento del sistema ya que depende de configuraciones de DirectX que van directamente relacionadas con la versin de Windows. En el apartado de conclusiones (2.3.) se comenta los resultados de la prueba de la aplicacin en otros sistemas operativos. Debido a que el proyecto est ntimamente ligado al uso de DirectX, y este a su vez funciona en el entorno Windows (son unas libreras desarrolladas por Microsoft), la aplicacin en ningn caso funcionar con una plataforma diferente a Windows.
-6-
Es el entorno de desarrollo empleado para la realizacin de la aplicacin (ilustracin 4). Concretamente la aplicacin est desarrollada con el lenguaje Visual C++, y se ha desarrollado una aplicacin MFC basada en un dilogo que permite un manejo sencillo de la misma.
Es un conjunto de libreras desarrolladas por Microsoft que permiten el desarrollo de utilidades de diferente ndole como pueden ser grficos, sonidos, y entre otras cosas, el control de los dispositivos Hardware del sistema, con lo que se ha empleado para el control del dispositivo capturador. Hemos utilizado concretamente entre todos los paquetes de libreras el denominado DirectShow que es el que se encarga de esta labor. Es necesario tener instaladas las libreras DirectX 9.0a (como mnimo) para la utilizacin de la aplicacin. Tiene un entorno de desarrollo (SDK) que contiene toda la documentacin, tutoriales, ejemplos y aplicaciones de inters, como por ejemplo GraphEdit, que es una aplicacin que hemos utilizado para verificar el correcto funcionamiento de la parte de la aplicacin relacionada con DirectShow. Concretamente se han desarrollado dos grafos DirectShow (explicacin ms detallada en captulo 3), uno para la grabacin de anuncios (grafo 2), y otro que va capturando de forma peridica la entrada de audio para despus ser comparada con los anuncios que tenemos almacenados (grafo 1).
-7-
Estos dos grafos antes de la programacin en el entorno del Visual Studio se han formado en la aplicacin GraphEdit que viene incorporada en el SDK de DirectX. Esta aplicacin te informa si la conexin entre dos filtros es posible, te da informacin sobre los filtros y tambin sobre los pines de cada filtro. En las ilustraciones 6 y 7 respectivamente se refleja el grafo 1 y 2 en la aplicacin GraphEdit.
-8-
CASO
CPU
Intel Centrino 1.4 GHz Intel P4 2.4 GHz Intel P4 2.6 GHz Intel P3 864 Mhz AMD K6-2 400 Mhz
MEM.
512 MB
S.O.
WIN. XP
TARJETA TV
Hauppauge WinTV USB
FM
SI
O.K. SI
1 2 3 4 5
256 MB
WIN. XP
Hauppauge WinTV USB Best Buy Easy TV Pinnacle PCTV PRO Hauppauge WinTV USB
SI
SI SI
SI
512 MB
WIN. XP
NO
256 MB
WIN. XP
NO
256 MB
WIN. 98
SI
SI
2.3.2. CONCLUSIONES.
Las pruebas van encaminadas a ver si se encontraba algn tipo de tarjeta en la que no funcionara la aplicacin. Se ha comprobado en los sistemas anteriores que teniendo las libreras de DirectX 9.0a (o superior) ha funcionado correctamente la aplicacin incluso
-9-
en Windows 98, pero el funcionamiento en este no era igual que en Windows XP. El funcionamiento ms adecuado se obtiene en el sistema operativo Windows XP, y se recomienda el uso de la aplicacin en este sistema operativo.
Clase incorporada al crear el proyecto de aplicacin MFC. No se ha modificado nada dentro de ella. En ella nace la aplicacin al ejecutarse y es esta clase la que abre el dilogo principal de la aplicacin, y la que devuelve el control al sistema cuando se cierra.
- 10 -
CRadioDlg.
Clase incorporada al crear el proyecto de aplicacin MFC. Es la clase principal del programa ya que es una aplicacin basada en dilogo. Es esta clase la que utiliza las dems clases que le sirven de apoyo para la labor a realizar. CAboutDlg.
Clase incorporada al crear el proyecto de aplicacin MFC. Es una clase derivada de la clase CDialog, y la utilidad que tiene es mostrarnos un dilogo sobre la versin del producto. CButtonST.
Clase utilizada para decoracin de la interfase. Tanto para poner iconos en los botones del dilogo, como para cambiar la forma del cursor cuando est encima de un botn. CMemDC.
Clase utilizada por la clase CButtonST y que implementa un contexto de dispositivo de memoria. CDialosint.
Clase que tiene como utilidad mostrarnos un dilogo para la sintonizacin del dispositivo. CConfiguracin.
Clase que tiene como utilidad mostrarnos un dilogo para la configuracin del dispositivo. Se pueden configurar algunos parmetros como son el tiempo de captura, el umbral y el formato de dato de entrada (TV o FM). CArchivos.
Clase que tiene como utilidad mostrarnos un dilogo para la eleccin de los anuncios que van a formar parte del proceso de deteccin.
- 11 -
_capstuff
Esta es la estructura de datos dedicada a almacenar las referencias a las interfaces utilizadas para el control de la tarjeta de TV/FM. Solo tendremos una estructura de datos de este tipo. Las interfaces que utiliza son explicadas en el apartado 3.1.2. de la memoria. En el cuadro de texto que contiene la ilustracin 8 se muestra la declaracin de esta estructura de datos.
struct _capstuff { ICaptureGraphBuilder2 *pBuilder; IAMCrossbar *pBar; IGraphBuilder *pFg; IMoniker *pMoniker; IAMTVTuner * pradio; IBaseFilter * pSrc, *pGrabberf, *pnull, *pWAVDest, *pWriter; ISampleGrabber * pGrabber; IMediaControl *pControl; IFileSinkFilter2 *pFileSink; }gcap;
Ilustracin 8: Estructura de datos capstuff.
archivo_wav
Estructura que contiene informacin sobre cada anuncio a detectar. Tendremos una tabla de estructuras de este tipo, donde el nmero de elementos de la tabla ser el de anuncios a detectar. El cuadro de texto que contiene la ilustracin 9 se muestra la declaracin de la estructura de datos.
- 12 -
struct archivo_wav { float *archivo; double *energia; int detectado; int fallo; int N1; long frecuencia; CString anuncio; int posibles_detecciones; };
Ilustracin 9: Estructura de datos archivo_wav.
Donde: archivo: apunta a las muestras del anuncio. energia: apunta al vector de energas del anuncio (explicado en apartado), sirve para una correcta normalizacin del proceso de correlacin. detectado: enumera las veces que se ha detectado, es informacin para el decisor. fallo: enumera las veces que ha fallado, es informacin para el decisor. N1: nmero de muestras del anuncio. frecuencia: frecuencia donde se grab el anuncio. anuncio: nombre del anuncio. posibles_detecciones: entero que refleja segn las condiciones de la deteccin (nmero de anuncios...) cuantas veces se puede detectar el anuncio en cuestin.
- 13 -
desee comparar. Se puede hacer la grabacin con cualquier otro programa con la restriccin de que tiene que ser en formato .wav.
Audio Capture
SampleGrabber
Null Renderer
A continuacin se hace una descripcin de los filtros que componen el grafo y que se ven representados en la ilustracin 10. Filtros: Audio Capture: filtro que representa la tarjeta capturadora. SampleGrabber: filtro DirectShow que almacena las muestras que van pasando por l en un buffer. Null Renderer: Necesario para que este grafo funcione. Hace las funciones de sumidero en este grafo.
Grafo 2: Grafo que sirve como herramienta de grabacin para obtener as las tramas de audio que van a ser comparadas con posterioridad.
Audio Capture
WavDest
File Writer
- 15 -
Filtros: Audio Capture: filtro que representa la tarjeta capturadora. WavDest: filtro DirectShow que sirve para poder grabar las muestras que vienen de la tarjeta a disco en formato WAV. File Writer: filtro DirectShow que representa el fichero de destino de las muestras.
- 16 -
3.1.2.2. ICaptureGraphBuilder2.
Interfaz usada para construir un grafo concretamente de tipo captura, es decir, donde intervenga un dispositivo de captura. Mtodos: SetFiltergraph: especifica un grafo en concreto. Sirve para relacionarlo con el Filter Graph Manager. FindInterface: busca en el grafo si alguno de los filtros implementan una determinada interfaz.
3.1.2.3. IBaseFilter.
Sirve para controlar los filtros. Todos los filtros DirectShow implementan esta interfaz. Lo primero es instanciar el filtro mediante el mtodo CoCreateInstance como se muestra de ejemplo a continuacin:
hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&gcap.pnull);
El caso que se refleja es el del filtro Null Renderer. Y despus de esto con el mtodo AddFilter se une el filtro al grafo. Este es el proceso para unir al grafo un filtro DirectShow, es decir, en nuestro caso de los 5 filtros diferentes que usamos, son todos menos el filtro de captura de audio que representa la tarjeta capturadora externa y como unirlo al grafo se explicar en el apartado 3.1.2.11..
3.1.2.4. IMediaControl:
Interfaz que proporciona mtodos para controlar el flujo de datos a travs del grafo. Mtodos: Run: para que empiecen a funcionar todos los filtros en el grafo. Stop: detiene el funcionamiento del grafo.
- 17 -
3.1.2.5. IAMCrossbar.
Es una interfaz que la implementa el filtro Analog Video Crossbar Filter, y que sirve para dirigir las seales de una fuente (tanto analgica como digital) hacia un dispositivo de captura. Se usa para conectar el dispositivo de captura con la tarjeta de audio del sistema y as poder controlar con la tarjeta de audio del sistema el proceso (las tarjetas de TV se unen directamente con la tarjeta de audio del sistema tanto en el caso de que sean tarjetas externas como internas). Lo que hacemos es activar el dispositivo capturador para que empiece a funcionar pero trabajamos con la tarjeta de audio interna del sistema ya que suele tener mejores propiedades de audio y trabaja con numerosos formatos. Mtodos: Route: conecta dos pines que se le pasa como parmetro.
3.1.2.6. IFileSinkFilter2.
Interfaz que es implementada por el filtro que representa el fichero donde se almacenan las muestras en el proceso de grabacin. Mtodos: SetMode: se le pasa como parmetro la etiqueta AM_FILE_OVERWRITE , e indica que el fichero se sobrescribir si antes exista uno de mismo nombre. SetFileName: para indicar el nombre del fichero de destino.
3.1.2.7. ISampleGrabber.
Interfaz que es implementada por el filtro SampleGrabber, que era el filtro encargado de almacenar las muestras capturadas en un buffer interno. Mtodos: SetBufferSamples: si se le pasa TRUE como parmetro comienza a almacenar en un buffer interno las muestras que van pasando por l. El tamao de dicho buffer se determina mediante la interfaz IAMBufferNegotiation (se comentar posteriormente).
- 18 -
GetCurrentBuffer: te da una copia de las muestras ms recientes que el filtro recibi, en un buffer de datos que le pasas como parmetro al mtodo.
3.1.2.8. IAMTVTuner.
Interfaz que proporciona mtodos para la sintonizacin del dispositivo. Mtodos: Put_Mode: para determinar que sintonizacin vamos a realizar, en el caso de FM se pasa como parmetro AMTUNER_MODE_FM_RADIO y en el caso de TV AMTUNER_MODE_TV. put_InputType: para determinar si la entrada de informacin viene por el cable o la antena. Put_Channel: para sintonizar a la frecuencia que queramos. Tiene tres parmetros. El que vamos a utilizar va a ser el primero (los otros dos sern siempre cero) y este en el caso de FM tiene que corresponderse con el valor de la frecuencia (Hz.) de la emisora deseada, y en el caso de TV con el canal correspondiente.
3.1.2.9. IAMStreamConfig.
Interfaz usada para conseguir el formato deseado de los datos , con ella se consigue capturar a 8 Khz., 8 bits por muestra, y un solo canal (mono). Al menos en el caso de la tarjeta de TV/FM empleada no funcionaba a ese formato, es decir, no tenamos el control suficiente para trabajar en ese formato y por eso trabajamos con la tarjeta interna de sonido del sistema. Mtodos: GetFormat: devuelve el formato de datos preferido o establecido de un determinado pin de salida. SetFormat: Establece un determinado formato para el pin de salida del dispositivo de captura usado.
- 19 -
3.1.2.10. IAMBufferNegotiation.
Interfaz usada para el control del buffer interno que almacena las muestras de la captura. Mtodos: SuggestAllocatorProperties: sugiere al pin determinado las propiedades preferidas para el buffer interno.
3.1.2.12. IPin.
Se usa para identificar los pines de los filtros y realizar una conexin entre ellos.
- 20 -
Mtodos: QueryDirection: devuelve la direccin del pin, es decir, si es un pin de salida o de entrada.
QueryInterface: mtodo que usa un elemento de IBaseFilter para adaptarse a una interfaz especfica.
void iniciacaptura();
Iniciasintonizacion: Rutina para configurar y encontrar correctamente la interfaz de sintonizacin IAMTVTuner. Tambin llama a las rutinas de lectura de frecuencias (o canales dependiendo del caso) que lee las frecuencias donde se desea hacer el proceso de deteccin del archivo frecuencias.cfg.
void iniciasintonizacion();
- 21 -
GetPin: rutina que sirve para obtener un pin de un determinado filtro. Hay que pasarle como parmetro adems del filtro correspondiente, en que direccin queremos buscar el pin, es decir, si es de salida o de entrada y un puntero a una referencia IPin donde te la rutina te devuelve el resultado.
void OnGrabaradio();
OnDeteccion: rutina que se ejecuta tras pulsar el botn DETECCIN del dilogo principal. Se encarga de preparar e inicializar el grafo de deteccin y adems la fase de establecimiento del proceso de deteccin. Este proceso est descrito ms detenidamente en el captulo 4.
void OnDeteccion();
OnSalir: rutina que se ejecuta tras pulsar el botn SALIR del dilogo principal. Se encarga de liberar todos los punteros de forma adecuada, detiene el grafo mediante el mtodo Stop de la interfaz IMediaControl y cierra la aplicacin.
void OnSalir();
OnSeldisp: rutina que se ejecuta tras pulsar el botn SELECCIONAR DISPOSITIVO del dilogo principal. Se encarga de seleccionar el dispositivo de captura que vamos a utilizar de la lista de dispositivos de captura que aparece en el dilogo principal de la aplicacin y que representa los dispositivos encontrados en el sistema, y lo aade al grafo, una vez hecho esto llama a la rutina iniciasintonizacion.
void OnSeldisp();
- 22 -
EnumFiltersWithMonikerToList: rutina que utiliza otras dos rutinas (EnumFiltersAndMonikersToList y AddFilterToListWithMoniker) para rellenar una lista con los dispositivos encontrados en el sistema. Se puede utilizar con muchos tipos de dispositivos, tiene tres parmetros, el primero es para pasarle un elemento de la interfaz ICreateEnum, el segundo es para indicarle qu tipos de dispositivos se quiere listar, y el tercero la lista de destino.
void OnArchivosAnuncios();
OnArchivosSalir: rutina que se ejecuta al pulsar el elemento SALIR del men ARCHIVOS. La accin que realiza es cerrar la aplicacin del mismo modo que lo hace el botn SALIR del dilogo principal.
void OnSalir();
OnConfigurarSintonizador: rutina que se ejecuta al pulsar el elemento SINTONIZADOR del men CONFIGURAR. Te muestra un dilogo donde puedes sintonizar el dispositivo capturador al canal deseado.
void OnConfigurarSintonizador();
OnConfiguracion: rutina que se ejecuta al pulsar el elemento CONFIGURACIN del men CONFIGURAR. Te muestra un dilogo donde puedes configurar ciertos aspectos como son el tipo de entrada (TV o FM), el tiempo de captura y el umbral.
void OnConfiguracion();
OnHelpVersin: rutina que se ejecuta al pulsar el elemento VERSION del men ACERCA DE. Te muestra un dilogo donde te da informacin acerca de la aplicacin.
void OnHelpVersin();
- 23 -
Ilustracin 10
4. Se van incorporando los filtros al grafo con el mtodo AddFilter. Incorporar un filtro a un grafo no significa que este conectado, es decir, todava no tiene ninguna funcionalidad, despus se tiene que conectar con otro filtro con el mtodo conecta en el orden deseado. Lo primero que se hace es unir el filtro al grafo con AddFilter, despus se configurara el filtro de manera conveniente a nuestras necesidades y por ltimo se conecta para que forme parte del camino del flujo de datos. Un ejemplo de este proceso se observa en
- 24 -
el cuadro de texto que contiene la ilustracin 13, donde se encuentra el proceso de conexin del grafo de deteccin (grafo 1).
// Primero se instancia el filtro hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&gcap.pGrabberf); hr = gcap.pFg->AddFilter(gcap.pGrabberf, L"Sample Grabber"); //Ahora a compartir el interfaz gcap.pGrabberf->QueryInterface(IID_ISampleGrabber, (void**)&gcap.pGrabber); //Configuramos adecuadamente el tipo de dato que va a llegar //para asegurarnos de que no haya problemas gcap.pGrabber->SetMediaType(pmt); //para activar el modo buffer se llama a SetBufferSamples hr = gcap.pGrabber->SetOneShot(FALSE); hr = gcap.pGrabber->SetBufferSamples(TRUE); //Falta el filtro Null Renderer //Primero creo el filtro hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&gcap.pnull); hr = gcap.pFg->AddFilter(gcap.pnull, L"Null Renderer"); //los conectamos conecta(gcap.pSrc,gcap.pGrabberf); conecta(gcap.pGrabberf,gcap.pnull); Ilustracin 13: Formacin Grafo DirectShow (2).
5. Hay ocasiones en las que queremos que algn filtro del grafo soporte algn tipo de interfaz particular y esto se hace con el mtodo QueryInterface. Se muestra en la ilustracin 14 un uso de este mtodo para hacer que el grafo contenga la funcionalidad de la interfaz IMediaControl.
6. Una vez que tengamos todo configurado y conectado solo queda indicarle al grafo que comience a funcionar y para ello se utiliza el mtodo Run de la interfaz IMediaControl, tal y como refleja la ilustracin 15. - 25 -
hr = gcap.pControl->Run();
Nombre_variable.SetIcon(ID_ICON);
3. Para cambiar el cursor cuando se este situado sobre algn botn se usa el mtodo SetBtnCursor de la siguiente forma.
Nombre_variable.SetBtnCursor(ID_CURSOR);
Nota: evidentemente para poder realizarlo tienes que tener importado en tu lista de recursos tanto el icono preciso como el cursor, y es su respectivo identificador el que se pasa como parmetro a los respectivos mtodos.
- 26 -
rxy (l ) = x ( n ) * y ( n l )
n
Tal y como se coment anteriormente la correlacin cruzada es un algoritmo que se le aplica a dos seales (x(n), y(n)). En la implementacin del algoritmo una de esas seales se va desplazando con respecto a la otra para generar los valores de la correlacin cruzada para cada valor del parmetro l, y en cada desplazamiento se calcula la suma de los productos entre las muestras de las dos seales que coinciden en ese momento. - 27 -
Para la implementacin de este algoritmo en nuestra aplicacin hemos adoptado por desplazar la ms pequea sobre la grande, donde la pequea es lo que se va capturando de forma peridica y la grande es el anuncio a comparar. Si la longitud de X(n) es N1, y la longitud de Y(n) es N2 (en nuestro caso N2<N1), el resultado de este proceso es otra seal de N2 + N1 -1 puntos. Este sera el resultado terico del proceso de correlacin cruzada, pero a la hora de la implementacin y por razones de eficiencia computacional el proceso no comprende las colas resultando solamente una seal de N2N1+1 puntos. Las colas son aquellas zonas donde no entran en la operacin todos los trminos de la seal ms pequea. Esto se ve reflejado en la ilustracin 8.
x(n)
y(n)
La ilustracin 16 refleja uno de los dos casos de colas, donde las primeras muestras de y(n) se multiplicaran por cero. Y el otro sera igual pero situada la seal y(n) al final de x(n). Ese vector de correlacin representa el resultado de la comparacin entre ambas seales, pero para hacer una interpretacin del mismo ms correcta es necesario una correcta normalizacin. Para conseguir esa normalizacin se divide cada uno de los coeficientes de correlacin por la raz cuadrada de las energas tal como refleja la siguiente
- 28 -
expresin, donde para calcular las energas solo se toman en cuenta los puntos que han intervenido en la suma de productos de las seales.
rxy ( l ) =
x(n) * y (n l ) Ex ( l ) * Ey
l = 0,1,..., N1 N 2
En nuestro proceso el valor de Ey corresponde con la suma del cuadrado de las muestras de la seal y(n) que es la seal que estamos capturando. Esta energa se mantiene constante para el clculo de la correlacin cruzada ya que los puntos de la seal y(n) siempre sern los mismos los que intervengan en el clculo. En el caso de Ex es un poco ms complejo ya que corresponde con la suma del cuadrado de las muestras de la seal x(n) que intervienen en el clculo, es decir, es la suma del cuadrado de N2 muestras dependiendo del desplazamiento de la seal y(n). Por lo tanto no es un valor constante y va a depender del desplazamiento de y(n) con lo que nos dar lugar a un vector de energas. Las expresiones de ambas energas se muestran a continuacin:
Ey =
N 2 1 n =0
y ( n) * y ( n)
N 2 1 n =0
Ex(l ) =
x(n + l ) * x(n + l )
l = 0,1,..., N1 N 2
Tras realizar esto hemos conseguido acotar el vector correlacin normalizado entre -1 y 1, con lo que ya estamos a disposicin de interpretar los resultados. Es evidente que cuanto ms cercanos estemos a 1 significar que las seales que han formado parte del proceso de correlacin se parecen ms. En la implementacin de este algoritmo se busca el mximo de los coeficientes del vector correlacin cruzada normalizada. Es este valor mximo el que vamos a comparar con un cierto valor que le denominamos umbral de la deteccin y es el que va a decidir si la deteccin ha sido correcta o no. En el caso de que haya sido correcto se puntualizar en el archivo de resultados y en una lista de anuncios detectados situada en el dilogo principal
- 29 -
de la aplicacin. Por lo tanto la lista mostrar todos los mximos de correlacin que superen el umbral.
- 30 -
Segn se ve en la expresin anterior el nmero de muestras que luego van a formar parte del algoritmo de correlacin es directamente proporcional a la frecuencia de muestreo. Un ejemplo de ese resultado se puede ver en la tabla 3 donde se encuentran los valores del nmero de muestras en funcin al tiempo de muestreo en el caso de un anuncio de 20 segundos.
Teniendo en cuenta que con el proceso utilizado para la deteccin el nmero de operaciones aumenta al cuadrado con el nmero de muestras es evidente que nos interesa la frecuencia de muestreo ms baja posible para conseguir nuestros objetivos. Con todo lo anterior la frecuencia de muestreo utilizada ha sido de 8 Khz. ya que aunque no permita una correcta reconstruccin de la seal en algunos casos, hemos comprobado mediante numerosas pruebas que es lo suficientemente buena como para que mediante la correlacin seamos capaces de detectar cuando se est emitiendo un determinado anuncio. Es evidente que sera mucho mejor poder trabajar con una frecuencia de muestreo mayor ya que as reduciramos la probabilidad de error del proceso pero debido a la cantidad de muestras que tiene tendra que ser un proceso que no trabajara en tiempo real.
- 31 -
Probabilidad de no deteccin: probabilidad de que no detecte nada cuando se este emitiendo un anuncio. Probabilidad de falsa alarma: probabilidad de que detecte un anuncio cuando no se este emitiendo.
Para tener valores aceptables de la probabilidad de error se debe tener un mnimo en el nmero de muestras, que implica un mnimo en el tiempo de captura. Segn se consult en la referencia [9], donde se hace un estudio estadstico de este caso, utilizando la funcin de distribucin Beta, llegando a la conclusin que para una correcta deteccin se necesitan
- 32 -
como mnimo 1000 muestras, con lo que el tiempo de captura era 125 mseg ( a una frecuencia de muestreo de 8 Khz. ). Este es un mnimo terico que procede de un estudio estadstico, se han realizado multitud de pruebas con otros tiempos de captura menores con el fin de poder mejorar en eficiencia computacional. El resultado de esas pruebas se encuentran en el apartado 4.4 de la memoria. Conforme se baja el tiempo de captura se tiene una mayor probabilidad de error pero se gana en eficiencia computacional. Es un parmetro que se queda de configuracin en la aplicacin (a diferencia de los tres anteriores que son fijos). Aunque el valor ms adecuado es el mnimo terico, en ocasiones el usuario puede optar por disminuir ese mnimo en busca de una optimizacin computacional, aunque esto no siempre ser conveniente (depender de los anuncios). En el apartado 4.4 se describe y analiza la eleccin de los tiempos de captura, describindose las numerosas pruebas realizadas y evaluando las conclusiones derivadas de las mismas.
- 33 -
detectados que esta subida no enmascara tambin las detecciones correctas). En el caso de que la deteccin no sea correcta con un umbral de 0,5 no se recomienda disminuirlo, ya que el nmero de falsas alarmas aumentar considerablemente. En este caso se recomienda usar un tiempo de captura mayor, y si ya estamos con 125 mseg. es recomendable volver a realizar la grabacin del anuncio. Debido a todo esto se decidi que fuera un parmetro que se pudiera modificar por parte del usuario final.
Lectura_anuncios: Rutina que realiza todo lo referente a la lectura de los anuncios seleccionados para la deteccin, y para ello se basa en las rutinas Leewav, calcula_vector_energia y
- 34 -
calcula_posibles_detecciones. Los almacena de modo adecuado dentro de la estructura de datos archivo_wav. Tambin se asegura si hay algn anuncio seleccionado y de no ser as te muestra el dilogo correspondiente para su seleccin.
void lectura_anuncios();
Leewav: Rutina que se le pasa como entrada el nombre del archivo a leer (solamente el nombre, pero se tiene que encontrar en el directorio ARCHIVOS), y te devuelve las muestras de ese archivo en un vector de float. Tambin se obtiene el nmero de muestras mediante un parmetro que se le pasa por referencia. Esta rutina controla la correcta lectura de archivos .wav sea cual sea su procedencia, ya que la cabecera de los mismos es diferente dependiendo de con que aplicacin se haya grabado el anuncio (en el anexo se aporta ms informacin sobre el formato WAV).
Calcula_posibles_detecciones: Rutina que calcula las posibles detecciones de un anuncio dependiendo de con qu parmetros se haga la prueba. Una mejor explicacin de lo que significa el nmero posible de detecciones de un anuncio se encuentra en el apartado 4.5. de la memoria.
Lectura_frecuencias: Rutina que hace todo lo necesario para la lectura de las frecuencias donde queremos realizar el proceso de deteccin. El usuario puede introducir las frecuencias deseadas mediante un fichero denominado frecuencias.cfg y que se encuentra en el directorio base de la aplicacin. Los detalles de cmo introducir esas frecuencias de modo correcto se encuentran en el apartado 5.4. de la memoria.
void lectura_frecuencias();
Lectura_cadenas_tv: Rutina que hace todo lo necesario para la lectura de las cadenas de TV (en el caso de que la aplicacin este configurada en modo TV). El usuario debe de introducir las cadenas deseadas en el fichero de configuracin frecuencias.cfg y que se encuentra en el directorio base de la aplicacin. Los detalles de cmo introducir la lista de canales en el fichero de
- 35 -
void lectura_canales_tv();
prueba_piloto: rutina que se encarga de realizar una correlacin con un anuncio de referencia (anuncio_piloto.wav) y as se calcula el tiempo de computacin para dicho anuncio. Ese tiempo se emplear posteriormente para el clculo del nmero de detecciones posibles por anuncio. Para medir estos tiempos se ha hecho uso de la librera time.h.
void prueba_piloto();
calcula_frecuencias_correlacion: rutina que se encarga de rellenar una tabla de long con las frecuencias (o cadenas) donde se debe de hacer el proceso de deteccin. Mediante el fichero frecuencias.cfg se introducen las frecuencias posibles, estas despus aparecen en el dilogo de seleccin de anuncios, y dependiendo de la seleccin se formar la tabla de frecuencias.
void calcula_frecuencias_correlacion();
OnTimer: Rutina que representa la periodicidad del proceso de deteccin. Esta rutina se ejecuta cada vez que vence el temporizador de la aplicacin. Como el temporizador se reinicia al final de la rutina se garantiza la periodicidad de la aplicacin sin llegar a ser un bucle infinito (que absorbera todos los recursos del sistema).
Cambiacanal: Rutina que sintoniza a la cadena de radio de FM o la cadena de TV (dependiendo del caso) que se le pasa como parmetro. En el caso de FM la frecuencia que se le pasa como parmetro debe de estar en Hz.
Correlacin: Rutina que calcula el valor mximo de la correlacin cruzada normalizada de dos seales que se le pasa como parmetro. Con el mximo calculado llama a la rutina decisor.
Decisor: Rutina que se encarga de comparar el valor mximo que se le pasa como parmetro con el umbral de deteccin, si es mayor llama a la rutina anota_resultado. Adems tiene un criterio de decisin basado en el nmero de detecciones posibles de cada anuncio que determinar si es el anuncio detectado o no. El algoritmo que sigue el proceso de decisin se describe en profundidad en el apartado 4.5. de la memoria.
Anota_resultado: Rutina que se encarga de reflejar en la lista del dilogo principal y en el fichero de resultado los anuncios detectados.
- 37 -
- 38 -
TIEMPO CAPTURA (SEG.) 0.125 0.100 0.09 0.08 0.075 0.07 0.06 0.05 0.04 0.03 0.025 0.02 0.01
TIEMPO COMPUTACIN (MSEG.) 2804 2244 2094 1802 1712 1582 1362 1141 931 701 590 481 251
El tiempo de captura mayor escogido es el ptimo segn el proceso estadstico que ya cit en el apartado 4.2.4. En el caso de que el usuario quiera conocer el tiempo de computacin en un determinado caso puede obtener una aproximacin eligiendo el tiempo de captura deseado y haciendo una simple regla de tres entre la suma de los tiempos de los anuncios seleccionados, el tiempo de computacin para el tiempo de captura seleccionado (de la tabla anterior) y los 28 segundos que es la duracin aproximada del anuncio de referencia. Es importante saber el tiempo que tarda el proceso de forma peridica para un correcto uso del detector de anuncios. Si por ejemplo tenemos el anuncio de referencia y nos ponemos a detectarlo en una sola cadena con 0,125 segundos sabemos por la tabla anterior que el proceso tarda en dar una pasada casi 3 segundos. El sistema est diseado para que refleje los resultados tanto en la lista como en el archivo cada vez que lo detecte. Como estamos en una sola cadena y el anuncio dura unos 28 segundos el sistema deber de detectarlo unas 9 (o 10) veces de media. Con lo que si el usuario maneja este tipo de informacin implcita en el proceso tendr un mejor criterio de comprobacin para la deteccin. Si en el caso del ejemplo anterior solo aparece un detectado en pantalla, es muy probable que solo sea una falsa alarma, en cambio si aparecen ms pues se puede certificar que es una deteccin correcta. Adems es importante conocer el tiempo del proceso en cada caso particular para verificar si es factible o no la herramienta desarrollada. Para ello se calcula el tiempo de computacin tal y como se ha explicado anteriormente (teniendo en cuenta todos los anuncios que formen parte del proceso). Para que sea factible el proceso el resultado debe ser menor que la duracin del
- 39 -
anuncio ms corto que forme parte del proceso. El clculo se refleja en la siguiente expresin.
Donde: T.C.T.(seg.) : El tiempo de computacin total del proceso. T.T.Anuncios(seg.) : El tiempo total de los anuncios seleccionados en el proceso. T.C.(seg.): El tiempo de computacin escogido de la tabla de la ilustracin 11 dependiendo del tiempo de captura seleccionado y dividido por 1000 para expresarlo en segundos.
El tiempo de computacin (T.C.) depende del ordenador en el que se est trabajando. Este tiempo es necesario para calcular el nmero posible de detecciones de un determinado anuncio (ver apartado 4.5) que es un parmetro que utiliza el decisor en su algoritmo. Debido a esto se calcula ese tiempo en la fase de establecimiento del algoritmo de deteccin.
- 40 -
Esta ilustracin es reflejo de la prueba realizada para calcular los tiempos de conmutacin. Dicha prueba consiste en hacer una grabacin donde intervenga la conmutacin de cadenas, para despus observar los resultados en MATLAB. En este caso la prueba ha consistido en sintonizar una emisora de FM y despus pasar a un canal de TV. Basndonos en la grfica el nmero de muestras que dura el periodo de conmutacin son 54000 45000 = 9000, que con una frecuencia de muestreo de 8 Khz. que es con la que trabajamos nos da como resultado un tiempo de conmutacin de ms de un segundo. Esta prueba se ha secundado con la medicin del tiempo en la aplicacin resultando un tiempo de 1,3 segundos. Son tiempos de conmutacin excesivos y por eso la aplicacin no est diseada para trabajar conmutando emisoras de FM y TV, en una misma ejecucin. En el caso de la conmutacin en un mismo tipo de entrada cadena de radio o TV (segn sea el caso) la representacin de MATLAB se ilustra en la ilustracin 19. El experimento es el mismo con los mismos tiempos y solo cambiando la sintonizacin dependiendo del caso, as que debera de apreciarse el periodo de conmutacin en las mismas muestras aproximadamente, y la figura refleja que esa zona es casi imperceptible.
- 41 -
Y mediante la medicin de tiempos en la aplicacin da como resultado el tiempo de 0,1 segundos que son 800 muestras y por eso es casi imperceptible. La diferencia entre los dos experimentos realizados es notable y por ello se ha optado por la solucin de desarrollar la aplicacin para que solo permita la deteccin de un grupo de canales de radio, o de canales de TV pero no entremezclados entre s.
- 42 -
Es evidente que la eleccin de un tiempo de captura menor va a aumentar la probabilidad de error, pero el tiempo de computacin va a disminuir considerablemente y va a permitir una mayor seleccin de anuncios y de cadenas. En cada prueba se especifica la duracin del anuncio que se utiliza y la duracin de la prueba. El parmetro que va a ir variando a lo largo de las pruebas es el tiempo de captura. El umbral de deteccin permanecer fijo a lo largo de las pruebas y su valor es 0,5. Las pruebas pretenden ser una orientacin de cara al usuario para un ajuste posterior del umbral de deteccin. Adems se reflejar en una tabla los resultados ms importantes de la prueba que son:
Duracin del anuncio: representa la duracin del anuncio utilizado para la prueba. Duracin de la prueba: el tiempo que ha estado la aplicacin detectando. Deteccin: se anotar en las tablas los valores del mximo de la correlacin cuando se detecte. Tambin se reflejar el nmero de detecciones. Nmero de correlaciones: representa el nmero de correlaciones que se han realizado a lo largo de la duracin de la prueba. No deteccin: se anotar el valor del mximo de la correlacin cuando no lo detecte. En el caso de detectarlo siempre se anotar el valor ms pequeo de ellos como reflejo de lo ms cercano al fallo en la deteccin. Falsa alarma: se anotarn el nmero de falsas alarmas ocurridas a lo largo del proceso. Adems se anotar el mayor de todos esos valores.
Se van a clasificar las pruebas como pruebas de FM y de TV, y dentro de estas se dividirn en pruebas correspondientes a anuncios grabados y detectados en la misma cadena y en las que la cadena es diferente.
- 43 -
diferentes los resultados que se exponen corresponden a pruebas siempre con el mismo anuncio.
TABLA RESULTADO PRUEBAS (125 MSEG) DURACIN PRUEBA (SEG.) 3600 segundos DURACIN ANUNCIO (SEG.) 28 segundos NMERO CORRELACIONES 1272 DETECCIN: 0.719474 VALORES DETECTADOS 0.745797 0.838725 0.735068 0.644228 0.695858 0.785313 0.629237 0.555057 0.579072 NO DETECCIN: VALORES NO DETECTADOS FALSA ALARMA: TOTAL 0 VALOR MAYOR 0.418618 COMENTARIOS: Son unos resultados muy buenos. En una hora de grabacin no se ha obtenido ninguna falsa alarma. Esto no significa que no haya nunca falsas alarmas con estos parmetros, pero s es un reflejo de la baja probabilidad de error que tiene el proceso en este caso y que si aparece una falsa alarma esta se presentar con toda seguridad de forma aislada y con valores cercanos a 0,5.
Tabla 5: Prueba FM 125 mseg.
- 44 -
TABLA RESULTADO PRUEBAS (100 MSEG) DURACIN PRUEBA (SEG.) 4800 segundos DURACIN ANUNCIO (SEG.) 28 segundos NMERO CORRELACIONES 2090 DETECCIN: 0.675718 VALORES DETECTADOS 0.50237 0.735822 0.541747 0.583228 0.611289 0.796734 0.678963 NO DETECCIN: 0.44814 VALORES NO DETECTADOS FALSA ALARMA: TOTAL 6 VALOR MAYOR 0.544701 COMENTARIOS: El nmero de falsas alarmas no es elevado. Hay que tener en cuenta que se han presentado de forma aislada y espordica en los 80 minutos de deteccin. Aunque los resultados no son tan buenos como los anteriores, pero el proceso sigue siendo factible con el umbral de 0,5.
- 45 -
4.4.3.1.1.3. 90 MSEG:
TABLA RESULTADO PRUEBAS (90 MSEG) DURACIN PRUEBA (SEG.) 3600 segundos DURACIN ANUNCIO (SEG.) 27 segundos NMERO CORRELACIONES 1670 DETECCIN: 0.541926 VALORES DETECTADOS 0.694484 0.680579 0.617272 0.563161 0.794023 0.580843 0.657791 NO DETECCIN: 0.34585 VALORES NO DETECTADOS 0.30279 0.402349 0.487067 0.435318 FALSA ALARMA: TOTAL 1 VALOR MAYOR 0.545953 COMENTARIOS: Demasiados valores no detectados. Esto empieza a ser un comportamiento no deseado. Las falsas alarmas se quedan en una buena proporcin.
- 46 -
4.4.3.1.1.4. 80 MSEG:
TABLA RESULTADO PRUEBAS (80 MSEG) DURACIN PRUEBA (SEG.) 3600 segundos DURACIN ANUNCIO (SEG.) 28 segundos NMERO CORRELACIONES 1832 DETECCIN: 0.79075 VALORES DETECTADOS 0.779303 0.730766 0.773051 0.574557 0.55876 0.514566 0.503984 NO DETECCIN: Todos los dems son no detectados. VALORES NO DETECTADOS En torno a 7 veces. FALSA ALARMA: TOTAL 10 VALOR MAYOR 0.554896 COMENTARIOS: Los resultados han empeorado considerablemente con respecto a los anteriores. Se tienen demasiadas falsas alarmas. Lo que es ms preocupante es la gran probabilidad de no deteccin.
- 47 -
4.4.3.1.1.5. 75 MSEG:
TABLA RESULTADO PRUEBAS (75 MSEG) DURACIN PRUEBA (SEG.) 3600 segundos DURACIN ANUNCIO (SEG.) 1895 segundos NMERO CORRELACIONES 1956 DETECCIN: 0.546275 VALORES DETECTADOS 0.559874 NO DETECCIN: Todos los dems son no detectados. VALORES NO DETECTADOS En torno a 14 veces. FALSA ALARMA: TOTAL 2 VALOR MAYOR 0.566606 COMENTARIOS: Habra fallado en la deteccin alrededor de 14 veces, lo cual es demasiado. Debido a estos resultados se concluyen en este tiempo de muestreo las pruebas de FM en misma cadena.
- 48 -
- 49 -
TABLA RESULTADO PRUEBAS (125 MSEG) DURACIN PRUEBA (SEG.) 3600 segundos DURACIN ANUNCIO (SEG.) 27 segundos NMERO CORRELACIONES 1384 DETECCIN: 0.798555 VALORES DETECTADOS 0.751583 0.841755 0.776946 0.872686 0.794023 0.870426 0.809763 0.824234 0.859476 NO DETECCIN: VALORES NO DETECTADOS FALSA ALARMA: TOTAL 1 VALOR MAYOR 0.561273 COMENTARIOS: Se refleja un mejor comportamiento que en la prueba de FM, esto puede ser debido a que la calidad de la seal que llega por la antena de TV es mejor que la de FM. Viendo los resultados de las detecciones se observa que se podra subir un poco ms el umbral (tal vez a 0.55 o 0.6) y as disminuiramos la probabilidad de error sin que afecte demasiado a la probabilidad de deteccin.
- 50 -
TABLA RESULTADO PRUEBAS (100 MSEG) DURACIN PRUEBA (SEG.) 3600 segundos DURACIN ANUNCIO (SEG.) 28 segundos NMERO CORRELACIONES 1567 DETECCIN: 0.734606 VALORES DETECTADOS 0.878421 0.815686 0.855235 0.749646 0.863439 0.733144 0.850438 0.753155 0.813936 0.797073 0.85384 NO DETECCIN: VALORES NO DETECTADOS FALSA ALARMA: TOTAL 26 VALOR MAYOR 0.641732 COMENTARIOS: El nmero de falsas alarmas es ms elevado que en el caso de la radio. Se ha cambiado de anuncio con respecto a la prueba de 125 porque se ha dejado de emitir el anterior. Nos ha dado muchas falsas alarmas pero por el contrario nos da muy buenas propiedades de deteccin. Las falsas alarmas han aparecido de forma espordica y con valores cercanos a 0,5 con lo que son fcilmente descubiertas. Viendo los resultados de los valores detectados tal vez sea interesante subir un poco el umbral de deteccin para corregir as las falsas alarmas, ya que los valores detectados estn muy por encima del umbral (0,5).
Tabla 11: Prueba TV 100 mseg.
- 51 -
4.4.3.2.1.3. 90 MSEG.
TABLA RESULTADO PRUEBAS (90 MSEG) DURACIN PRUEBA (SEG.) 3600 segundos DURACIN ANUNCIO (SEG.) 28 segundos NMERO CORRELACIONES 1680 DETECCIN: 0.563848 VALORES DETECTADOS 0.797944 0.707956 0.813583 0.687222 0.777917 0.816483 0.631247 0.82167 0.711654 0.794637 0.769021 0.708772 0.763509 NO DETECCIN: VALORES NO DETECTADOS FALSA ALARMA: TOTAL 22 VALOR MAYOR 0.694682 COMENTARIOS: Sigue habiendo muchas falsas alarmas. Se refleja un comportamiento ms desfavorable que la prueba anterior debido a que los valores detectados son menores que en 100 mseg. y el mayor valor de falsa alarma encontrado es mayor que el de 100 mseg. En comparacin con su anlogo en FM ofrece mejores resultados ya que aunque tiene ms falsas alarmas pero la deteccin aporta resultados mucho ms favorables (no tiene ningn valor no detectado).
Tabla 12: Prueba TV 90 mseg.
- 52 -
4.4.3.2.1.4. 80 MSEG.
TABLA RESULTADO PRUEBAS (80 MSEG) DURACIN PRUEBA (SEG.) 3600 segundos DURACIN ANUNCIO (SEG.) 28 segundos NMERO CORRELACIONES 1832 DETECCIN: 0.789809 VALORES DETECTADOS 0.850341 0.745543 0.660441 0.711634 0.793488 0.75766 0.632259 0.732108 0.742045 0.557095 0.513547 0.669168 0.786232 0.701513 0.61781 NO DETECCIN: 0.470368 VALORES NO DETECTADOS FALSA ALARMA: TOTAL Alrededor de 50 VALOR MAYOR 0.670315 COMENTARIOS: Se tienen muchas falsas alarmas aunque se presentan de manera espordica. La deteccin sigue siendo buena aunque con valores muy pequeos y cercanos a los valores de las falsas alarmas.
- 53 -
4.4.3.2.1.5. 75 MSEG.
TABLA RESULTADO PRUEBAS (75 MSEG) DURACIN PRUEBA (SEG.) 3600 segundos DURACIN ANUNCIO (SEG.) 28 segundos NMERO CORRELACIONES 1956 DETECCIN: 0.889612 VALORES DETECTADOS 0.894542 0.859036 0.891163 0.889624 0.938044 0.927093 0.890967 0.868901 0.827815 0.817964 0.926623 0.886618 0.898926 0.823316 NO DETECCIN: VALORES NO DETECTADOS FALSA ALARMA: TOTAL Alrededor de 100 VALOR MAYOR 0.739362 COMENTARIOS: El nmero de falsas alarmas es preocupante. An as el decisor las interpreta como falsas alarmas. Pero si se trabajara con ms anuncios habra problemas. Como los resultados de deteccin son muy altos hay que ir pensando en subir el umbral de deteccin.
- 54 -
4.4.3.2.1.6. 70 MSEG.
TABLA RESULTADO PRUEBAS (70 MSEG) DURACIN PRUEBA (SEG.) 3600 segundos DURACIN ANUNCIO (SEG.) 28 segundos NMERO CORRELACIONES 2183 DETECCIN: 0.775853 VALORES DETECTADOS 0.873107 0.848691 0.68619 0.750697 0.586971 0.787503 0.729053 0.776796 0.694129 0.764154 0.682163 0.771405 0.765666 0.74415 0.645923 0.727603 NO DETECCIN: VALORES NO DETECTADOS FALSA ALARMA: TOTAL Alrededor de 150 VALOR MAYOR 0.739362 COMENTARIOS: Aunque la deteccin sigue siendo correcta, el nmero de falsas alarmas es muy grande, adems ha fallado incluso una vez con el decisor, lo que quiere decir que se han presentado una vez de forma contigua. Adems los valores de deteccin no son muy altos, con lo que no se solucionara el problema subiendo el umbral de deteccin. Debido a todas estas razones se finalizan aqu las pruebas realizadas con la TV.
Tabla 15: Prueba TV 70 mseg.
- 55 -
El comportamiento de la radio FM y de la TV son diferentes tal y como reflejan los resultados. En la radio se pararon las pruebas porque no se producan de correlacin cuando se emita el anuncio, en cambio en la TV debido al enorme nmero de falsas alarmas. Esto puede ser debido a la calidad de seal de cada una de las fuentes que llega a la tarjeta. Se han hecho pruebas con otros anuncios en FM para ver si la tendencia era la misma en cuanto a probabilidad de no deteccin, y se ha comprobado que se asemeja bastante a los resultados obtenidos en la TV donde se detectaban con grandes valores y tena ms falsas alarmas. Con lo que se concluye que si la seal de entrada es correcta (tanto FM como TV) y las grabaciones tambin, el patrn de resultados se asemeja mucho a los resultados aportados en las pruebas de TV. En las pruebas donde se reflejen valores muy altos (por ejemplo en TV con el anuncio de las pruebas anteriores) es recomendable subir el nivel del umbral por ejemplo a 0,6 ya que esto reducira considerablemente el nmero de falsas alarmas sin enmascarar las detecciones. Mientras sea posible siempre se recomienda usar la aplicacin con tiempo de captura 125 mseg. En ambos casos la deteccin en cadenas con anuncios obtenidos de otra diferente ha sido errnea. La grabacin del anuncio que forme parte del proceso de deteccin debe ser correcta, por ejemplo no debe incluir los silencios de detrs ni de delante. Es importante esto ya que esos silencios son una fuente de falsas alarmas. La forma del anuncio, si tiene o no muchos silencios, o por ejemplo una meloda de fondo, hace que tenga ms falsas alarmas o menos y de ah que la configuracin de los parmetros de la aplicacin
- 56 -
est pensada para hacerla cada usuario de modo particular a sus necesidades.
El anuncio usado en las pruebas de FM aportaba muy buenos resultados de falsas alarmas, ya que se han comprobado con otros anuncios que el nmero de falsas alarmas aumenta con respecto a lo que reflejan las pruebas, asemejndose bastante a las pruebas de TV. Con todo lo anterior se conluye que debido a que el patrn general es el que reflejan los resultados presentados en las pruebas de TV, la causa principal de no disminuir an ms el tiempo de captura es debido a las falsas alarmas y a que los valores obtenidos de falsas alarmas conforme vamos reduciendo los tiempos de captura se van asemejando a los valores de deteccin.
4.5. DECISOR.
La aplicacin muestra tanto en el dilogo principal como en el archivo todos los resultados que tengan un valor mximo mayor que el umbral de deteccin. A priori se desconoce si los resultados pertenecen a una falsa alarma o es una deteccin correcta. Ya se ha comentado que para discernir una falsa alarma de una deteccin correcta hay que utilizar ms informacin como puede ser el valor mximo del proceso de correlacin (no es lo mismo una deteccin por 0,55 que por 0,8), o el nmero de detecciones correlativas ya que las falsas alarmas se suelen presentar de forma aislada. Para entender como trabaja el decisor y cules son sus lmites hay que introducir algunos conceptos:
Nmero de detecciones posibles por anuncio: Es el nmero de pasadas que le da tiempo a hacer a la aplicacin en la duracin de un determinado anuncio. Para ello se calcula el tiempo de computacin del proceso total (apartado 4.4.1.) y dividimos por este la duracin de cada uno de los anuncios. El cociente nos da el nmero de detecciones posibles para cada anuncio.
- 57 -
Es cuando el nmero de detecciones posibles para algn anuncio que forme parte del proceso de deteccin sea 1.
Ya se ha comentado y se ha reflejado en los resultados de las pruebas que las falsas alarmas aparecen normalmente de forma espordica, separadas entre s y con valores cercanos al umbral. Se va a emplear la informacin de que las falsas alarmas aparecen separadas entre s como criterio para diferenciar de algn modo una deteccin correcta de una falsa alarma. En esto se basa el decisor, y por eso no es recomendable tener la aplicacin funcionando al lmite de sus posibilidades ya que en ese determinado anuncio donde el nmero de detecciones posibles sea 1, no se puede usar la informacin de dos detecciones consecutivas porque solo se da una posible deteccin de ese determinado anuncio. En estos casos, cuando la aplicacin trabaje al lmite de sus posibilidades en algn anuncio, aquel anuncio no pasar por el algoritmo de decisin, solamente si el valor sale mayor que el umbral se apuntar en la lista y el archivo, pero ser tarea del usuario el comprobar el valor mximo de la correlacin en el fichero para determinar si ha sido una deteccin correcta o por el contrario una falsa alarma. Por esta razn se recomienda no usar la aplicacin al lmite de sus posibilidades ya que pierde mucha fiabilidad en la deteccin. El algoritmo del decisor se basa en la aparicin de forma aislada de las falsas alarmas para distinguir estas de las detecciones correctas. Hay que calcular para cada anuncio el nmero de detecciones posibles segn el caso. Si para algn anuncio este nmero de detecciones sale uno, entonces estaremos trabajando al lmite con ese anuncio y no se ejecutar sobre l el proceso de deteccin. La idea consiste en que al menos se pueda detectar el anuncio dos veces, as si tenemos dos consecutivas ser considerado una deteccin. La condicin que sigue es menos restrictiva y consiste en que se detecte la mitad de las veces posibles pero lo que pasa es que si las veces posibles son dos entonces estaramos en un caso similar al lmite y por eso en ese caso la condicin es mucho ms restrictiva. En el caso de que el decisor finalice el proceso con el resultado de deteccin correcta se escribir ANUNCIO DETECTADO, tanto en el dilogo principal como en el archivo de resultados.
- 58 -
Una mejor descripcin del algoritmo de decisin se encuentra en el diagrama de flujo de la ilustracin 20:
DECISOR
SI
>umbral?
NO
Fallo=0 Detectado=0
FIN
Umbral: valor con el que se compara el mximo del vector de correlacin. Fallo: variable que tiene cada anuncio (en la estructura archivo_wav) y que enumera el nmero de veces que el mximo del vector de correlacin es menor que el umbral. Detectado: variable que tiene cada anuncio y que enumera el nmero de veces que ha sido detectado (mximo mayor que el umbral). Condicin: se elabora una condicin que consiste en comprobar si el nmero de detecciones ha sido mayor que el nmero de detecciones
- 59 -
posibles de ese anuncio dividido entre dos (en el caso de que no salga entero se toma el entero superior ms cercano). Excepto en el caso en que el nmero de detecciones posible sea dos donde se compara con el nmero de detecciones posibles (2).
- 60 -
Esta es la pantalla principal de la aplicacin. Tal como se refleja en la ilustracin 21 tiene 4 botones, dos listas de datos, y un men. Comentaremos el men ms adelante en el apartado 5.2.
- 61 -
En la lista DISPOSITIVOS DE CAPTURA aparecen listados los dispositivos capturadores que estn presentes en el sistema. En el caso de que no aparezca aqu ninguno la causa podra ser de que la tarjeta capturadora no este instalada correctamente. En el caso de la ilustracin se ve en la lista dos elementos, el primero corresponde a la tarjeta interna de audio del PC y el segundo a la externa ya descrita en el captulo 2. Como se explic anteriormente la frecuencia de muestreo para los dos procesos era de 8 Khz., por lo tanto el dispositivo que se seleccione debe ser capaz de trabajar a dicha frecuencia. Como regla se recomienda seleccionar la tarjeta interna del PC ya que se ha comprobado que se tiene un mejor funcionamiento de la aplicacin porque se tiene ms control sobre ella. En el caso de la tarjeta usada para el desarrollo del proyecto no funcionaba correctamente a una frecuencia de muestreo de 8 Khz. En el caso de tener una tarjeta de TV (sin FM) debera de aparecer en la lista solamente la tarjeta interna de audio del PC aunque se han comprobado en otros sistemas que a veces aparece tambin el mdem (u otros dispositivos desconocidos), y se seleccionara la tarjeta de sonido. Una vez que se selecciona se pulsa el botn SELECCIONAR DISPOSITIVO y entonces de momento se debera de escuchar algo (aunque sea solo ruido) de no ser as pulsa el botn SALIR de la aplicacin. Entonces ejecuta el programa que viene incorporado con la tarjeta capturadora, en el caso de no encontrarlo comprueba si hay que instalarlo y tras esto lo ejecutas. Despus de ejecutarlo y comprobar que funciona correctamente cierra el programa y vuelve a ejecutar la aplicacin de deteccin.
5.2. MENU.
En este apartado se hace una descripcin del men incorporado al dilogo. Los elementos que lo conforman estarn disponibles segn convenga, es decir, que estarn habilitados los submens en funcin al estado en que se encuentre la aplicacin. Este tiene tres elementos como se ve en la ilustracin 20 que son: 5.2.1. Archivos.
- 62 -
Que consta de dos elementos a su vez tal como se refleja en la ilustracin 22: 5.2.1.1. Anuncios. Al seleccionar este elemento sale un dilogo donde se seleccionan los anuncios que queremos detectar (ilustracin 23). Cada anuncio va asociado a una frecuencia que es la frecuencia en la que se grab el anuncio y es en esta frecuencia donde se debe de usar para la deteccin en caso de que queramos un funcionamiento correcto de la aplicacin (tal y como se comprob en las pruebas realizadas en el apartado de la memoria 4.4.). Para ello se crea previamente una carpeta llamada ARCHIVOS dentro del directorio base donde est el ejecutable y ah tenemos que almacenar los archivos .wav que queremos como referencia para la deteccin. Se selecciona un archivo y se asocia a una frecuencia. Las frecuencias salen en un desplegable y se corresponden con las frecuencias introducidas en el fichero frecuencias.cfg. Tras seleccionarlo se pulsa en AADIR que provoca que el sistema almacene la informacin y adems borra de la lista de anuncios el anuncio escogido. Para terminar de elegir las frecuencias se pulsa en el botn SALIR.
- 63 -
5.2.1.2. Salir. Cierra la aplicacin. Tiene el mismo efecto que el botn SALIR del dilogo principal. 5.2.2. Configurar. Este men tiene dos elementos tal como se refleja en la ilustracin 24. A continuacin se hace una descripcin ms detallada de ambos elementos.
- 64 -
5.2.2.1. Sintonizador. Al seleccionar este elemento sale un cuadro de dilogo como el que refleja la ilustracin 25 y que sirve para sintonizar la cadena de radio o TV.
Su uso es para la tarea de grabacin debido a que en el caso de la deteccin la introduccin de las frecuencias con las que se trabajara ser a partir de un fichero como se explicar ms adelante. En este caso y al igual del dilogo explicado anteriormente se pulsa en ACEPTAR en el caso de que se quiera que se sintonice adecuadamente y en CANCELAR en caso contrario. Hay que introducir las frecuencias en Hz. en el caso de FM o el canal de TV en su defecto. El caso de introducir una cantidad no vlida est controlado por el sistema. Es un submen que estar disponible despus de seleccionar el dispositivo de captura. 5.2.2.2. Configuracin. Al seleccionar este elemento aparece un dilogo secundario como el que se muestra en la ilustracin 26.
- 65 -
Tal como refleja la ilustracin este dilogo sirve para cambiar el tipo de entrada FM/TV y adems los parmetros tiempo de captura y umbral. Tiene por defecto que se seleccione FM, 0.125 seg. para el tiempo de captura y 0.5 para el umbral de deteccin. El funcionamiento es semejante a los dilogos anteriores en cuanto al funcionamiento de los botones. Hay que tener en cuenta que si se quiere cambiar el tipo de entrada o el tiempo de captura hay que hacerlo antes de seleccionar el dispositivo. 5.2.3. Acerca De. Solo tiene un elemento que es VERSION y al seleccionarlo nos muestra el dilogo de informacin acerca del producto mostrado en la ilustracin 27.
- 66 -
5.3. GRABACIN.
Una vez seleccionado el dispositivo de captura tal y como se explic en el punto 5.1. se debe de sintonizar el sistema adecuadamente tal y como se explico en el men CONFIGURACIN. Tras esto se pulsa en el botn GRABAR y te sale un dilogo estndar de salvar un archivo en el entorno Windows (ilustracin 28). El directorio debe de ser ARCHIVOS en el directorio base de la aplicacin y no hay ninguna restriccin en cuanto al nombre del archivo. Una vez aceptado esto y si el dispositivo de captura que hemos seleccionado es adecuado, empezar la grabacin y para terminarla solo hay que pulsar el botn SALIR. Es muy probable que aparezca un error cuando se va a emplear la aplicacin para realizar una grabacin. Este error es debido a que se est usando el filtro WavDest en el grafo de grabacin y este filtro no est registrado en el sistema. La explicacin de cmo solucionar este problema se encuentra en el apartado 5 del anexo 1.
- 67 -
5.4. DETECCIN.
Al igual que en el proceso de grabacin hay que seleccionar el dispositivo de captura tal y como se ha descrito en el punto 5.1. La aplicacin utiliza un archivo llamado configuracin.cfg para conocer las cadenas a las que se quiere hacer el proceso de deteccin. Con lo que antes de hacer ninguna deteccin hay que rellenar ese archivo convenientemente. Para ello se abre el bloc de notas (o cualquier otro editor) y se escriben las cadenas deseadas una en cada lnea tal y como refleja la ilustracin 29. En el caso de ser cadenas de TV es del mismo modo.
- 68 -
Tras esto se guarda el archivo con nombre configuracin.cfg en el directorio base de la aplicacin. El sistema controla que las cadenas introducidas sean vlidas (en ambos casos tanto en FM como en TV). La ilustracin 29 refleja el caso de FM, pero el caso de TV es semejante pero utilizando los canales de TV. Ahora se seleccionan los anuncios que van a detectarse mediante el men ANUNCIOS dentro de ARCHIVO. Por ltimo se pulsa el botn DETECTAR. En el caso de pulsar el botn DETECTAR sin haber seleccionado ningn anuncio aparece el dilogo de seleccionar anuncios automticamente. Para parar la aplicacin se pulsa en SALIR. Los resultados de la deteccin se observan en la lista ANUNCIOS DETECTADOS donde aparece primero la hora, despus el anuncio y por ltimo la frecuencia a la que fue detectado (ilustracin 30). Es importante destacar que esto no tiene porque ser detecciones correctas, tambin pueden corresponderse a falsas alarmas, es el decisor (apartado 4.5 de la memoria) el que decidir si es una deteccin correcta y si es as apuntar tanto en la lista como en el fichero que el anuncio ha sido detectado, en la ilustracin 31 se refleja como resultara en el fichero de resultados (en la lista sera semejante).
- 69 -
Es posible de que aparezcan dos veces seguidas indicndonos ANUNCIO DETECTADO, pero es debido al algoritmo del decisor. Con que salga una es suficiente para interpretarlo como una deteccin correcta. Aunque no aparece la hora de la deteccin es la misma que la anterior entrada, que sera la de arriba en el caso del archivo y la de debajo en el caso de la lista en el dilogo principal. El fichero generado se llama resultado.txt y es donde se escriben los resultados. Este fichero no borra los resultados anteriores y en el caso de que la aplicacin no lo encuentre genera uno nuevo, por lo que una opcin para tener los resultados almacenados por das es al final del da quitar el fichero del directorio base de la aplicacin.
- 70 -
lnea de entrada pero no ajustarla al mximo ya que se distorsionara la captura de sonido. Adems es conveniente quitar el micrfono ya que puede ser que aumente el ruido de las grabaciones. Esto se refleja en la ilustracin 32:
Ilustracin 32: Configuracin sonido del sistema. 2. ELECCIN TIEMPO CAPTURA: como ya se ha comentado a lo largo de la memoria el tiempo de captura es un parmetro ntimamente ligado al tiempo de computacin y a la probabilidad de error del sistema. Lo ideal es que el tiempo de captura sea de 125 mseg. (que es el valor predeterminado), pero hay ocasiones en los que ese tiempo de captura no es factible debido a su gran tiempo de computacin. En estos casos habr que reducirlo hasta donde sea conveniente pero recordando siempre que esto afectar al correcto funcionamiento del sistema (tendr una probabilidad de error mayor). La comprobacin de que un tiempo de captura es factible para un determinado proceso se encuentra en el apartado tiempo de computacin (4.4.1.). 3. ELECCIN UMBRAL DE DETECCIN: despus de elegir el tiempo de captura se elige el umbral de deteccin que de manera predeterminada tiene el valor 0,5 y se puede optar por cambiarlo en caso que se crea necesario. Para cambiarlo de manera razonada se pueden observar las pruebas hechas en el apartado 4.4.3., tambin el usuario se puede guiar de su propia experiencia con la aplicacin. 4. INICIAR APLICACIN: ejecutar la aplicacin. Antes de empezar el proceso de deteccin hay que rellenar de manera adecuada (descrito en 5.4.) el fichero frecuencias.cfg.
- 71 -
5. COMENZAR DETECCIN: primero se configura el sistema con los parmetros adecuados segn el punto 2 y 3. Despus se selecciona el dispositivo de captura. Posteriormente se seleccionan los anuncios que van a formar parte del proceso y para terminar se pulsa en el botn DETECCIN. 6. ESTUDIO DE LOS RESULTADOS: Tras la ejecucin de la aplicacin llega lo ms importante que es la interpretacin de los resultados. Ya se ha comentado que hay una deteccin correcta cuando se apunta ANUNCIO DETECTADO tanto en la lista del dilogo como en el fichero. En el caso de trabajar en el lmite de las posibilidades de la aplicacin (concepto explicado en el apartado de decisor 4.5.) no se ejecutar el algoritmo de decisin con lo que para determinar si el pico de correlacin es una falsa alarma o es un valor detectado la nica informacin de la que disponemos es el resultado que ha dado la deteccin (solo aparece en el fichero) ya que si se acerca mucho al umbral no ser del todo fiable. Normalmente las falsas alarmas se presentan de forma aislada y con un resultado cercano al umbral. Con toda esta informacin el usuario podr interpretar de una forma ms correcta los resultados obtenidos por la aplicacin y adems podr aprender de ellos para una mejor configuracin del sistema para utilizaciones posteriores.
- 72 -
Desarrollar una aplicacin destinada a la deteccin de los anuncios de TV teniendo en cuenta tanto el audio como el video. Al tener en cuenta ambos factores se tiene mayor informacin de la seal capturada y esto conlleva una menor probabilidad de error en la deteccin.
- 73 -
- 74 -
algo (aunque sea solo ruido) ya est solucionado, en el caso de que no se escuche nada se cierra la aplicacin y se ejecuta la aplicacin de radio que venga en dicho software. Si al ejecutarla no funcionara el fallo est en la instalacin o tal vez en la tarjeta capturadora. Si se comprueba que funciona se cierra y se vuelve a ejecutar la aplicacin de deteccin.
1 SOLUCIN:
Una posible forma de realizar esto es con el entorno del Visual Studio. En el SDK viene el filtro WavDest como ejemplo, y para registrarlo tenemos que seguir los siguientes pasos: 1. Evidentemente tener instalado el SDK de DirectX y el Visual Studio. 2. Abrir el proyecto de Visual Studio correspondiente al ejemplo del filtro WavDest. En el caso de que la instalacin del SDK se haya dejado los directorios por defecto este se encuentra en:
C:\DX90SDK\Samples\C++\DirectShow\Filters\WavDest
En caso contrario la ruta ser la misma solo que aadiendo los directorios correspondientes despus de C:. (en el caso de no tener instalado el SDK, el proyecto de WavDest se encuentra ubicado dentro del CD del proyecto). 3. Hay que construir el fichero WavDest.ax y para ello se selecciona Rebuild All del men Build, dar un error porque no se ha construido todava la librera strembasd.lib. Para generar esta librera hay que abrir el proyecto de Visual Studio que se encuentra en el directorio:
- 75 -
C:\DX90SDK\Samples\C++\DirectShow\BaseClasses
Se selecciona Rebuild All, y as se genera la librera strembasd.lib, y una vez hecho esto ya se puede generar el fichero WavDest.ax. 4. Hay que registrarlo y para ello se selecciona Register Control del men Tools.
1. Abrir el men ejecutar de la barra de inicio. 2. Ejecutar la aplicacin Regsvr32 seguida de la ruta completa del archivo wavdest.ax, en el caso de que se copie la carpeta WavDest directamente en el directorio raiz la ejecucin sera semejante a: Regsvr32 C:\WavDest\Debug_Unicode\wavdest.ax 3. En el caso de que el registro del filtro sea correcto aparecer una pantalla semejante a la de la ilustracin 33 :
NOTA: En las dos opciones es necesario tener instalado el Visual Studio. Adems se ha comprobado que el correcto funcionamiento del filtro es mientras el Visual Studio permanece instalado en el sistema.
- 76 -
- 77 -
Los datos numricos que ocupan ms de un byte se representan de la siguiente forma: Primero estn los bytes menos significativos, y a continuacin los ms significativos.
- 78 -
///////////////////////////////////////////////////////////////////////////// // CRadioApp: // See Radio.cpp for the implementation of this class // class CRadioApp : public CWinApp { public: CRadioApp(); // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CRadioApp) public: virtual BOOL InitInstance(); //}}AFX_VIRTUAL // Implementation //{{AFX_MSG(CRadioApp) // NOTE - the ClassWizard will add and remove member functions here. // DO NOT EDIT what you see in these blocks of generated code ! //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_RADIO_H__8975FB44_119A_45F1_8728_697743F5B053__INCLUDED_)
- 79 -
Radio.cpp
// Radio.cpp : Defines the class behaviors for the application. // #include "stdafx.h" #include "Radio.h" #include "RadioDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CRadioApp BEGIN_MESSAGE_MAP(CRadioApp, CWinApp) //{{AFX_MSG_MAP(CRadioApp) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG ON_COMMAND(ID_HELP, CWinApp::OnHelp) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CRadioApp construction CRadioApp::CRadioApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance } ///////////////////////////////////////////////////////////////////////////// // The one and only CRadioApp object CRadioApp theApp; ///////////////////////////////////////////////////////////////////////////// // CRadioApp initialization BOOL CRadioApp::InitInstance() { AfxEnableControlContainer(); // // // // Standard initialization If you are not using these features and wish to reduce the size of your final executable, you should remove from the following the specific initialization routines you do not need. // Call this when using MFC in a shared DLL // Call this when linking to MFC statically
- 80 -
CRadioDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); if (nResponse == IDOK) { // TODO: Place code here to handle when the dialog is // dismissed with OK } else if (nResponse == IDCANCEL) { // TODO: Place code here to handle when the dialog is // dismissed with Cancel } // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application's message pump. return FALSE;
- 81 -
static const GUID CLSID_WavDest = { 0x3c78b8e2, 0x6c4d, 0x11d1, { 0xad, 0xe2, 0x0, 0x0, 0xf8, 0x75, 0x4b, 0x99 } }; ///////////////////////////////////////////////////////////////////////////// // CRadioDlg dialog struct archivo_wav { float *archivo; double *energia; int detectado; int fallo; int N1; long frecuencia; CString anuncio; int posibles_detecciones; }; class CRadioDlg : public CDialog { // Construction public: CRadioDlg(CWnd* pParent = NULL); // Dialog Data //{{AFX_DATA(CRadioDlg) enum { IDD = IDD_RADIO_DIALOG }; CListBox m_anuncio; CButtonST m_grabar; CButtonST m_deteccion; CButtonST m_salir;
// standard constructor
- 82 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL CListBox m_ListaCaptura; CString m_status; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CRadioDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); //}}AFX_VIRTUAL // Implementation protected: HICON m_hIcon; // Generated message map functions //{{AFX_MSG(CRadioDlg) virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); afx_msg void OnSalir(); afx_msg void OnHelpVersin(); afx_msg void OnSeldisp(); afx_msg void OnDeteccion(); afx_msg void OnGrabaradio(); afx_msg void OnTimer(UINT nIDEvent); afx_msg void OnConfigurarSintonizador(); afx_msg void OnArchivosAnuncios(); afx_msg void OnArchivosSalir(); afx_msg void OnConfiguracion(); //}}AFX_MSG DECLARE_MESSAGE_MAP() protected: void UtilDeleteMediaType(AM_MEDIA_TYPE *pmt); HRESULT SetAudioProperties(int nChannels,int nBytesPerSample,int nFrequency, float tiempo_captura); void iniciacaptura(); void iniciasintonizacion(); void AddFilterToListWithMoniker(const TCHAR *szFilterName,IMoniker *pMoniker, CListBox& ListFilters); HRESULT EnumFiltersAndMonikersToList(IEnumMoniker *pEnumCat, CListBox& ListFilters); HRESULT EnumFiltersWithMonikerToList(ICreateDevEnum *pSysDevEnum, const GUID *clsid, CListBox& List); HRESULT GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin); void conecta(IBaseFilter * filtro1,IBaseFilter * filtro2); float *leewav(int *N1,CString nombre); void lectura_anuncios(); void lectura_frecuencias(); void lectura_canales_tv(); double calculo_energia(float *muestras,int longitud); void correlacion(archivo_wav *anuncio,float *data2,int N2,double energia2); void decisor(archivo_wav *anuncio,double maximo); double *calcula_vector_energia(float *data1,int N1); void anota_resultado(archivo_wav *anuncio,double maximo);
// DDX/DDV support
- 83 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL int calcula_posibles_detecciones(int N1); void calcula_frecuencias_correlacion(); void prueba_piloto(); public: void cambia_canal(long canal); CConfiguracion configuracion; CDialosint dialogo2; CArchivos dialogo_archivo; long *frecuencias; long *frecuencias_correlacion; private:
}; //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_RADIODLG_H__3B0CEA02_43B6_4949_9DD7_0909CF92726C__INCLUDED_)
- 84 -
CRadioDlg.cpp
// RadioDlg.cpp : implementation file // #include #include #include #include #include #include #include "Dshow.h" "stdafx.h" "Radio.h" "RadioDlg.h" <math.h> "time.h" <atlbase.h>
#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #define SAFE_RELEASE(i) {if (i) {i->Release(); i = NULL;}} ///////////////////////////////////////////////////////////////////////////// // ESTRUCTURA DE DATOS struct _capstuff { ICaptureGraphBuilder2 *pBuilder; IAMCrossbar *pBar; IGraphBuilder *pFg; IMoniker *pMoniker; IAMTVTuner * pradio; IBaseFilter * pSrc, *pGrabberf, *pnull, *pWAVDest, *pWriter; ISampleGrabber * pGrabber; IMediaControl *pControl; IFileSinkFilter2 *pFileSink; }gcap;
///////////////////////////////////////////////////////////////////////////// // VARIABLES HRESULT hr; AM_MEDIA_TYPE *pmt; char *pBuffer; int N1; long N2; clock_t time1,time2; archivo_wav *tabla_anuncios; int freq; long frecuencia_anterior;
- 85 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL double tiempo_procesado_total; CMenu *Menu; CTime actual; fstream fichero_resultado;
///////////////////////////////////////////////////////////////////////////// // CAboutDlg dialog used for App About class CAboutDlg : public CDialog { public: CAboutDlg(); // Dialog Data //{{AFX_DATA(CAboutDlg) enum { IDD = IDD_ABOUTBOX }; //}}AFX_DATA // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CAboutDlg) protected: virtual void DoDataExchange(CDataExchange* pDX); //}}AFX_VIRTUAL // Implementation protected: //{{AFX_MSG(CAboutDlg) //}}AFX_MSG DECLARE_MESSAGE_MAP() }; CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) { //{{AFX_DATA_INIT(CAboutDlg) //}}AFX_DATA_INIT } void CAboutDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CAboutDlg) //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //{{AFX_MSG_MAP(CAboutDlg) // No message handlers //}}AFX_MSG_MAP END_MESSAGE_MAP()
// DDX/DDV support
/////////////////////////////////////////////////////////////////////////////
- 86 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL // CRadioDlg dialog CRadioDlg::CRadioDlg(CWnd* pParent /*=NULL*/) : CDialog(CRadioDlg::IDD, pParent) { //{{AFX_DATA_INIT(CRadioDlg) m_status = _T(""); //}}AFX_DATA_INIT // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CRadioDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CRadioDlg) DDX_Control(pDX, IDC_LIST2, m_anuncio); DDX_Control(pDX, IDC_GRABARADIO, m_grabar); DDX_Control(pDX, IDC_DETECCION, m_deteccion); DDX_Control(pDX, IDC_SALIR, m_salir); DDX_Control(pDX, IDC_LISTACAPTURA, m_ListaCaptura); DDX_Text(pDX, IDC_STATUS, m_status); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CRadioDlg, CDialog) //{{AFX_MSG_MAP(CRadioDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_BN_CLICKED(IDC_SALIR, OnSalir) ON_COMMAND(ID_HELP_VERSIN, OnHelpVersin) ON_BN_CLICKED(IDC_SELDISP, OnSeldisp) ON_BN_CLICKED(IDC_DETECCION, OnDeteccion) ON_BN_CLICKED(IDC_GRABARADIO, OnGrabaradio) ON_WM_TIMER() ON_COMMAND(ID_CONFIGURAR_SINTONIZADOR, OnConfigurarSintonizador) ON_COMMAND(ID_ARCHIVOS_ANUNCIOS, OnArchivosAnuncios) ON_COMMAND(ID_ARCHIVOS_SALIR, OnArchivosSalir) ON_COMMAND(ID_CONFIGURACION, OnConfiguracion) //}}AFX_MSG_MAP END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////// // CRadioDlg message handlers BOOL CRadioDlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu.
- 87 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here Menu=GetMenu(); // Pongo los iconos pertinentes m_salir.SetIcon(IDI_EXIT); m_deteccion.SetIcon(IDI_ICON1); m_grabar.SetIcon(IDI_ICON2); m_salir.SetBtnCursor(IDC_CURSOR1); m_deteccion.SetBtnCursor(IDC_CURSOR1); m_grabar.SetBtnCursor(IDC_CURSOR1); // Habilito y deshabilito los botones correspondientes GetDlgItem(IDC_SELDISP)->EnableWindow(TRUE); GetDlgItem(IDC_DETECCION)->EnableWindow(FALSE); GetDlgItem(IDC_GRABARADIO)->EnableWindow(FALSE); // Deshabilito los menus adecuados EnableMenuItem(*Menu,ID_CONFIGURAR_SINTONIZADOR,MF_DISABLED||MF_GRAYED); EnableMenuItem(*Menu,ID_ARCHIVOS_ANUNCIOS,MF_DISABLED||MF_GRAYED); // Relleno la lista de captura e inicio el grafo iniciacaptura();
- 88 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL // Inicializo algunas variables freq=0; dialogo_archivo.seleccion=0; m_status=""; //doy valor por defecto al tiempo decaptura y al umbral configuracion.m_tiempo_captura=0.125; configuracion.m_umbral=0.5; //pongo por defecto la deteccin en FM. configuracion.m_fm=0;
//inicializo archivo de resultados CString auxiliar; actual=CTime::GetCurrentTime(); auxiliar="Inicializando aplicacion .... "+actual.Format( "%d-%m-%Y" )+"\n"; fichero_resultado.open("resultado.txt",ios::out | ios::app ); fichero_resultado << auxiliar; return TRUE; // return TRUE unless you set the focus to a control } void CRadioDlg::OnSysCommand(UINT nID, LPARAM lParam) { if ((nID & 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog::OnSysCommand(nID, lParam); } } // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework.
- 89 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL void CRadioDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon);
} else { } }
CDialog::OnPaint();
// The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CRadioDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } ////////////////////////////////////////////////////////////////////// void CRadioDlg::OnSalir() { // TODO: Add your control notification handler code here fichero_resultado.close(); gcap.pControl->Stop(); //liberamos la memoria reservada SAFE_RELEASE(gcap.pBuilder); SAFE_RELEASE(gcap.pFg); SAFE_RELEASE(gcap.pMoniker); SAFE_RELEASE(gcap.pSrc); SAFE_RELEASE(gcap.pradio); SAFE_RELEASE(gcap.pControl); SAFE_RELEASE(gcap.pWAVDest); SAFE_RELEASE(gcap.pWriter);
- 90 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL SAFE_RELEASE(gcap.pFileSink); SAFE_RELEASE(gcap.pGrabber); SAFE_RELEASE(gcap.pGrabberf); SAFE_RELEASE(gcap.pnull); SAFE_RELEASE(gcap.pBar); UtilDeleteMediaType(pmt); m_ListaCaptura.ResetContent(); // delete [] dialogo.frecuencias; Menu->DestroyMenu(); CoUninitialize(); delete [] tabla_anuncios; OnOK(); }
////////////////////////////////////////////////////////////////////// HRESULT CRadioDlg::EnumFiltersWithMonikerToList(ICreateDevEnum *pSysDevEnum, const GUID *clsid, CListBox& List) { HRESULT hr; IEnumMoniker *pEnumCat = NULL; // Se instancia el enumerador de dispositivos de sistema si este no existe if (pSysDevEnum == NULL) { hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, IID_ICreateDevEnum, (void **)&pSysDevEnum); if FAILED(hr) return hr; } // Se enumeran todos los filtros de la categora seleccionada hr = pSysDevEnum->CreateClassEnumerator(*clsid, &pEnumCat, 0); if (SUCCEEDED(hr)) { hr = EnumFiltersAndMonikersToList(pEnumCat, List); pEnumCat->Release(); } pSysDevEnum->Release(); return hr;
- 91 -
////////////////////////////////////////////////////////////////////// HRESULT CRadioDlg::EnumFiltersAndMonikersToList(IEnumMoniker *pEnumCat, CListBox& ListFilters) { HRESULT hr=S_OK; IMoniker *pMoniker=0; ULONG cFetched=0; VARIANT varName={0}; int nFilters=0; // En el caso de que no haya filtros de ese tipo se muestra <<No entries>> if (!pEnumCat) { ListFilters.AddString(TEXT("<< No entries >>\0")); return S_FALSE; } // Enumerate all items associated with the moniker while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) { IPropertyBag *pPropBag; ASSERT(pMoniker); hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); ASSERT(SUCCEEDED(hr)); ASSERT(pPropBag); if (FAILED(hr)) continue; // Se lee el nombre del filtro del property bag varName.vt = VT_BSTR; hr = pPropBag->Read(L"FriendlyName", &varName, 0); if (FAILED(hr)) continue; // Se convierte de BSTR name a CString CString str(varName.bstrVal); SysFreeString(varName.bstrVal); nFilters++; // Se aaden el nombre del filtro al ListBox AddFilterToListWithMoniker(str, pMoniker, ListFilters); pPropBag->Release(); // No se libera el IMoniker para poder usarlo despues } } return hr;
- 92 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL ////////////////////////////////////////////////////////////////////// void CRadioDlg::AddFilterToListWithMoniker(const TCHAR *szFilterName, IMoniker *pMoniker, CListBox& ListFilters) { if (!szFilterName) return; int nSuccess = ListFilters.AddString(szFilterName); int nIndexNew = ListFilters.FindStringExact(-1, szFilterName); } nSuccess = ListFilters.SetItemDataPtr(nIndexNew, pMoniker);
// Create the Filter Graph Manager. hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&gcap.pFg); // Create the Capture Graph Builder. hr = CoCreateInstance((REFCLSID)CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, (REFIID)IID_ICaptureGraphBuilder2, (void **)&gcap.pBuilder); // Associate the graph with the builder. gcap.pBuilder->SetFiltergraph(gcap.pFg);
- 93 -
IEnumPins *pEnum = NULL; IPin *pPin = NULL; HRESULT hr; hr = pFilter->EnumPins(&pEnum); if (FAILED(hr)) { return hr; } while(pEnum->Next(1, &pPin, 0) == S_OK) { PIN_DIRECTION PinDirThis; hr = pPin->QueryDirection(&PinDirThis); if (FAILED(hr)) { pPin->Release(); pEnum->Release(); return hr; } if (PinDir == PinDirThis) { // Devuelve un puntero a IPin por referencia. *ppPin = pPin; pEnum->Release(); return S_OK; } pPin->Release(); } // Si no encontramos ningn pin. pEnum->Release(); return E_FAIL;
} ////////////////////////////////////////////////////////////////////// void CRadioDlg::conecta(IBaseFilter * filtro1,IBaseFilter * filtro2) { //para conectar con la funcion connect de IGraphBuilder necesito //los pins a conectar IPin * pinprueba1, * pinprueba2; GetPin(filtro1,PINDIR_OUTPUT,&pinprueba1); GetPin(filtro2,PINDIR_INPUT,&pinprueba2); gcap.pFg->Connect(pinprueba1,pinprueba2); (pinprueba1)->Release(); (pinprueba2)->Release(); }
- 94 -
////////////////////////////////////////////////////////////////////// //funcin que prepara toda la caracterstica del audio. HRESULT CRadioDlg::SetAudioProperties(int nChannels,int nBytesPerSample,int nFrequency,float Tiempo_captura) { HRESULT hr=0; IPin *pPin=0; IAMBufferNegotiation *pNeg=0; IAMStreamConfig *pCfg=0; // Calcula el nmero de bytes por segundo. long lBytesPerSecond = (long) (nBytesPerSample * nFrequency * nChannels); // Pone el tamao del buffer de trabajo long lBufferSize = (long) ((float) lBytesPerSecond * Tiempo_captura); // Obtengo el pin de salida del dispoditivo de captura hr = GetPin(gcap.pSrc, PINDIR_OUTPUT, &pPin); if (SUCCEEDED(hr)) { // Intento de encontrar el interface IAMBufferNegotiation hr = pPin->QueryInterface(IID_IAMBufferNegotiation, (void **)&pNeg); if (FAILED(hr)) { pPin->Release(); } else { // Pongo las propiedades adecuadas ALLOCATOR_PROPERTIES prop={0}; prop.cbBuffer = lBufferSize; prop.cBuffers = 6; prop.cbAlign = nBytesPerSample * nChannels; hr = pNeg->SuggestAllocatorProperties(&prop); pNeg->Release(); } // Configuracin de audio deseada if (FAILED(hr)) { hr = pPin->QueryInterface(IID_IAMStreamConfig, (void **)&pCfg);
pPin->Release();
- 95 -
else {
hr = pCfg->GetFormat(&pmt); if (SUCCEEDED(hr)) { //Rellenamos con los valores deseados WAVEFORMATEX *pWF = (WAVEFORMATEX *) pmt->pbFormat; pWF->nChannels = (WORD) nChannels; pWF->nSamplesPerSec = nFrequency; pWF->nAvgBytesPerSec = lBytesPerSecond; pWF->wBitsPerSample = (WORD) (nBytesPerSample * 8); pWF->nBlockAlign = (WORD) (nBytesPerSample * nChannels); hr = pCfg->SetFormat(pmt); } // liberamos interfaces pCfg->Release(); pPin->Release();
} } return hr; }
////////////////////////////////////////////////////////////////////// void CRadioDlg::OnHelpVersin() { // TODO: Add your command handler code here CAboutDlg version; version.DoModal(); } //////////////////////////////////////////////////////////////////////
void CRadioDlg::OnSeldisp() {
- 96 -
// TODO: Add your control notification handler code here int nItem=m_ListaCaptura.GetCurSel(); if (nItem== LB_ERR) { MessageBox("Seleccionar dispositivo"); } else { gcap.pMoniker= (IMoniker *) m_ListaCaptura.GetItemDataPtr(nItem); ((gcap.pMoniker))->BindToObject(0,0, IID_IBaseFilter, (void**)&gcap.pSrc); // pSrc es el filtro de captura gcap.pFg->AddFilter(gcap.pSrc, L"Audio Capture"); // Configuramos las propiedades de audio deseadas SetAudioProperties(1,1,8000,configuracion.m_tiempo_captura); // Encontrar la sintonizacin iniciasintonizacion();
// Habilito y deshabilito los botones adecuados GetDlgItem(IDC_LISTACAPTURA)->EnableWindow(FALSE); GetDlgItem(IDC_SELDISP)->EnableWindow(FALSE); GetDlgItem(IDC_DETECCION)->EnableWindow(TRUE); GetDlgItem(IDC_GRABARADIO)->EnableWindow(TRUE); // Habilito los menus adecuados EnableMenuItem(*Menu,ID_ARCHIVOS_ANUNCIOS,MF_ENABLED); EnableMenuItem(*Menu,ID_CONFIGURAR_SINTONIZADOR,MF_ENABLED); EnableMenuItem(*Menu,ID_CONFIGURACION,MF_DISABLED||MF_GRAYED); gcap.pControl->Run(); } }
- 97 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL ////////////////////////////////////////////////////////////////////// void CRadioDlg::iniciasintonizacion() { //me parece que para encontrar el filtro voy //a necesitar crear momentaneamente un filtro //de captura de video ICreateDevEnum * pDevEnum; IEnumMoniker * pClassEnum; IMoniker * pmVideo; IBaseFilter * pSrc; CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, IID_ICreateDevEnum, (void **)&pDevEnum);
((pmVideo))->BindToObject(0,0, IID_IBaseFilter, (void**)&pSrc); gcap.pFg->AddFilter(pSrc, L"Video Capture"); hr = gcap.pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, pSrc, IID_IAMTVTuner, (void **)&gcap.pradio); if(hr != S_OK) { hr = gcap.pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pSrc, IID_IAMTVTuner, (void **)&gcap.pradio); } // Con la interfaz IAMCrossbar nos aseguramos el funcionamiento correcto. hr = gcap.pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video, pSrc,IID_IAMCrossbar, (void**)&gcap.pBar); if (SUCCEEDED(hr))
- 98 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL { IBaseFilter *pFilter = NULL; hr = gcap.pBar->QueryInterface(IID_IBaseFilter, (void**)&pFilter); if (SUCCEEDED(hr)) { gcap.pBar->Route (1,3); } } } else { //si no lo intento con el filtro de captura de audio. hr = gcap.pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, gcap.pSrc, IID_IAMTVTuner, (void **)&gcap.pradio); if(hr != S_OK) { hr = gcap.pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, gcap.pSrc, IID_IAMTVTuner, (void **)&gcap.pradio); } hr = gcap.pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video, gcap.pSrc,IID_IAMCrossbar, (void**)&gcap.pBar); if (SUCCEEDED(hr)) { IBaseFilter *pFilter = NULL; hr = gcap.pBar->QueryInterface(IID_IBaseFilter, (void**)&pFilter); if (SUCCEEDED(hr)) { gcap.pBar->Route (1,3); } } } if(hr==S_OK) { // COMPRUEBO SI EST EN MODO RADIO O MODO T.V. if(configuracion.m_fm==0) { gcap.pradio->put_Mode(AMTUNER_MODE_FM_RADIO );
- 99 -
hr = gcap.pradio->put_InputType(0,TunerInputAntenna); // hago la lectura de las frecuencias que vienen en el // fichero frecuencias.cfg lectura_frecuencias(); // sintonizo la primera de las escritas gcap.pradio->put_Channel(frecuencias[0],0,0); dialogo_archivo.freq=frecuencias; } else { gcap.pradio->put_Mode(AMTUNER_MODE_TV ); hr = gcap.pradio->put_InputType(0,TunerInputAntenna); // hago la lectura de los canales de TV que vienen en el // fichero frecuencias.cfg lectura_canales_tv(); gcap.pradio->put_Channel(frecuencias[0],0,0); dialogo_archivo.freq=frecuencias; } } else { } //libero aqui pero no se si me va a dar problemas //porque gcap.pradio esta asociado a pSrc SAFE_RELEASE(pDevEnum); SAFE_RELEASE(pClassEnum); SAFE_RELEASE(pmVideo); SAFE_RELEASE(pSrc); MessageBox("No se encontr el dispositivo sintonizador en el sistema"); GetDlgItem(IDC_DETECCION)->EnableWindow(FALSE);
- 100 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL void CRadioDlg::UtilDeleteMediaType(AM_MEDIA_TYPE *pmt) { if (pmt == NULL) { return; } if (pmt->cbFormat != 0) { CoTaskMemFree((PVOID)pmt->pbFormat); pmt->cbFormat = 0; pmt->pbFormat = NULL;
////////////////////////////////////////////////////////////////////// void CRadioDlg::OnDeteccion() { // TODO: Add your control notification handler code here // Deshabilito los botones correspondientes GetDlgItem(IDC_DETECCION)->EnableWindow(FALSE); GetDlgItem(IDC_GRABARADIO)->EnableWindow(FALSE); // Deshabilito los menus adecuados EnableMenuItem(*Menu,ID_CONFIGURAR_SINTONIZADOR,MF_DISABLED||MF_GRAYED); EnableMenuItem(*Menu,ID_ARCHIVOS_ANUNCIOS,MF_DISABLED||MF_GRAYED); gcap.pControl->Stop(); hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&gcap.pGrabberf); hr = gcap.pFg->AddFilter(gcap.pGrabberf, L"Sample Grabber");
- 101 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL //Ahora a compartir el interfaz gcap.pGrabberf->QueryInterface(IID_ISampleGrabber, (void**)&gcap.pGrabber); //Configuramos adecuadamente el tipo de dato que va a llegar //para asegurarnos de que no haya problemas gcap.pGrabber->SetMediaType(pmt);
//para activar el modo buffer se llama a SetBufferSamples hr = gcap.pGrabber->SetOneShot(FALSE); hr = gcap.pGrabber->SetBufferSamples(TRUE); //Falta el filtro Null Renderer //Primero creo el filtro hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&gcap.pnull); hr = gcap.pFg->AddFilter(gcap.pnull, L"Null Renderer"); //los conectamos conecta(gcap.pSrc,gcap.pGrabberf); conecta(gcap.pGrabberf,gcap.pnull); //Empieza a funcionar el grafo hr = gcap.pControl->Run();
m_status="detectando ..."; UpdateData(FALSE); Sleep(300); gcap.pGrabber->GetCurrentBuffer(&N2,NULL); // Se hace una prueba piloto para ver cuanto tarda en // hacer el proceso de correlacin prueba_piloto(); // Se pone la primera de las frecuencias y se inicializa
- 102 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL // la variable frecuencia_anterior. gcap.pControl->Stop(); //leemos los anuncios y calculamos sus energias lectura_anuncios(); calcula_frecuencias_correlacion(); cambia_canal(frecuencias_correlacion[freq]); frecuencia_anterior=frecuencias_correlacion[freq]; freq++; gcap.pControl->Run(); SetTimer(ID_TIMER,300,NULL); } ////////////////////////////////////////////////////////////////////// void CRadioDlg::OnGrabaradio() { // TODO: Add your control notification handler code here // Para poner el nombre del archivo // Abro un dilogo para poner el nombre requerido CFileDialog dialogo_archivo(FALSE,"wav"); if (dialogo_archivo.DoModal()==IDOK) { // Primero hay que parar el grafo gcap.pControl->Stop(); // Deshabilito los botones adecuados GetDlgItem(IDC_DETECCION)->EnableWindow(FALSE); GetDlgItem(IDC_GRABARADIO)->EnableWindow(FALSE); // Deshabilito los mens adecuados EnableMenuItem(*Menu,ID_CONFIGURAR_SINTONIZADOR,MF_DISABLED||MF_GRAYED); EnableMenuItem(*Menu,ID_ARCHIVOS_ANUNCIOS,MF_DISABLED||MF_GRAYED);
- 103 -
// Creo el filtro WAVDest // Nota el filtro WAVDest tiene que esta registrado en el sistema // Instrucciones de como hacerlo en la memoria hr = CoCreateInstance(CLSID_WavDest, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void **)&gcap.pWAVDest); // Aado el filtro WAVDest al grafo hr = gcap.pFg->AddFilter(gcap.pWAVDest, L"WAV Dest"); // Creo el filtro que representa la escritura hr = CoCreateInstance(CLSID_FileWriter, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void **)&gcap.pWriter); gcap.pWriter->QueryInterface(IID_IFileSinkFilter2, (void**)&gcap.pFileSink); gcap.pFileSink->SetMode(AM_FILE_OVERWRITE);
// Las lneas siguientes son para cambiar el tipo de CString a lo que // me piden en SetFileName que es unsigned short *. USES_CONVERSION; WCHAR wszFileName[MAX_PATH]; wcsncpy(wszFileName, T2W(dialogo_archivo.GetPathName()), NUMELMS(wszFileName)-1); wszFileName[MAX_PATH-1] = 0; // Se pone nombre del archivo gcap.pFileSink->SetFileName(wszFileName,NULL); hr = gcap.pFg->AddFilter((IBaseFilter *)gcap.pWriter, L"File Writer"); // para conectar los filtros conecta(gcap.pSrc,gcap.pWAVDest); conecta(gcap.pWAVDest,gcap.pWriter); //y a grabar gcap.pControl->Run(); m_status="grabando ...";
- 104 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL UpdateData(FALSE); } } ////////////////////////////////////////////////////////////////////// void CRadioDlg::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default KillTimer(ID_TIMER); int j; long cbBuffer=0; // Esta primera llamada es para obtener el tamao del buffer necesitado hr = gcap.pGrabber->GetCurrentBuffer(&cbBuffer, NULL); // Reservamos memoria para el buffer pBuffer = new char[cbBuffer]; if (!pBuffer) { MessageBox("fuera de memoria"); // Se recogen las muestras en el buffer hr = gcap.pGrabber->GetCurrentBuffer(&cbBuffer,(long *)pBuffer); // Se normalizan entre -1 y 1 float *norma=new float[cbBuffer]; for(j=0;j<cbBuffer;j++) { norma[j]=(float)pBuffer[j]/128; }
- 105 -
//////////////////////////////////////////////////////////////////////
- 106 -
//Busqueda de la palabra Data char auxiliar[80]; wav.Read(auxiliar,80); int j; for(j=0;j<76;j++) { if(auxiliar[j]=='d') if(auxiliar[j+1]=='a') if(auxiliar[j+2]=='t') if(auxiliar[j+3]=='a') break; } // Despus tengo que posicionar el puntero long posicion; //con esto determino la longitud del archivo y los bytes de las muestras son //dicha longitud menos 46 bytes que son los de la cabecera WAV posicion=wav.Seek(j+4,CFile::begin); unsigned long tama[1]; wav.Read(tama,4); char *muestras=new char[tama[0]]; wav.Read(muestras,tama[0]); *N1=tama[0]; float *normalizado=new float[tama[0]]; for(j=0;j<*N1;j++) normalizado[j]=(float)muestras[j]/128; delete [] muestras; return normalizado;
- 107 -
////////////////////////////////////////////////////////////////////// void CRadioDlg::OnConfigurarSintonizador() { // TODO: Add your command handler code here } dialogo2.DoModal();
////////////////////////////////////////////////////////////////////// void CRadioDlg::OnArchivosAnuncios() { // TODO: Add your command handler code here dialogo_archivo.DoModal(); } ////////////////////////////////////////////////////////////////////// void CRadioDlg::lectura_anuncios() { // Comprobacion de que antes se ha seleccionado algn anuncio while(dialogo_archivo.seleccion==0) { MessageBox("NO HAY ANUNCIOS SELECCIONADOS"); dialogo_archivo.DoModal(); } tabla_anuncios=new archivo_wav[dialogo_archivo.seleccion]; int j;
- 108 -
for(j=0;j<dialogo_archivo.seleccion;j++) { tabla_anuncios[j].archivo=leewav(&tabla_anuncios[j].N1,dialogo_archivo.temporal[j]); tabla_anuncios[j].energia=calcula_vector_energia(tabla_anuncios[j].archivo, tabla_anuncios[j].N1); tabla_anuncios[j].detectado=0; tabla_anuncios[j].fallo=0; tabla_anuncios[j].frecuencia=dialogo_archivo.frecuencias[j]; tabla_anuncios[j].anuncio=dialogo_archivo.temporal[j]; } // SE CALCULA EL TIEMPO DE PROCESADO TOTAL tiempo_procesado_total=0; for(j=0;j<dialogo_archivo.seleccion;j++) tiempo_procesado_total+=tabla_anuncios[j].N1; tiempo_procesado_total*=(((float)(time2time1)/1000)*configuracion.m_tiempo_captura)/(225000*0.125); for(j=0;j<dialogo_archivo.seleccion;j++) { tabla_anuncios[j].posibles_detecciones=calcula_posibles_detecciones(tabla_anuncios[j].N1); if(tabla_anuncios[j].posibles_detecciones<1) { //NO SE PUEDE DETECTAR MessageBox("SATURACIN DE APLICACIN, TERMINE LA APLICACIN Y SELECCIONE UN MENOR NMERO DE ANUNCIOS"); } if(tabla_anuncios[j].posibles_detecciones==1) { //NO SE PUEDE DETECTAR MessageBox("SE ESTA TRABAJANDO AL LIMITE DE LA APLICACIN"); } } }
//////////////////////////////////////////////////////////////////////
- 109 -
double CRadioDlg::calculo_energia(float *muestras,int longitud) { double energia=0; int j; for(j=0;j<longitud;j++) { energia+=(muestras[j]*muestras[j]); } return energia; }
////////////////////////////////////////////////////////////////////// void CRadioDlg::correlacion(archivo_wav *anuncio,float *data2,int N2,double energia2) { double maximo=0; float *data1=(*anuncio).archivo; int N1=(*anuncio).N1; double *energia1=(*anuncio).energia; int size=N1-N2+1; int j,i; ///// INICIALIZO A CERO double *correlacion=new double [size]; for(j=0;j<size;j++) { correlacion[j]=0; }
for(i=0;i<N1-N2+1;i++) { for(j=0;j<N2;j++)
- 110 -
correlacion[i]+=data1[j+i]*data2[j];
double umbral=configuracion.m_umbral; if (maximo>umbral) { (*anuncio).detectado++; (*anuncio).fallo=0; anota_resultado(anuncio,maximo); // ANOTAR EN FICHERO RESULTADO // ANOTAR EN EL DIALOGO PRINCIPAL if((*anuncio).detectado>=((int)ceil((float)anuncio->posibles_detecciones/2))) { //MENSAJE DE DETECTADO if ((int)ceil((float)anuncio->posibles_detecciones/2)==1) { if(anuncio->posibles_detecciones==2) { if(anuncio->detectado>=anuncio->posibles_detecciones) { m_anuncio.InsertString(0,"< ANUNCIO DETECTADO > "+anuncio->anuncio);
- 111 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL fichero_resultado << "< ANUNCIO DETECTADO > " << anuncio->anuncio << "\n"; (*anuncio).fallo=0; (*anuncio).detectado=0; } } else { // SE ESTA TRABAJANDO AL LIMITE CON ESE ANUNCIO (*anuncio).fallo=0; (*anuncio).detectado=0; }
} else { m_anuncio.InsertString(0,"< ANUNCIO DETECTADO > "+anuncio->anuncio); fichero_resultado << "< ANUNCIO DETECTADO > " << anuncio->anuncio << "\n"; (*anuncio).fallo=0; (*anuncio).detectado=0; } } } else {
} } //////////////////////////////////////////////////////////////////////
- 112 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL double *CRadioDlg::calcula_vector_energia(float *data1,int N1) { double *resultado=new double[N1-N2+1]; int j,i; for(i=0;i<N1-N2+1;i++) resultado[i]=0; for(i=0;i<N1-N2+1;i++) { for(j=0;j<N2;j++) { resultado[i]+=data1[j+i]*data1[j+i]; } }
return resultado;
////////////////////////////////////////////////////////////////////// void CRadioDlg::lectura_frecuencias() { frecuencias=new long[10]; char temporal[10]; int i,j; for(i=0;i<10;i++) frecuencias[i]=0; CFile archivo_frecuencias; archivo_frecuencias.Open("frecuencias.cfg",CFile::modeRead); for(i=0;i<10;i++) { archivo_frecuencias.Read(temporal,10); frecuencias[i]= strtol(temporal,NULL,10); } //PARA VERIFICAR QUE LAS FRECUENCIAS SON FRECUENCIAS CORRECTAS
- 113 -
if (frecuencias[i]==0) break; } }
} ////////////////////////////////////////////////////////////////////// void CRadioDlg::lectura_canales_tv() { frecuencias=new long[10]; char temporal[4]; int i,j; for(i=0;i<10;i++)
- 114 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL frecuencias[i]=0; CFile archivo_frecuencias; archivo_frecuencias.Open("frecuencias.cfg",CFile::modeRead); for(i=0;i<10;i++) { archivo_frecuencias.Read(temporal,4); frecuencias[i]= strtol(temporal,NULL,10); } //PARA VERIFICAR QUE LOS CANALES DE T.V. ESTN EN EL RANGO CORRECTO for(i=0;i<10;i++) { while (frecuencias[i]>100) { for(j=i;j<9;j++) { frecuencias[j]=frecuencias[j+1]; } frecuencias[9]=0;
if (frecuencias[i]==0) break; } }
//BUCLE PARA VER SI ESTAN LOS CANALES REPETIDOS for(j=1;j<10;j++) for(i=1;i<j+1;i++) if(frecuencias[j]==frecuencias[j-i]) frecuencias[j]=0;
//////////////////////////////////////////////////////////////////////
- 115 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL void CRadioDlg::OnArchivosSalir() { // TODO: Add your command handler code here OnSalir(); } ////////////////////////////////////////////////////////////////////// void CRadioDlg::anota_resultado(archivo_wav *anuncio,double maximo) { CString resultado; actual=CTime::GetCurrentTime(); resultado = actual.Format( "%H:%M:%S " ); resultado+=(*anuncio).anuncio; resultado+=" EN "; char temporal[10]; _ltoa(anuncio->frecuencia,temporal,10); resultado+=temporal; m_anuncio.InsertString(0,resultado); resultado+=" CON VALOR: "; //Y tambin lo almaceno en el fichero fichero_resultado << resultado << maximo << "\n"; } ////////////////////////////////////////////////////////////////////// void CRadioDlg::OnConfiguracion() { // TODO: Add your command handler code here } configuracion.DoModal();
- 116 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL /////////////////////////////////////////////////////////////////////// int CRadioDlg::calcula_posibles_detecciones(int N1) { int resultado; resultado=(int)(((float)N1/8000)/tiempo_procesado_total); return resultado; }
////////////////////////////////////////////////////////////////////// void CRadioDlg::calcula_frecuencias_correlacion() { int i; int j; int k=0; BOOL repetido; frecuencias_correlacion=new long[dialogo_archivo.seleccion+1]; for(j=0;j<=dialogo_archivo.seleccion;j++) frecuencias_correlacion[j]=0; frecuencias_correlacion[0]=tabla_anuncios[0].frecuencia; k++; for (j=1;j<dialogo_archivo.seleccion;j++) { for(i=0;i<k;i++) { if(tabla_anuncios[j].frecuencia==frecuencias_correlacion[i]) { repetido=TRUE; break; } else } repetido=FALSE;
- 117 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL if(!repetido) { frecuencias_correlacion[k]=tabla_anuncios[j].frecuencia; k++; } } } /////////////////////////////////////////////////////////////
void CRadioDlg::prueba_piloto() { int j; archivo_wav anuncio_piloto; // Se lee el anuncio piloto anuncio_piloto.archivo=leewav(&anuncio_piloto.N1,"anuncio_piloto.wav"); anuncio_piloto.energia=calcula_vector_energia(anuncio_piloto.archivo,anuncio_piloto.N1); anuncio_piloto.detectado=0; anuncio_piloto.fallo=0; anuncio_piloto.frecuencia=0; anuncio_piloto.anuncio="anuncio_piloto.wav"; anuncio_piloto.posibles_detecciones=1; // Reservamos memoria para el buffer time1=clock(); pBuffer = new char[N2]; if (!pBuffer) { MessageBox("fuera de memoria"); } // Se recogen las muestras en el buffer hr = gcap.pGrabber->GetCurrentBuffer(&N2,(long *)pBuffer); // Se normalizan entre -1 y 1 float *norma=new float[N2]; for(j=0;j<N2;j++) { norma[j]=(float)pBuffer[j]/128;
- 118 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL } // Se calcula la energa del trozo de audio capturado double energia2=0; energia2=calculo_energia(norma,N2); // se realiza el proceso de correlacin correlacion(&anuncio_piloto,norma,N2,energia2); delete [] pBuffer; delete [] norma; time2=clock(); }
- 119 -
// DDX/DDV support
};
//{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
- 120 -
- 121 -
Archivos.cpp
// Archivos.cpp : implementation file // #include #include #include #include "stdafx.h" "Radio.h" "Archivos.h" "RadioDlg.h"
#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CArchivos dialog
void CArchivos::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CArchivos) DDX_Control(pDX, IDC_DESPLEGAFREQ, m_freq); DDX_Control(pDX, IDC_LISTARCHIVO, m_lista); //}}AFX_DATA_MAP //Pongo esta lnea para poner los archivos en la List Box m_lista.Dir(0x0000,"ARCHIVOS\\*.wav"); //Rellenamos la lista de frecuencias con las frecuencias introducidas //anteriormente por el usuario. int j=0; char auxiliar[10]; while(freq[j]!=0) {
- 122 -
_ltoa(freq[j],auxiliar,10); m_freq.AddString(auxiliar); j++; } } BEGIN_MESSAGE_MAP(CArchivos, CDialog) //{{AFX_MSG_MAP(CArchivos) ON_BN_CLICKED(IDC_BUTTON1, OnLista) ON_BN_CLICKED(IDC_BUTTON2, Onexit) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CArchivos message handlers void CArchivos::OnLista() { // TODO: Add your control notification handler code here CString auxiliar; if (m_lista.GetCurSel()!=LB_ERR) { m_lista.GetText(m_lista.GetCurSel(),temporal[seleccion]); if(m_freq.GetCurSel()!=CB_ERR) { m_freq.GetLBText(m_freq.GetCurSel(),auxiliar); frecuencias[seleccion]=strtol(auxiliar,NULL,10); seleccion++; //ME ASEGURO QUE NO SE PUEDA VOLVER A SELECCIONAR //BORRNDOLO DE LA LISTA m_lista.DeleteString(m_lista.GetCurSel()); } else { } else }
- 123 -
MessageBox("SELECCIONA UN ANUNCIO");
////////////////////////////////////////////////////////////////////// void CArchivos::Onexit() { // TODO: Add your control notification handler code here OnOK(); }
- 124 -
// DDX/DDV support
};
//{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_DIALOSINT_H__28645B3F_7033_44AB_96A3_3897F5A8A910__INCLUDED_)
- 125 -
Dialosint.cpp
// Dialosint.cpp : implementation file // #include #include #include #include "stdafx.h" "Radio.h" "RadioDlg.h" "Dialosint.h"
#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CDialosint dialog CDialosint::CDialosint(CWnd* pParent /*=NULL*/) : CDialog(CDialosint::IDD, pParent) { //{{AFX_DATA_INIT(CDialosint) m_sintoniza = 0; //}}AFX_DATA_INIT } void CDialosint::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CDialosint) DDX_Text(pDX, IDC_SINTFREC, m_sintoniza); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CDialosint, CDialog) //{{AFX_MSG_MAP(CDialosint) ON_BN_CLICKED(IDC_SALIR2, OnSalir2) ON_BN_CLICKED(IDC_OK, OnOk) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CDialosint message handlers void CDialosint::OnSalir2() { // TODO: Add your control notification handler code here
- 126 -
////////////////////////////////////////////////////////////////////// // En esta rutina se sintoniza el canal deseado. void CDialosint::OnOk() { // TODO: Add your control notification handler code here UpdateData(TRUE); CRadioDlg dialogo; dialogo.cambia_canal(m_sintoniza); OnOK(); }
- 127 -
// DDX/DDV support
};
//{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
- 128 -
- 129 -
Configuracion.cpp
// Configuracion.cpp : implementation file // #include "stdafx.h" #include "Radio.h" #include "Configuracion.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CConfiguracion dialog CConfiguracion::CConfiguracion(CWnd* pParent /*=NULL*/) : CDialog(CConfiguracion::IDD, pParent) { //{{AFX_DATA_INIT(CConfiguracion) m_umbral = 0.0f; m_tiempo_captura = 0.0f; m_fm = -1; //}}AFX_DATA_INIT } void CConfiguracion::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CConfiguracion) DDX_Text(pDX, IDC_UMBRAL, m_umbral); DDV_MinMaxFloat(pDX, m_umbral, 0.f, 1.f); DDX_Text(pDX, IDC_TIEMPO_CAPTURA, m_tiempo_captura); DDX_Radio(pDX, IDC_FM, m_fm); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CConfiguracion, CDialog) //{{AFX_MSG_MAP(CConfiguracion) ON_BN_CLICKED(IDC_ACEPTAR, OnAceptar) ON_BN_CLICKED(IDC_CANCELAR, OnCancelar) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CConfiguracion message handlers void CConfiguracion::OnAceptar() { // TODO: Add your control notification handler code here
- 130 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL UpdateData(TRUE); OnOK(); } ////////////////////////////////////////////////////////////////////// void CConfiguracion::OnCancelar() { // TODO: Add your control notification handler code here OnOK(); }
- 131 -
// Comment this if you don't want that CButtonST hilights itself // also when the window is inactive (like happens in Internet Explorer) #define ST_LIKEIE // Comment this if you don't want to use CMemDC class #define ST_USE_MEMDC ///////////////////////////////////////////////////////////////////////////// // CButtonST window class CButtonST : public CButton { // Construction public: CButtonST(); ~CButtonST(); enum {ST_ALIGN_HORIZ, ST_ALIGN_VERT}; // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CButtonST) public: virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); protected: virtual void PreSubclassWindow(); //}}AFX_VIRTUAL // Implementation public: BOOL SetBtnCursor(int nCursorId = -1); void SetFlatFocus(BOOL bDrawFlatFocus, BOOL bRepaint = FALSE);
- 132 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL BOOL GetFlatFocus(); void SetDefaultActiveFgColor(BOOL bRepaint = FALSE); void SetActiveFgColor(COLORREF crNew, BOOL bRepaint = FALSE); const COLORREF GetActiveFgColor(); void SetDefaultActiveBgColor(BOOL bRepaint = FALSE); void SetActiveBgColor(COLORREF crNew, BOOL bRepaint = FALSE); const COLORREF GetActiveBgColor(); void SetDefaultInactiveFgColor(BOOL bRepaint = FALSE); void SetInactiveFgColor(COLORREF crNew, BOOL bRepaint = FALSE); const COLORREF GetInactiveFgColor(); void SetDefaultInactiveBgColor(BOOL bRepaint = FALSE); void SetInactiveBgColor(COLORREF crNew, BOOL bRepaint = FALSE); const COLORREF GetInactiveBgColor(); void SetShowText(BOOL bShow = TRUE); BOOL GetShowText(); void SetAlign(int nAlign); int GetAlign(); void SetFlat(BOOL bState = TRUE); BOOL GetFlat(); void DrawBorder(BOOL bEnable = TRUE); void SetIcon(int nIconInId, int nIconOutId = NULL, BYTE cx = 32, BYTE cy = 32); static const short GetVersionI(); static const char* GetVersionC(); protected: //{{AFX_MSG(CButtonST) afx_msg void OnCaptureChanged(CWnd *pWnd); afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); afx_msg void OnKillFocus(CWnd* pNewWnd); afx_msg void OnMouseMove(UINT nFlags, CPoint point); //}}AFX_MSG private: DECLARE_MESSAGE_MAP() void DrawTheIcon(CDC* pDC, CString* title, RECT* rcItem, CRect* captionRect, BOOL IsPressed, BOOL IsDisabled); int m_nAlign; BOOL m_bShowText; BOOL m_bDrawBorder; BOOL m_bIsFlat; BOOL m_MouseOnButton; BOOL m_bDrawFlatFocus; HCURSOR m_hCursor; HICON m_hIconIn; HICON m_hIconOut; BYTE m_cyIcon;
- 133 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL BYTE m_cxIcon; COLORREF m_crInactiveBg; COLORREF m_crInactiveFg; COLORREF m_crActiveBg; COLORREF m_crActiveFg;
};
#ifdef ST_USE_MEMDC ////////////////////////////////////////////////// // CMemDC - memory DC // // Author: Keith Rule // Email: keithr@europa.com // Copyright 1996-1997, Keith Rule // // You may freely use or modify this code provided this // Copyright is included in all derived versions. // // History - 10/3/97 Fixed scrolling bug. // Added print support. // 25 feb 98 - fixed minor assertion bug // // This class implements a memory Device Context class CMemDC : public CDC { public: // constructor sets up the memory DC CMemDC(CDC* pDC) : CDC() { ASSERT(pDC != NULL); m_pDC = pDC; m_pOldBitmap = NULL; m_bMemDC = !pDC->IsPrinting(); if (m_bMemDC) // Create a Memory DC { pDC->GetClipBox(&m_rect); CreateCompatibleDC(pDC); m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), m_rect.Height()); m_pOldBitmap = SelectObject(&m_bitmap); SetWindowOrg(m_rect.left, m_rect.top); } else // Make a copy of the relevent parts of the current DC for printing { m_bPrinting = pDC->m_bPrinting; m_hDC = pDC->m_hDC; m_hAttribDC = pDC->m_hAttribDC; }
- 134 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL if (m_bMemDC) { // Copy the offscreen bitmap onto the screen. m_pDC->BitBlt(m_rect.left, m_rect.top, m_rect.Width(), m_rect.Height(), this, m_rect.left, m_rect.top, SRCCOPY); //Swap back the original bitmap. SelectObject(m_pOldBitmap); } else { // All we need to do is replace the DC with an illegal value, // this keeps us from accidently deleting the handles associated with // the CDC that was passed to the constructor. m_hDC = m_hAttribDC = NULL; }
// Allow usage as a pointer CMemDC* operator->() {return this;} // Allow usage as a pointer operator CMemDC*() {return this;} private: CBitmap m_bitmap; // Offscreen bitmap CBitmap* m_pOldBitmap; // bitmap originally found in CMemDC CDC* m_pDC; // Saves CDC passed in constructor CRect m_rect; // Rectangle of drawing area. BOOL m_bMemDC; // TRUE if CDC really is a Memory DC. }; #endif ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Developer Studio will insert additional declarations immediately before the previous line. #endif
- 135 -
ButtonST.cpp
// ButtonST.cpp : implementation file // #include "stdafx.h" #include "Radio.h" #include "ButtonST.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif
///////////////////////////////////////////////////////////////////////////// // CButtonST CButtonST::CButtonST() { m_MouseOnButton = FALSE; m_hIconIn = NULL; m_hIconOut = NULL; m_cxIcon = 0; m_cyIcon = 0; m_hCursor = NULL; // Default type is "flat" button m_bIsFlat = TRUE; // By default draw border in "flat" button m_bDrawBorder = TRUE; // By default icon is aligned horizontally m_nAlign = ST_ALIGN_HORIZ; // By default show the text button m_bShowText = TRUE; // By default, for "flat" button, don't draw the focus rect m_bDrawFlatFocus = FALSE; SetDefaultInactiveBgColor(); SetDefaultInactiveFgColor(); SetDefaultActiveBgColor(); SetDefaultActiveFgColor(); } // End of CButtonST CButtonST::~CButtonST() { // Destroy the icons (if any) if (m_hIconIn != NULL) ::DeleteObject(m_hIconIn);
- 136 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL if (m_hIconOut != NULL) ::DeleteObject(m_hIconOut); // Destroy the cursor (if any) if (m_hCursor != NULL) ::DestroyCursor(m_hCursor); } // End of ~CButtonST
BEGIN_MESSAGE_MAP(CButtonST, CButton) //{{AFX_MSG_MAP(CButtonST) ON_WM_CAPTURECHANGED() ON_WM_SETCURSOR() ON_WM_KILLFOCUS() ON_WM_MOUSEMOVE() //}}AFX_MSG_MAP END_MESSAGE_MAP() void CButtonST::SetIcon(int nIconInId, int nIconOutId, BYTE cx, BYTE cy) { HINSTANCE hInstResource = AfxFindResourceHandle(MAKEINTRESOURCE(nIconInId), RT_GROUP_ICON); // Set icon when the mouse is IN the button m_hIconIn = (HICON)::LoadImage(hInstResource/*AfxGetApp()->m_hInstance*/, MAKEINTRESOURCE(nIconInId), IMAGE_ICON, 0, 0, 0); // Set icon when the mouse is OUT the button m_hIconOut = (nIconOutId == NULL) ? m_hIconIn : (HICON)::LoadImage(hInstResource/*AfxGetApp()->m_hInstance*/, MAKEINTRESOURCE(nIconOutId), IMAGE_ICON, 0, 0, 0); m_cxIcon = cx; m_cyIcon = cy; RedrawWindow(); } // End of SetIcon BOOL CButtonST::SetBtnCursor(int nCursorId) { HINSTANCE hInstResource; // Destroy any previous cursor if (m_hCursor != NULL) ::DestroyCursor(m_hCursor); m_hCursor = NULL; // If we want a cursor if (nCursorId != -1) { hInstResource = AfxFindResourceHandle(MAKEINTRESOURCE(nCursorId), RT_GROUP_CURSOR); // Load icon resource m_hCursor = (HCURSOR)::LoadImage(hInstResource/*AfxGetApp()>m_hInstance*/, MAKEINTRESOURCE(nCursorId), IMAGE_CURSOR, 0, 0, 0); // If something wrong then return FALSE if (m_hCursor == NULL) return FALSE; }
- 137 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL return TRUE; } // End of SetBtnCursor void CButtonST::SetFlat(BOOL bState) { m_bIsFlat = bState; Invalidate(); } // End of SetFlat BOOL CButtonST::GetFlat() { return m_bIsFlat; } // End of GetFlat void CButtonST::SetAlign(int nAlign) { switch (nAlign) { case ST_ALIGN_HORIZ: m_nAlign = ST_ALIGN_HORIZ; break; case ST_ALIGN_VERT: m_nAlign = ST_ALIGN_VERT; break; } Invalidate(); } // End of SetAlign int CButtonST::GetAlign() { return m_nAlign; } // End of GetAlign void CButtonST::DrawBorder(BOOL bEnable) { m_bDrawBorder = bEnable; } // End of DrawBorder const char* CButtonST::GetVersionC() { return "2.3"; } // End of GetVersionC const short CButtonST::GetVersionI() { return 23; // Divide by 10 to get actual version } // End of GetVersionI void CButtonST::SetShowText(BOOL bShow) {
- 138 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL m_bShowText = bShow; Invalidate(); } // End of SetShowText BOOL CButtonST::GetShowText() { return m_bShowText; } // End of GetShowText void CButtonST::OnMouseMove(UINT nFlags, CPoint point) { CWnd* pWnd; // Finestra attiva CWnd* pParent; // Finestra che contiene il bottone CButton::OnMouseMove(nFlags, point); // If the mouse enter the button with the left button pressed // then do nothing if (nFlags & MK_LBUTTON && m_MouseOnButton == FALSE) return; // If our button is not flat then do nothing if (m_bIsFlat == FALSE) return; pWnd = GetActiveWindow(); pParent = GetOwner(); if ((GetCapture() != this) && ( #ifndef ST_LIKEIE pWnd != NULL && #endif pParent != NULL)) { m_MouseOnButton = TRUE; //SetFocus(); // Thanks Ralph! SetCapture(); Invalidate(); } else { CRect rc; GetClientRect(&rc); if (!rc.PtInRect(point)) { // Redraw only if mouse goes out if (m_MouseOnButton == TRUE) { m_MouseOnButton = FALSE; Invalidate(); } // If user is NOT pressing left button then release capture! if (!(nFlags & MK_LBUTTON)) ReleaseCapture(); } } } // End of OnMouseMove
- 139 -
void CButtonST::OnKillFocus(CWnd * pNewWnd) { CButton::OnKillFocus(pNewWnd); // If our button is not flat then do nothing if (m_bIsFlat == FALSE) return; if (m_MouseOnButton == TRUE) { m_MouseOnButton = FALSE; Invalidate(); } } // End of OnKillFocus void CButtonST::OnCaptureChanged(CWnd *pWnd) { if (m_MouseOnButton == TRUE) { ReleaseCapture(); Invalidate(); } // Call base message handler CButton::OnCaptureChanged(pWnd); } // End of OnCaptureChanged void CButtonST::DrawItem(LPDRAWITEMSTRUCT lpDIS) { #ifdef ST_USE_MEMDC CDC *pdrawDC = CDC::FromHandle(lpDIS->hDC); CMemDC memDC(pdrawDC); CDC *pDC = &memDC; #else CDC* pDC = CDC::FromHandle(lpDIS->hDC); #endif CPen *pOldPen; BOOL bIsPressed = (lpDIS->itemState & ODS_SELECTED); BOOL bIsFocused = (lpDIS->itemState & ODS_FOCUS); BOOL bIsDisabled = (lpDIS->itemState & ODS_DISABLED); CRect itemRect = lpDIS->rcItem; if (m_bIsFlat == FALSE) { if (bIsFocused) { CBrush br(RGB(0,0,0)); pDC->FrameRect(&itemRect, &br); itemRect.DeflateRect(1, 1); } } // Prepare draw... paint button's area with background color COLORREF bgColor;
- 140 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL if ((m_MouseOnButton == TRUE) || (bIsPressed)) bgColor = GetActiveBgColor(); else bgColor = GetInactiveBgColor(); CBrush br(bgColor); pDC->FillRect(&itemRect, &br); // Disegno lo sfondo del bottone //CBrush br(GetSysColor(COLOR_BTNFACE)); //pDC->FillRect(&itemRect, &br); // Draw pressed button if (bIsPressed) { if (m_bIsFlat == TRUE) { if (m_bDrawBorder == TRUE) { CPen penBtnHiLight(PS_SOLID, 0, GetSysColor(COLOR_BTNHILIGHT)); // Bianco CPen penBtnShadow(PS_SOLID, 0, GetSysColor(COLOR_BTNSHADOW)); // Grigio scuro // Disegno i bordi a sinistra e in alto // Dark gray line pOldPen = pDC->SelectObject(&penBtnShadow); pDC->MoveTo(itemRect.left, itemRect.bottom-1); pDC->LineTo(itemRect.left, itemRect.top); pDC->LineTo(itemRect.right, itemRect.top); // Disegno i bordi a destra e in basso // White line pDC->SelectObject(penBtnHiLight); pDC->MoveTo(itemRect.left, itemRect.bottom-1); pDC->LineTo(itemRect.right-1, itemRect.bottom-1); pDC->LineTo(itemRect.right-1, itemRect.top-1); // pDC->SelectObject(pOldPen);
} else // ...else draw non pressed button { CPen penBtnHiLight(PS_SOLID, 0, GetSysColor(COLOR_BTNHILIGHT)); // White CPen pen3DLight(PS_SOLID, 0, GetSysColor(COLOR_3DLIGHT)); // Light gray CPen penBtnShadow(PS_SOLID, 0, GetSysColor(COLOR_BTNSHADOW)); // Dark gray CPen pen3DDKShadow(PS_SOLID, 0, GetSysColor(COLOR_3DDKSHADOW)); // Black if (m_bIsFlat == TRUE) { if (m_MouseOnButton == TRUE && m_bDrawBorder == TRUE) { // Disegno i bordi a sinistra e in alto // White line pOldPen = pDC->SelectObject(&penBtnHiLight);
- 141 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL pDC->MoveTo(itemRect.left, itemRect.bottom-1); pDC->LineTo(itemRect.left, itemRect.top); pDC->LineTo(itemRect.right, itemRect.top); // Disegno i bordi a destra e in basso // Dark gray line pDC->SelectObject(penBtnShadow); pDC->MoveTo(itemRect.left, itemRect.bottom-1); pDC->LineTo(itemRect.right-1, itemRect.bottom-1); pDC->LineTo(itemRect.right-1, itemRect.top-1); // pDC->SelectObject(pOldPen); } } else { // Disegno i bordi a sinistra e in alto // White line pOldPen = pDC->SelectObject(&penBtnHiLight); pDC->MoveTo(itemRect.left, itemRect.bottom-1); pDC->LineTo(itemRect.left, itemRect.top); pDC->LineTo(itemRect.right, itemRect.top); // Light gray line pDC->SelectObject(pen3DLight); pDC->MoveTo(itemRect.left+1, itemRect.bottom-1); pDC->LineTo(itemRect.left+1, itemRect.top+1); pDC->LineTo(itemRect.right, itemRect.top+1); // Disegno i bordi a destra e in basso // Black line pDC->SelectObject(pen3DDKShadow); pDC->MoveTo(itemRect.left, itemRect.bottom-1); pDC->LineTo(itemRect.right-1, itemRect.bottom-1); pDC->LineTo(itemRect.right-1, itemRect.top-1); // Dark gray line pDC->SelectObject(penBtnShadow); pDC->MoveTo(itemRect.left+1, itemRect.bottom-2); pDC->LineTo(itemRect.right-2, itemRect.bottom-2); pDC->LineTo(itemRect.right-2, itemRect.top); // pDC->SelectObject(pOldPen); } } // Read the button title CString sTitle; GetWindowText(sTitle); // If we don't want the title displayed if (m_bShowText == FALSE) sTitle.Empty(); CRect captionRect = lpDIS->rcItem; // Draw the icon if (m_hIconIn != NULL) { DrawTheIcon(pDC, &sTitle, &lpDIS->rcItem, &captionRect, bIsPressed, bIsDisabled); } // Write the button title (if any)
- 142 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL if (sTitle.IsEmpty() == FALSE) { // Disegno la caption del bottone // Se il bottone e' premuto muovo la captionRect di conseguenza if (bIsPressed) captionRect.OffsetRect(1, 1); // ONLY FOR DEBUG // Evidenzia il rettangolo in cui verra' centrata la caption //CBrush brBtnShadow(RGB(255, 0, 0)); //pDC->FrameRect(&captionRect, &brBtnShadow); #ifdef ST_USE_MEMDC // Get dialog's font CFont *pCurrentFont = GetFont(); CFont *pOldFont = pDC->SelectObject(pCurrentFont); #endif if ((m_MouseOnButton == TRUE) || (bIsPressed)) { pDC->SetTextColor(GetActiveFgColor()); pDC->SetBkColor(GetActiveBgColor()); } else { pDC->SetTextColor(GetInactiveFgColor()); pDC->SetBkColor(GetInactiveBgColor()); } // Center text CRect centerRect = captionRect; pDC->DrawText(sTitle, -1, captionRect, DT_SINGLELINE|DT_CALCRECT); captionRect.OffsetRect((centerRect.Width() - captionRect.Width())/2, (centerRect.Height() captionRect.Height())/2); /* RFU captionRect.OffsetRect(0, (centerRect.Height() - captionRect.Height())/2); captionRect.OffsetRect((centerRect.Width() - captionRect.Width())-4, (centerRect.Height() captionRect.Height())/2); */ pDC->DrawState(captionRect.TopLeft(), captionRect.Size(), (LPCTSTR)sTitle, (bIsDisabled ? DSS_DISABLED : DSS_NORMAL), TRUE, 0, (CBrush*)NULL); #ifdef ST_USE_MEMDC pDC->SelectObject(pOldFont); #endif } if (m_bIsFlat == FALSE || (m_bIsFlat == TRUE && m_bDrawFlatFocus == TRUE)) { // Draw the focus rect if (bIsFocused) { CRect focusRect = itemRect; focusRect.DeflateRect(3, 3); pDC->DrawFocusRect(&focusRect); } } } // End of DrawItem
- 143 -
void CButtonST::DrawTheIcon(CDC* pDC, CString* title, RECT* rcItem, CRect* captionRect, BOOL IsPressed, BOOL IsDisabled) { CRect iconRect = rcItem; switch (m_nAlign) { case ST_ALIGN_HORIZ: if (title->IsEmpty()) { // Center the icon horizontally iconRect.left += ((iconRect.Width() - m_cxIcon)/2); } else { // L'icona deve vedersi subito dentro il focus rect iconRect.left += 3; captionRect->left += m_cxIcon + 3; } // Center the icon vertically iconRect.top += ((iconRect.Height() - m_cyIcon)/2); break; case ST_ALIGN_VERT: // Center the icon horizontally iconRect.left += ((iconRect.Width() - m_cxIcon)/2); if (title->IsEmpty()) { // Center the icon vertically iconRect.top += ((iconRect.Height() - m_cyIcon)/2); } else { captionRect->top += m_cyIcon; } break; } // If button is pressed then press the icon also if (IsPressed) iconRect.OffsetRect(1, 1); // Ole'! pDC->DrawState(iconRect.TopLeft(),iconRect.Size(), (m_MouseOnButton == TRUE || IsPressed) ? m_hIconIn : m_hIconOut, (IsDisabled ? DSS_DISABLED : DSS_NORMAL),(CBrush*)NULL); } // End of DrawTheIcon void CButtonST::PreSubclassWindow() { // Add BS_OWNERDRAW style SetButtonStyle(GetButtonStyle() | BS_OWNERDRAW); CButton::PreSubclassWindow(); } // End of PreSubclassWindow void CButtonST::SetDefaultInactiveBgColor(BOOL bRepaint) { m_crInactiveBg = ::GetSysColor(COLOR_BTNFACE);
- 144 -
DETECCIN AUTOMTICA DE ANUNCIOS EN RADIO EN TIEMPO REAL if (bRepaint == TRUE) Invalidate(); } // End of SetDefaultInactiveBgColor void CButtonST::SetInactiveBgColor(COLORREF crNew, BOOL bRepaint) { m_crInactiveBg = crNew; if (bRepaint == TRUE) Invalidate(); } // End of SetInactiveBgColor const COLORREF CButtonST::GetInactiveBgColor() { return m_crInactiveBg; } // End of GetInactiveBgColor void CButtonST::SetDefaultInactiveFgColor(BOOL bRepaint) { m_crInactiveFg = ::GetSysColor(COLOR_BTNTEXT); if (bRepaint == TRUE) Invalidate(); } // End of SetDefaultInactiveFgColor void CButtonST::SetInactiveFgColor(COLORREF crNew, BOOL bRepaint) { m_crInactiveFg = crNew; if (bRepaint == TRUE) Invalidate(); } // End of SetInactiveFgColor const COLORREF CButtonST::GetInactiveFgColor() { return m_crInactiveFg; } // End of GetInactiveFgColor void CButtonST::SetDefaultActiveBgColor(BOOL bRepaint) { m_crActiveBg = ::GetSysColor(COLOR_BTNFACE); if (bRepaint == TRUE) Invalidate(); } // End of SetDefaultActiveBgColor void CButtonST::SetActiveBgColor(COLORREF crNew, BOOL bRepaint) { m_crActiveBg = crNew; if (bRepaint == TRUE) Invalidate(); } // End of SetActiveBgColor const COLORREF CButtonST::GetActiveBgColor() { return m_crActiveBg; } // End of GetActiveBgColor void CButtonST::SetDefaultActiveFgColor(BOOL bRepaint)
- 145 -
m_crActiveFg = ::GetSysColor(COLOR_BTNTEXT); if (bRepaint == TRUE) Invalidate(); } // End of SetDefaultActiveFgColor void CButtonST::SetActiveFgColor(COLORREF crNew, BOOL bRepaint) { m_crActiveFg = crNew; if (bRepaint == TRUE) Invalidate(); } // End of SetActiveFgColor const COLORREF CButtonST::GetActiveFgColor() { return m_crActiveFg; } // End of GetActiveFgColor void CButtonST::SetFlatFocus(BOOL bDrawFlatFocus, BOOL bRepaint) { m_bDrawFlatFocus = bDrawFlatFocus; // Repaint the button if (bRepaint == TRUE) Invalidate(); } // End of SetFlatFocus BOOL CButtonST::GetFlatFocus() { return m_bDrawFlatFocus; } // End of GetFlatFocus
BOOL CButtonST::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { // If a cursor was specified then use it! if (m_hCursor != NULL) { ::SetCursor(m_hCursor); return TRUE; } return CButton::OnSetCursor(pWnd, nHitTest, message); } // End of OnSetCursor
- 146 -
BIBLIOGRAFA:
[1] Ifeachor, E. C., Y Jervis, B. W. Digital signal processing : a practical Prentice-Hall. [2] Stremler, F. G. Introduccin a los Sistemas de Comunicacin. Addison-Wesley. [3] Chapman, D. Teach Yourself Visual C++ 6 in 21 days. Sams. [4] Dunlop, R. Teach Yourself DirectX 7 in 24. Sams. [5] Ceballos Sierra, F. J. Visual C++ : Programacin Avanzada en Win32. Ra-Ma. [6] Bargen, B., Y Donnelly, P. Inside DirectX. Microsoft Press. [7] STEVENS, Al. Y WALNUM, Clayton. Programacin con C++. Anaya Multimedia. [8] Zaratian, B. Microsoft Visual C++ 6.0 : Manual del Programador. McGraw-Hill. [9] Vallejo Prez, R. J. Deteccin de Tramas de Audio con Sound Blaster. Proyecto fin de carrera.
approach.
Tiempo Real.
[10] Cadenas Martn, I. E. Deteccin Automtica de Anuncios en Televisin en Proyecto fin de carrera. [11] Aprenda C++ como si estuviera en primero. Manual obtenido en internet. URL: http://mat21.etsii.upm.es/ayudainf/aprendainf/Cpp/manualcpp.pdf [12] MSDN. Ayuda del Visual Studio. [13] Microsoft DirectX 9.0 SDK. Documentation for C++. [14] Press, W. H. Numerical recipes in C : the art of scientific computing. Cambridge University Press. [15] http://www.lawebdelprogramador.com/
- 147 -