Sie sind auf Seite 1von 185

INGENIERA DE TELECOMUNICACIN

rea de Teora de la Seal y Comunicaciones


Departamento de Ingeniera Electrnica
Escuela Superior de Ingenieros
Universidad de Sevilla




PROYECTO FIN DE CARRERA


DETECCIN E IDENTIFICACIN DE ANUNCIOS DE RADIO Y
TELEVISIN EN TIEMPO REAL







AUTOR: Ernesto Subir Nimo.

DIRECTOR: Jos Ramn Cerquides Bueno.

Sevilla, Marzo 2007
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
i
INDICE

CAPTULO 1: INTRODUCCIN Y OBJETIVOS.....................................................................1

CAPTULO 2: ALGORITMO DE DETECCIN.........................................................................3
2.1.- IDENTIFICACIN UTILIZANDO AUDIO FINGERPRINTING...............................................3
2.2.- ESQUEMA UTILIZADO EN LA APLICACIN........................................................................6
2.1.1.- ELEMENTOS QUE COMPONEN UNA FINGERPRINT. ...................................................................7
2.1.2.- COMPONENTES DE UN SISTEMA DE AUDIO FINGERPRINTING ....................................................8
2.1.2.1.- EXTRACCION DE FINGERPRINTS .................................................................................9
2.1.2.1.1.- CABECERA........................................................................................................9
2.1.2.1.2.- MODELADO DE FINGERPRINT..................................................................................13
2.1.2.2.- ALGORITMO DE BUSQUEDA .......................................................................................14
2.3.- PARAMETROS QUE INTERVIENEN EN EL PROCESO ..........................................................17
2.2.1.- FRECUENCIA DE MUESTREO ...............................................................................................17
2.2.2.- NUMERO DE BITS POR MUESTRA .........................................................................................17
2.2.3.- NUMERO DE CANALES .......................................................................................................18
2.2.4.- TIEMPO DE CAPTURA........................................................................................................18
2.2.5.- UMBRAL DE DETECCIN ....................................................................................................19

CAPTULO 3: HARDWARE Y SOFTWARE..............................................................................20
3.1. HARDWARE .........................................................................................................................20
3.1.1. SISTEMA .........................................................................................................................20
3.1.2. TARJETA CAPTURADORA.....................................................................................................21
3.2. SOFTWARE ..........................................................................................................................23
3.2.1. SISTEMA OPERATIVO.........................................................................................................23
3.2.2. VISUAL STUDIO 6.0 ...........................................................................................................23
3.2.3. DIRECTX 9.0a...................................................................................................................24
3.3. FUNCIONAMIENTO EN OTROS SISTEMAS ..........................................................................26
3.3.1. PROBLEMAS SURGIDOS EN EL DESARROLLO DEL PROYECTO.......................................................26
3.3.2. SISTEMAS APTOS PARA EL FUNCIONAMIENTO DE LA APLICACIN................................................27
3.4. ESTRUCTURA DEL PROGRAMA............................................................................................28
3.4.1. DIAGRAMA DE CLASES........................................................................................................28
3.4.2. ESTRUCTURAS DE DATOS ...................................................................................................29

CAPTULO 4: DESARROLLO DE LA APLICACIN...............................................................32
4.1.- DESARROLLO DE LA INTERFASE DE
COMUNICACIN ENTRE PC Y TARJETA CAPTURADORA...................................................32
4.1.1. GRAFOS Y FILTROS............................................................................................................33
4.1.2. INTERFACES Y MTODOS....................................................................................................35
4.1.3. RUTINAS EMPLEADOS ........................................................................................................39
4.1.4. BREVE DESCRIPCIN DEL PROCESO......................................................................................41
4.2.- IMPLEMENTACION DEL ALGORITMO DE DETECCION.......................................................44
4.2.1.- FASES DEL ALGORITMO.....................................................................................................44
4.2.1.1.- FASE DE ESTABLECIMIENTO ......................................................................................44
4.2.1.2.- FASE DE APLICACIN DEL ALGORITMO ........................................................................46
4.2.2.- BREVE DESCRIPCION DEL PROCESO DE DETECCIN ................................................................48
4.3. OTRAS CLASES PARA DECORACIN DE LA INTERFASE......................................................51

CAPTULO 5: FASE DE PRUEBAS. RESULTADOS Y CONCLUSIONES............................53
5.1.- TIEMPOS DE COMPUTACION.............................................................................................53
5.2.- LIMITE DE LA APLICACIN ...............................................................................................57
5.3.- PRUEBAS REALIZADAS ......................................................................................................58
5.3.1.- PRUEBAS EN MISMA CADENA..............................................................................................59
5.3.2.- PRUEBAS EN DIFERENTE CADENA ........................................................................................61
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
ii
5.4.- CONCLUSIONES .................................................................................................................63
5.5.- LINEAS FUTURAS DE INVESTIGACION..............................................................................64

CAPTULO 6: MANUAL DE USUARIO.....................................................................................66
6.1. INICIO DE LA APLICACIN.................................................................................................66
6.2. MENU...................................................................................................................................67
6.2.1. ARCHIVOS .......................................................................................................................68
6.2.2. CONFIGURAR ...................................................................................................................69
6.2.3. ACERCA DE......................................................................................................................72
6.3. GRABACIN ........................................................................................................................73
6.4. DETECCIN .........................................................................................................................74
6.5. CONFIGURACIN DE PARMETROS ...................................................................................77

CAPTULO 7: MANUAL DEL DESARROLLADOR...................................................................80
7.1.- DESCRIPCIN DE LA APLICACIN....................................................................................81
7.2.- REQUERIMIENTOS.............................................................................................................81
7.2.1.- HARDWARE NECESARIO PARA EL DESARROLLO.......................................................................81
7.2.2.- SOFTWARE NECESARIO PARA EL DESARROLLO.......................................................................81
7.3.- DESARROLLO DE LA INTERFASE DE COMUNICACIN
APLICACIN-HARDWARE..................................................................................................88
7.3.1.- COMUNICACIN ENTRE LOS DIFERENTES COMPONENTES.........................................................88
7.3.2.- MODO DE FUNCIONAMIENTO DE DIRECTSHOW......................................................................89
7.4.- ESTRUCTURA DE LA APLICACIN......................................................................................91
7.4.1.- CREANDO LA BASE DE DATOS.............................................................................................91
7.4.2.- IMPLEMENTANDO EL ALGORITMO DE IDENTIFICACIN ............................................................92
7.5.- BIBLIOGRAFA RECOMENDADA ........................................................................................95

ANEXOS

ANEXO 1: POSIBLES PROBLEMAS DE LA APLICACIN...................................................96

ANEXO 2: FORMATO DE LOS FICHEROS WAV....................................................................99

ANEXO 3: CODIGO FUENTE......................................................................................................101

BIBLIOGRAFIA.............................................................................................................................178


Deteccin e identificacin de anuncios de radio y televisin en tiempo real
iii
LISTA DE FIGURAS

Figura 1: Procedimientos necesarios en la tarea de identificacin ............................................... 5
Figura 2: Esquema de nuestra aplicacin
(integrando un sistema de audio fingerprinting) ............................................................ 6
Figura 3: Correspondencias entre sub-fingerprints, fingerprint-blocks y fingerprints ................. 7
Figura 4: Transformacin de un anuncio en su correspondiente fingerprint ................................ 8
Figura 5: Esquema de un sistema de audio fingerprinting ............................................................
Figura 6: Esquema del bloque extraccin de fingerprints ............................................................. 8
Figura 7: Tratamiento realizado por el bloque segmentado & solapado....................................... 10
Figura 8: Esquema de extraccin de una sub-fingerprint
correspondiente a un segmento..................................................................................... 12
Figura 9: Algoritmo de generacin de los bits de una sub-fingerprint .......................................... 13
Figura 10: Esquema de generacin de la representacin final de una fingerprint ........................ 14
Figura 11: Proceso de bsqueda de un fingerprint-block dentro
de las fingerprints de los anuncios a detectar.............................................................. 15
Figura 12: Proceso de comparacin entre 2 fingerprint-blocks..................................................... 16
Figura 13: Evolucin de la BER en funcin del tiempo................................................................... 16
Figura 14: Relacin entre el nmero de muestras y la frecuencia de muestreo ........................... 17
Figura 15: Tiempo de captura necesario para extraer un fingerprint-block ................................. 19
Figura 16: Caractersticas sistema utilizado.................................................................................. 21
Figura 17: WINTV USB................................................................................................................... 22
Figura 18: S.O. Windows XP........................................................................................................... 23
Figura 19: Visual Studio 6.0........................................................................................................... 24
Figura 20: DirectX 9.0a .................................................................................................................. 24
Figura 21: Grafo 1 en la aplicacin GraphEdit ............................................................................... 25
Figura 22: Grafo 2 en la aplicacin GraphEdit ............................................................................... 26
Figura 23: AverMedia AVERTV Studio 103..................................................................................... 26
Figura 24: Estructura de datos capstuff ..................................................................................... 30
Figura 25: Estructura de datos archivo_fpr ................................................................................ 30
Figura 26: Grafo 1 .......................................................................................................................... 33
Figura 27: Grafo 2 .......................................................................................................................... 34
Figura 28: Formacin Grafo DirectShow........................................................................................ 42
Figura 29: Formacin Grafo DirectShow (2).................................................................................. 43
Figura 30: Formacin Grafo DirectShow (3).................................................................................. 43
Figura 31: Formacin Grafo DirectShow (4).................................................................................. 43
Figura 32. Fase de establecimiento del algoritmo......................................................................... 48
Figura 33. Fase de establecimiento del algoritmo (2) ................................................................... 49
Figura 34. Fase de aplicacin del algoritmo................................................................................... 50
Figura 35. Fase de aplicacin del algoritmo (2)............................................................................. 51
Figura 36. Tiempo de establecimiento del algoritmo de audio fingerprinting .............................. 55
Figura 37. Tiempo de computacin del algoritmo de audio fingerprinting ................................... 56
Figura 38. Comparativa entre los tiempos de computacin de
la aplicacin anterior y la aplicacin desarrollada en este proyecto............................ 57
Figura 39. Resultados obtenidos con anuncios detectados en la
misma frecuencia que se grabaron............................................................................... 61
Figura 40. Resultados obtenidos con anuncios detectados en una
frecuencia distinta en la que se grabaron .................................................................... 63
Figura 41: Dilogo principal ........................................................................................................... 66
Figura 42: Men Archivos .............................................................................................................. 68
Figura 43: Dilogo Archivos ........................................................................................................... 69
Figura 44: Men Configurar ........................................................................................................... 70
Figura 45: Dilogo Sintonizador .................................................................................................... 71
Figura 46: Dilogo Configuracin .................................................................................................. 72
Figura 47: Dilogo Versin............................................................................................................. 73
Figura 48: Dilogo guardar archivo .fpr......................................................................................... 74
Figura 49: Muestra archivo frecuencias.cfg................................................................................... 74
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
iv
Figura 50. Mensaje de Lmite de Saturacin de la Aplicacin........................................................ 75
Figura 51. Mensaje de Saturacin de la Aplicacin........................................................................ 75
Figura 52: Muestra anuncio detectado .......................................................................................... 76
Figura 53: Muestra fichero resultados ........................................................................................... 77
Figura 54: Configuracin sonido del sistema (grabacin) ............................................................. 78
Figura 55. Iniciando Microsoft Visual C++.................................................................................... 83
Figura 56. Creando una aplicacin MFC AppWizard ...................................................................... 84
Figura 57. Creando una aplicacin basada en dilogos ................................................................. 85
Figura 58. Entorno de desarrollo de Microsoft Visual C++............................................................ 86
Figura 59. Libreras enlazadas al compilador ................................................................................ 88
Figura 60. Comunicacin entre hardware, S.O, DirectX y la aplicacin......................................... 89
Figura 61. Ejemplo de grafo de captura DirectShow..................................................................... 89
Figura 62. Tareas asociadas a la creacin de una base de datos................................................... 92
Figura 63. Tareas asociadas a la identificacin de anuncios ......................................................... 93
Figura 64: Mensaje de registro correcto........................................................................................ 98









Deteccin e identificacin de anuncios de radio y televisin en tiempo real
v
LISTA DE TABLAS

Tabla 1: Caractersticas tcnicas tarjeta WinTV ............................................................................ 22
Tabla 2: Sistemas donde se ha comprobado el correcto funcionamiento
de la aplicacin ................................................................................................................ 27
Tabla 3. Tiempos de establecimiento y de computacin del algoritmo de
audio fingerprinting.......................................................................................................... 54
Tabla 4. Funcionamientos posibles en funcin del nmero de detecciones posible...................... 58
Tabla 5. Resultados obtenidos con anuncios detectados en la
misma frecuencia que se grabaron................................................................................... 60
Tabla 6. Resultados obtenidos con anuncios detectados en una frecuencia
distinta en la que se grabaron .......................................................................................... 62
Tabla 7. Formato de los ficheros .wav ........................................................................................... 99


































Deteccin e identificacin de anuncios de radio y televisin en tiempo real
1

CAPTULO 1: INTRODUCCIN Y OBJETIVOS


Es de sobra conocida la importancia de los anuncios publicitarios para las
emisoras de radio o de televisin. Los contratos publicitarios son una fuente de
ingreso muy importante para estos medios de comunicacin. El tipo de contrato
depende del horario de emisin del anuncio ya que no es lo mismo la emisin
en horario de mxima audiencia que en otro horario.

Por lo tanto debido a las grandes sumas que se mueven en este mbito
puede ser muy til una aplicacin que de algn modo certifique en tiempo real
lo que se haba acordado anteriormente en el contrato.

Este proyecto se basa en la mejora de una aplicacin que proporcionaba
una solucin a la deteccin de anuncios de radio en FM y de televisin [11]. Las
mejoras introducidas pretenden hacer la aplicacin ms eficiente
computacionalmente ya que sta era su principal carencia.

Las herramientas necesarias para utilizar la aplicacin son un ordenador
personal y una tarjeta capturadora TV/FM, se ha verificado tambin el correcto
funcionamiento en un sistema con una tarjeta capturadora de TV
exclusivamente.

Para el desarrollo de la aplicacin anterior se emple como herramienta
de programacin el Visual Studio [17] y las libreras DirectX [18] para controlar
la tarjeta capturadora. Dentro del Visual Studio se emple el lenguaje de
programacin Visual C++, y se desarroll una aplicacin basada en dilogo que
facilitaba la utilizacin de la herramienta por parte del usuario. Debido a esto
para la realizacin de las mejoras hemos utilizado las mismas herramientas.

La aplicacin desarrollada utiliza un algoritmo de deteccin basado en
audio fingerprinting [3] para la comparacin de la seal de entrada con los
anuncios almacenados en una base de datos.

Este algoritmo extrae las caractersticas acsticas ms relevantes de la
seal de entrada y genera con ellas una huella que la identifica de manera
unvoca. Esta huella generada la compara con las huellas de los anuncios
que tiene previamente almacenados en una base de datos. Si el resultado de
esta comparacin est por debajo de un cierto valor umbral se habr producido
una deteccin.

Est capacitada para monitorizar una nica sintona de radio o un nico
canal de TV (pero no ambas a la vez) con mltiples anuncios simultneamente.

Por lo tanto el objetivo es el desarrollo de una aplicacin que cumpla con
los siguientes requisitos:
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
2

Funcionamiento 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.

Eficiencia computacional:

Cuanto ms eficiente sea la aplicacin se obtendrn mejores
resultados y posibilitar el funcionamiento con un mayor nmero
de anuncios y cadenas.

Sencillez:

Debe de ser sencilla de utilizar y con una interfaz amigable de
cara al usuario.

Portabilidad:

Debe funcionar en todos los sistemas, y no debe 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 se pueden ver en
el captulo 3.


La memoria est estructurada en 7 captulos. En el captulo 2 haremos
un estudio exhaustivo del algoritmo de deteccin utilizado para la identificacin
de anuncios. En el captulo 3 describiremos el hardware y el software utilizados
en las fases de desarrollo y de prueba de la aplicacin. En el captulo 4
comentaremos las principales rutinas desarrolladas con el objeto de controlar
adecuadamente la tarjeta capturadora e implementar el algoritmo de deteccin.
En el captulo 5 se expondrn los resultados obtenidos en la fase de pruebas de
la aplicacin, en este captulo se comprobor la eficiencia computacional y el
potencial identificador de este algoritmo. En el captulo 6 se facilitar un manual
de usuario para un correcto uso de la aplicacin. Por ltimo en el captulo 7 se
proporciona un manual de desarrollador destinado a facilitar futuros desarrollos
de este proyecto. Este ltimo manual pretende hacer ms sencilla la labor de
implementacin de algoritmos matemticos en un lenguaje de programacin de
propsito general como es Visual C++.





Deteccin e identificacin de anuncios de radio y televisin en tiempo real
3

CAPTULO 2: ALGORITMO DE DETECCIN

En este apartado se desarrolla el algoritmo usado para la deteccin de
los anuncios.

Como algoritmo de deteccin hemos utilizado un sistema de audio
fingerprinting, que como se ver a continuacin resulta muy eficiente y
adecuado para nuestra aplicacin.

En primer lugar se presenta una visin general de las virtudes y
bondades de esta tcnica as como algunos ejemplos tpicos de su
implementacin.

A continuacin se hace un estudio exhaustivo de la estrategia concreta
elegida de entre todas las estrategias existentes.

Por ltimo se justifican los valores escogidos para los parmetros ms
importantes que intervienen en el proceso de identificacin.


2.1.- IDENTIFICACIN UTILIZANDO AUDIO
FINGERPRINTING

Como se coment en el captulo 1, el problema consiste en identificar los
anuncios que se emiten tanto en la radio FM como en la televisin. Para esta
tarea es necesario contrastar las tramas de audio capturadas con las de los
anuncios que se quieren detectar. Necesitamos alguna tcnica que nos permita
ver el grado de similitud entre dos tramas de audio. La primera solucin que se
puede pensar es utilizar el algoritmo de correlacin para hacer las
comparaciones, pero es una solucin que adolece de un excesivo coste
computacional, adems de una importante falta de robustez, por tanto
debemos buscar una tcnica que sea ms eficiente.

Como solucin a este problema hemos utilizado una tcnica conocida
como Audio Fingerprinting. Esta tcnica presenta unas propiedades que la
hacen muy adecuada para nuestro problema. Las ms interesantes para
nuestra aplicacin segn [1] son:

Robusta: permite la identificacin con alto nivel de distorsin en
la seal e interferencia en el canal de transmisin. Esta
propiedad es muy importante para nosotros porque las tramas
de audio que capturamos proceden de radiodifusin y en
algunos casos la seal puede estar muy degrada.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
4
Eficiente computacionalmente: Cuanto menor tiempo nos lleve
comparar dos tramas de audio, ms anuncios podremos
detectar simultneamente.

Precisa: El nmero de identificaciones correctas es muy alto y
por tanto la tasa de fallos muy baja.

Audio Fingerprinting es el proceso por el cual somos capaces de
identificar una pieza de audio (en nuestro caso un anuncio) a partir de unos
pocos segundos de audio. Para realizar esta identificacin se necesita un
complejo tratamiento matemtico y la exploracin de una base de datos [3].

Para realizar la tarea de identificacin es necesario buscar propiedades o
caractersticas en la seal de audio que sean comunes a todas ellas y lo
suficientemente robustas como para permitir la identificacin en escenarios
poco favorables. Audio Fingerprinting pretende extraer estas caractersticas y
con ellas generar una representacin o huella que sea compacta para
utilizarla como elemento identificador en el proceso de identificacin.

Con el objetivo de generar una huella de una muestra desconocida de
audio de unos pocos segundos de longitud [3] propone dar una serie de pasos.
En primer lugar se convierte en un vector de baja dimensin. En este proceso
de conversin se extraen de la seal ciertas caractersticas espectrales basadas
en consideraciones psico-acsticas. Esta huella, o fingerprint como es
conocida, se compara con una base de datos de fingerprints pre-calculadas
para de determinar si esa muestra se corresponde con alguno de los elementos
de la base de datos.

Hay dos componentes fundamentales en cualquier sistema de Audio
Fingerprinting. El primero es el proceso matemtico con el que calculamos las
fingerprints. El segundo involucra sofisticados algoritmos de bsqueda [6] y [7]
para escanear bases de datos de fingerprints previamente calculadas en busca
de similitudes.

Vemos por tanto, que en la tarea de identificacin existen dos
procedimientos claramente diferenciados. El primero de ellos es la creacin de
la base de datos que contendr las fingerprints de los anuncios y el segundo es
la identificacin de esos anuncios. Estos procedimientos se pueden ver en la
figura 1.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
5

Figura 1. Procedimientos necesarios en la tarea de identificacin.

Para extraer una fingerprint son necesarios unos pocos segundos de
audio, normalmente con algo ms de 3 segundos es suficiente. Una tcnica
comn es separar el trozo de audio en pequeos segmentos. Entonces por cada
segmento se extraen las caractersticas comentadas anteriormente. Para ello
existen numerosas estrategias, las ms comunes suelen incluir: Coeficientes de
Fourier, MFCC [8] (Coeficientes Cepstrales en las Frecuencias de Mel), LPC
(Codificacin Lineal Predictiva), Media y Varianza de las caractersticas, etc.

El siguiente paso es mapear esas caractersticas extradas en una
representacin ms compacta. En este caso tambin existen varias estrategias,
como pueden ser: HMM (Modelo de Markov Oculto), Cuantizacin u otros
mtodos. Esta representacin compacta es la que se utilizar posteriormente en
el proceso de identificacin.

Como ejemplos de esquemas de extraccin de fingerprints podemos ver
el esquema propuesto por el equipo de desarrolladores de Microsoft [5]. En
primer lugar muestrean la seal de audio a una tasa de 11.025 kHz y la
convierten a una seal mono (un solo canal). Entonces la seal muestreada se
separa en segmentos (con un factor de solape de 2) y se le aplica una MCLT
[9] (Modulated Complex Lapped Transform). Con los resultados de esta
transformacin se genera un vector de 128 bits que pasar a ser de 64 bits
despus de emplear una tcnica conocida como Anlisis de Discriminacin de la
Distorsin. Esta estrategia resulta en un vector generado cada 243.6
milisegundos. Estos vectores calculados identifican unvocamente a la seal de
audio y se pueden utilizar para identificarla posteriormente.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
6
Otro esquema propuesto en [2] se basa en una estrategia parecida. En
este caso la seal de audio tambin se segmenta con un factor de solape de
31/32 (cada segmento corresponde a unos 12,8 milisegundos). Este solape es
debido a que las caractersticas de cada segmento son muy similares y varan
lentamente de uno a otro. Por tanto el solapamiento repercute en una mayor
robustez. A cada segmento se le aplica una transformada rpida de Fourier y se
hace pasar por un banco de filtros logartmicamente espaciados. Con todo esto
se genera un vector de 32 bits que igual que en el caso anterior identifica a la
seal de audio.


2.2.- ESQUEMA UTILIZADO EN LA APLICACION

Un esquema general del sistema que utilizaremos en nuestra aplicacin
se puede ver en la figura 2.


Figura 2. Esquema de nuestra aplicacin (integrando un sistema de audio
fingerprinting).

Como se puede ver en la figura 2, la forma de actuar en el procedimiento
de identificacin es, capturar peridicamente unos pocos segundos de audio de
la seal recogida en la antena para despus extraerle su correspondiente
fingerprint. Esta fingerprint se compara con las que tenemos almacenadas
previamente en nuestra base de datos para determinar si la emisin recibida se
corresponde con alguno de los anuncios que queremos detectar. Los resultados
del proceso de identificacin se muestran por pantalla y en un fichero de
resultados.

En este esquema es necesario elegir una estrategia para la extraccin de
fingerprints y un algoritmo de bsqueda para el escaneo de la base de datos.
De entre todas las estrategias existentes hemos elegido la propuesta en [2]
para la extraccin de fingerprints. En el apartado 2.2.2.1 se realizar un estudio
ms exhaustivo de este esquema propuesto. Para el algoritmo de bsqueda se
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
7
ha elegido el algoritmo conocido como fuerza bruta. La justificacin de esta
eleccin se har en el apartado 2.2.2.2.


2.2.1.- ELEMENTOS QUE COMPONEN UNA FINGERPRINT

En un sistema de audio fingerprinting es importante definir ciertos
trminos, seguiremos la terminologa adoptada en [2]:

sub-fingerprint: es la unidad mnima de un sistema de audio
fingerprinting, se trata de un vector de 32 bits. Por s mismo no
contiene la suficiente informacin para identificar un anuncio.

Fingerprint-block: es la unidad mnima de identificacin, se
trata de una cadena de 256 sub-fingerprints. Contiene la
suficiente informacin para identificar un anuncio.

Fingerprint: cada fingerprint corresponde a cada anuncio que se
quiere detectar. Es una cadena de sub-fingerprints de longitud
variable (depender de la longitud del anuncio).

En la figura 3 se pueden ver estos elementos y las correspondencias entre
unos y otros.

Figura 3. Correspondencias entre sub-fingerprints, fingerprint-blocks y
fingerprints.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
8
Este sistema pretende convertir una cadena de audio en una cadena de sub-
fingerprints. Por tanto los anuncios que forman parte de nuestra base de datos
previamente se han debido transformar en sus correspondientes fingerprints
Este proceso se puede ver en la figura 4.


Figura 4. Transformacin de un anuncio en su correspondiente fingerprint.


2.2.2.- COMPONENTES DEL SISTEMA DE AUDIO
FINGERPRINTING

El esquema utilizado se puede ver en la figura 5. Como se puede observar
se compone de dos bloques fundamentales: el bloque de extraccin de
fingerprints y el algoritmo de bsqueda.


Figura 5. Esquema de un sistema de audio fingerprinting [1].

El primer bloque se encarga de acondicionar la seal recogida en la
antena y de extraerle sus caractersticas acsticas ms relevantes generando
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
9
una representacin para stas que sea concisa y robusta. En otras palabras,
este bloque se encarga de extraer una fingerprint de la seal recogida en la
antena. El segundo bloque se encarga de buscar la fingerprint extrada entre las
fingerprints de los anuncios que se pretenden detectar, el algoritmo que se
utiliza en este bloque depende fuertemente del tamao de la base de datos, es
decir, del nmero de anuncios.


2.2.2.1.- EXTRACCION DE FINGERPRINTS

Este primer bloque se descompone en dos partes: la cabecera (front-
end) y el modelado de fingerprint (fingerprint modeling). La cabecera es la que
se encarga de acondicionar la seal de audio de entrada y de extraerle las
caractersticas acsticas ms importantes, todas esas caractersticas conforman
un resumen que identifica a dicha seal de manera unvoca. El modelado de
fingerprint le da formato a ese resumen. En la figura 6 se puede ver un
esquema de este bloque.

Figura 6. Esquema del bloque extraccin de fingerprints.

Como se puede ver la cabecera se compone de varios bloques, cada uno
de ellos tiene una misin bien definida. A continuacin se describen las
funciones de cada parte con ms detalle.


2.2.2.1.1.- CABECERA

La seal que se recoge de la antena es una seal analgica, por tanto no
es apta para poder ser procesada en un ordenador. Se requiere pues un pre-
procesado para acondicionarla.
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
10
2.2.2.1.1.1.- PRE-PROCESADO

En nuestra aplicacin la seal que se recoge de la antena es una seal
procedente de una emisin radioelctrica. La tarjeta capturadora se encarga de
demodular esa seal y entregar una seal analgica de audio en banda base.
Para poder manipular esa seal en nuestro ordenador necesitamos hacer una
conversin analgica digital. Esta es la misin de este bloque. Los parmetros
que se eligen para esta conversin se escogen de forma que aseguremos una
mayor eficiencia computacional. Una explicacin ms detallada de la eleccin de
estos parmetros se puede ver en los apartados 2.3.1, 2.3.2 y 2.3.3.


2.2.2.1.1.2.- SEGMENTADO & SOLAPADO (FRAMING & OVERLAP)

Como se coment anteriormente este esquema pretende convertir una
cadena de audio en una cadena de sub-fingerprints. Para llevar a cabo este
cometido el siguiente bloque realiza una serie de tareas. Estas tareas se pueden
ver de una forma ms grfica en la figura 7.


Figura 7. Tratamiento realizado por el bloque segmentado & solapado.

Una suposicin clave que hacemos en la extraccin de las caractersticas
acsticas de la seal, es que suponemos que la seal se puede considerar como
estacionaria durante un intervalo de unos cuantos milisegundos. Por tanto,
como se puede ver (figura 7), la seal se segmenta en trozos de longitud
0.4096 seg. Cada segmento tiene en total 2048 muestras. Estos segmentos
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
11
extrados estn solapados con un factor de solape de 31/32. El solapamiento es
necesario para asegurar la robustez del sistema frente a cambios en la seal de
entrada. Cada segmento se multiplica por una ventana de Hamming para
suavizar las discontinuidades al principio y al final de dicho segmento. Con este
esquema conseguimos extraer una sub-fingerprint cada 12.8 milisegundos por
cada segmento de audio. Si este proceso contina durante todo el tiempo
correspondiente a una seal de audio, estaremos transformando una cadena de
audio en una cadena de sub-fingerprints.


2.2.2.1.1.3.- TRANSFORMACION LINEAL. ESTIMACIN ESPECTRAL

Las caractersticas acsticas ms importantes de una seal de audio, en
nuestro caso una seal vocal se encuentran en el dominio de la frecuencia. Por
tanto tenemos que buscar una transformacin que nos traslade del dominio del
tiempo al de la frecuencia para poder extraer esas caractersticas. En este
bloque es muy importante buscar un algoritmo que realice la transformacin de
forma rpida y eficiente, ya que nuestro sistema trabaja en tiempo real. La
transformacin es la parte del sistema que tiene un mayor coste computacional.
Segn [2] el algoritmo ms adecuado es la transformada rpida de Fourier
(FFT) y por tanto este ha sido el algoritmo utilizado. Para hacer la
transformacin se utilizan un total de 2048 muestras, es decir, realizamos una
FFT de N=2048 puntos.


2.2.2.1.1.4.- EXTRACCIN DE CARACTERSTICAS

Para caracterizar un anuncio debemos buscar caractersticas estables y
robustas que lo identifiquen de manera unvoca. Con este fin se han propuesto
muchas caractersticas. En [1] podemos ver algunas de las ms importantes,
como por ejemplo: (SFM) Spectral Flatness Measure, que es una estimacin de
la calidad del tono o ruido para una banda en el espectro. Band Representative
Vectors, estos vectores representan una lista de ndices que corresponden a
frecuencias de la banda de inters con tonos significativos (es decir, con picos
con una amplitud significativa). Segn [2] el signo de la diferencia de energas
(simultneamente en el eje temporal y frecuencial) es una propiedad que se
muestra muy robusta frente a muchos tipos de procesamiento y es
relativamente sencilla de implementar, por tanto de entre todas las opciones
elegimos esta ltima. Para calcular estas diferencias es necesario realizar una
serie de pasos que se pueden ver en la figura 8.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
12

Figura 8. Esquema de extraccin de una sub-fingerprint correspondiente a un
segmento.

Como se puede ver el segmento transformado se hace pasar por un
banco de filtros. Este banco de filtros selecciona un total de 33 bandas de
frecuencias no solapadas. Estas bandas pertenecen al rango que va desde los
300 a los 2000 Hz (estas frecuencias se corresponden con las mas importantes
para el sistema auditivo humano) y tienen una escala logartmica.
Posteriormente a cada banda se le calcula su energa para obtener un vector de
33 elementos donde cada elemento corresponde a la energa parcial de cada
banda. Este ltimo vector se utiliza para calcular las diferencias entre las
distintas bandas de energa y obtener el vector binario de resultados que no es
ms que la sub-fingerprint objetivo. Si denotamos ) , ( m n E
p
a la energa parcial
de la banda m-sima del segmento n-simo y ) , ( m n F al bit m-simo
correspondiente al segmento n-simo. Los bits del sub-fingerprint se pueden
calcular como:

+ +
> + +
=
0 )) 1 , 1 ( ) , 1 ( ( ) 1 , ( ) , ( 0
0 )) 1 , 1 ( ) , 1 ( ( ) 1 , ( ) , ( 1
) , (
m n E m n E m n E m n E si
m n E m n E m n E m n E si
m n F
p p p p
p p p p


En el clculo de los bits de la sub-fingerprint intervienen las diferentes
bandas de energa del segmento actual y las del anterior, ya que la
diferenciacin se hace tanto el tiempo como en la frecuencia, este ltimo
comentario se puede ver con ms claridad en la figura 9. Como se deduce de la
ecuacin anterior los bits a 1 corresponden a diferencias de energas positivas
y los bits a 0 a diferencias de energas negativas.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
13

Figura 9. Algoritmo de generacin de los bits de una sub-fingerprint.

El bloque con que aparece detrs del primer sumador es un desfasador
en el tiempo. De esta forma se consigue la diferenciacin en el tiempo.


2.2.2.1.1.5.- POST-PROCESADO

El esquema de la figura 6 es un diagrama genrico propuesto por [1]. En
nuestro caso particular no nos hace falta.


2.2.2.1.2.- MODELADO DE FINGERPRINT

Este bloque tiene como funcin dar una representacin final a la
fingerprint extrada de una muestra de audio, ya sea un anuncio completo o
una de las capturas peridicas de la antena. En nuestra aplicacin la
representacin es muy sencilla, consiste simplemente en colocar cada
subfingerprint una detrs de otra. De forma que la representacin final de una
fingerprint es una matriz con una dimensin de 32 columnas (el nmero de bits
de una sub-fingerprint) y nmero de filas variable (depender del tamao de la
muestra de audio). En el caso de ser un fingerprint-block ser de 256 filas. En
la figura 10 se puede ver como se va generando un fingerprint-block a partir de
las sub-fingerprints extradas de una seal de audio

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
14

Figura 10. Esquema de generacin de la representacin final de una fingerprint.

Como se puede ver en la figura el fingerprint-block (o fingerprint) final
ser una matriz de unos y ceros de 32 columnas y un nmero variable de filas.
Los 1 se representan como pixels negros y los 0 como pixels blancos.


2.2.2.2.- ALGORITMO DE BUSQUEDA

La tarea que debe realizar el algoritmo de bsqueda es, una vez extrado
el fingerprint-block de la seal capturada debe comprobar si corresponde a
alguno de los fingerprint-blocks que componen las fingerprints de los anuncios
que se quieren detectar. Para llevar a cabo este cometido existen numerosos
algoritmos. Como se dice en [1] todos ellos estn orientados a hacer ms
eficiente la bsqueda y dependen fuertemente del tamao de la base de datos.
Para nuestra aplicacin concreta, la base de datos nunca superar los 50
elementos ya que si superamos este valor la aplicacin satura y deja de
funcionar correctamente. Por tanto vemos que nuestra base de datos tiene un
tamao muy reducido, lo que nos permite utilizar un algoritmo de bsqueda
conocido como fuerza bruta. Este proceso se ilustra en la figura 11.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
15

Figura 11. Proceso de bsqueda de un fingerprint-block dentro de las fingerprints de
los anuncios a detectar.

Como se ve en la figura 11 para comprobar si el fingerprint-block
extrado pertenece o no a un anuncio, el algoritmo de bsqueda debe comparar
secuencialmente el fingerprint-block con todos los que existen en la fingerprint
del anuncio. Para ello empieza por el primer anuncio haciendo la comparacin
con el fingerprint block que va desde la fila 0 a la fila 255, despus con el que
va desde la fila 1 a la 256 y as sucesivamente hasta completar la fingerprint
completa. Cuando acabe con el primer anuncio har lo mismo con el segundo y
as hasta completar todos los anuncios que se quieran detectar.

Para realizar las comparaciones entre los diferentes fingerprint-blocks [2]
propone utilizar la distancia de Hamming. En nuestro caso es muy adecuada
porque tenemos que comparar matrices binarias. De esta manera cuando
calculamos la distancia Hamming entre los fingerprint-blocks estamos
calculando el nmero de bits en que difieren y con este valor calculamos la tasa
de error de bit (BER) entre ellos. Esta operacin se hace con todos los
fingerprints-blocks del anuncio y seleccionamos la mnima BER que hemos
obtenido, posteriormente se compara con un valor umbral, si est por debajo
del umbral concluimos que el fingerprint-block pertenece al anuncio y por tanto
se ha detectado el anuncio. Este proceso se puede ver grficamente en la
figura 12.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
16

Figura 12. Proceso de comparacin entre 2 fingerprint-blocks.

El valor umbral con el que se compara la BER no se elige aleatoriamente.
Una explicacin ms detallada de cmo se elige este parmetro se puede ver
en el apartado 2.3.5.

En la figura 13 podemos ver un ejemplo de evolucin de la BER a lo
largo de una hora de emisin.


Figura 13. Evolucin de la BER en funcin del tiempo.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
17
Como se puede apreciar la BER tiene un valor medio de
aproximadamente de 0,45. En torno a los 1000 segundos de emisin se ve
claramente como la BER cae hasta valores por debajo de los 0,35
producindose por tanto una deteccin.


2.3.- PARAMETROS QUE INTERVIENEN EN EL PROCESO

Los parmetros ms importantes son los que se describen a
continuacin.


2.3.1.- FRECUENCIA DE MUESTREO

El primer paso que hay que dar en el proceso de digitalizacin de la
seal de entrada es el muestreo. El valor de la frecuencia de muestreo (F
sam
) se
debe elegir convenientemente. No hay que olvidar que nuestra aplicacin est
pensada para trabajar en tiempo real. Por tanto es muy importante minimizar el
nmero de muestras con el que tiene que trabajar el sistema. El nmero de
muestras es directamente proporcional a la frecuencia de muestreo, esta
relacin se puede ver en la figura 14.


Figura 14. Relacin entre el nmero de muestras y la frecuencia de muestreo.

En nuestra aplicacin el tiempo de captura es constante, una explicacin
ms detallada de este parmetro se puede ver en el apartado 2.3.4. Viendo la
relacin anterior se deduce que la frecuencia de muestreo debe de ser lo ms
pequea posible. El esquema de deteccin propuesto por [2] utiliza una
frecuencia de muestreo de 5 KHz. Esta frecuencia puede ser insuficiente si los
anuncios que se pretenden detectar tienen mucha msica (ya que la msica
tiene frecuencias por encima de los 3 kHz.) pero en la prctica esta frecuencia
se ha mostrado lo suficientemente buena como para detectar anuncios con muy
baja probabilidad de error. Por tanto esta ha sido la frecuencia de muestreo
elegida.


2.3.2.- NUMERO DE BITS POR MUESTRA

Tras el muestreo de la seal analgica el siguiente paso para la
digitalizacin de la seal de entrada es la cuantizacin que en este caso es una
cuantizacin uniforme.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
18
Tras esto viene la codificacin, hemos elegido utilizar 8 bits por muestra,
ya que nos da una calidad lo suficientemente buena para nuestro proceso.


2.3.3.- NUMERO DE CANALES

En este caso las posibles elecciones son 1 o 2, o lo que es lo mismo
Mono o Estreo, pero para una mejor eficiencia computacional hemos elegido
Mono (se tienen la mitad de muestras).


2.3.4.- TIEMPO DE CAPTURA

La aplicacin est diseada para capturar peridicamente una seal
recibida por la antena y buscar entre los anuncios que se desean detectar para
comprobar si esa captura corresponde a algn anuncio emitido.

Por tanto debemos capturar una muestra de audio que tenga la longitud
suficiente para identificar a un anuncio. Como se coment anteriormente en el
punto 2.2.1 la unidad mnima de identificacin es un fingerprint-block, as que
el tiempo mnimo de captura es el tiempo necesario para extraer un fingerprint-
block, o lo que es igual, extraer 256 sub-fingerprints.

En el apartado 2.2.2.1.1.2 se dijo que se extraa una sub-fingerprint cada
12,8 milisegundos (debido al solapamiento). As que para extraer 256 sub-
fingerprints necesitaremos un tiempo:



En otras palabras, para las 255 primeras sub-fingerprints se aprovecha el
solapamiento, pero para la nmero 256 hay que coger un segmento completo.
Esta explicacin se ilustra en la figura 15.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
19

Figura 15. Tiempo de captura necesario para extraer un fingerprint-block.


2.3.5.- UMBRAL DE DETECCION

Dos seales de audio se consideran iguales si la distancia
Hamming entre los fingerprint-blocks derivados de ellas esta por debajo de un
cierto umbral T. Este valor umbral determina directamente la tasa a la cual dos
seales de audio son declaradas incorrectamente iguales, a la que llamaremos
P
f
, (Probabilidad de un falso positivo). Un valor de T bajo nos garantiza que la
probabilidad de que dos seales iguales sean identificas como diferentes sea
muy baja.

Tal y como se propone en [2], dado un fingerprint-block F
1,
la
probabilidad de que un fingerprint-block F
2
aleatoriamente elegido tenga menos
de N BER T = errores con respecto a F
1
viene dada por:

|

\
|
= N
BER
erfc BER P
f
2 3
) 2 1 (
2
1
) (

Siendo N el nmero de bits total (32x256=8192 bits).

En [2] se propone utilizar un valor umbral para la BER de 0,35. Esto
significa que de los 8192 bits debe haber menos de 2867 bits errneos para
decidir que los dos fingerprint-blocks comparados son iguales. Si usamos la
formula anterior para calcular la probabilidad de que dos bloques sean
identificados como iguales cuando no lo son con un umbral de 0.35 vemos que
obtenemos un valor de
20
10 6 , 3 ) 35 , 0 (

=
f
P , es decir, un valor muy pequeo, por
tanto utilizaremos este valor en nuestra aplicacin.
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
20

CAPTULO 3: HARDWARE Y SOFTWARE

En este captulo se hace la descripcin del Hardware y el Software
empleados para la realizacin del proyecto. Esto se expone en los dos primeros
apartados del captulo.

En el apartado 3.3 se exponen los problemas de tipo hardware
encontrados en la realizacin del proyecto y las soluciones adoptadas as como
los sistemas y configuraciones donde se ha demostrado que la aplicacin
funciona.


3.1.- HARDWARE

3.1.1.- SISTEMA

El PC utilizado es un porttil de procesador INTEL CENTRINO a 1.6 GHz.,
con 512 MB de RAM DDR como refleja en la figura 16. Hay que destacar que
este ha sido el equipo con el que se complet el desarrollo de la aplicacin
aunque en un principio se comenz con otro equipo pero dificultades que se
comentarn en el apartado 2.3.1. motivaron el cambio de hardware.

Es el sistema con el que se han realizado las pruebas y medidas de
tiempos de computacin. Es muy importante la velocidad del microprocesador
en una aplicacin de tan elevado coste computacional como esta.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
21

Figura 16: Caractersticas sistema utilizado.

Se ha demostrado que la aplicacin anterior funcionaba correctamente
en otros sistemas con diferentes configuraciones. Un resumen de estos
resultados se puede ver en el apartado 2.3.2.


3.1.2.- TARJETA CAPTURADORA

Al igual que en el apartado 2.1.1. la tarjeta capturadora con la que se
termin de desarrollar la aplicacin no fue la misma que con la que se
comenz. Problemas derivados de la tarjeta capturadora original motivaron que
se cambiara por otra. Estos problemas se comentarn en el apartado 2.3.1. Se
decidi por tanto utilizar la misma tarjeta capturadora que se utiliz en el
desarrollo de la aplicacin anterior.

La tarjeta empleada fue la WINTV USB de HAUPPAUGE (Figura 17), o
tambin conocida como el modelo 678.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
22

Figura 17: WINTV USB.

En la tabla 1 se hace un listado de las caractersticas tcnicas ms
importantes de la tarjeta empleada:


CARACTERSTICAS TCNICAS DE WinTV USB FM

Configuracin mnima
PC con Windows 98, 2000, Millenium y XP con procesador
Pentium 166 Mhz mnimo.
Sintonizador : Sintonizador Philips 125.
Formato sintona Pal B/G
Chip vdeo USBVision
Formato de puerto PCI 2.1
Radio Radio FM
Entrada vdeo
Una entrada S/Video y un adaptador S-Video / Vdeo
Compuesto (RCA).
Audio Entrada y salida de sonido
Compatibilidad Windows 98, 2000, Millennium Edition y XP.
Sintona
Sintona automtica, vista previa de 16 canales,
memorizacin de los canales, visualizacin en ventanas de
Windows y pantalla completa.
Captura de imgenes
Captura de imgenes fijas y en movimiento en formato
BMP, TIFF, GIF, JPEG, blanco y negro. Formato mximo:
800 x 600 pxeles.
Captura de vdeos
Captura de vdeos AVI YUV 4:2:2 (320 x 240 con 25
imgenes por segundo en PAL) y compatible MPEG-4.
Timer TV y Radio
Puede programar la visualizacin y grabacin de sus
programas TV preferidos con la aplicacin TV Scheduler.
Teletexto
Recepcin del Teletexto con el programa VTPlus.
Memorizacin de sus pginas ms usuales.
Creacin Vdeo CD Posibilidad de grabar vdeos en Vdeo CDs.
Tabla 1: Caractersticas tcnicas tarjeta WinTV.



Deteccin e identificacin de anuncios de radio y televisin en tiempo real
23
3.2.- SOFTWARE

3.2.1.- SISTEMA OPERATIVO

El sistema operativo utilizado ha sido el Windows XP Profesional (figura
18).


Figura 18: S.O. Windows XP.

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.

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.


3.2.2.- VISUAL STUDIO 6.0

Como se coment en el captulo 1 las herramientas empleadas en el
desarrollo del proyecto iban a ser las mismas que las empleadas en la versin
anterior. Debido a esto se ha utilizado el Microsoft Visual Studio 6.0.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
24

Figura 19: Visual Studio 6.0.

Es el entorno de desarrollo empleado para la realizacin de la aplicacin
(figura 19). Concretamente la aplicacin est desarrollada con el lenguaje
Visual C++, y se ha desarrollado una aplicacin MFC basada en dilogos que
permite un manejo sencillo de la misma.


3.2.3.- DIRECTX 9.0a

Siguiendo con el argumento del apartado 2.2.2 las libreras utilizadas han
sido las proporcionadas por Microsoft en su paquete conocido como DirectX.
(figura 20).


Figura 20: DirectX 9.0a.

DirectX 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
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
25
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 4), 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).

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 Figuras 21 y 22 respectivamente se refleja el grafo 1 y 2 en la
aplicacin GraphEdit.


Figura 21: Grafo 1 en la aplicacin GraphEdit.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
26

Figura 22: Grafo 2 en la aplicacin GraphEdit.


3.3.- FUNCIONAMIENTO EN OTROS SISTEMAS

En este apartado comentaremos los problemas de hardware surgidos
durante el desarrollo del proyecto y se muestran los diferentes sistemas y
configuraciones donde se ha demostrado que la aplicacin funciona
correctamente.


3.3.1.- PROBLEMAS SURGIDOS EN EL DESARROLLO DEL
PROYECTO

En un primer momento la tarjeta capturadora elegida para el desarrollo
del proyecto fue la Avermedia AVERTV Studio 103, esta tarjeta se puede ver en
la figura 23. El fabricante nos proporciona junto con la tarjeta un CD en el que
vienen los controladores necesarios para poder utilizarla y un software de
utilidades.


Figura 23: AverMedia AVERTV Studio 103.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
27
La aplicacin no funcionaba correctamente con esta tarjeta, mostraba un
funcionamiento parcial. Concretamente slo se poda configurar la tarjeta en
modo TV y no nos permita la configuracin en modo FM. Este problema era
debido a que el paquete de libreras de DirectX no proporcionaba un control
pleno sobre la tarjeta capturadora.

Para resolver este problema existan dos soluciones. La primera era crear
un controlador que nos permitiese un control pleno sobre la tarjeta, pero esta
solucin se sala del mbito del proyecto, por tanto se decidi adoptar la
segunda solucin que consista en cambiar de tarjeta capturadora.

Para asegurar un correcto funcionamiento la tarjeta empleada ha sido la
tarjeta que se utiliz en el desarrollo de la aplicacin anterior [11], de esta
forma aseguramos que no Vamos a encontrarnos con problemas hardware en
el desarrollo del proyecto. Esta tarjeta es la Hauppauge WINTV USB que se
puede ver en la figura 17.

El equipo con el que se comenz el proyecto era un PC de sobremesa
ubicado en los laboratorios de la Escuela Superior de Ingenieros. Como se
puede ver en la figura 23 la tarjeta original es una tarjeta interna, por lo que su
uso estaba restringido a equipos de sobremesa. La eleccin de una tarjeta USB
abri la posibilidad de utilizar otro equipo para desarrollar el proyecto.
Finalmente se decidi utilizar el equipo comentado en el apartado 3.1.1 ya que
ofreca mejores prestaciones que el equipo original y una mayor portabilidad.


3.3.2.- SISTEMAS APTOS PARA EL FUNCIONAMIENTO DE LA
APLICACION

En la tabla 2 se muestran los sistemas y configuraciones donde se ha
demostrado que la aplicacin funciona correctamente segn [11].

CASO CPU MEMORIA S.O. TARJETA TV FM OK
1
Intel
Centrino
1.4 GHz

512 MB


WIN. XP

Hauppauge
WinTV USB

SI


SI

2
Intel P4
2.4 GHz


256 MB


WIN. XP

Hauppauge
WinTV USB

SI


SI

3
Intel P4
2.6 GHz


512 MB


WIN. XP

Best Buy Easy
TV

NO


SI

4
Intel P3
864 Mhz


256 MB


WIN. XP

Pinnacle
PCTV
PRO

NO


SI

5
Intel P3
864 Mhz


256 MB


WIN. 98

Hauppauge
WinTV USB

SI


SI

Tabla 2: Sistemas donde se ha comprobado el correcto funcionamiento de la
aplicacin.
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
28
Para que la aplicacin funcione correctamente [11] asegura que es
necesario tener instaladas las libreras de DirectX 9.0a o superiores. El
funcionamiento es correcto incluso en Windows 98, aunque se recomienda el
uso del sistema operativo Windows XP.


3.4.- ESTRUCTURA DEL PROGRAMA

El cdigo est desarrollado en el lenguaje Visual C++, que es un
lenguaje de programacin de alto nivel orientado a objeto (ms informacin en
referencias [12], [14] y [17]).

Debido al uso de la programacin orientada a objeto, el cdigo se divide
en clases, donde cada una de ellas tiene sus propios mtodos y variables. En
este captulo se hace una descripcin de las clases que componen el cdigo y
adems de las estructuras de datos definidas para una mejor compresin del
mismo.


3.4.1.- DIAGRAMA DE CLASES

En este apartado se describen las clases que forman parte del cdigo,
haciendo un breve comentario sobre cada una de ellas.

El desarrollo de la aplicacin se ha hecho en el entorno del Visual Studio
y se ha generado un proyecto que es un MFC AppWizard, dentro de este
hemos empleado una aplicacin basada en dilogos y hemos dejado la
posibilidad de crear el dilogo Acerca de. Por lo tanto la inicializacin del
proyecto a travs de los Wizards de inicializacin del entorno te da de entrada
(en este caso) 3 clases, que son CRadioApp, CRadioDlg y CAboutDlg. Las
restantes clases que componen el programa han sido desarrolladas y tiene una
funcionalidad propia que ser descrita en su apartado correspondiente.

CRadioApp.

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.

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.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
29
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 valor 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.


3.4.2.- ESTRUCTURAS DE DATOS

Se han creado dos estructuras de datos, una con la informacin precisa
de los interfaces que se usan para el correcto control del dispositivo capturador
y otra que est relacionada con el algoritmo de deteccin y tiene informacin
sobre cada anuncio a detectar.

_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.
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
30

Las interfaces que utiliza se explican en el apartado 4.1.2 de la
memoria.

En la figura 24 se muestra la declaracin de esta estructura de
datos.


Figura 24: Estructura de datos capstuff.

archivo_fpr

Esta estructura contiene informacin sobre cada anuncio que se
quiera detectar. Tendremos una tabla de estructuras de este tipo,
donde el nmero de elementos de la tabla ser el de anuncios a
detectar.

En la figura 25 se muestra la declaracin de esta estructura de
datos.


Figura 25: Estructura de datos archivo_fpr.

Donde:

archivo: apunta a las muestras de la huella del anuncio.
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
31

N1: nmero de muestras de la huella del anuncio.

frecuencia: frecuencia donde se grab el anuncio.

anuncio: nombre del anuncio.

posibles_detecciones: variable que refleja segn las condiciones de la
deteccin
(nmero de anuncios) cuantas veces se puede detectar el anuncio en
cuestin.


Deteccin e identificacin de anuncios de radio y televisin en tiempo real
32

CAPTULO 4: DESARROLLO DE LA APLICACIN

Esta aplicacin tiene dos partes bien diferenciadas. La primera es el
desarrollo de una interfase que permita al usuario hacer uso de la aplicacin e
interactuar con el hardware. La segunda implementa un algoritmo eficiente
para la tarea de la identificacin.

Este captulo se compone de 3 apartados. En el primer apartado se
comentan las interfaces y rutinas empleadas para el desarrollo de la interfase
de comunicacin entre PC y tarjeta. En el segundo apartado se describen las
rutinas utilizadas para implementar el algoritmo de identificacin, es decir, el
algoritmo de Audio Fingerprinting. Por ltimo en el tercer apartado se muestran
las clases necesarias para hacer ms amigable el entorno grfico de la
aplicacin.

Para el primer apartado se ha consultado abundante bibliografa. Se ha
consultado la referencia [11], ya que como se coment en el captulo 1 el
objetivo del proyecto es mejorar la eficiencia computacional de una aplicacin
ya existente que proporcionaba una solucin al problema de deteccin de
anuncios de radio y televisin. Debido a esto, se ha respetado la parte del
desarrollo de la interfase, introduciendo tan slo leves modificaciones. Tambin
se han consultado numerosos manuales de programacin del lenguaje Visual
C++ [12], [14] y [15], as como bibliografa especfica referente a las libreras
de DirectX [13] y [18]. De entre todas estas referencias las ms utilizadas han
sido la referencia [11], debido a que la interfase desarrollada en la aplicacin
anterior se ha respetado casi en su totalidad y la documentacin que viene con
el SDK [18] gracias a que era muy completa y contena algunos ejemplos
desarrollados en C++ que sirven de mucha ayuda para comprender el
funcionamiento de las libreras.

Para el segundo apartado ha sido necesaria documentacin acerca de
implementacin de funciones matemticas en el lenguaje C++ [10] as como
bibliografa donde se describe exhaustivamente el algoritmo de identificacin
[2]. Es importante resaltar que el algoritmo de Audio Fingerprinting tiene una
componente matemtica muy fuerte y el lenguaje de programacin es un
lenguaje de propsito general. Por tanto es de vital importancia una correcta
implementacin de funciones matemticas bsicas para una buena eficiencia
computacional.


4.1.- DESARROLLO DE LA INTERFASE DE
COMUNICACIN ENTRE PC Y TARJETA CAPTURADORA

Uno de los componentes software utilizados han sido las libreras de
DirectX. Dentro de estas hemos utilizado ms concretamente las libreras de
DirectShow, que proporcionan las herramientas necesarias para el control de
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
33
dispositivos Hardware instalados en el sistema y ms concretamente de los
dispositivos capturadores que es lo que nos interesa en este caso, como una
tarjeta capturadora de video/FM.

En este apartado se hace una descripcin exhaustiva de cmo utilizando
las libreras de DirectShow se puede controlar un dispositivo Hardware sin
utilizar la herramienta software que suele acompaarle.

El funcionamiento de DirectShow se basa en la correcta conexin de
filtros DirectShow, controlando adecuadamente sus propiedades y haciendo las
conexiones con los pines adecuados de cada filtro. Un filtro representa un
dispositivo instalado en el sistema de forma Hardware o Software teniendo una
funcionalidad propia.

Al conjunto de varios filtros conectados se le denomina grafo y el propio
SDK proporciona la herramienta GraphEdit para hacer diseo de grafos y
comprobar su funcionamiento antes de la etapa de programacin. En el
apartado 3.2.3 de la memoria se muestran unos ejemplos del uso de la
herramienta GraphEdit.

Se han desarrollado dos grafos. El grafo 1 que es el principal y que lleva
el funcionamiento de deteccin de tramas de audio, y el grafo 2 que es
secundario pero tambin importante ya que a partir de l proporcionamos una
herramienta al usuario para grabar los anuncios que posteriormente desee
identificar.


4.1.1.- GRAFOS Y FILTROS

Grafo 1: Es el grafo principal de la aplicacin. Su funcionamiento se basa
en el almacenamiento de las muestras de audio en un buffer y la
realizacin del algoritmo de deteccin con el contenido del buffer.


Figura 26: Grafo 1.

A continuacin se hace una descripcin de los filtros que componen el
grafo y que se ven representados en la figura 26.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
34
Filtros:

001 & Hauppauge WinTV USB Pro Audio: filtros que representan 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: Este grafo sirve como herramienta de grabacin para obtener
as las huellas de los anuncios que van a ser comparadas con
posterioridad.

Para extraer las huellas de los anuncios se necesitan dos pasos. El
primero es capturar todas las muestras de audio del anuncio en cuestin
y el segundo es calcular todas las huellas de esa cadena de audio
capturada. La funcin de este grafo es precisamente realizar este primer
paso. (Figura 27).

Como a priori no se conoce la duracin del anuncio, la estrategia es
capturar el anuncio completo y almacenarlo en un fichero en formato
.wav para acto seguido extraer las huellas. El formato .wav es muy
adecuado ya que es muy fcil el acceso a las muestras de audio.


Figura 27: Grafo 2.

Filtros:

001 & Hauppauge WinTV USB Pro Audio: filtros que representan 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.
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
35
4.1.2.- INTERFACES Y MTODOS

DirectShow dispone de una amplia coleccin de interfaces y mtodos, en
este apartado se comenta las ms importantes interfaces y dentro de ellas los
mtodos ms relevantes que se han usado en el desarrollo de la aplicacin para
una mejor compresin del cdigo.

Una documentacin ms detallada se puede encontrar en el SDK de
DirectX [18].

Interfaces:

4.1.2.1.- IGraphBuilder.

Es una interfaz necesaria para construir un grafo de filtros. Esta interfaz
est implementada por el filtro que controla todo el grafo y que se denomina:
Filter Graph Manager.

Mtodos:

AddFilter: aade un filtro al grafo. Necesita de un parmetro que sea
un puntero a IBaseFilter que es otra interfaz que se comentar
posteriormente.

Connect: mtodo que sirve para conectar dos pines.

4.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.

4.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,
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
36
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..

4.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.

4.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.

4.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:

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
37
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.

4.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).

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.

4.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.

4.1.2.9.- IAMStreamConfig.

Interfaz usada para conseguir el formato deseado de los datos, con ella
se consigue capturar a 5 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.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
38
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.

4.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.

4.1.2.11.- ICreateDevEnum, IEnumMoniker e IMoniker.

Usadas conjuntamente para conseguir enumerar los dispositivos
hardware del sistema y as poder encontrar el dispositivo de captura adecuado
a nuestras necesidades.

A continuacin se hace una breve descripcin del proceso sin profundizar
en exceso en cada uno de los pasos.

El primer paso sera la instanciacin del filtro que sirve para la
enumeracin de los dispositivos que se encuentran instalados en el sistema. La
interfaz que es implementada por este filtro es ICreateDevEnume.

Despus se emplea el mtodo de esta interfaz CreateClassEnumerator
donde se le pasa como parmetro que tipo de dispositivo se quiere enumerar y
un puntero a una interfaz IEnumMoniker que es una interfaz donde se
almacena informacin de los dispositivos enumerados y que les permite al
sistema distinguir uno de otro.

Tras esto solo falta quedarnos con el dispositivo deseado con el mtodo
Next de la interfaz IEnumMoniker. Cada vez que se llama a este mtodo se
avanza un dispositivo en la lista y se asocia este dispositivo seleccionado en una
interfaz IMoniker que se le pasa como parmetro al mtodo.

Por ltimo para unir al grafo el dispositivo deseado se usa el mtodo
BindToObject de la interfaz IMoniker y as conseguimos asociar el dispositivo
a una interfaz IBaseFilter, y tras esto se emplea el ya conocido mtodo
AddFilter para aadir el filtro al grafo.


Deteccin e identificacin de anuncios de radio y televisin en tiempo real
39
4.1.2.12.- IPin.

Se usa para identificar los pines de los filtros y realizar una conexin
entre ellos.

Mtodos:

QueryDirection: devuelve la direccin del pin, es decir, si es un pin de
salida o de entrada.

4.1.2.13.- Otros mtodos de inters.

CocreateInstance: para instanciar un filtro.

QueryInterface: mtodo que usa un elemento de IBaseFilter para
adaptarse a una interfaz especfica.


4.1.3.- RUTINAS EMPLEADAS

Para entender el funcionamiento de las rutinas que se comentan a
continuacin se ha consultado la referencia [11]. Estas rutinas se
implementaron utilizando el lenguaje de programacin Visual C++ en el
entorno de desarrollo de Visual Studio. A continuacin se hace una descripcin
sobre algunas de las rutinas empleadas para el control de la interfase.

SetAudioProperties: rutina para el control del formato de audio
capturado. Controla la frecuencia de muestreo, los bytes por muestra, y
el nmero de canales de entrada (mono o estreo). Tambin controla el
tamao del buffer interno de datos ya que se le pasa como parmetro el
tiempo de captura y el tamao del buffer de datos que es el resultado
del producto entre el tiempo de captura y la frecuencia de muestreo.

HRESULT SetAudioProperties(int nChannels,int nBytesPerSample,int
nFrequency,float tiempo_captura);

Iniciacaptura: rutina que inicia el desarrollo del grafo DirectShow y
llama a la rutina EnumFiltersWithMonikerToList que es la que se
encarga de enumerar los dispositivos capturadores instalados en el
sistema en la lista que aparece en el dilogo principal de la aplicacin.

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.
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
40

void iniciasintonizacion();

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.

HRESULT GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin
**ppPin);

Conecta: rutina que conecta dos filtros a partir de sus respectivos
interfaces IBaseFilter. La conexin se hace de modo que el pin de salida
del filtro 1 se conecta al de entrada del filtro 2.

void conecta(IBaseFilter * filtro1,IBaseFilter * filtro2);

OnGrabaradio: rutina que se ejecuta tras pulsar el botn GRABAR del
dilogo principal. Se encarga de preparar e inicializar todo el grafo de
grabacin.

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.

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. El dispositivo se elige entre
los dispositivos encontrados en el sistema y que aparecen el dilogo
principal de la aplicacin. Una vez hecho esto llama a la rutina
iniciasintonizacion.

void OnSeldisp();

EnumFiltersWithMonikerToList: rutina que utiliza otras dos rutinas
(EnumFiltersAndMonikersToList y AddFilterToListWithMoniker) para
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
41
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.

HRESULT EnumFiltersWithMonikerToList(ICreateDevEnum
*pSysDevEnum,const GUID *clsid, CListBox& List);

OnArchivosAnuncios: rutina que se ejecuta al pulsar el elemento
ANUNCIOS del men ARCHIVOS. Te muestra un dilogo para
seleccionar los anuncios que van a formar parte del proceso de
deteccin.

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 en el 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) y el valor 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();



4.1.4.- BREVE DESCRIPCIN DEL PROCESO

En este apartado se hace una descripcin de los pasos a seguir para
realizar estos grafos en Visual C++.
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
42
1. Libreras: para utilizar DirectShow en la aplicacin hace falta incluir las
libreras y archivos de cabecera correspondientes. Para realizar esto hay que
incluir los archivos de cabecera DShow.h y Qedit.h y adems linkarle la
librera Strmiids.lib.

2. Filter Graph Manager: tras las libreras ya se puede hacer uso de todas
las interfaces de DirectShow y por ello lo primero es crear (o instanciar) el filtro
principal para crear el grafo.

3. Se asocia este filtro principal al filtro especfico de captura indicndole
de esta forma al sistema que el grafo que vamos a desarrollar tiene un
elemento de captura de datos. Los puntos 2 y 3 se ven reflejados en el cuadro
de texto que aparece en la figura 28.


Figura 28: Formacin Grafo DirectShow.

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
el cuadro de texto que contiene la figura 29, donde se encuentra el proceso de
conexin del grafo de deteccin (grafo 1).

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
43

Figura 29: 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 figura 30 un uso de este mtodo para hacer que el grafo
contenga la funcionalidad de la interfaz IMediaControl.


Figura 30: Formacin Grafo DirectShow (3).

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 figura 31.


Figura 31: Formacin Grafo DirectShow (4).




Deteccin e identificacin de anuncios de radio y televisin en tiempo real
44
4.2.- IMPLEMENTACIN DEL ALGORITMO DE
DETECCIN

En este apartado se comentan las rutinas desarrolladas para la
implementacin del algoritmo de deteccin.

En primer lugar comentaremos las distintas fases que se pueden
distinguir en la ejecucin del algoritmo de audio fingerprinting.

En segundo lugar haremos una breve descripcin del proceso de
deteccin.


4.2.1.- FASES DEL ALGORITMO DE DETECCIN

En el proceso de deteccin, despus de la correcta configuracin del
grafo DirectShow, se pueden distinguir dos fases: La fase de establecimiento y
la fase de aplicacin.


4.2.1.1.- FASE DE ESTABLECIMIENTO

Es una fase que solo se ejecuta una vez en el proceso de deteccin. En
esta fase lo que se hace es preparar los anuncios que van a ser detectados y
las frecuencias que van a ser examinadas.

Los anuncios se leen de un archivo .fpr. Cada archivo contiene la
fingerprint correspondiente a un anuncio. Estos archivos se encuentran en el
directorio ARCHIVOS dentro de la carpeta base de la aplicacin. Estos se leen y
se almacenan en memoria para una mayor eficiencia del proceso.

Para almacenar cada anuncio se ha utilizado la estructura de datos
denominada archivo_fpr ya comentada en el apartado 2.4.2. Las rutinas
relacionadas con esta fase de establecimiento se describen a continuacin:

Lectura_anuncios: Rutina que realiza todo lo referente a la lectura de
los anuncios seleccionados para la deteccin, y para ello se basa en la
rutinas Lee_finger. Los almacena de modo adecuado dentro de la
estructura de datos archivo_fpr. Tambin se asegura si hay algn
anuncio seleccionado y de no ser as te muestra el dilogo
correspondiente para su seleccin.

void lectura_anuncios();

Lee_finger: Rutina que se le pasa como entrada el nombre del archivo a
leer (el nombre y la extensin, pero se tiene que encontrar en el
directorio ARCHIVOS), y te devuelve las muestras de ese archivo en un
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
45
vector de enteros. Tambin se obtiene el nmero de muestras mediante
un parmetro que se le pasa por referencia.

int *lee_finger(int *N1,CString nombre);

Calcula_saturaciones: Rutina que se encarga de comprobar si la
aplicacin puede detectar correctamente los anuncios elegidos. Para ello
se apoya en la rutina calcula_posibles_detecciones con el objetivo de
comprobar si cada anuncio se puede detectar a lo menos una vez. Se le
pasa como parmetro el tiempo de procesado total y en caso de
problemas nos avisa mediante mensajes de error.

void calcula_saturaciones(double tiempo_procesado_total)

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 5.2 de la
memoria.

int calcula_posibles_detecciones(int N1);

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 6.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 configuracin de modo correcto se
encuentran en el apartado 6.4 de la memoria.

void lectura_canales_tv();

calcula_frecuencias_deteccion: 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.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
46
void calcula_frecuencias_deteccin();


4.2.1.2.- FASE DE APLICACIN DEL ALGORITMO

El algoritmo se aplicar de forma peridica hasta que el usuario lo
detenga. Los mtodos desarrollados para esta fase se describen a continuacin:

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).

void OnTimer(UINT nIDEvent);

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.

void cambia_canal(long canal);

Extrae_fingerprint: Rutina que se encarga de transformar un anuncio
en su correspondiente fingerprint, para ello se le pasa como parmetro
las muestras de audio del anuncio, el nombre del anuncio y el nmero de
muestras. Esta rutina se basa en las rutinas realft, modulo,
extrae_subfingerprint y escribe_subfingerprint. La fingerprint
obtenida se almacena en un fichero con extensin .fpr

void extrae_fingerprint(float *audio,int N1, CString nombre_archivo);

Extrae_fingerprint_block: Rutina que se encarga de extraer un
fingerprint_block a partir de las muestras capturadas en la antena, para
ello se le pasa como parmetro las muestras almacenadas en el buffer y
el nmero de muestras que se han capturado. Esta rutina al igual que la
anterior se basa en las rutinas realft, modulo y
extrae_subfingerprint.

void extrae_fingerprint_block(float *audio,int N1,int
finger_block[256][32]);

Realft: Para realizar la tranformacin al dominio de la frecuencia se
consult la referencia [10], esta rutina realiza una FFT de una seal real.
Para ello se le pasan como parmetros las muestras de la seal que se
quiere transformar, el nmero de puntos que tendr la transformada y
una bandera que indica el sentido de la transformacin. En nuestro caso
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
47
este ltimo parmetro debe valer siempre 1 para indicar que la
transformacin es del dominio del tiempo al de la frecuencia.

void realft(double data[], unsigned long n, int isign);

Modulo: Rutina que calcula el modulo de un vector de nmeros
complejos. Se utiliza para calcular el modulo de la FFT. A esta rutina se
le pasa como parmetro un vector de nmeros complejos y otro vector
donde se almacenar el resultado. Para desarrollar esta rutina se ha
hecho uso de la librera math.h.

void modulo( double *mod_fft_frame, double *fft_frame )

Extrae_subfingerprint: Rutina que calcula una sub-fingerprint a partir
del mdulo de la FFT de la seal de audio capturada. Se le pasa como
parmetro un vector donde se almacenar la sub-fingerprint calculada,
una tabla donde se almacenarn las energas parciales de cada banda y
el mdulo de la FFT.

void extrae_subfingerprint(int *subfingerprint, double
energia[2][33], double *mod_fft_frame)

Calcula_BER: Rutina que calcula la BER mnima entre un fingerprint-
block extrado de una captura de audio y todos los fingerprint-blocks que
forman parte de un anuncio que se quiere detectar. Para ello se le pasan
como parmetros un puntero donde se almacenar la BER calculada, el
fingerprint-block extrada, la fingerprint del anuncio que se quiere
detectar y el nmero de bytes que tiene el fingerprint del anuncio.

void calcula_BER( float *BER, int *block, int *fichero, int Nbytes)

Decisor: Rutina que se encarga de comparar el valor de la BER que se
le pasa como parmetro con el umbral de deteccin, si es menor llama a
la rutina anota_resultado.

void decisor(archivo_wav *anuncio,double maximo);

Anota_resultado: Rutina que se encarga de reflejar en la lista del
dilogo principal y en el fichero de resultado los anuncios detectados.

void anota_resultado(archivo_wav *anuncio,double maximo);

El fichero de resultado se denomina resultado.txt y en el fichero
se van almacenando los resultados de la aplicacin en sus diferentes
ejecuciones. Cuando se ejecuta la aplicacin se escribe en l un mensaje
donde aparece tambin la fecha actual, y despus van apareciendo las
detecciones junto con las cadenas donde se detectaron, la hora y
adems ( y solo en el fichero ) se escribe tambin el valor que provoc la
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
48
deteccin, de este modo se puede hacer una mejor interpretacin del
resultado ya que no es lo mismo una deteccin de 0,15 o 0,20 a una de
0,33 por ejemplo, y esto va a ayudar a la mejora de la deteccin de los
anuncios por parte del usuario.


4.2.2.- BREVE DESCRIPCIN DEL PROCESO DE DETECCIN

En primer lugar se ejecuta la fase de establecimiento del algoritmo. En
esta primera fase se leen los anuncios y las frecuencias o canales de TV.
Tambin se computa el tiempo de procesado para calcular el nmero de
detecciones posibles para cada anuncio. Los pasos que se van a seguir son los
siguientes:

1. Lectura de anuncios. En primer lugar se leen los anuncios que van a
formar parte del proceso de deteccin. En este paso se almacenan las muestras
de las fingerprints correspondientes a cada anuncio.

2. Lectura de frecuencias. Una vez almacenados los anuncios se leen las
frecuencias o cadenas de TV en las que se van a detectar los anuncios.

3. Se establece el temporizador que asegura la periodicidad del
algoritmo. Este temporizador tendr un valor ligeramente superior al tiempo de
captura. Con esto garantizamos que capturamos un nmero suficiente de
muestras para extraer un fingerprint-block. Los pasos 1, 2 y 3 se ven reflejados
en el cuadro de texto que aparece en la figura 32.


Figura 32. Fase de establecimiento del algoritmo.
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
49
4. Clculo del tiempo de procesado. En esta fase de establecimiento es
necesario calcular el tiempo que tarda el algoritmo en extraer el fingerprint-
block de las muestras del buffer y el tiempo que necesita para calcular la BER
con las fingerprints de los anuncios que forman parte del proceso.

5. Con el tiempo de procesado calculado se calcula mediante la rutina
calcula_saturaciones el nmero de veces que se podr detectar cada anuncio.
En caso de que exista algn tipo de problema la funcin avisar mediante
mensajes de error (explicacin ms detallada en el apartado 5.2 de la
memoria). Estos dos puntos se pueden observar en el cuadro de texto que
aparece en la figura 33.


Figura 33. Fase de establecimiento del algoritmo (2).

En segundo lugar se ejecuta la fase de aplicacin. En esta fase se
ejecuta peridicamente el algoritmo para identificar los anuncios emitidos. Los
pasos a seguir son:

6. Se recogen las muestras de audio capturadas del buffer.

7. Se extrae un fingerprint-block de las muestras del buffer. Este paso y
el anterior se ven reflejados en el cuadro de texto que aparece en la figura 34.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
50

Figura 34. Fase de aplicacin del algoritmo.

Los siguientes pasos se realizan por cada anuncio seleccionado para la
deteccin.

8. Se calcula la mnima BER entre el fingerprint-block extrado y todos los
fingerprint-blocks que pertenecen a cada anuncio.

9. Esta BER calculada se compara con un valor umbral. Si est por
debajo del umbral se escribir en pantalla y en el fichero de resultados la
deteccin del anuncio. Estos pasos se ven en el cuadro de texto de la figura 35.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
51

Figura 35. Fase de aplicacin del algoritmo (2).

Esta fase de aplicacin se ejecutar hasta que el usuario termine la
aplicacin.


4.3.- OTRAS CLASES PARA DECORACIN DE LA
INTERFASE

Se ha usado una clase denominada CButtonST para poner iconos a los
botones del dilogo y adems para que el cursor del ratn cambie cuando este
situado encima de un botn.

En las libreras del Visual C++ ya exista una clase para controlar los
botones del dilogo llamada CButton.

Los cambios que queramos realizar en el aspecto de los botones no te
permita hacerlo la clase CButton por si sola y por ello hay que usar una clase
que derive de ella y sobrecargar sus mtodos virtuales, en especial el mtodo
DrawItem.

Para realizar estas acciones hay que hacer los siguientes pasos:

1. Definir una variable miembro al botn de tipo CButtonST.

2. Para poner un icono se usa el mtodo SetIcon de la siguiente forma:

Nombre_variable.SetIcon(ID_ICON);

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
52
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 es necesario tener importado
en la 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.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
53

CAPTULO 5: FASE DE PRUEBAS. RESULTADOS Y
CONCLUSIONES

Este captulo del proyecto ha sido muy costoso tanto en tiempo y
esfuerzo, ya que conlleva el anlisis de muchas horas de grabaciones.

Las pruebas realizadas intentan demostrar la eficiencia computacional del
algoritmo de audio fingerprinting. Por otra parte tambin intentan ver cul es el
lmite de la aplicacin a la hora de la deteccin, es decir, cuntos anuncios es
capaz de detectar simultneamente sin dejar de funcionar correctamente.

Por ltimo se presentan una serie de conclusiones que sirven como gua
a la hora de utilizar la aplicacin.


5.1.- TIEMPOS DE COMPUTACION

En este apartado se examina el tiempo de computacin del algoritmo
que vamos a utilizar.

Para ello se ha medido el tiempo que tarda la aplicacin en las fases de
establecimiento y de aplicacin del algoritmo variando el nmero de anuncios
que se van a detectar. Los anuncios utilizados tienen una duracin comprendida
entre los 13 y los 38 segundos. Estos resultados se pueden ver en la tabla 3.

N de
Anuncios
Tiempo de
establecimiento
(seg.)
Tiempo de
computacin
(seg.)
Lmite
saturacin
(n
anuncios)
1 0.09 0.26 NO
2 0.11 0.44 NO
3 0.13 0.61 NO
4 0.13 0.681 NO
5 0.14 0.801 NO
6 0.15 0.912 NO
7 0.16 1.022 NO
8 0.17 1.162 NO
9 0.181 1.372 NO
10 0.19 1.492 NO
11 0.191 1.712 NO
12 0.201 1.773 NO
13 0.201 1.882 NO
14 0.21 2.013 NO
15 0.21 2.203 NO
16 0.22 2.394 NO
17 0.221 2.584 NO
18 0.23 2.604 NO
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
54
19 0.23 2.724 NO
20 0.26 2.844 NO
21 0.29 3.165 NO
22 0.29 3.185 NO
23 0.301 3.334 NO
24 0.31 3.405 NO
25 0.311 3.605 NO
26 0.32 3.736 NO
27 0.33 3.905 NO
28 0.33 4.056 NO
29 0.331 4.106 NO
30 0.34 4.257 NO
31 0.34 4.476 NO
32 0.35 4.617 NO
33 0.36 4.756 NO
34 0.35 4.807 NO
35 0.351 4.917 NO
36 0.37 5.178 NO
37 0.39 5.408 NO
38 0.391 5.467 NO
39 0.401 5.508 NO
40 0.41 5.668 NO
41 0.41 5.859 NO
42 0.421 5.988 NO
43 0.42 6.109 NO
44 0.431 6.209 NO
45 0.431 6.309 NO
46 0.4 6.399 NO
47 0.41 6.539 NO
48 0.451 6.76 SI

Tabla 3. Tiempos de establecimiento y de computacin del algoritmo de audio
fingerprinting.

Estos tiempos dependen del equipo en el que se ejecute la aplicacin en
nuestro caso es el equipo comentado en el apartado 3.1.1.

El tiempo de establecimiento tiene poca importancia en el proceso, ya
que como se puede ver en la tabla, nunca supera el medio segundo. Adems la
fase de establecimiento se realiza una vez al principio del proceso y no tiene
relevancia.

Es importante saber el tiempo que tarda la aplicacin de forma peridica
para hacer un uso correcto del detector. Por ejemplo, si miramos la tabla
anterior vemos que si seleccionamos 14 anuncios, la aplicacin tarda en dar
una pasada unos 2 segundos. De esta forma, si el anuncio en cuestin dura
unos 20 segundos, la aplicacin debera detectarlo de media unas 9 0 10 veces.

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
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
55
caso del ejemplo anterior solo aparece un detectado en pantalla, puede tratarse
de una falsa alarma, en cambio si aparecen ms pues se puede certificar que es
una deteccin correcta.

Estos tiempos calculados se pueden ver tambin en las figuras 36 y 37.


Figura 36. Tiempo de establecimiento del algoritmo de audio fingerprinting.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
56

Figura 37. Tiempo de computacin del algoritmo de audio fingerprinting.

En el captulo 1 se deca que la aplicacin est capacitada para trabajar
con una nica sintona de radio o un nico canal de TV (pero no ambas
opciones a la vez). Para que tericamente la aplicacin pudiese monitorizar
varias sintonas de radio a la vez (o varios canales de TV) se debera cumplir
que el tiempo de procesado sea mayor que el tiempo de captura de forma que
en cada ciclo el buffer tuviese nicamente muestras de una nica emisora.
Viendo la tabla 3 vemos que esta condicin se cumple para un nmero mayor
de 25 anuncios. Por tanto cabra pensar que se podra utilizar la aplicacin en
este modo con ms de 25 anuncios. Realmente no es as porque como veremos
en el captulo 5.3 el programa ofrece unos resultados bastante desfavorables a
partir de 20 anuncios.

Uno de los objetivos principales de este proyecto era mejorar la
eficiencia computacional de la aplicacin anterior. Como prueba de esta mejora
se han medido los tiempos de computacin de la aplicacin anterior. Esta
aplicacin utilizaba el algoritmo de correlacin para contrastar las tramas de
audio. En la figura 38 se pueden ver comparados los tiempos de computacin
de la aplicacin anterior y la aplicacin desarrollada.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
57

Figura 38. Comparativa entre los tiempos de computacin de la aplicacin anterior y
la aplicacin desarrollada en este proyecto.

Podemos ver claramente como el algoritmo de audio fingerprinting es
claramente mejor en cuanto a eficiencia computacional se refiere.


5.2.- LIMITE DE LA APLICACIN

Para que la aplicacin funcione adecuadamente, el tiempo de
computacin debe ser menor que la duracin del anuncio ms corto que se
quiera detectar. De esta forma se podr detectar al menos una vez.

El sistema est diseado para calcular este tiempo en la primera
ejecucin del algoritmo de deteccin. Una vez hecho esto calcula el nmero de
veces que puede detectar cada anuncio. Para ello divide el tiempo de duracin
de cada anuncio entre el tiempo de computacin calculado antes. El resultado
de esta operacin puede no ser entero, en ese caso se redondea al menor
entero.

Si el cociente anterior es mayor que 1 quiere decir que el anuncio se
podr detectar en su emisin ms de una vez, por tanto se podr distinguir de
una falsa alarma. Puede ser que el cociente de cmo resultado 1. Esto quiere
decir que el anuncio slo se podr detectar a lo ms una vez y no podramos
distinguirlo de una falsa alarma. Por ltimo el cociente puede dar cero y esto
indica que el anuncio no se puede detectar y por tanto la aplicacin no
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
58
funcionar correctamente. Un resumen de estos resultados se puede ver en la
tabla 4.



Nmero detecciones posible Explicacin
> 1 Funcionamiento Correcto
=1 Lmite de Saturacin
= 0 Saturacin
Tabla 4. Funcionamientos posibles en funcin del nmero de detecciones posible.


En la tabla 3 se puede ver como la aplicacin es capaz de funcionar
correctamente con 47 anuncios. A partir de 48 anuncios la aplicacin trabajara
en el lmite de saturacin y los resultados no seran 100% fiables. En el
apartado 5.3 veremos que realmente no es capaz de trabajar correctamente
con tantos anuncios y que la fiabilidad de la aplicacin empieza a disminuir.


5.3.- PRUEBAS REALIZADAS

Este apartado pretende ser una sntesis de las innumerables pruebas
realizadas para la verificacin del correcto funcionamiento de la aplicacin.

Para probar la fiabilidad de la aplicacin se ha desarrollado una
estrategia de grabacin y deteccin simultnea. De forma que paralelamente a
la deteccin se grababa la emisora que se estaba detectando con la intencin
de poder comprobar a posteriori si la deteccin fue o no correcta.

Todas las pruebas realizadas se han hecho en FM. Dentro de ellas
podemos distinguir dos tipos: pruebas correspondientes a anuncios grabados y
detectados en la misma cadena y a anuncios grabados y detectados en una
cadena diferente.

Las pruebas tenan como objetivo calcular cul es el lmite real de la
aplicacin. En el apartado 5.1 vimos que tericamente la aplicacin puede
funcionar hasta con 47 anuncios simultneamente. En estas pruebas hemos
tratado de comprobar si este lmite terico era real.

En todas las pruebas existen una serie de parmetros fijos que
comentamos a continuacin:

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
59
Duracin: La duracin de todas las pruebas ha sido de 8 horas.

Umbral de deteccin: El umbral elegido ha sido de 0,35.


El parmetro que se ido variando ha sido el nmero de anuncios a
detectar. Posteriormente a la prueba se ha calculado el porcentaje de aciertos
como:


5.3.1.- PRUEBAS EN MISMA CADENA

Esta prueba consiste en hacer la grabacin del anuncio en una cadena y
realizar el proceso de deteccin en la misma cadena con dicho anuncio.

En la siguiente tabla se pueden ver los resultados obtenidos para
anuncios grabados en una frecuencia y detectados en esa misma frecuencia.

N de anuncios Fallos
Falsas
Alarmas
Aciertos
Porcentaje
acierto (%)
1 0 0 2 100
2 0 0 4 100
3 0 0 4 100
4 0 0 5 100
5 0 0 5 100
6 0 0 8 100
7 0 0 8 100
8 0 0 9 100
9 0 0 10 100
10 0 0 11 100
11 0 0 11 100
12 0 0 9 100
13 0 0 13 100
14 1 0 12 92,23
15 1 0 14 93,33
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
60
16 2 0 19 90,47
17 3 0 25 89,28
18 3 0 27 90
19 4 0 28 87,5
20 6 0 21 77,77
21 6 0 20 76,92
22 8 0 18 69,23
23 9 0 16 64
24 12 0 16 57,14
25 12 0 15 55,55
26 12 0 14 53,84
27 13 0 13 50
28 12 0 12 50
29 12 0 11 47,82
30 12 0 10 45,45
Tabla 5. Resultados obtenidos con anuncios detectados en la misma frecuencia que
se grabaron.

En la tabla 5 se reflejan los resultados obtenidos para un mximo de 30
anuncios. Como el porcentaje de acierto para 30 anuncios tomaba un valor por
debajo del 50%, no se ha continuado realizando pruebas con ms anuncios.
Consideramos que un valor por debajo del 50% no es tolerable. Estos
resultados obtenidos los podemos ver tambin en la figura 39.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
61

Figura 39. Resultados obtenidos con anuncios detectados en la misma frecuencia
que se grabaron.

Como se puede apreciar en la figura el porcentaje de aciertos empieza a
decaer levemente a partir de los 14 anuncios pero todava tiene unos valores
aceptables. A partir de los 20 anuncios los resultados empiezan a no ser tan
buenos y la aplicacin empieza a no ser tan fiable. Por encima de los 20
anuncios el porcentaje de aciertos decae rpidamente.

Es muy importante resaltar que la aplicacin no ha detectado ninguna
falsa alarma en todas las pruebas realizadas. Si en el fichero de resultados
apareca una nica deteccin de un anuncio, sta siempre corresponda a una
deteccin correcta. Este resultado demuestra el potencial de identificacin que
tiene el algoritmo de audio fingerprinting.

Estos resultados demuestran que a pesar de que tericamente la
aplicacin podra trabajar sin llegar a saturarse con 47 anuncios, para tener
unos resultados aceptables la aplicacin no debera de trabajar
simultneamente con ms de 20 anuncios.


5.3.2.- PRUEBAS EN DIFERENTE CADENA

Esta prueba consiste en hacer la grabacin del anuncio en una cadena y
realizar el proceso de deteccin en una cadena diferente a la anterior con dicho
anuncio.
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
62

En la tabla 6 se pueden ver los resultados obtenidos en esta prueba.

N de anuncios Fallos
Falsas
Alarmas
Aciertos
Porcentaje
acierto (%)
1 0 0 3 100
2 0 0 3 100
3 0 0 2 100
4 0 0 4 100
5 0 0 4 100
6 0 0 5 100
7 0 0 2 100
8 1 0 5 83,33
9 1 0 3 75
10 2 0 3 60
11 3 0 4 57,14
12 5 0 5 50
13 6 0 6 50
14 6 0 5 45,45
15 6 0 5 45,45
16 7 0 5 41,66
Tabla 6. Resultados obtenidos con anuncios detectados en una frecuencia distinta
en la que se grabaron.

En la tabla anterior se reflejan los resultados obtenidos para un mximo
de 16 anuncios. Como el porcentaje de acierto para 16 anuncios tomaba un
valor por debajo del 50%, no se ha continuado realizando pruebas con ms
anuncios. Consideramos que un valor por debajo del 50% no es tolerable. Estos
resultados obtenidos los podemos ver tambin en la figura 40.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
63

Figura 40. Resultados obtenidos con anuncios detectados en una frecuencia distinta
en la que se grabaron.

Como se puede apreciar en la figura en esta prueba el porcentaje de
aciertos se mantiene en un 100% hasta los 7 anuncios. A partir de este valor
los resultados empiezan a ser muy desfavorables observando una cada muy
pronunciada para el porcentaje de aciertos. En esta prueba tampoco se
produjeron falsas alarmas.

Este problema es debido a pre-ecualizaciones de las emisoras de FM
antes de emitir. El detector no est preparado para este problema.

Estos resultados tan negativos aconsejan no utilizar el detector de este
modo. Si se decide hacerlo recomendamos hacerlo siempre con un nmero
menor de 7 anuncios.


5.4.- CONCLUSIONES

De los resultados obtenidos con las pruebas realizadas se desprenden las
siguientes conclusiones:

El algoritmo de audio fingerprinting es de media unas 5 o 6
veces ms rpido que el algoritmo de correlacin lo que permite
trabajar con muchos ms anuncios simultneamente.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
64
El programa est capacitado para detectar hasta 20 anuncios
simultneamente si los anuncios se detectan en la misma
frecuencia que se grabaron y hasta con 7 anuncios si se
detectan en una frecuencia distinta a la que se grabaron.

El programa podra trabajar tericamente con varias sintonas de
radio o de TV siempre que se trabaje con ms de 25 anuncios,
pero los resultados que se obtendran no seran del todo fiables.
Por tanto se recomienda utilizarlo siempre para monitorizar una
nica sintona de radio o un nico canal de TV.


5.5.- LINEAS FUTURAS DE INVESTIGACION

En este ltimo captulo de la memoria se exponen algunas de las
posibles lneas de investigacin que pueden ampliar y mejorar el proyecto.

MEJORA EFICIENCIA COMPUTACIONAL: A pesar de que esta
versin del proyecto mejora considerablemente la eficiencia
computacional de la versin anterior [11], la mejora en la
eficiencia computacional siempre es necesaria si se quiere que
este proyecto aspire a cotas mayores. Esta mejora
computacional consiste en el desarrollo de un algoritmo que
desempee la misma labor que el presente pero que realice un
menor nmero de operaciones.

De conseguir una mejora sustancial en el proceso permitira el
uso de la aplicacin con un mayor nmero de cadenas y
anuncios simultneamente.

REDUCCIN DEL TIEMPO DE CAPTURA: Conseguir un menor
tiempo de captura sera de vital importancia. Esto permitira a la
aplicacin trabajar simultneamente con varias cadenas con un
bajo nmero de anuncios.

SOFISTICADOS ALGORITMOS DE BSQUEDA: En este proyecto
la base de datos est limitada por el tiempo de computacin. Si
el tiempo de computacin disminuye permitira ampliar el
nmero de anuncios en la base de datos. Por tanto sera
necesario mejorar el algoritmo de bsqueda para minimizar el
tiempo de exploracin de la base de datos y mantener en
niveles aceptables el tiempo de computacin.

DESARROLLO COMPLETO DETECTOR ANUNCIOS TV: Desarrollar
una aplicacin destinada a la deteccin de los anuncios de TV
teniendo en cuenta tanto el audio como el video.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
65
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.




Deteccin e identificacin de anuncios de radio y televisin en tiempo real
66

CAPTULO 6: MANUAL DE USUARIO

El desarrollo de la aplicacin tena como objetivo la rapidez y la eficacia
computacional, pero en un segundo plano se ha diseado pensando en la
facilidad de manejo por parte del usuario final.

En este captulo se va a presentar un manual para la utilizacin de la
aplicacin. Para este captulo se han consultado las referencias [11] y [12].

Este manual est pensado para que cualquier lector pueda hacer un uso
correcto de la aplicacin, pero para tener un mayor control sobre la aplicacin
sera de gran utilidad que el lector tuviese unos conocimientos previos sobre
Visual Studio.

Como ya se ha descrito en numerosas ocasiones en el documento la
aplicacin realiza dos tareas independientes que son la de deteccin y la de
grabacin de anuncios para su posterior deteccin.


6.1.- INICIO DE LA APLICACIN

Despus de la ejecucin aparecer una pantalla como la siguiente:


Figura 41: Dilogo principal.
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
67
Esta es la pantalla principal de la aplicacin. Tal como se refleja en la
figura 41 tiene 4 botones, dos listas de datos, y un men. Comentaremos el
men ms adelante en el apartado 6.2.

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 que la tarjeta capturadora no est
instalada correctamente.

En el caso de la figura 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 3.

Como se explic anteriormente la frecuencia de muestreo para los dos
procesos era de 5 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 5
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.

6.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 42 que son:



Deteccin e identificacin de anuncios de radio y televisin en tiempo real
68
6.2.1.- Archivos


Figura 42: Men Archivos.

Que consta de dos elementos a su vez tal como se refleja en la figura 42.


6.2.1.1.- Anuncios

Al seleccionar este elemento sale un dilogo donde se seleccionan los
anuncios que queremos detectar (figura 43). 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 5.3 de la memoria).

Para ello se crea previamente una carpeta llamada ARCHIVOS dentro
del directorio base donde est el ejecutable y ah tenemos que
almacenar los archivos .fpr 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
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
69
anuncio escogido. Para terminar de elegir las frecuencias se pulsa en el
botn SALIR.


Figura 43: Dilogo Archivos.


6.2.1.2.- Salir

Cierra la aplicacin. Tiene el mismo efecto que el botn SALIR del
dilogo principal.


6.2.2.- Configurar

Este men tiene dos elementos tal como se refleja en la figura 44. A
continuacin se hace una descripcin ms detallada de ambos
elementos.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
70

Figura 44: Men Configurar.


6.2.2.1.- Sintonizador

Al seleccionar este elemento sale un cuadro de dilogo como el que
refleja la figura 45 y que sirve para sintonizar la cadena de radio o TV.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
71

Figura 45: Dilogo Sintonizador.

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.


6.2.2.2.- Configuracin

Al seleccionar este elemento aparece un dilogo secundario como el que
se muestra en la figura 46.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
72

Figura 46: Dilogo Configuracin.

Tal como refleja la ilustracin este dilogo sirve para cambiar el tipo de
entrada FM/TV y adems el parmetro valor umbral. Tiene por defecto
que se seleccione FM y 0.35 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
valor umbral hay que hacerlo antes de seleccionar el dispositivo.


6.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 figura 47.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
73

Figura 47: Dilogo Versin.


6.3.- GRABACIN

Una vez seleccionado el dispositivo de captura tal y como se explic en el
apartado 6.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 (figura 48). 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.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
74

Figura 48: Dilogo guardar archivo .fpr.


6.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 6.1.

La aplicacin utiliza un archivo llamado frecuencias.cfg para conocer las
cadenas en 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 figura 49.

En el caso de ser cadenas de TV es del mismo modo.


Figura 49: Muestra archivo frecuencias.cfg.
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
75

Tras esto se guarda el archivo con nombre frecuencias.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 figura 49 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.

Si una vez que se pulsa el botn DETECTAR aparece un mensaje en el
que nos avisa de que se est trabajando al lmite de saturacin de la aplicacin,
nos est avisando que hay anuncios que slo se podrn detectar una vez y
pueden ser confundidos con falsas alarmas. Por tanto debemos seleccionar un
nmero menor de anuncios. Tambin puede que nos aparezca un mensaje que
nos indica que la aplicacin est saturada, esto directamente indica que hay
anuncios que no se podrn detectar y hay que cerrar la aplicacin y seleccionar
un nmero menor de anuncios. Estas dos situaciones se pueden ver en las
figuras 50 y 51.


Figura 50. Mensaje de Lmite de Saturacin de la Aplicacin.



Figura 51. Mensaje de Saturacin de la Aplicacin.

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 (figura 52). Tambin aparecen el fichero
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
76
resultados.txt (figura 53), donde tambin se muestra la BER (Tasa de Error de
Bit) que se obtuvo en la deteccin.


Figura 52: Muestra anuncio detectado.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
77

Figura 53: Muestra fichero resultados.

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.


6.5.- CONFIGURACIN DE PARMETROS

En este apartado se resumen los conceptos desarrollados en toda la
memoria, siendo imprescindible su lectura para conseguir un funcionamiento a
medida de la aplicacin.

Es conveniente haber ledo antes el captulo 2 de la memoria, en el que
se fundamenta todo el proceso e introduce al lector en lo que sera la
configuracin de los parmetros en la aplicacin.

A continuacin se hace una descripcin sobre los pasos a seguir para la
configuracin del sistema en el proceso de deteccin en cada caso particular.

1. AJUSTE CONFIGURACIN SONIDO: hay que configurar el sonido del
ordenador personal de manera conveniente, hay que activar la lnea de
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
78
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 figura 54:


Figura 54: Configuracin sonido del sistema (grabacin).

2. ELECCIN UMBRAL DE DETECCIN: El umbral de deteccin tiene un
valor por defecto de 0,35 y se puede optar por cambiarlo en caso que se
crea necesario. Se recomienda no hacerlo ya que este valor ofrece muy
buenos resultados aunque tambin el usuario se puede guiar de su
propia experiencia con la aplicacin.

3. INICIAR APLICACIN: ejecutar la aplicacin. Antes de empezar el
proceso de deteccin hay que rellenar de manera adecuada (descrito en
6.4.) el fichero frecuencias.cfg.

4. COMENZAR DETECCIN: primero se configura el sistema con los
parmetros adecuados segn el punto 2. 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.

5. ESTUDIO DE LOS RESULTADOS: Tras la ejecucin de la aplicacin
llega lo ms importante que es la interpretacin de los resultados.

En el caso de trabajar en el lmite de saturacin de la aplicacin
(concepto explicado en el apartado de 6.4) es posible que nos aparezca
una deteccin de un anuncio aislada. Esto puede ser una deteccin
correcta o una falsa alarma y no tendramos forma de distinguirlas salvo
mirando el valor de la BER con el que se ha detectado, si es un valor
cercano al valor umbral es muy probable que fuese una falsa alarma,
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
79
aunque no tendramos ninguna certeza. Por tanto es recomendable no
trabajar nunca en esta situacin.

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.


Deteccin e identificacin de anuncios de radio y televisin en tiempo real
80

CAPTULO 7: MANUAL DEL DESARROLLADOR

Este manual est destinado a facilitar la introduccin de mejoras en el
presente proyecto as como hacer ms sencilla la implementacin de este tipo
de algoritmos con fuerte componente matemtico en el lenguaje de
programacin Visual C++.


Contenidos

1.- Descripcin de la aplicacin

2.- Requerimientos
2.1.- Hardware necesario para el desarrollo
2.2.- Software necesario para el desarrollo
2.2.1.- Sistema Operativo
2.2.2.- Microsoft Visual Studio 2005
2.2.2.1.- Iniciando Microsoft Visual C++
2.2.2.2.- Creando la aplicacin
2.2.2.3.- Entorno de desarrollo de Microsoft Visual C++
2.2.3.- SDK (Software Development Kit) de DirectX
2.2.3.1.- Componentes de DirectX
2.2.3.2.- Utilizando libreras DirectX

3.- Desarrollo de la interfase de comunicacin aplicacin-hardware
3.1.- Comunicacin entre los diferentes componentes
3.2.- Modo de funcionamiento de DirectShow
3.2.1.- Interfaces necesarios para controlar un dispositivo de captura
3.2.2.- Creando un grafo DirectShow

4.- Estructura de la aplicacin
4.1.- Creando la base de datos
4.1.1.- Tareas asociadas a la creacin de la base de datos
4.2.- Implementando el algoritmo de identificacin
4.2.1.- Caractersticas que debe tener el algoritmo de identificacin
4.2.2.- Tareas asociadas al proceso de identificacin
4.2.2.- Implementando algoritmos de identificacin en Visual C++

5.- Bibliografa recomendada










Deteccin e identificacin de anuncios de radio y televisin en tiempo real
81
7.1.- DESCRIPCIN DE LA APLICACIN

La presente aplicacin pretende proporcionar una solucin al problema
de la identificacin de anuncios de radio y de televisin en tiempo real.

Para este propsito se desarrolla una aplicacin con una interfaz grfica
amigable y de fcil uso y comprensin por parte del usuario.

Esta aplicacin debe necesitar un hardware sencillo, fcil de adquirir y
asequible econmicamente.


7.2.- REQUERIMIENTOS

7.2.1.- HARDWARE NECESARIO PARA EL DESARROLLO

Para la ejecucin de la aplicacin as como para el desarrollo de futuras
mejoras es necesario contar con un PC domstico o un equipo porttil como
plataforma donde la aplicacin correr.

Para la captura de las tramas de audio de los anuncios de radio y
televisin se necesita una tarjeta capturadora. Esta tarjeta puede ser externa o
interna si el equipo es un PC o externa en caso de tratarse de un equipo
porttil.


7.2.2.- SOFTWARE NECESARIO PARA EL DESARROLLO

7.2.2.1.- SISTEMA OPERATIVO

La plataforma de trabajo elegida para el desarrollo y ejecucin de la
aplicacin es el sistema operativo Windows. La aplicacin debe funcionar
adecuadamente en versiones superiores a Windows 98.


7.2.2.2.- MICROSOFT VISUAL STUDIO 2005

Para desarrollar las futuras mejoras o versiones diferentes de la
aplicacin se necesita una herramienta de programacin con la que escribir el
cdigo fuente de la aplicacin.

Para sistemas operativos Windows Microsoft proporciona el software de
desarrollo conocido como Microsoft Visual Studio.

Microsoft Visual Studio 2005 proporciona una amplia variedad de
herramientas para el desarrollo de aplicaciones software. Estas herramientas
son:
.NET Framework.
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
82
ASP.NET.
Visual Basic.
Visual C#.
Visual C++.
Visual J#.

De entre todas estas herramientas se utiliza el lenguaje de programacin
Visual C++. La razn es que las otras herramientas estn ms enfocadas al
desarrollo de aplicaciones web o aplicaciones que interaccionan con grandes
bases de datos.

Por tanto para la implementacin de la aplicacin es necesario tener
instalada la herramienta Visual C++.


7.2.2.2.1- INICIANDO VISUAL C++

Una vez instalado Microsoft Visual C++ en el equipo debemos iniciar el
entorno de desarrollo, para ello debemos seguir los siguientes pasos:

1. En el escritorio de Windows, situamos el puntero del ratn en el men
Inicio, en la esquina inferior izquierda, y pulsamos el botn izquierdo
del ratn.
2. Elegir la opcin Programas en el men Inicio.
3. En el siguiente men, aparece la opcin Microsoft Visual C++ 6.0.
4. Elegir la opcin Microsoft Visual C++ 6.0 en el men.
5. Transcurrido el tiempo de carga, se muestra el escritorio de Microsoft
Visual C++ 6.0. Cerrar la ventana adicional que se presenta, Tip of the
day, pulsando el botn Close.

Estos pasos se ilustran en la figura 55.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
83

Figura 55. Iniciando Microsoft Visual C++.


7.2.2.1.2.- CREANDO LA APLICACIN

Una vez abierto Microsoft Visual C++ debemos generar un nuevo
proyecto que ser el esqueleto de nuestra aplicacin. De entre las muchas
opciones que ofrece Visual C++ elegimos generar una aplicacin MFC
AppWizard. Esta opcin genera un archivo ejecutable que presenta al usuario
una ventana principal con la que interaccionar. Vemos esta opcin en la figura
56.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
84

Figura 56. Creando una aplicacin MFC AppWizard.

La forma de interactuar con la aplicacin de entre las opciones que se
presenten debe ser mediante dilogos. Por tanto dentro de la opcin AppWizard
se debe elegir crear un proyecto basado en dilogos (figura 57).

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
85

Figura 57. Creando una aplicacin basada en dilogos.


7.2.2.1.3.- ENTORNO DE DESARROLLO DE MICROSOFT VISUAL C++

El entorno de desarrollo de Visual C++ es un entorno grfico muy
ilustrativo. Se descompone en 5 partes:

Men.
Barra de Herramientas.
Workspace.
Editor de Cdigo Fuente.
Ventana de presentacin.
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
86

Figura 58. Entorno de desarrollo de Microsoft Visual C++.


7.2.2.3.- SDK (SOFTWARE DEVELOPMENT KIT) DE DIRECTX

Para el desarrollo de este tipo de aplicaciones es necesario contar con
una serie de libreras que permitan utilizar y controlar adecuadamente el
hardware. Para este fin Microsoft proporciona una serie de libreras conocidas
como DirectX. Estas libreras permiten controlar dispositivos hardware de
diferente ndole. En nuestra aplicacin slo necesitamos las libreras que
proporcionen un control pleno sobre dispositivos de captura. Estas libreras las
facilita el paquete de desarrollo conocido como DirectShow.

El paquete de libreras de DirectX est disponible en la pgina web de
Microsoft (www.microsoft.com). Tan slo es necesario descargarlas y seguir los
pasos de instalacin.


7.2.2.3.1.- COMPONENTES DE DIRECTX

DirectX se compone de varios componentes, los comentamos a
continuacin:

DirectX Graphics: se utiliza para la programacin de aplicaciones con
grficos.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
87
Microsoft DirectInput: se utiliza para controlar todo tipo de
dispositivos de entrada.

Microsoft DirectPlay: se utiliza para programar juegos multijugador
en red.

Microsoft DirectSound: se utiliza para desarrollar aplicaciones de
audio de alta calidad que reproduzcan y capturen formas de onda.

Microsoft DirectMusic: provee una solucin para el desarrollo de
reproductores de audio.

Microsoft DirectShow: se utiliza para controlar dispositivos de captura

En nuestro caso tenemos que controlar una tarjeta capturadora para
monitorizar los canales de radio y de televisin, por tanto slo haremos uso del
componente DirectShow.


7.2.2.3.2.- UTILIZANDO LIBRERAS DIRECTSHOW

Una vez instaladas las libreras DirectShow en el equipo es necesario
enlazarlas al compilador de Visual C++ para poder hacer un uso correcto de
ellas. Esta opcin se encuentra en la pestaa Tools del men principal,
concretamente hay que elegir la opcin options. Esto se muestra en la figura
59.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
88

Figura 59. Libreras enlazadas al compilador.


7.3.- DESARROLLO DE LA INTERFASE DE COMUNICACIN
APLICACIN-HARDWARE

En este apartado se explica como crear la interfase de comunicacin
entre el dispositivo capturador y la aplicacin. En primer lugar se comenta como
se comunican los diferentes componentes que forman parte del proceso y en
segundo lugar se comentan las herramientas especficas que se deben usar.


7.3.1.- COMUNICACIN ENTRE LOS DIFERENTES COMPONENTES

En este apartado se comenta brevemente como se comunican entre s
los diferentes componentes que forman parte del proyecto para que el futuro
desarrollador tenga una idea general del proceso. En la figura 60 se puede ver
un esquema de bloques de este proceso. Como se puede ver en la figura para
hacer uso del hardware, el desarrollador tan slo debe conocer las
herramientas que proporciona DirectX para tal fin. En otras palabras, no debe
preocuparse de cmo se comunica DirectX con los manejadores del hardware.
Esta particularidad facilita mucho la labor de programacin. Si a esto anterior le
sumamos que DirectX proporciona en su documentacin multitud de cdigo
fuente de ejemplo, podemos concluir que resulta relativamente sencillo la
implementacin de la interfase de comunicacin entre la aplicacin y el
hardware.
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
89

Figura 60. Comunicacin entre hardware, S.O, DirectX y la aplicacin.


7.3.2.- MODO DE FUNCIONAMIENTO DE DIRECTSHOW

El funcionamiento de DirectShow se basa en la correcta conexin de
filtros DirectShow, controlando adecuadamente sus propiedades y haciendo las
conexiones con los pines adecuados de cada filtro. Un filtro representa un
dispositivo instalado en el sistema de forma Hardware o Software teniendo una
funcionalidad propia. En la figura 61 se puede ver un ejemplo de un grafo de
captura DirectShow que guarda los datos capturados en un archivo.


Figura 61. Ejemplo de grafo de captura DirectShow.




Deteccin e identificacin de anuncios de radio y televisin en tiempo real
90
7.3.2.1.- INTERFACES NECESARIOS PARA CONTROLAR UN
DISPOSITIVO DE CAPTURA

DirectShow dispone de una amplia coleccin de interfaces para controlar
los parmetros y propiedades de los filtros de que dispone. A continuacin
comentamos los ms importantes que son necesarios para el control de un
dispositivo de captura. De esta forma ahorramos al desarrollador la inversin de
un preciado tiempo en la lectura de los interfaces disponibles.

IGraphBuilder: es una interfaz necesaria para construir un grafo de
filtros.

ICaptureGraphBuilder2: Interfaz usada para construir un grafo
concretamente de tipo captura, es decir, donde intervenga un
dispositivo de captura.

IBaseFilter: Sirve para controlar los filtros.

IMediaControl: Interfaz que proporciona mtodos para controlar el
flujo de datos a travs del grafo.

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.

IAMTVTuner: Interfaz que proporciona mtodos para la
sintonizacin del dispositivo.

IAMStreamConfig: Interfaz usada para conseguir el formato
deseado de los datos.

ICreateDevEnum, IEnumMoniker e IMoniker: Usadas
conjuntamente para conseguir enumerar los dispositivos hardware del
sistema y as poder encontrar el dispositivo de captura adecuado a
nuestras necesidades.


7.3.2.2.- CREANDO UN GRAFO DIRECTSHOW

Para crear un grafo de captura DirectShow hay que realizar dar una serie
de pasos:

1. Instanciar el filtro principal para el grafo.

hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IGraphBuilder, (void **)&gcap.pFg);

2. Instanciar el filtro de grafo de captura.
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
91

hr = CoCreateInstance((REFCLSID)CLSID_CaptureGraphBuilder2,
NULL, CLSCTX_INPROC, (REFIID)IID_ICaptureGraphBuilder2,
(void **)&gcap.pBuilder);

3. Asociar este grafo de captura con el grafo principal.

gcap.pBuilder->SetFiltergraph(gcap.pFg);

Llegado a este punto tendramos creado un grafo de captura, a partir de
este momento se deben ir aadiendo filtros al grafo hasta que ste adquiera la
configuracin deseada. Para conectar cualquier nuevo filtro hay que:
instanciarlo, aadirlo al grafo y conectarlo. Por ejemplo para aadir un buffer al
grafo.

4. Instanciar el filtro que representa el buffer (Sample Grabber).

hr = CoCreateInstance(CLSID_SampleGrabber, NULL, LSCTX_INPROC_SERVER,
IID_IBaseFilter, (void**)&gcap.pGrabberf);

5. Aadir el filtro al grafo.

hr = gcap.pFg->AddFilter(gcap.pGrabberf, L"Sample Grabber");

6. Conectar el filtro con los filtros convenientes.

conecta(gcap.pSrc,gcap.pGrabberf);

Esta manera de proceder se debe realizar para todos los filtros que se
quieran aadir al grafo de captura.


7.4.- ESTRUCTURA DE LA APLICACIN

Para desarrollar cualquier tipo de aplicacin que tenga como objetivo la
deteccin de anuncios en tiempo real es necesario implementar dos tareas
independientes. La primera es la creacin de la base de datos que se va usar
como referencia para la deteccin. La segunda es la implementacin de un
algoritmo de identificacin con el que comparar los anuncios que se emiten y
los anuncios en la base de datos.


7.4.1.- CREANDO LA BASE DE DATOS

7.4.1.1.- TAREAS ASOCIADAS A LA CREACIN DE LA BASE DE DATOS

La base de datos que sirve como referencia para la identificacin debe
contener elementos que identifiquen los anuncios de manera unvoca. Estos
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
92
elementos se obtendrn a partir de las muestras de audio originales del anuncio
emitido ya sea de radio o televisin.

Para crear la base de datos se debe implementar una tarea de grabacin.
Esta tarea debe almacenar en algn formato concreto las muestras de audio
capturadas por la tarjeta capturadora. Para este propsito es necesario
implementar un grafo DirectShow que realice esta grabacin.

Una vez almacenadas las muestras de audio se puede proceder al clculo
de los elementos que identificarn a los anuncios en el proceso de deteccin. La
naturaleza de estos elementos est ntimamente ligada al algoritmo de
identificacin. Como ejemplos podemos citar el algoritmo de correlacin, en el
que el elemento identificador sern las tramas de audio grabadas de la tarjeta
capturadora o el algoritmo de audio fingerprinting, en el que el elemento
identificador sern las huellas extradas de las muestras de audio.

Por ltimo debemos procurarle un formato concreto al elemento
identificador calculado para almacenarlo e indexarlo adecuadamente en la base
de datos.

Las tareas necesarias para la creacin de la base de datos se pueden ver
en la figura 62.


Figura 62. Tareas asociadas a la creacin de una base de datos.


7.4.2.- IMPLEMENTANDO EL ALGORITMO DE IDENTIFICACIN

7.4.2.1.- CARACTERSTICAS QUE DEBE TENER EL ALGORITMO DE
IDENTIFICACIN

Las caractersticas ms importantes que debe tener el algoritmo de
identificacin son:

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
93
Robusto: debe permitir la identificacin con alto nivel de
distorsin en la seal e interferencia en el canal de transmisin.
Esta propiedad es muy importante porque las muestras de
audio que capturamos proceden de radiodifusin y en algunos
casos la seal puede estar muy degrada.

Eficiente computacionalmente: Cuanto menor tiempo lleve
comparar dos tramas de audio, ms anuncios podremos
detectar simultneamente.

Precisa: El nmero de identificaciones correctas debe ser muy
alto y por tanto la tasa de fallos muy baja.


7.4.2.2.- TAREAS ASOCIADAS AL PROCESO DE IDENTIFICACIN

La segunda de las tareas es la tarea de identificacin. Esta tarea debe
proporcionar una solucin al problema de la comparacin entre los anuncios
emitidos y los anuncios en la base de datos.

Al igual que en la creacin de la base de datos, es necesario dar una
serie de pasos que son comunes a la mayora de los algoritmos de
identificacin. Estos pasos se pueden ver en la figura 63.


Figura 63. Tareas asociadas a la identificacin de anuncios.

Como vemos en la figura el primer paso es capturar las muestras de
audio con la tarjeta capturadora. El nmero de muestras capturado no tiene
que ser el mismo que el nmero de muestras que componen el anuncio
completo. De hecho debe ser as para tener una mejor eficiencia
computacional.

Los pasos segundo y tercero pueden no estar dependiendo del algoritmo
elegido. Como norma se puede decir que cunto ms sofisticado es el algoritmo
de identificacin, estos dos pasos siempre aparecern y adems sern ms
complejos.
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
94

Una vez calculado el elemento identificador el siguiente paso es
compararlo con los elementos identificadores de la base de datos que
representan a los anuncios que se desean detectar. En este paso debemos
utilizar alguna tcnica que nos permita cuantificar cmo de parecidos son dos
elementos identificadores. Esta tcnica deber ser escogida convenientemente
e ir en funcin de la representacin adoptada para el elemento identificador.

Por ltimo, una vez obtenido el valor de la comparacin el siguiente paso
es contrastarlo con un valor umbral. La eleccin de este valor umbral se hace
en base a la probabilidad de error de identificacin que depender de la
naturaleza de cada algoritmo. Si el resultado de esta comparacin es positivo se
concluye que el anuncio se ha detectado, si es negativo el anuncio no se habr
emitido.


7.4.2.3.- IMPLEMENTANDO ALGORITMOS DE IDENTIFICACIN EN
VISUAL C++

Visual C++ es un lenguaje de programacin de propsito general. En
principio no es el ms adecuado para implementar cualquier tipo de algoritmo
con un fuerte componente matemtico.

Visual C++ en su paquete de libreras facilita la librera math.h. En esta
librera se pueden encontrar funciones trigonomtricas bsicas, logartmicas y
clculo de races cuadradas o valores absolutos. A priori estas funciones pueden
ser insuficientes para algoritmos complejos como son los algoritmos de
identificacin.

Tareas tpicas que realizan los algoritmos de identificacin pueden ser:
transformadas al dominio de la frecuencia, operaciones con nmeros
complejos, etc. Estas tareas si se implementan incorrectamente pueden
suponer un coste computacional excesivo para aplicaciones como la nuestra
que trabajan en tiempo real.

Como norma general recomendamos buscar bibliografa especfica para
la implementacin de funciones matemticas bsicas. Por funciones bsicas
entendemos: operaciones con vectores o matrices (determinante, clculo de
matriz inversa), transformadas de la seal (FFT, IDFT), operaciones con
nmeros complejos (mdulo de un nmero complejo, descomposicin en forma
polar), etc. Existe una amplia bibliografa que tiene este tipo de funciones
implementadas en C++ de forma que el desarrollador tan slo tiene que
copiarlas y utilizarlas.


7.5.- BIBLIOGRAFA RECOMENDADA

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
95
[1] Press, W. H. Numerical recipes in C : the art of scientific computing.
Cambridge University Press.

[2] Chapman, D. Teach Yourself Visual C++ 6 in 21 days.

[3] Dunlop, R. Teach Yourself DirectX 7 in 24 hours.

[4] Demian C. Panello. Introduccin a la Programacin Orientada a
Objetos. Manual obtenido en internet.
URL: http://www.dcp.com.ar/

[5] Demian C. Panello. Apunte de Visual C++.
Manual obtenido en internet.
URL: http://www.dcp.com.ar/

[6] Paul Bustamante, Iker Aguinaga, Miguel Aybar, Iigo Lazacano y Luis
Olaizola. Aprenda C++ Avanzado como si estuviera en primero.

[7] MSDN. Ayuda del Visual Studio.

[8] Microsoft DirectX 9.0 SDK. Documentation for C++.




Deteccin e identificacin de anuncios de radio y televisin en tiempo real
96

ANEXO 1: POSIBLES PROBLEMAS DE LA
APLICACIN

Anexo que argumenta los posibles problemas que pueden surgir al
utilizar la aplicacin y aporta soluciones a los mismos.


A1.1. INSTALACIN DE LIBRERAS

Hay que tener instalada en el sistema las libreras DirectX 9.0a (o alguna
superior). Las libreras se pueden conseguir de muchas formas. El software que
viene con la tarjeta capturadora suele tenerlas. De no ser as se pueden
descargar gratuitamente de Microsoft (www.microsoft.com).


A1.2. LISTA DE ANUNCIOS CAPTURADOS VACA

Si la lista de anuncios aparece vaca, y se tiene la constancia de tener
almacenado algn anuncio, hay que comprobar que el directorio donde se
almacenan los anuncios se llama ARCHIVOS, y se encuentra en el directorio
base de la aplicacin (donde se encuentra el ejecutable).

Adems los anuncios almacenados en este directorio deben ser de
extensin .wav.


A1.3. PROBLEMAS CUANDO SE PULSA DETECTAR

El problema ms frecuente est relacionado con el fichero
frecuencias.cfg. Hay que asegurarse que existe en la aplicacin un fichero
frecuencias.cfg y que se encuentre situado en el directorio base de la
aplicacin (donde se encuentra el ejecutable de la aplicacin).

Adems hay que introducir la informacin de los canales de manera
adecuada tal y como se ha explicado en el apartado 6.4 de la memoria.


A1.4. NO SE ESCUCHA CUANDO SE SELECCIONA EL
DISPOSITIVO

Si la tarjeta capturadora est instalada convenientemente (con los
controladores actualizados) y no se escucha nada en la aplicacin al ejecutarse,
hay que instalar tambin el software que viene acompaando a la tarjeta. Tras
la instalacin de ese software se vuelve a ejecutar la aplicacin, si se escucha
algo (aunque sea solo ruido) ya est solucionado, en el caso de que no se
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
97
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.


A1.5. PROBLEMAS CUANDO SE PULSA GRABAR

La primera vez que se ejecuta la aplicacin y que su funcionamiento sea
correcto si intentas grabar algo es muy probable que salga un error que no
permita continuar.

Este error es debido a que el grafo DirectShow utilizado para la
grabacin contiene el filtro WAVDEST, y este filtro con las versiones DirectX
actuales no se instala ni se registra en el sistema.

La solucin est en registrar este filtro en el sistema (archivo
WavDest.ax). Vamos a aportar 2 soluciones al problema:

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:

C:\DX90SDK\Samples\C++\DirectShow\BaseClasses

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
98
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.

2 SOLUCIN: Registrar el filtro mediante la aplicacin Regsvr32.

Pasos:

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 figura 64:


Figura 64: Mensaje de registro correcto.

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.



Deteccin e identificacin de anuncios de radio y televisin en tiempo real
99

ANEXO 2: FORMATO DE LOS FICHEROS WAV

El formato WAV es uno de los formatos de fichero ms utilizados para
almacenar sonidos.

Se trata de almacenar las muestras una tras otra (a continuacin de la
cabecera del fichero, que entre otras cosas indica la frecuencia de muestreo),
sin ningn tipo de compresin de datos, con cuantificacin uniforme.

La sencillez de este formato lo hace ideal para el tratamiento digital del
sonido. La cabecera puede discernir segn que aplicacin se escoja para la
formacin del fichero .WAV, pero lo importante al menos en nuestro caso es
que los datos van siempre detrs de data y Nmero de bytes muestreados,
y en esto se basa la rutina leewav desarrollada, en buscar en el fichero la
palabra data.


FORMATO DE LOS FICHEROS .WAV

Bytes
Contenido
Usual
Propsito/Descripcin
00-03 "RIFF" Bloque de identificacin (sin comillas).
04-07 ??? Entero largo. Tamao del fichero en bytes, incluyendo cabecera.
08-11 "WAVE" Otro identificador.
12-15 "fmt " Otro identificador.
16-19 16, 0, 0, 0 Tamao de la cabecera hasta este punto.
20-21 1, 0
Etiqueta de formato. (Algo as como la versin del tipo de formato
utilizado).
22-23 1, 0 Nmero de canales (2 si es estreo).
24-27 ??? Frecuencia de muestreo (muestras/segundo).
28-31 ??? Nmero medio de bytes/segundo.
32-33 1, 0 Alineamiento de bloque.
34-35 8, 0 Nmero de Bits por muestra (normalmente 8, 16 32).
36-39 "data" Marcador que indica el comienzo de los datos de las muestras.
40-43 ??? Nmero de bytes muestreados.
resto ??? Muestras (cuantificacin uniforme)
Tabla 7. Formato de los ficheros .wav.


Deteccin e identificacin de anuncios de radio y televisin en tiempo real
100
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.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
101

ANEXO 3: CDIGO FUENTE

A3.1. Clase CRadioApp

Radio.h

// Radio.h : main header file for the RADIO application
//

#if !defined(AFX_RADIO_H__8975FB44_119A_45F1_8728_697743F5B053__INCLUDED_)
#define AFX_RADIO_H__8975FB44_119A_45F1_8728_697743F5B053__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#ifndef __AFXWIN_H__
#error include 'stdafx.h' before including this file for PCH
#endif

#include "resource.h" // main symbols

/////////////////////////////////////////////////////////////////////////////
// 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 //efined(AFX_RADIO_H__8975FB44_119A_45F1_8728_697743F5B053__INCLUDED_)

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
102
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
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
103
// the specific initialization routines you do not need.

#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif

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;
}
























Deteccin e identificacin de anuncios de radio y televisin en tiempo real
104
A3.2. Clase CRadioDlg

RadioDlg.h

// RadioDlg.h : header file
//

#if !defined (AFX_RADIODLG_H__3B0CEA02_43B6_
4949_9DD7_0909CF92726C__INCLUDED_)
#define AFX_RADIODLG_H__3B0CEA02_43B6_4949_9DD7_0909CF92726C__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

////////////////////////////////////////////////////////////////////////////
//
// Definimos las constantes de nuestra funcion

#define N 2048
#define MAX_TAM 18368
#define Pi 3.141592654
#define SWAP(a,b) tempr=(a);(a)=(b);(b)=tempr


#include "Dshow.h"
#include "Dialosint.h"
#include "Archivos.h"
#include "Configuracion.h"
#include "Qedit.h"
#include <fstream.h>
#include "ButtonST.h"


static const GUID CLSID_WavDest =
{ 0x3c78b8e2, 0x6c4d, 0x11d1, { 0xad, 0xe2, 0x0, 0x0, 0xf8, 0x75, 0x4b, 0x99 } };

/////////////////////////////////////////////////////////////////////////////
// CRadioDlg dialog

struct archivo_fpr {
int *archivo;
int N1;
long frecuencia;
CString anuncio;
int posibles_detecciones;
};


class CRadioDlg : public CDialog
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
105
{
// Construction
public:
CRadioDlg(CWnd* pParent = NULL); // standard constructor

// Dialog Data
//{{AFX_DATA(CRadioDlg)
enum { IDD = IDD_RADIO_DIALOG };
CListBox m_anuncio;
CButtonST m_grabar;
CButtonST m_deteccion;
CButtonST m_salir;
CListBox m_ListaCaptura;
CString m_status;
//}}AFX_DATA

// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CRadioDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}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,double
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
106
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();
void decisor(archivo_fpr *anuncio,float BER);
void anota_resultado(archivo_fpr *anuncio,float BER);
int calcula_posibles_detecciones(int N1);
void calcula_frecuencias_deteccion();
void extrae_fingerprint(float *audio,int N1, CString nombre_archivo);
void extrae_subfingerprint( int *subfingerprint, double energia[2][33], double
*mod_fft_frame);
void escribe_subfingerprint( int *subfingerprint, CString nombre_anuncio);
void modulo( double *mod_fft_frame, double *fft_frame );
void realft(double data[], unsigned long n, int isign);
void four1(double data[], unsigned long nn, int isign);
void actualiza_energia( double energia[2][33] );
void extrae_fingerprint_block(float *audio,int N1,int finger_block[256][32]);
void cambia_formato(int finger_block[256][32], int *block);
void calcula_BER( float *BER, int *block, int *fichero, int Nbytes);
int *lee_finger(int *N1,CString nombre_anuncio);
void calcula_saturaciones(double tiempo_procesado_total);

public:

void cambia_canal(long canal);
CConfiguracion configuracion;
CDialosint dialogo2;
CArchivos dialogo_archivo;
long *frecuencias;
long *frecuencias_deteccion;
CString nombre_anuncio;


private:
};



//{{AFX_INSERT_LOCATION}}
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
107
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif //
!defined(AFX_RADIODLG_H__3B0CEA02_43B6_4949_9DD7_0909CF92726C__INCLUDED_
)













































Deteccin e identificacin de anuncios de radio y televisin en tiempo real
108
CRadioDlg.cpp

// RadioDlg.cpp : implementation file
//

#include "Dshow.h"
#include "stdafx.h"
#include "Radio.h"
#include "RadioDlg.h"
#include <math.h>
#include "time.h"
#include <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_fpr *tabla_anuncios;
int freq;
long frecuencia_anterior;
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
109
double tiempo_procesado_total;
CMenu *Menu;
CTime actual;
fstream fichero_resultado;
double tiempo_captura;
int grabar=0;
bool primera_ejecucion=TRUE;

/////////////////////////////////////////////////////////////////////////////
// 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); // DDX/DDV support
//}}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
}


Deteccin e identificacin de anuncios de radio y televisin en tiempo real
110
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
// No message handlers
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// 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()
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
111
/////////////////////////////////////////////////////////////////////////////
// CRadioDlg message handlers

BOOL CRadioDlg::OnInitDialog()
{
CDialog::OnInitDialog();

// Add "About..." menu item to system menu.

// 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);
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
112
// 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();

// Inicializo algunas variables

freq=0;
dialogo_archivo.seleccion=0;
m_status="";

//doy valor por defecto al tiempo de captura y al umbral

tiempo_captura=3.6736;

configuracion.m_umbral=0.35;

//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();
}
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
113
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.

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

gcap.pControl->Stop(); // Paro el grafo de grabacion
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
114

if( grabar==TRUE )
{
int size=strlen(nombre_anuncio);

char *auxiliar=new char[size];

strcpy(auxiliar,nombre_anuncio);

for(int j=0;j<size;j++)
{
if(auxiliar[j]=='f')
if(auxiliar[j+1]=='p')
if(auxiliar[j+2]=='r')
break;
}

auxiliar[j]='w';
auxiliar[j+1]='a';
auxiliar[j+2]='v';

//ahora extraigo las subfingerprints de la cadena de audio grabada.

float *muestras;
int N_muestras;

muestras=leewav(&N_muestras,auxiliar);

extrae_fingerprint(muestras,N_muestras,nombre_anuncio);

CFile wav;
wav.Remove(auxiliar); // borramos el archivo wav que creamos para extraer las
// fingerprints

grabar=FALSE;
}

fichero_resultado.close();

//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);
SAFE_RELEASE(gcap.pFileSink);
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
115
SAFE_RELEASE(gcap.pGrabber);
SAFE_RELEASE(gcap.pGrabberf);
SAFE_RELEASE(gcap.pnull);
SAFE_RELEASE(gcap.pBar);


UtilDeleteMediaType(pmt);

// Hay que borrar tambin las listas que se vayan creando

m_ListaCaptura.ResetContent();

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();
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
116
return hr;
}

//////////////////////////////////////////////////////////////////////

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);


Deteccin e identificacin de anuncios de radio y televisin en tiempo real
117
pPropBag->Release();

// No se libera el IMoniker para poder usarlo despues
}

return hr;
}

//////////////////////////////////////////////////////////////////////

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);
}

//////////////////////////////////////////////////////////////////////

void CRadioDlg::iniciacaptura()
{
// pongo el cdigo necesario para empezar

CoInitialize(NULL);

// 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);

hr = gcap.pFg->QueryInterface(IID_IMediaControl, (void **)&gcap.pControl);

EnumFiltersWithMonikerToList(NULL,&CLSID_AudioInputDeviceCategory,
m_ListaCaptura);
}


Deteccin e identificacin de anuncios de radio y televisin en tiempo real
118
//////////////////////////////////////////////////////////////////////

HRESULT CRadioDlg::GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin)
{
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);
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
119

hr=gcap.pFg->Connect(pinprueba1,pinprueba2);

(pinprueba1)->Release();
(pinprueba2)->Release();
}

//////////////////////////////////////////////////////////////////////
//funcin que prepara toda la caracterstica del audio.

HRESULT CRadioDlg::SetAudioProperties(int nChannels,int nBytesPerSample,int
nFrequency,double 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 dispositivo 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();
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
120
}

// Configuracin de audio deseada

hr = pPin->QueryInterface(IID_IAMStreamConfig, (void **)&pCfg);

if (FAILED(hr))
{
pPin->Release();
}
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();
}

//////////////////////////////////////////////////////////////////////



Deteccin e identificacin de anuncios de radio y televisin en tiempo real
121
void CRadioDlg::OnSeldisp()
{
// 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,5000,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);

hr=gcap.pControl->Run();

}
}


//////////////////////////////////////////////////////////////////////

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
122
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);

hr=pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,
&pClassEnum, 0);

ULONG cFetched;

if(hr==S_OK)
{
if (pClassEnum->Next(1, &pmVideo, &cFetched) == S_OK)
{
((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))
{
IBaseFilter *pFilter = NULL;
hr = gcap.pBar->QueryInterface(IID_IBaseFilter, (void**)&pFilter);
if (SUCCEEDED(hr))
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
123
{
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 );

hr = gcap.pradio->put_InputType(0,TunerInputAntenna);

// hago la lectura de las frecuencias que vienen en el
// fichero frecuencias.cfg

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
124
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
{
MessageBox("No se encontr el dispositivo sintonizador en el sistema");
GetDlgItem(IDC_DETECCION)->EnableWindow(FALSE);
}

//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);
}

//////////////////////////////////////////////////////////////////////

// Para liberar correctamente las estructuras de tipo AM_MEDIA_TYPE

void CRadioDlg::UtilDeleteMediaType(AM_MEDIA_TYPE *pmt)
{
if (pmt == NULL){
return;
}
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
125


if (pmt->cbFormat != 0)
{
CoTaskMemFree((PVOID)pmt->pbFormat);

pmt->cbFormat = 0;
pmt->pbFormat = NULL;
}


if (pmt->pUnk != NULL)
{
pmt->pUnk->Release();
pmt->pUnk = NULL;
}

CoTaskMemFree((PVOID)pmt);
}

//////////////////////////////////////////////////////////////////////

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");

//Ahora a compartir el interfaz

hr=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
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
126

hr= 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);

//leemos los anuncios

lectura_anuncios();

calcula_frecuencias_deteccion();

cambia_canal(frecuencias_deteccion[freq]);

frecuencia_anterior=frecuencias_deteccion[freq];

freq++;

//Empieza a funcionar el grafo

hr = gcap.pControl->Run();

m_status="detectando ...";
UpdateData(FALSE);

SetTimer(ID_TIMER,3700,NULL);
}

//////////////////////////////////////////////////////////////////////


Deteccin e identificacin de anuncios de radio y televisin en tiempo real
127
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

// EL FICHERO QUE SE CREARA TENDRA EXTENSION *.fpr

CString nombre;
int size;
CFileDialog dialogo_archivo(FALSE,"fpr");

if (dialogo_archivo.DoModal()==IDOK)
{
grabar=TRUE; // empezamos a grabar

// 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);

// Guardo el nombre del anuncio a grabar en la variable publica anuncio

nombre_anuncio=dialogo_archivo.GetPathName();

// 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");

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
128
// 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 *.

nombre=dialogo_archivo.GetPathName();
size=strlen(nombre);

char *auxiliar=new char[size];

strcpy(auxiliar,nombre);

for(int j=0;j<size;j++)
{
if(auxiliar[j]=='f')
if(auxiliar[j+1]=='p')
if(auxiliar[j+2]=='r')
break;
}

auxiliar[j]='w';
auxiliar[j+1]='a';
auxiliar[j+2]='v';

USES_CONVERSION;

WCHAR wszFileName[MAX_PATH];
wcsncpy(wszFileName, T2W(auxiliar), 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);


Deteccin e identificacin de anuncios de radio y televisin en tiempo real
129
//y a grabar

gcap.pControl->Run();

m_status="grabando ...";

UpdateData(FALSE);

delete [] auxiliar;
}
}

//////////////////////////////////////////////////////////////////////

void CRadioDlg::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default

KillTimer(ID_TIMER);

time1=clock();

int j;
long cbBuffer=0;
int finger_block[256][32];
int block[256];
float BER=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);

float *buffer=new float[cbBuffer];

for(j=0; j<cbBuffer; j++)
buffer[j]=(float)pBuffer[j];


Deteccin e identificacin de anuncios de radio y televisin en tiempo real
130
// Se cambia de canal

if(frecuencias_deteccion[1]!=0)
{
cambia_canal(frecuencias_deteccion[freq]);

frecuencia_anterior=frecuencias_deteccion[freq];

freq++;

if (frecuencias_deteccion[freq]==0)
freq=0;
}

// Bucle para los distintos anuncios

for(j=0;j<dialogo_archivo.seleccion;j++)
{
if(frecuencia_anterior==tabla_anuncios[j].frecuencia)
{
// Se extrae el fingerprint-block del trozo de audio capturado

extrae_fingerprint_block(buffer,cbBuffer,finger_block);

cambia_formato(finger_block,block);

calcula_BER(&BER,block,tabla_anuncios[j].archivo,tabla_anuncios[j].N1);

decisor(&tabla_anuncios[j],BER);
}
}

delete [] pBuffer;

delete [] buffer;

time2=clock();

// En la primera ejecucion calculamos el tiempo de procesado y vemos cuantas detecciones
// podemos hacer de cada anuncio. Si trabajamos al lmite o en saturacin con algn anuncio
// avisamos de ello.

if(primera_ejecucion==TRUE)
{
tiempo_procesado_total=0;

tiempo_procesado_total=((double)(time2-time1)/1000);

calcula_saturaciones(tiempo_procesado_total);
}
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
131

primera_ejecucion=FALSE;


SetTimer(ID_TIMER,1,NULL);


CDialog::OnTimer(nIDEvent);
}

//////////////////////////////////////////////////////////////////////

float *CRadioDlg::leewav(int *N1,CString nombre)
{
CFile wav(nombre,CFile::modeRead);

//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_fichero=new char[tama[0]];

wav.Read(muestras_fichero,tama[0]);

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
132
*N1=tama[0];

float *muestras=new float[tama[0]];

for(j=0;j<*N1;j++)
muestras[j]=(float)muestras_fichero[j];

wav.Close();

return muestras;
}

//////////////////////////////////////////////////////////////////////

void CRadioDlg::OnConfigurarSintonizador()
{
// TODO: Add your command handler code here

dialogo2.DoModal();
}

//////////////////////////////////////////////////////////////////////

void CRadioDlg::cambia_canal(long canal)
{
gcap.pradio->put_Channel(canal,0,0);
}

//////////////////////////////////////////////////////////////////////

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_fpr[dialogo_archivo.seleccion];
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
133

int j;

for(j=0;j<dialogo_archivo.seleccion;j++)
{
tabla_anuncios[j].archivo=lee_finger(&tabla_anuncios[j].N1,
dialogo_archivo.temporal[j]);
tabla_anuncios[j].frecuencia=dialogo_archivo.frecuencias[j];
tabla_anuncios[j].anuncio=dialogo_archivo.temporal[j];
}
}

//////////////////////////////////////////////////////////////////////

void CRadioDlg::decisor(archivo_fpr *anuncio,float BER)
{
double umbral=configuracion.m_umbral;

if (BER<umbral)
{
anota_resultado(anuncio,BER);

// ANOTAR EN FICHERO RESULTADO

// ANOTAR EN EL DIALOGO PRINCIPAL
}
}

//////////////////////////////////////////////////////////////////////

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);

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
134
}

//PARA VERIFICAR QUE LAS FRECUENCIAS SON FRECUENCIAS CORRECTAS

for(i=0;i<10;i++)
{
while (((frecuencias[i]>108000000)||(frecuencias[i]<87500000)))
{
for(j=i;j<9;j++)
{
frecuencias[j]=frecuencias[j+1];

}
frecuencias[9]=0;



if (frecuencias[i]==0)
break;

}
}

//BUCLE PARA VER SI ESTAN REPETIDAS

for(j=1;j<10;j++)
for(i=1;i<j+1;i++)
if(frecuencias[j]==frecuencias[j-i])
frecuencias[j]=0;
}

//////////////////////////////////////////////////////////////////////

void CRadioDlg::lectura_canales_tv()
{
frecuencias=new long[10];

char temporal[4];

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++)
{
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
135
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;
}

//////////////////////////////////////////////////////////////////////

void CRadioDlg::OnArchivosSalir()
{
// TODO: Add your command handler code here

OnSalir();
}

//////////////////////////////////////////////////////////////////////

void CRadioDlg::anota_resultado(archivo_fpr *anuncio,float BER)
{
CString resultado;

actual=CTime::GetCurrentTime();

resultado = actual.Format( "%H:%M:%S " );
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
136

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 << BER << "\n";
}

//////////////////////////////////////////////////////////////////////

void CRadioDlg::OnConfiguracion()
{
// TODO: Add your command handler code here

configuracion.DoModal();
}

///////////////////////////////////////////////////////////////////////

int CRadioDlg::calcula_posibles_detecciones(int N1)
{

int resultado;
double tiempo_anuncio;

// cada 12,8 mseg se genera una sub-fingerprint (32 bits = 4 bytes)

tiempo_anuncio=(N1*12.8)/4;

tiempo_anuncio=tiempo_anuncio/1000;

resultado=(int)(tiempo_anuncio/tiempo_procesado_total);

return resultado;
}



Deteccin e identificacin de anuncios de radio y televisin en tiempo real
137
//////////////////////////////////////////////////////////////////////

void CRadioDlg::calcula_frecuencias_deteccion()
{

int i;
int j;
int k=0;

BOOL repetido;

frecuencias_deteccion=new long[dialogo_archivo.seleccion+1];


for(j=0;j<=dialogo_archivo.seleccion;j++)
frecuencias_deteccion[j]=0;

frecuencias_deteccion[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_deteccion[i])
{
repetido=TRUE;
break;
}
else
repetido=FALSE;

}
if(!repetido)
{
frecuencias_deteccion[k]=tabla_anuncios[j].frecuencia;
k++;
}
}
}

////////////////////////////////////////////////////////////////////////////////////////////////
// A esta funcion se le pasa como parametro un puntero a las muestras de un archivo wav y
// el numero de muestras totales. Con estos parametros la funcion calcula una sucesion de
// subfingerprints y crea un fichero con el mismo nombre

void CRadioDlg::extrae_fingerprint(float *audio,int N1, CString nombre_archivo)
{
int n=0;
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
138
int m=0;
int j=0;
int overlap=0;
int Npoints=N;
double energia[2][33];
int subfingerprint[32];
double ventana_hanning[N];
double frame[N];
double mod_fft_frame[N];

// para la primera subfingerprint las condiciones iniciales son nulas

for(n=0; n<2; n++)
{
for(m=0; m<33; m++)
energia[n][m]=0;
}
// generamos la ventana de hanning

for (m=0; m<N; m++)
ventana_hanning[m]=0.5-0.5*(float)cos(2*Pi*m/(N-1));

while( overlap+N<N1)
{
for(m=0; m<N; m++)
frame[m]=audio[m+overlap]*ventana_hanning[m];

realft(frame, Npoints, 1); // calculamos la fft de N=2048 puntos del frame obtenido

modulo(mod_fft_frame,frame); // calculamos el modulo de la DFT

extrae_subfingerprint(subfingerprint,energia,mod_fft_frame);

escribe_subfingerprint(subfingerprint,nombre_archivo);

actualiza_energia(energia);

overlap=overlap+64; // actualizamos el factor de overlap
}
}

/////////////////////////////////////////////////////////////////////////////////////////////////
// Esta funcion recibe como parametros un puntero donde almacenar el subfingerprint calculado,
// un puntero a la tabla de energias, y la fft del frame obtenido

void CRadioDlg::extrae_subfingerprint( int *subfingerprint, double energia[2][33], double
*mod_fft_frame)
{
int m=0;
int j=0;
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
139

const int muestras[34]={122,130,137,146,154,163,173,183,194,206,218,231,
244,259,274,291,308,326,345,366,387,410,435,461,488,517,547,580,
614,650,689,730,773,819};

// calculamos la energia parcial de cada banda del espectro

for( m=0; m<33; m++)
{
for( j=muestras[m]; j<(muestras[m+1]-1); j++)
energia[1][m]=energia[1][m]+(mod_fft_frame[j]*mod_fft_frame[j]);
}

// calculamos los bits correspondientes del subfingerprint

for( m=0; m<32; m++)
{
if( energia[1][m]-energia[1][m+1]-energia[0][m]+energia[0][m+1] > 0 )
{
subfingerprint[m]=1;
}
else
{
subfingerprint[m]=0;
}
}
}

///////////////////////////////////////////////////////////////////////////////////////////////

void CRadioDlg::extrae_fingerprint_block(float *audio,int N1,int finger_block[256][32])
{
int n=0;
int i=0;
int m=0;
int j=0;
int overlap=0;
int Npoints=N;
double energia[2][33];
int subfingerprint[32];
double ventana_hanning[N];
double frame[N];
double mod_fft_frame[N];

// para la primera subfingerprint las condiciones iniciales son nulas

for(n=0; n<2; n++)
{
for(m=0; m<33; m++)
energia[n][m]=0;
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
140
}

// generamos la ventana de hanning

for (m=0; m<N; m++)
ventana_hanning[m]=0.5-0.5*cos(2*Pi*m/(N-1));

if(N1>=18368) // Comprobamos que tenemos muestras suficientes para calcular un
//fingerblock
{
for(i=0; i<256; i++)
{
for(m=0; m<N; m++)
frame[m]=audio[m+overlap]*ventana_hanning[m];

realft(frame, Npoints, 1); // calculamos la fft de N=2048 puntos del frame

modulo(mod_fft_frame,frame); // calculamos el modulo de la DFT

extrae_subfingerprint(subfingerprint,energia,mod_fft_frame);

for(j=0; j<32; j++)
finger_block[i][j]=subfingerprint[j];

actualiza_energia(energia);

overlap=overlap+64; // actualizamos el factor de overlap
}
}
else
MessageBox("fuera de memoria");
}

//////////////////////////////////////////////////////////////////////////////////////////////////

void CRadioDlg::escribe_subfingerprint( int *subfingerprint, CString nombre_anuncio)
{
int i=0;
int qword=0x00000000;
int MASK=0x00000001;
CFile archivo;

archivo.Open( nombre_anuncio,CFile::modeCreate | CFile::modeNoTruncate |
CFile::modeWrite);
archivo.SeekToEnd();

for(i=0; i<32; i++)
{
if(subfingerprint[i]==1)
{
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
141
qword<<=1;
qword|=MASK;
}
else
qword<<=1;
}

archivo.Write(&qword,sizeof(qword));

archivo.Close();

}

//////////////////////////////////////////////////////////////////////////////////////////////////

void CRadioDlg::modulo( double *mod_fft_frame, double *fft_frame )
{
int i;

mod_fft_frame[0]=fabs(fft_frame[0]);

for(i=1; i<(N/2-1); i++)
mod_fft_frame[i]=sqrt((fft_frame[2*i]*fft_frame[2*i])+
(fft_frame[2*i+1]*fft_frame[2*i+1]));

// hasta aqui tendra la mitad de las muestras, ahora tengo que aplicar la simetria para
// obtener la otra mitad

for(i=N/2; i<N; i++)
mod_fft_frame[i]=mod_fft_frame[(N-1)-i];
}

////////////////////////////////////////////////////////////////////////////////////////////////

void CRadioDlg::realft(double data[], unsigned long n, int isign)
{

unsigned long i,i1,i2,i3,i4,np3;
double c1=0.5,c2,h1r,h1i,h2r,h2i;
double wr,wi,wpr,wpi,wtemp,theta; // Double precision for the trigonometric recurrences.
theta=3.141592653589793/(double) (n>>1); //Initialize the recurrence.

if (isign == 1)
{
c2 = -0.5;
four1(data-1,n>>1,1); // The forward transform is here.
}
else
{
c2=0.5; // Otherwise set up for an inverse transform.
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
142
theta = -theta;
}

wtemp=sin(0.5*theta);
wpr = -2.0*wtemp*wtemp;
wpi=sin(theta);
wr=1.0+wpr;
wi=wpi;
np3=n+2;

for (i=2;i<=(n>>2);i++)
{

i4=1+(i3=np3-(i2=1+(i1=i+i-2))-1); // Case i=1 done separately below.
h1r=c1*(data[i1]+data[i3]); // The two separate transforms are separated out of data.
h1i=c1*(data[i2]-data[i4]);
h2r = -c2*(data[i2]+data[i4]);
h2i=c2*(data[i1]-data[i3]);
data[i1]=h1r+wr*h2r-wi*h2i; // Here they are recombined to form the true
// transform of the original real data.
data[i2]=h1i+wr*h2i+wi*h2r;
data[i3]=h1r-wr*h2r+wi*h2i;
data[i4] = -h1i+wr*h2i+wi*h2r;
wr=(wtemp=wr)*wpr-wi*wpi+wr; // The recurrence.
wi=wi*wpr+wtemp*wpi+wi;
}

if (isign == 1)
{
data[1] = (h1r=data[1])+data[2]; // Squeeze the first and last data together to get
// them all within the original array.
data[2] = h1r-data[2];
}
else
{
data[1]=c1*((h1r=data[1])+data[2]);
data[2]=c1*(h1r-data[2]);
four1(data,n>>1,-1); // This is the inverse transform for the case isign=-1.
}
}

////////////////////////////////////////////////////////////////////////////////////////////////
// Replaces data[1..2*nn] by its discrete Fourier transform, if isign is input as 1; or replaces
// data[1..2*nn] by nn times its inverse discrete Fourier transform, if isign is input as -1.
// data is a complex array of length nn or, equivalently, a real array of length 2*nn. nn MUST
// be an integer power of 2 (this is not checked for!).

void CRadioDlg::four1(double data[], unsigned long nn, int isign)
{
unsigned long n,mmax,m,j,istep,i;
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
143
double wtemp,wr,wpr,wpi,wi,theta; // Double precision for the trigonometric recurrences.
double tempr,tempi;

n=nn << 1;
j=1;

for (i=1;i<n;i+=2)
{ // This is the bit-reversal section of the routine.
if (j > i)
{
SWAP(data[j],data[i]); //Exchange the two complex numbers.
SWAP(data[j+1],data[i+1]);
}

m=nn;

while (m >= 2 && j > m)
{
j -= m;
m >>= 1;
}

j += m;
}

// Here begins the Danielson-Lanczos section of the routine.

mmax=2;

while (n > mmax)
{ // Outer loop executed log2 nn times.
istep=mmax << 1;
theta=isign*(6.28318530717959/mmax); // Initialize the trigonometric recurrence.
wtemp=sin(0.5*theta);
wpr = -2.0*wtemp*wtemp;
wpi=sin(theta);
wr=1.0;
wi=0.0;

for (m=1;m<mmax;m+=2)
{ // Here are the two nested inner loops.
for (i=m;i<=n;i+=istep)
{
j=i+mmax; // This is the Danielson-Lanczos formula:
tempr=wr*data[j]-wi*data[j+1];
tempi=wr*data[j+1]+wi*data[j];
data[j]=data[i]-tempr;
data[j+1]=data[i+1]-tempi;
data[i] += tempr;
data[i+1] += tempi;
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
144
}

wr=(wtemp=wr)*wpr-wi*wpi+wr; // Trigonometric recurrence.
wi=wi*wpr+wtemp*wpi+wi;
}

mmax=istep;
}
}

////////////////////////////////////////////////////////////////////////////////////////////////

void CRadioDlg::actualiza_energia( double energia[2][33] )
{
int m;

// actualizamos la tabla de energias para la siguiente iteracion

for( m=0; m<33; m++)
energia[0][m]=energia[1][m];

for(m=0; m<33; m++)
energia[1][m]=0;
}

////////////////////////////////////////////////////////////////////////////////////////////////

void CRadioDlg::cambia_formato(int finger_block[256][32], int *block)
{
int i=0;
int j=0;
int qword=0;
int MASK=0x00000001;

for(i=0; i<256; i++)
{
for(j=0; j<32; j++)
{
if(finger_block[i][j]==1)
{
qword<<=1;
qword|=MASK;
}
else
qword<<=1;
}
block[i]=qword;
}
}

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
145


/////////////////////////////////////////////////////////////////////////////////////////////////

void CRadioDlg::calcula_BER( float *BER, int *block, int *fichero, int Nbytes)
{
int i=0;
int j=0;
int k=0;
float minimo=1;
float acarreo=0;
float BER_aux=0;
int aux1;
int aux2;
int MASK=0x80000000;

while( i+256<(Nbytes/4) )
{
acarreo=0;

for(j=0; j<256; j++)
{
aux1=block[j]^fichero[i+j];

for(k=0;k<32;k++)
{
if( (aux2=aux1&MASK)!=0 )
acarreo++;

aux1<<=1;
}
}

BER_aux=(acarreo/8192); // 8192 es el numero total de bits en un fingerprint-block

if( BER_aux<=minimo )
minimo=BER_aux;

i++;
}

*BER=minimo;
}

//////////////////////////////////////////////////////////////////////////////////////////////////

int *CRadioDlg::lee_finger(int *N1,CString nombre_anuncio)
{

nombre_anuncio="ARCHIVOS\\"+nombre_anuncio;
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
146

int size;

CFile anuncio;
anuncio.Open( nombre_anuncio,CFile::modeRead);

size=anuncio.GetLength();

int *muestras_anuncio=new int[size/4];


for(int i=0; i<(size/4); i++)
anuncio.Read(&muestras_anuncio[i],4);

*N1=size;

return muestras_anuncio;
}

//////////////////////////////////////////////////////////////////////////////////////////////

void CRadioDlg::calcula_saturaciones(double tiempo_procesado_total)
{
int j=0;

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");
}
}
}



Deteccin e identificacin de anuncios de radio y televisin en tiempo real
147
A3.3. Clase CArchivos

Archivos.h

#if !defined(AFX_ARCHIVOS_H__A6E8C0DA_F3A0_4774_
A2BE_39566E1A7B6E__INCLUDED_)
#define AFX_ARCHIVOS_H__A6E8C0DA_F3A0_4774_A2BE_39566E1A7B6E__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// Archivos.h : header file
//


/////////////////////////////////////////////////////////////////////////////
// CArchivos dialog

class CArchivos : public CDialog
{
// Construction
public:
CArchivos(CWnd* pParent = NULL); // standard constructor


// Dialog Data
//{{AFX_DATA(CArchivos)
enum { IDD = IDD_DIALOG3 };
CComboBox m_freq;
CListBox m_lista;
//}}AFX_DATA
long *freq;
CString temporal[100];
long frecuencias[100];
int seleccion;

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CArchivos)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL

// Implementation
protected:

// Generated message map functions
//{{AFX_MSG(CArchivos)
afx_msg void OnLista();
afx_msg void Onexit();
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
148
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_ARCHIVOS_H__A6E8C0DA_F3A0_4774
_A2BE_39566E1A7B6E__INCLUDED_)









































Deteccin e identificacin de anuncios de radio y televisin en tiempo real
149
Archivos.cpp

// Archivos.cpp : implementation file
//

#include "stdafx.h"
#include "Radio.h"
#include "Archivos.h"
#include "RadioDlg.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////////////////////
// CArchivos dialog

CArchivos::CArchivos(CWnd* pParent /*=NULL*/)
: CDialog(CArchivos::IDD, pParent)
{
//{{AFX_DATA_INIT(CArchivos)
//}}AFX_DATA_INIT
}

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\\*.fpr");

//Rellenamos la lista de frecuencias con las frecuencias introducidas
//anteriormente por el usuario.

int j=0;

char auxiliar[10];

while(freq[j]!=0)
{

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
150
_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
{
MessageBox("SELECCIONA UNA FRECUENCIA");
}
}
else
{
MessageBox("SELECCIONA UN ANUNCIO");
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
151

}
}

//////////////////////////////////////////////////////////////////////

void CArchivos::Onexit()
{
// TODO: Add your control notification handler code here

OnOK();
}




































Deteccin e identificacin de anuncios de radio y televisin en tiempo real
152
A3.4. Clase CDialosint

Dialosint.h

#if !defined(AFX_DIALOSINT_H__28645B3F_7033_44AB_
96A3_3897F5A8A910__INCLUDED_)
#define AFX_DIALOSINT_H__28645B3F_7033_44AB_96A3_3897F5A8A910__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// Dialosint.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CDialosint dialog

class CDialosint : public CDialog
{
// Construction
public:
CDialosint(CWnd* pParent = NULL); // standard constructor

// Dialog Data
//{{AFX_DATA(CDialosint)
enum { IDD = IDD_DIALOG2 };
long m_sintoniza;
//}}AFX_DATA

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CDialosint)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL

// Implementation
protected:

// Generated message map functions
//{{AFX_MSG(CDialosint)
afx_msg void OnSalir2();
afx_msg void OnOk();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
153
#endif // !defined(AFX_DIALOSINT_H__28645B3F_7033_
44AB_96A3_3897F5A8A910__INCLUDED_)
















































Deteccin e identificacin de anuncios de radio y televisin en tiempo real
154
Dialosint.cpp

// Dialosint.cpp : implementation file
//

#include "stdafx.h"
#include "Radio.h"
#include "RadioDlg.h"
#include "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

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
155
OnOK();
}

//////////////////////////////////////////////////////////////////////
// En esta rutina se sintoniza el canal pertinente.

void CDialosint::OnOk()
{
// TODO: Add your control notification handler code here

UpdateData(TRUE);

CRadioDlg dialogo;

dialogo.cambia_canal(m_sintoniza);

OnOK();
}
































Deteccin e identificacin de anuncios de radio y televisin en tiempo real
156
A3.5. Clase CConfiguracion

Configuracion.h

#if !defined(AFX_CONFIGURACION_H__0C1C2B59_0A7A_
499E_A58F_560C063F4832__INCLUDED_)
#define AFX_CONFIGURACION_H__0C1C2B59_0A7A_499E_
A58F_560C063F4832__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

// Configuracion.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CConfiguracion dialog

class CConfiguracion : public CDialog
{
// Construction
public:
CConfiguracion(CWnd* pParent = NULL); // standard constructor

// Dialog Data
//{{AFX_DATA(CConfiguracion)
enum { IDD = IDD_DIALOG6 };
double m_umbral;
int m_fm;
//}}AFX_DATA


// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CConfiguracion)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL

// Implementation
protected:

// Generated message map functions
//{{AFX_MSG(CConfiguracion)
afx_msg void OnAceptar();
afx_msg void OnCancelar();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
157
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_CONFIGURACION_H__0C1C2B59_0A7A_
499E_A58F_560C063F4832__INCLUDED_)













































Deteccin e identificacin de anuncios de radio y televisin en tiempo real
158
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_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_MinMaxDouble(pDX, m_umbral, 0.f, 1.f);
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
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
159

UpdateData(TRUE);
OnOK();

}

//////////////////////////////////////////////////////////////////////

void CConfiguracion::OnCancelar()
{
// TODO: Add your control notification handler code here

OnOK();
}




































Deteccin e identificacin de anuncios de radio y televisin en tiempo real
160
A3.6. Clase CButtonST (Clase CMemDC est includa en
ButtonST.h)

ButtonST.h

#if !defined(AFX_BUTTONST_H__B07118FE_52A5_4B67_
B2B4_351291562378__INCLUDED_)
#define AFX_BUTTONST_H__B07118FE_52A5_4B67_B2B4_351291562378__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

// ButtonST.h : header file
//

// 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
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
161
public:
BOOL SetBtnCursor(int nCursorId = -1);

void SetFlatFocus(BOOL bDrawFlatFocus, BOOL bRepaint = FALSE);
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

DECLARE_MESSAGE_MAP()
private:
void DrawTheIcon(CDC* pDC, CString* title, RECT* rcItem,
CRect* captionRect, BOOL IsPressed, BOOL IsDisabled);
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
162

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;
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();
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
163

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;
}
}

// Destructor copies the contents of the mem DC to the original DC
~CMemDC()
{
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.
};

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
164
#endif

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous
//line.

#endif









































Deteccin e identificacin de anuncios de radio y televisin en tiempo real
165
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


Deteccin e identificacin de anuncios de radio y televisin en tiempo real
166
CButtonST::~CButtonST()
{
// Destroy the icons (if any)
if (m_hIconIn != NULL) ::DeleteObject(m_hIconIn);
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;

Deteccin e identificacin de anuncios de radio y televisin en tiempo real
167
// 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;
}

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


Deteccin e identificacin de anuncios de radio y televisin en tiempo real
168
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)
{
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) &&
(
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
169
#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


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();
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
170
}

// 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;
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)
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
171
{
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
{
CBrush brBtnShadow(GetSysColor(COLOR_BTNSHADOW));
pDC->FrameRect(&itemRect, &brBtnShadow);
}
}
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);
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
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
172
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);
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
173
}

// Write the button title (if any)
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))
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
174
{
// Draw the focus rect
if (bIsFocused)
{
CRect focusRect = itemRect;
focusRect.DeflateRect(3, 3);
pDC->DrawFocusRect(&focusRect);
}
}
} // End of DrawItem


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
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
175
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);
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
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
176


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)
{
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)
{
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
177
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



#undef ST_USE_MEMDC
#undef ST_LIKE
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
178

BIBLIOGRAFIA

[1] Pedro Cano and Eloi Batlle, Ton Kalker and Jaap Haitsma. A Review of
Algorithms for Audio Fingerprinting.

[2] Jaap Haitsma and Ton Kalker. A Highly Robust Audio Fingerprinting
System.

[3] Wes Hatch. A Quick Review of Audio Fingerprinting.

[4] Pedro Cano, Eloi Batlle, Emilia Gmez, Leandro de C.T.Gomes y
Madeleine Bonnet. Audio Fingerprinting: Concepts and
Applications.

[5] Christopher J.C. Burges, John C. Platt y Soumya Jana .EXTRACTING
NOISE-ROBUST FEATURES FROM AUDIO DATA.

[6] M.L.Miller, M.A. Rodriguez and I.J.Cox. Audio Fingerprinting:Nearest
Neighbor Search in High Dimensional Binary Spaces. IEEE
International workshop on MMSP, 2002

[7] A. Kimura, K. Kashino, T. Kurozumi, and H. Murase. Very quick audio
searching: introducing global pruning to the time-series active
search. in Proc. of Int. Conf. on Computational Intelligence and
Multimedia Applications, Salt Lake City, Utah, May 2001.

[8] Logan, B. (2000). Mel frequency cepstral coefficients for music
modeling. In International Symposium on Music Information Retrieval.

[9] H. S. Malvar. A modulated complex lapped transform and
applications to audio processing. Proc. IEEE ICASSP, Phoenix, AZ,
March 1999.

[10] Press, W. H. Numerical recipes in C : the art of scientific computing.
Cambridge University Press.

[11] Javier Ponce Surez. Deteccin Automtica de Anuncios en Radio
en Tiempo Real. Proyecto Fin de Carrera.

[12] Chapman, D. Teach Yourself Visual C++ 6 in 21 days.

[13] Dunlop, R. Teach Yourself DirectX 7 in 24 hours.

[14] Demian C. Panello. Introduccin a la Programacin Orientada a
Objetos. Manual obtenido en internet.
URL: http://www.dcp.com.ar/
Deteccin e identificacin de anuncios de radio y televisin en tiempo real
179

[15] Demian C. Panello. Apunte de Visual C++.
Manual obtenido en internet.
URL: http://www.dcp.com.ar/

[16] Paul Bustamante, Iker Aguinaga, Miguel Aybar, Iigo Lazacano y Luis
Olaizola. Aprenda C++ Avanzado como si estuviera en primero.

[17] MSDN. Ayuda del Visual Studio.

[18] Microsoft DirectX 9.0 SDK. Documentation for C++.

[19] http://www.lawebdelprogramador.com/

[20] http://www.solocodigo.com.

Das könnte Ihnen auch gefallen