c´odigo en c++ - servidor de la biblioteca de...

97
Ap´ endice B C´odigoenC++ Listados completos del c´odigo fuente del software desarrollado. B.1. Common.h #ifndef __COMMON_H__ #define __COMMON_H__ #include <stdlib.h> #include <stdio.h> #include <math.h> #include <memory.h> #include <string> #include <vector> #include <fstream> #include <limits> #include <crtdbg.h> typedef float real; using namespace std; // N´umero pi #define PI (real)3.1415926538 //! \brief Guarda una cadena de caracteres en un archivo. 181

Upload: vuongdang

Post on 02-Oct-2018

213 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

Apendice B

Codigo en C++

Listados completos del codigo fuente del software desarrollado.

B.1. Common.h

#ifndef __COMMON_H__

#define __COMMON_H__

#include <stdlib.h>

#include <stdio.h>

#include <math.h>

#include <memory.h>

#include <string>

#include <vector>

#include <fstream>

#include <limits>

#include <crtdbg.h>

typedef float real;

using namespace std;

// Numero pi

#define PI (real)3.1415926538

//! \brief Guarda una cadena de caracteres en un archivo.

181

Page 2: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

182 APENDICE B. CODIGO EN C++

//!

//! @param s La cadena de caracteres.

//! @param f Flujo de datos de archivo.

void SaveString( string &s, fstream &f );

//! \brief Carga una cadena de caracteres de un archivo.

//!

//! @param s La cadena de caracteres.

//! @param f Flujo de datos de archivo.

void LoadString( string &s, fstream &f );

//! \brief Guarda un vector de enteros en un archivo.

//!

//! @param v El vector de enteros.

//! @param f Flujo de datos de archivo.

void SaveIVector( vector<int> &v, fstream &f );

//! \brief Carga un vector de enteros de un archivo.

//!

//! @param v El vector de enteros.

//! @param f Flujo de datos de archivo.

void LoadIVector( vector<int> &v, fstream &f );

#endif //__COMMON_H__

Page 3: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.2. COMMON.CPP 183

B.2. Common.cpp

#include "Common.h"

void SaveString( string &s, fstream &f )

{

int n = s.length();

f.write( (char *)&n, sizeof(int) );

f.write( s.c_str(), n );

}

void LoadString( string &s, fstream &f )

{

int n;

f.read( (char *)&n, sizeof(int) );

char *cad = new char[n+1];

f.read( cad, n );

cad[n] = 0;

s = cad;

delete cad;

}

void SaveIVector( vector<int> &v, fstream &f )

{

int n = v.size();

f.write( (char *)&n, sizeof(int) );

for( int i = 0; i < n; i++ )

{

f.write( (char *)&v[i], sizeof(int) );

}

}

void LoadIVector( vector<int> &v, fstream &f )

{

v.clear();

int n, val;

f.read( (char *)&n, sizeof(int) );

for( int i = 0; i < n; i++ )

{

f.read( (char *)&val, sizeof(int) );

v.push_back( val );

Page 4: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

184 APENDICE B. CODIGO EN C++

}

}

Page 5: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.3. SIGNAL.H 185

B.3. Signal.h

#ifndef __SIGNAL_H__

#define __SIGNAL_H__

#include "Common.h"

#include <stdlib.h>

#include <math.h>

#include <memory.h>

class CSignal

{

//! \brief Puntero a la unica instancia de la clase.

//!

//! La clase sigue el patron \a singleton.

static CSignal *m_pInstance;

//! Se~nal acustica a analizar.

real *m_prSignal;

//! Numero de muestras en la se~nal.

int m_iNumMuestras;

//! Frecuencia de muestreo de la se~nal.

int m_iFrecuencia;

//! Longitud de la ventana de analisis.

int m_iLongVent;

//! Logaritmo en base 2 de la longitud de la ventana.

int m_iOrden;

//! Longitud de superposicion de las ventanas.

int m_iSupVent;

//! Array para la transformada en cada frame.

real **m_pprTransformada;

//! Numero de intervalos sobre los que se analiza la

//! transformada de Fourier.

int m_iNumFrames;

//! Array para almacenar los valores de la energıa de la se~nal.

real *m_prEnergia;

//! Arrays para almacenar los coeficientes cepstrales obtenidos.

real **m_pprCepstrales;

//! Numero de coeficientes cepstrales que se desean obtener.

int m_iNumCeps;

//! Vectores de caracterısticas que incluyen los coeficientes

Page 6: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

186 APENDICE B. CODIGO EN C++

//! cepstrales y la energıa con sus derivadas.

real *m_prCarac;

//! \brief Determinar ancho de la ventana.

//!

//! Determina la longitud de ventana que se debe coger para la

//! frecuencia utilizada.

void SetLongVent();

//! \brief Transformada de Fourier.

//!

//! Calcula la transformada de Fourier del frame \a t.

//! @param t Intervalo en el que se tiene que calcular la

//! transformada de Fourier.

void Fourier( int t );

//! \brief Calculo de los coeficientes cepstrales.

//!

//! Calcula los coeficientes cepstrales del frame \a t.

//! @param t Intervalo en el que se tiene que calcular los

//! coeficientes cepstrales. Es requisito haber llamado antes

//! al metodo \a Fourier().

void Mfcc( int t );

//! \brief Calcula las derivadas de los coeficientes y la

//! energıa.

//!

//! Para calcular las derivadas y la energıa se debe haber

//! llamado antes a los metodos \a Fourier() y \a Mfcc().

void Derivadas();

//! \brief Realiza la normalizacion de la se~nal de audio.

void Normaliza();

//! \brief Escala la se~nal a todo el ancho de banda.

void Banda();

//! \brief Ventana de Hamming.

//!

//! @param n Indice del valor de la ventana de Hamming que se

//! quiere obtener.

Page 7: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.3. SIGNAL.H 187

//! @return Devuelve el termino enesimo de una ventana de

//! Hamming de ancho igual al de los frames.

real W_Hamming( int n );

//! \brief Ventana de Hanning.

//!

//! @param n Indice del valor de la ventana de Hanning que se

//! quiere obtener.

//! @return Devuelve el termino enesimo de una ventana de

//! Hanning de ancho igual al de los frames.

real W_Hanning( int n );

//! \brief Ventana Rectangular.

//!

//! @param n Indice del valor de la ventana rectangular que se

//! quiere obtener.

//! @return Devuelve el termino enesimo de una ventana

//! rectangular de ancho igual al de los frames.

real W_Rectangular( int n );

//! \brief Constructor.

//!

//! El constructor de instancias de la clase es privado porque

//! esta sigue el patron \a singleton.

CSignal();

//! \brief Destructor.

//!

//! El destructor de instancias de la clase es privado porque

//! esta sigue el patron \a singleton.

~CSignal();

public:

//! \brief Obtencion de la instancia de la clase.

//!

//! La clase sigue el patron \a singleton y mediante este metodo

//! se obtiene la unica instancia de ella.

//! @return Devuelve el puntero a la instancia unica de la clase.

static CSignal *GetExtractor();

//! \brief Definicion de los datos del analisis.

Page 8: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

188 APENDICE B. CODIGO EN C++

//!

//! Como la clase sigue el patron singleton, en cada uso de ella

//! hay que difinir los datos y parametros con que se trabaja.

//! @param sig Array de la se~nal que se quire analizar.

//! @param numM Numero de muestras en \a sig.

//! @param frec Frecuancia de muestreo d la se~nal introducida.

//! @see SetNumCeps()

void SetAnalisis( real *sig, int numM, int frec );

//! \brief Realiza el analisis de la se~nal.

//!

//! Tras determinar los datos del analisis se llama a este

//! metodo pa ordenar la realizacion del analisis.

void Analiza();

//! \brief Numero de frames de la se~nal.

//!

//! @return Devuelve el numero de frames en que se ha dividido

//! la se~nal ara su analisis.

inline int GetNumFrames()

{

return m_iNumFrames;

}

//! Obtencion del vector de caracterıasticas.

//!

//! @param f Indice del frame para el que se quiere el vector de

//! caracterısticas.

//! @return Puntero al primer elemento del vector de

//! coeficientes. El numero de elementos que se devuelve es

//! igual al numero de coeficientes cepstrales calculados mas

//! el valor de la energıa y sus dos primeras derivadas.

real *GetCaract( int f );

//! \brief Determinar el numero de coeficientes cepstrales que se

//! quiere obtener.

//!

//! @param nc Numero de coeficientes cepstrales que se deben

//! calcular por cada frame.

//! @see SetAnalisis()

inline void SetNumCeps( int nc )

Page 9: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.3. SIGNAL.H 189

{

m_iNumCeps = nc;

}

//! \brief Se~nal en analisis.

//!

//! @return Puntero a la primera posicion de los datos de la

//! se~nal introducida.

inline real *GetSign()

{

return m_prSignal;

}

//! \brief Numero de muestras de la se~nal en analisis.

//!

//! @return Numero de muestras de la se~nal.

inline int GetNumMuestras()

{

return m_iNumMuestras;

}

//! \brief Determina la longitud de la ventana como la mınima.

void SetLongVentMin();

};

#endif //__SIGNAL_H__

Page 10: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

190 APENDICE B. CODIGO EN C++

B.4. Signal.cpp

#include "Signal.h"

CSignal *CSignal::m_pInstance = NULL;

CSignal *CSignal::GetExtractor()

{

// Si no se ha creado ya la instancia de la clase se hace ahora.

if(!m_pInstance)

m_pInstance = new CSignal;

// Se devuelve la instancia de la clase.

return m_pInstance;

}

CSignal::CSignal()

{

// Inicializacion de parametros.

m_iNumMuestras = 0;

m_iFrecuencia = 0;

m_prSignal = NULL;

m_pprTransformada = NULL;

m_prEnergia = NULL;

m_pprCepstrales = NULL;

m_prCarac = NULL;

}

void CSignal::SetAnalisis( real *sig, int numM, int frec )

{

int i;

// Devolucion de la memoria reservada en usos anteriores.

if( m_prSignal )

delete m_prSignal;

if( m_prEnergia )

delete m_prEnergia;

if( m_prCarac )

delete m_prCarac;

if( m_pprTransformada )

Page 11: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.4. SIGNAL.CPP 191

{

for( i = 0; i < m_iNumFrames; i++ )

delete m_pprTransformada[i];

delete m_pprTransformada;

}

if(m_pprCepstrales)

{

for( i = 0; i < m_iNumFrames * 3; i++ )

delete m_pprCepstrales[i];

delete m_pprCepstrales;

}

// Array para la se~nal

m_prSignal = new real[numM];

memcpy( m_prSignal, sig, sizeof(real) * numM );

m_iNumMuestras = numM;

m_iFrecuencia = frec;

// Determina la longitud del frame.

SetLongVent();

m_pprTransformada = NULL;

m_prEnergia = NULL;

m_pprCepstrales = NULL;

m_prCarac = NULL;

}

CSignal::~CSignal()

{

int i;

// Devolucion de la memoria reservada.

if(m_prSignal)

delete m_prSignal;

if( m_prEnergia )

delete m_prEnergia;

if( m_prCarac )

delete m_prCarac;

if( m_pprTransformada )

{

for( i = 0; i < m_iNumFrames; i++ )

Page 12: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

192 APENDICE B. CODIGO EN C++

delete m_pprTransformada[i];

delete m_pprTransformada;

}

if(m_pprCepstrales)

{

for( i = 0; i < m_iNumFrames * 3; i++ )

delete m_pprCepstrales[i];

delete m_pprCepstrales;

}

}

void CSignal::SetLongVent()

{

m_iLongVent = int( 0.03f * (real)m_iFrecuencia );

if( m_iLongVent < 384 )

{

m_iLongVent = 256;

m_iOrden = 8;

m_iSupVent = 100;

}

else if( m_iLongVent < 768 )

{

m_iLongVent = 512;

m_iOrden = 9;

m_iSupVent = 200;

}

else

{

m_iLongVent = 1024;

m_iOrden = 10;

m_iSupVent = 400;

}

}

void CSignal::SetLongVentMin()

{

m_iLongVent = 256;

m_iOrden = 8;

m_iSupVent = 100;

}

Page 13: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.4. SIGNAL.CPP 193

real CSignal::W_Hamming( int n )

{

if( n >= 0 && n < m_iLongVent )

return 0.54f - 0.46f * (real)cos( 2.0 * PI * (real)n

/ (real)( m_iLongVent - 1 ) );

else

return 0.0f;

}

real CSignal::W_Hanning( int n )

{

if( n >= 0 && n < m_iLongVent )

return 0.5f - 0.5f * (real)cos( 2.0 * PI * (real)n

/ (real)( m_iLongVent - 1 ) );

else

return 0.0f;

}

real CSignal::W_Rectangular( int n )

{

if( n >= 0 && n < m_iLongVent )

return 1.0f;

else

return 0.0f;

}

void CSignal::Analiza()

{

int i;

// Reinicializamos los arrays para la transformada de Fourier

// y la energıa.

if(m_pprTransformada)

{

for( i = 0; i < m_iNumFrames; i++ )

delete m_pprTransformada[i];

delete m_pprTransformada;

}

if(m_pprCepstrales)

{

Page 14: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

194 APENDICE B. CODIGO EN C++

for( i = 0; i < m_iNumFrames * 3; i++ )

delete m_pprCepstrales[i];

delete m_pprCepstrales;

}

if(m_prEnergia)

delete m_prEnergia;

m_prEnergia = NULL;

m_pprTransformada = NULL;

// El numero de frames es el siguiente.

m_iNumFrames = ( m_iNumMuestras - m_iSupVent )

/ ( m_iLongVent - m_iSupVent );

// Inicializamos los arrays

m_pprTransformada = new real *[m_iNumFrames];

m_pprCepstrales = new real *[m_iNumFrames * 3];

m_prEnergia = new real[m_iNumFrames * 3];

for( i = 0; i < m_iNumFrames * 3; i++ )

{

if( i < m_iNumFrames )

m_pprTransformada[i] = new real[m_iLongVent / 2];

m_pprCepstrales[i] = new real[m_iNumCeps];

}

// Normalizamos la se~nal.

Normaliza();

// Ancho de banda entre -1 y 1

Banda();

// Calculamos la transformada para cada frame.

for( i = 0; i < m_iNumFrames; i++ )

{

Fourier( i );

}

// Calculamos los coeficientes cepstrales para cada frame.

for( i = 0; i < m_iNumFrames; i++ )

{

Mfcc( i );

Page 15: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.4. SIGNAL.CPP 195

}

Derivadas();

}

void CSignal::Fourier( int tf )

{

real *TF = m_pprTransformada[tf];

int c = tf * (m_iLongVent - m_iSupVent);

// Array para la parte real de la transformada

real *SigR = new real[m_iLongVent];

// Array para la parte imaginaria de la transformada

real *SigI = new real[m_iLongVent];

// Variables auxiliares.

real t, theta, wr, wi;

real arg, dwr, dwi, tr, ti;

int i, j, k, n2, n, z;

// Introducimos en el array de la parte real la muestra pasada

// por la ventana de Hamming y el de la parte imaginaria lo

// iniciamos a cero.

for( i = 0; i < m_iLongVent; i++ )

{

SigR[i] = W_Hamming(i) * m_prSignal[c + i];

}

memset( SigI, 0, sizeof(real) * m_iLongVent );

theta = PI;

// Shuffle

n2 = (1<<m_iOrden)>>1;

j = 1;

for( i = 1; i < m_iLongVent; i++ )

{

if( i < j )

{

t = SigR[i-1];

SigR[i-1] = SigR[j-1];

Page 16: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

196 APENDICE B. CODIGO EN C++

SigR[j-1] = t;

}

k = n2;

while( k < j )

{

j -= k;

k >>= 1;

}

j += k;

}

// Transformada rapida de Fourier

n2 = 1;

for( i = 1; i <= m_iOrden; i++ )

{

n = n2;

n2 += n2;

wr = 1.0f;

wi = 0.0f;

arg = theta / (real)n;

dwr = (real)cos( arg );

dwi = (real)sin( arg );

for( j = 1; j < n; j++ )

{

for( k = j; k <= ( m_iLongVent ); k += n2 )

{

z = k + n;

tr = SigR[z-1] * wr + SigI[z-1] * wi;

ti = SigI[z-1] * wr - SigR[z-1] * wi;

SigR[z-1] = SigR[k-1] - tr;

SigI[z-1] = SigI[k-1] - ti;

SigR[k-1] += tr;

SigI[k-1] += ti;

}

tr = wr * dwr - wi * dwi;

wi = wi * dwr + wr * dwi;

wr = tr;

}

Page 17: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.4. SIGNAL.CPP 197

}

// Hasta aquı tenemos parte real e imaginaria de la transformada

// de Fourier.

// Cogemos la mitad de los elementos para obtener la magnitud

// de la transformada.

m_prEnergia[tf] = 0.0f;

for( i = 0; i < m_iLongVent/2; i++ )

{

SigR[i] = SigR[i] * SigR[i] / m_iLongVent;

SigI[i] = SigI[i] * SigI[i] / m_iLongVent;

TF[i] = (real)sqrt( SigR[i] + SigI[i] );

m_prEnergia[tf] += ( SigR[i] + SigI[i] );

}

m_prEnergia[tf] = (real)log( 2 * sqrt( 2 * m_prEnergia[tf] ) );

delete SigR;

delete SigI;

}

void CSignal::Mfcc( int t )

{

real *TF = m_pprTransformada[t];

real *MFCC = m_pprCepstrales[t];

real factor = 1.2f;

real amplitud = (real)m_iFrecuencia / (real)m_iLongVent;

real amplitud_k = amplitud / 1000.0f;

real fdelta = amplitud_k / 10.0f;

int izq = 1;

int cen = izq + (int)fdelta;

int der = cen + (int)fdelta;

real a, b;

int j, k, nfiltros;

int n = 1;

Page 18: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

198 APENDICE B. CODIGO EN C++

int i = 1;

real *filterbank = new real[ m_iLongVent/2 + 4 ];

while( n < amplitud_k )

{

filterbank[i-1] = 0;

b = 2.0f / (real)(( 2 + der - izq ) - 1);

for( j = izq; j <= der; j++ )

{

a = 1 - (real)fabs( (real)(cen - j) ) * b;

filterbank[i-1] += TF[j-1] * a;

}

i++;

n += (int)fdelta;

izq = n;

cen = izq + (int)fdelta;

der = cen + (int)fdelta;

}

while( der < m_iLongVent / 2 )

{

filterbank[i-1] = 0;

b = 2.0f / (real)(( 2 + der - izq ) - 1);

for( j = izq; j <= der; j++ )

{

a = 1 - (real)fabs( (real)(cen - j) ) * b;

filterbank[i-1] += TF[j-1] * a;

}

i += 1;

fdelta *= factor;

n += (int)fdelta;

izq = n;

cen = izq + (int)fdelta;

der = cen + (int)fdelta;

}

Page 19: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.4. SIGNAL.CPP 199

nfiltros = i - 1;

for( i = 0; i < nfiltros; i++ )

{

if( filterbank[i] >= 0 )

filterbank[i] = 20.0f * (real)log10( filterbank[i] );

else

filterbank[i] = 0.0f;

}

for( i = 0; i < m_iNumCeps; i ++ )

{

MFCC[i] = 0.0f;

for( k = 0; k < nfiltros; k++ )

{

a = ((real)k + 0.5f) * ( PI * (i + 1) );

a /= (real)nfiltros;

a = (real)cos( a );

MFCC[i] += filterbank[k] * a;

}

}

delete filterbank;

}

void CSignal::Derivadas()

{

int i, j;

real **DC = m_pprCepstrales + m_iNumFrames;

real **DDC = m_pprCepstrales + m_iNumFrames * 2;

real *DE = m_prEnergia + m_iNumFrames;

real *DDE = m_prEnergia + m_iNumFrames * 2;

for( j = 0; j < m_iNumCeps; j++ )

{

DC[0][j] = 0.0f;

DDC[0][j] = 0.0f;

Page 20: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

200 APENDICE B. CODIGO EN C++

DE[0] = 0.0f;

DDE[0] = 0.0f;

for( i = 1; i < m_iNumFrames; i++ )

{

DC[i][j] = m_pprCepstrales[i][j]

- m_pprCepstrales[i-1][j];

DDC[i][j] = DC[i][j] - DC[i-1][j];

DE[i] = m_prEnergia[i] - m_prEnergia[i - 1];

DDE[i] = DE[i] - DE[i-1];

}

}

}

real *CSignal::GetCaract( int f )

{

if( m_prCarac )

delete m_prCarac;

// Cada vector de caracterısticas incluye los ’m_iNumCeps’

// coeficientes cepstrales, la energıa y sus dos primeras

// derivadas.

m_prCarac = new real[m_iNumCeps + 3];

memcpy( m_prCarac, m_pprCepstrales[f],

sizeof(real)*m_iNumCeps );

m_prCarac[m_iNumCeps] = m_prEnergia[f];

m_prCarac[m_iNumCeps + 1] = m_prEnergia[f + m_iNumFrames];

m_prCarac[m_iNumCeps + 2] = m_prEnergia[f + 2 * m_iNumFrames];

return m_prCarac;

}

void CSignal::Normaliza()

{

real media = 0;

real varianza = 0;

int i;

Page 21: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.4. SIGNAL.CPP 201

// Se obtiene la media de la se~nal

for( i = 0; i < m_iNumMuestras; i++ )

{

media += m_prSignal[i] / (real)m_iNumMuestras;

}

// Se obtiene la varianza de la se~nal

for( i = 0; i < m_iNumMuestras; i++ )

{

varianza += (m_prSignal[i] - media)*(m_prSignal[i] - media)

/ (real)(m_iNumMuestras-1);

}

// Se normaliza la se~nal

for( i = 0; i < m_iNumMuestras; i++ )

{

m_prSignal[i] = (m_prSignal[i] - media) / varianza;

}

}

void CSignal::Banda()

{

real max = 0;

int i;

// Obtiene el valor maximo de la se~nal normalizada

for( i = 0; i < m_iNumMuestras; i++ )

{

real a = (real)fabs(m_prSignal[i]);

if( max < a )

max = a;

}

// Divide cada valor por el maximo

for( i = 0; i < m_iNumMuestras; i++ )

{

m_prSignal[i] /= max;

}

}

Page 22: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

202 APENDICE B. CODIGO EN C++

B.5. HMM.h

#ifndef __HMM_H__

#define __HMM_H__

#include "Common.h"

//! \brief Clase que representa un Modelo Oculto de Markov.

class HMM

{

//! \brief Tipo de modelo oculto de Markov.

//!

//! La diferenciacion entre distintos modelos no esta

//! implementada.

int m_nTipo;

//! \brief Numero de estados del modelo.

//!

//! Seran 3 por defecto.

int m_nNumEstados;

//! \brief Tama~no del conjunto de observacion

//!

//! Numero de elementos del conjunto de sımbolos observables.

int m_nNumElementos;

//! \brief Probabilidad de comienzo de la secuencia para cada

//! estado.

//!

//! Por defecto sera nulo para todos los estados excepto para

//! el primero. Solo se estimaran nuevo valores si se especifica

//! en el tipo de cadena. La longitud del vector sera igual al

//! numero de elementos del sistema.

real *m_prPi;

//! \brief Matriz de probabilidad de transicion entre estados.

//!

//! \f$a_{ij}\f$ = Probabilidad de pasar al estado \a i desde el

//! estado \a j. Segun el tipo de modelo algunas transiciones

//! estaran prohibidas por defecto. Por ejemplo en el caso de

//! cadenas sin retroceso de estados o sin saltos.

Page 23: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.5. HMM.H 203

real *m_prA;

//! \brief Probabilidad de emision de sımbolos.

//!

//! \f$b_j(k)\f$ = Probabilidad de que se emita el sımbolo

//! \f$v_k\f$ estando en el estado \a j.

real *m_prB;

//! Secuencia de observacion en estudio.

vector<int> m_Sec;

//! \brief Probabilidad de la secuencia de observacion parcial.

//!

//! \f$\alpha_t(i)\f$. Probabilidad de la secuencia de

//! observacion en estudio supuesta hasta el instante \a t y de

//! que en dicho instante el estado sea \a i.

real *m_prAlfa;

//! \brief Variable de retroceso.

//!

//! \f$\beta_t(i)\f$. Probabilidad de la secuencia de

//! observacion desde \a t+1 a \a T dado el estado \a i en el

//! instante \a t.

real *m_prBeta;

//! \brief Algoritmo de avance.

//!

//! Calcula \f$\alpha_t(i)\f$ mediante el algoritmo de avance.

//! Reserva el espacio necesario y almacena el puntero en

//! \a m_prAlfa.

void CalcAlfa();

//! \brief Algoritmo de retroceso.

//!

//! Calcula \f$\beta_t(i)\f$ mediante el algoritmo de retroceso.

//! Reserva el espacio necesario y almacena el puntero en

//! \a m_prBeta.

void CalcBeta();

//! \brief Calculo de \f$\gamma_t(i)\f$.

//!

Page 24: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

204 APENDICE B. CODIGO EN C++

//! Devuelve los valores de \a gamma en una fila para cada

//! estado \a i y para cada instante \a t por columnas. Si \a xi

//! toma valor NULL llama a CalcXi().

//! @param gamma Posicion de memoria donde escribir los valores

//! de \f$\gamma_t(i)\f$. El espacio debe estar reservado antes

//! de la llamada a la funcion y debe ser de tama~no

//! \a m_nNumEstados * \a max_T.

//! @param max_T Numero de elementos de la mas larga de las

//! secuencias de observacion.

//! @param xi Resultado del calculo de \f$\xi_t(i,j)\f$. Si es NULL

//! (valor por defecto) llama al metodo CalcXi().

void CalcGamma( real *gamma, int max_T, real *xi = NULL );

//! \brief Calculo de \f$\xi_t(i,j)\f$

//!

//! Devuelve los valores de \a xi en una matriz para cada

//! elemeto \a j, una fila para cada estado \a i y con cada

//! instante \a t por columnas; de modo que

//! \f$\xi_t(i,j)\f$ = xi[(i*m_nNumEstados + j)*max_T + t]

//! Si no se han calculado ya los valores \f$\alpha_t(i)\f$ y

//! \f$\beta_t(i)\f$, llama a los metodos CalcAlfa() y

//! CalcBeta().

//! @param xi Posicion de memoria donde escribir los valores de

//! \f$\xi_t(i,j)\f$. El espacio debe estar reservado antes de

//! la llamada a la funcion y debe ser de tama~no

//! \a m_nNumEstados * \a m_nNumElementos * \a max_T.

//! @param max_T Numero de elementos de la mas larga de las

//! secuencias de observacion.

void CalcXi( real *xi, int max_T );

//! \brief Algoritmo de Viterbi.

//!

//! @return Devuelve en un vector de enteros la secuencia de

//! estados optima para la observacion dada.

vector<int> Viterbi();

//! \brief Metodo de reestimacion de Baum-Welch.

//!

//! Esta funcion realiza un paso del metodo de reestimacion

//! de Baum-Welch.

void Paso_Baum_Welch();

Page 25: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.5. HMM.H 205

//! \brief Inicializa las matrices caracterısticas del modelo.

//!

//! Con la implementacion de los distintos tipos de modelos

//! ocultos de Markov variara la inicializacion de las matrices

//! caracterısticas.

void Inicializar();

//! \brief Devuelve la probabilidad de ocurrencia de la

//! secuencia de observacion.

//!

//! @return La probabilidad de ocurrecia de la secuencia en

//! /a m_Sec.

real Probabilidad();

//! \brief Determina la secuencia de observacion para estudiar

//! con el modelo.

void Observacion( vector<int> &sec );

public:

//! \brief Constructor.

//!

//! @param n Numero de estados del modelo.

//! @param m Numero de elementos del espacio observables.

//! @param tipo Tipo del modelo. Por defecto 0.

HMM( int n, int m, int tipo = 0 );

//! \brief Constructor vacio.

//!

//! Igual a HMM( 3, 16, 0 ).

HMM();

//! \brief Destructor.

~HMM();

//! \brief Probabilidad de una secuencia.

//!

//! Devuelve la probabilidad de ocurrencia de la secuencia

//! de observacion dada.

//! @param sec Vector de enteros que contiene la secuencia de

//! observacion.

Page 26: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

206 APENDICE B. CODIGO EN C++

//! @return La probabilidad de dicha secuencia.

real Probabilidad( vector<int> &sec );

//! \brief Entrenamieno del modelo

//!

//! Entrena el modelo a partir de un conjunto de secuencias de

//! observacion

//! @param secuencias Vector de vectores de enteros conteniendo

//! las secuencias de observacion.

//! @see EntrenarSecuencia()

void EntrenarGrupo( vector< vector<int> > &secuencias );

//! \brief Entrenamiento del modelo.

//!

//! Entrena el modelo a partir de una unica secuencia de

//! observacion

//! Este metodo es solo util para pruebas y experientos porque

//! no realiza un entrenamiento adecuado de un modelo.

//! @param sec Vector de enteros que contiene la secuencia de

//! observacion.

//! @see EntrenarSecuencia()

void EntrenarSecuencia( vector<int> &sec );

//! \brief Guarda el modelo en el archivo especificado.

//!

//! @param filename Nombre del archivo con la ruta completa.

void Save( string &filename );

//! \brief Guarda el modelo en el archivo especificado.

//!

//! @param file ’Stream’ del archivo donde se quiere guardar el

//! modelo.

void Save( fstream &file );

//! \brief Carga el modelo desde el archivo especificado.

//!

//! @param filename Nombre del archivo con la ruta completa.

void Load( string &filename );

//! \brief Carga el modelo desde el archivo especificado.

//!

Page 27: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.5. HMM.H 207

//! @param file Origen de datos del archivo del que se quiere

//! cargar el modelo.

void Load( fstream &file );

};

//! \brief Detecta si \a r es un numero real o si por el contrario

//! se ha producido un error en su obtencion.

//!

//! @param r Valor que se quiere comprobar.

//! @return \a true si \a r es un numero real o \a false en caso

//! contrario.

bool NotReal( real r );

#endif //__HMM_H__

Page 28: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

208 APENDICE B. CODIGO EN C++

B.6. HMM.cpp

#include "HMM.h"

HMM::HMM( int n, int m, int tipo )

{

m_nNumEstados = n;

m_nNumElementos = m;

m_nTipo = tipo;

Inicializar();

}

HMM::HMM()

{

m_nNumEstados = 3;

m_nNumElementos = 16;

m_nTipo = 0;

Inicializar();

}

void HMM::Inicializar()

{

int i, j;

int longA = m_nNumEstados * m_nNumEstados;

int longB = m_nNumEstados * m_nNumElementos;

real estInv = 1.0 / (real)m_nNumEstados;

real elemInv = 1.0 / (real)m_nNumElementos;

// Inicializacion del modelo.

// De momento se ignoran los tipos de estos.

m_prA = new real[longA];

m_prB = new real[longB];

m_prPi = new real[m_nNumEstados];

// Matriz A de probabilidad uniforme.

for( i = 0; i < longA; i++ )

m_prA[i] = estInv;

Page 29: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.6. HMM.CPP 209

// Matriz B de probabilidad uniforme.

for( i = 0; i < longB; i++ )

m_prB[i] = elemInv;

// Entrada en el modelo por el primer estado.

m_prPi[0] = 1.0;

for( i = 1; i < m_nNumEstados; i++ )

{

m_prPi[i] = 0.0;

}

// Puesta a NULL de las variables de avance y retroceso.

m_prAlfa = NULL;

m_prBeta = NULL;

}

HMM::~HMM()

{

if( m_prA )

delete m_prA;

if( m_prB )

delete m_prB;

if( m_prPi )

delete m_prPi;

if( m_prAlfa )

delete m_prAlfa;

if( m_prBeta )

delete m_prBeta;

}

void HMM::CalcAlfa()

{

int t, i, j, aux;

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return;

if( m_Sec.size() == 0 )

{

Page 30: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

210 APENDICE B. CODIGO EN C++

return;

}

// Tama~no de la secencia.

int T = (int)m_Sec.size();

// Reserva de memoria para los vectores alfa.

if( m_prAlfa )

delete m_prAlfa;

m_prAlfa = new real[m_nNumEstados * T];

// Calculo de alfa_0[i].

for( i = 0; i < m_nNumEstados; i++ )

{

m_prAlfa[i*T] = m_prPi[i]

* m_prB[ i*m_nNumElementos + m_Sec[0] ];

}

// Calculo de alfa_t[j]

for( t = 1; t < T; t++ )

{

for( j = 0; j < m_nNumEstados; j++ )

{

aux = j*T + t;

m_prAlfa[aux] = 0.0;

for( i = 0; i < m_nNumEstados; i++ )

{

m_prAlfa[aux] += m_prAlfa[i*T + t-1]

* m_prA[i*m_nNumEstados + j];

}

m_prAlfa[aux] *= m_prB[j*m_nNumElementos + m_Sec[t]];

}

}

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return;

}

Page 31: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.6. HMM.CPP 211

void HMM::CalcBeta()

{

int t, i, j, aux;

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return;

if( m_Sec.size() == 0 )

{

return;

}

// Longitud de la secuencia

int T = (int)m_Sec.size();

// Reserva de memoria para los vectores beta

if( m_prBeta )

delete m_prBeta;

m_prBeta = new real[m_nNumEstados * T];

// Calculo de beta_T(i)

for( i = 0; i < m_nNumEstados; i++ )

{

m_prBeta[i*T + T-1] = 1.0;

}

// Calculo de beta_t(i)

for( t = T-2; t >= 0; t-- )

{

for( i = 0; i < m_nNumEstados; i++ )

{

aux = i*T + t;

m_prBeta[aux] = 0.0;

for( j = 0; j < m_nNumEstados; j++ )

{

m_prBeta[aux] += m_prA[i*m_nNumEstados + j]

* m_prB[j*m_nNumElementos

+ m_Sec[t+1]] * m_prBeta[j*T + t+1];

Page 32: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

212 APENDICE B. CODIGO EN C++

}

}

}

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return;

}

vector<int> HMM::Viterbi()

{

vector<int> SecEst;

int i, j, t;

if( m_Sec.size() == 0 )

{

return SecEst;

}

int T = (int)m_Sec.size();

SecEst.resize( T );

// Reserva de memoria para los vectores Delta y Psi.

real *Delta = new real[m_nNumEstados * T];

int *Psi = new int[m_nNumEstados * T];

for( i = 0; i < m_nNumEstados; i++ )

{

Delta[i*T] = -log( m_prPi[i] )

-log( m_prB[i*m_nNumElementos + m_Sec[0]] );

Psi[i*T] = -1;

}

real aux, aux2;

int aux_i;

for( j = 0; j < m_nNumEstados; j++ )

{

for( t = 1; t < T; t++ )

{

aux_i = 0;

Page 33: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.6. HMM.CPP 213

aux = Delta[t-1] - log( m_prA[i*m_nNumEstados + j] );

for( i = 1; i < m_nNumEstados; i++ )

{

aux2 = Delta[i*T + t-1]

- log( m_prA[m_nNumEstados + j] );

if( aux2 < aux )

{

aux = aux2;

aux_i = i;

}

}

Delta[j*T + t] = aux

- log( m_prB[j*m_nNumElementos + m_Sec[t]] );

Psi[j*T + t] = aux_i;

}

}

SecEst[T-1] = 0;

aux = Delta[T-1];

for( i = 1; i < m_nNumEstados; i++ )

{

aux2 = Delta[i*T + T-1];

if( aux > aux2 )

{

SecEst[T-1] = i;

aux = aux2;

}

}

for( t = T-2; t >= 0; t++ )

{

SecEst[t] = Psi[SecEst[t+1]*T + t+1];

}

delete Delta;

delete Psi;

Page 34: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

214 APENDICE B. CODIGO EN C++

return SecEst;

}

void HMM::Paso_Baum_Welch()

{

int i, j, k, t;

real P;

if( m_Sec.size() == 0 )

return;

int T = (int)m_Sec.size();

real *Gamma = new real[m_nNumEstados * T];

real *Xi = new real[m_nNumEstados * m_nNumEstados * T];

if( !m_prAlfa )

CalcAlfa();

if( !m_prBeta )

CalcBeta();

P = Probabilidad();

for( i = 0; i < m_nNumEstados; i++ )

{

for( t = 0; t < T; t++ )

{

Gamma[i*T + t] = m_prAlfa[i*T + t] * m_prBeta[i*T + t];

for( j = 0; j < m_nNumEstados; j++ )

{

if( t != T-1 )

Xi[i*(m_nNumEstados*T) + j*T + t] =

m_prAlfa[i*T + t]

* m_prA[i*m_nNumEstados + j]

* m_prB[j*m_nNumElementos + m_Sec[t]]

* m_prBeta[j*T + t+1];

else

Xi[i*(m_nNumEstados*T) + j*T + t] = 0;

Page 35: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.6. HMM.CPP 215

}

}

}

real *sumGamma = new real[m_nNumEstados];

real sumXi;

real sumGammaCond;

real sumGamma0 = 0.0;

for( i = 0; i < m_nNumEstados; i++ )

{

sumGamma0 += Gamma[i*T];

}

for( i = 0; i < m_nNumEstados; i++ )

{

m_prPi[i] = Gamma[i*T] / sumGamma0;

sumGamma[i] = 0.0;

for( t = 0; t < T-1; t++ )

{

sumGamma[i] += Gamma[i*T + t];

}

for( k = 0; k < m_nNumElementos; k++ )

{

sumGammaCond = 0.0;

for( t = 0; t < T; t++ )

{

if( m_Sec[t] == k )

sumGammaCond += Gamma[i*T + t];

}

m_prB[i*m_nNumElementos + k] = sumGammaCond

/ ( sumGamma[i] + Gamma[i*T + T-1] );

}

}

for( i = 0; i < m_nNumEstados; i++ )

Page 36: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

216 APENDICE B. CODIGO EN C++

{

for( j = 0; j < m_nNumEstados; j++ )

{

sumXi = 0.0;

for( t = 0; t < T-1; t++ )

{

sumXi += Xi[i*(m_nNumEstados*T) + j*T + t];

}

m_prA[i*m_nNumEstados + j] = sumXi / sumGamma[i];

}

}

delete m_prAlfa;

m_prAlfa = NULL;

delete m_prBeta;

m_prBeta = NULL;

delete Gamma;

delete Xi;

delete sumGamma;

}

real HMM::Probabilidad()

{

real prob = 0.0;

int i;

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return 0.0;

if( !m_Sec.size() == 0 )

{

int T = (int)m_Sec.size();

if( m_prAlfa != NULL )

{

for( i = 0; i < m_nNumEstados; i++ )

{

prob += m_prAlfa[ i*m_nNumEstados + T-1 ];

Page 37: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.6. HMM.CPP 217

}

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return 0.0;

}

else if( m_prBeta != NULL )

{

for( i = 0; i < m_nNumEstados; i++ )

{

prob += m_prPi[i]

* m_prB[ i*m_nNumElementos + m_Sec[0] ]

* m_prBeta[ i*m_nNumEstados ];

}

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return 0.0;

}

else

{

CalcAlfa();

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return 0.0;

for( i = 0; i < m_nNumEstados; i++ )

{

prob += m_prAlfa[ i*m_nNumEstados + T-1 ];

}

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return 0.0;

}

}

return prob;

}

void HMM::Observacion( vector<int> &Sec )

{

Page 38: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

218 APENDICE B. CODIGO EN C++

m_Sec = Sec;

if( m_prAlfa )

{

delete m_prAlfa;

m_prAlfa = NULL;

}

if( m_prBeta )

{

delete m_prBeta;

m_prBeta = NULL;

}

}

real HMM::Probabilidad( vector<int> &Sec )

{

Observacion( Sec );

return Probabilidad();

}

void HMM::EntrenarGrupo( vector< vector<int> > &Secs )

{

int nSec = (int)Secs.size();

bool entrenando = true;

int i, j, k, s, t, siz;

int max_T = 0;

real gamma_sum, gamma_sum_cond, xi_sum, P, P2, pi_sum;

Inicializar();

// max_T = longitud maxima de las secuencias de entrenamiento.

for( s = 0; s < nSec; s++ )

{

siz = (int)Secs[s].size();

max_T = ( max_T < siz )? siz : max_T;

}

real **Gamma = new real*[nSec];

real **Xi = new real*[nSec];

Page 39: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.6. HMM.CPP 219

real *pi = new real[m_nNumEstados];

real *A = new real[m_nNumEstados * m_nNumEstados];

real *B = new real[m_nNumEstados * m_nNumElementos];

real *Aden = new real[m_nNumEstados * m_nNumElementos];

real *Bden = new real[m_nNumEstados * m_nNumElementos];

real *tempPi;

real *tempA;

real *tempB;

int numPasos = 0;

while( entrenando )

{

P = 0.0;

memset( pi,0,sizeof(real)*m_nNumEstados );

memset( A,0,sizeof(real)*m_nNumEstados*m_nNumEstados );

memset( B,0,sizeof(real)*m_nNumEstados*m_nNumElementos );

memset( Aden,0,sizeof(real)*m_nNumEstados*m_nNumEstados );

memset( Bden,0,sizeof(real)*m_nNumEstados*m_nNumElementos );

for( s = 0; s < nSec; s++ )

{

Observacion( Secs[s] );

CalcAlfa();

CalcBeta();

P += Probabilidad();

Gamma[s] = new real[m_nNumEstados * max_T];

Xi[s] = new real[m_nNumEstados * m_nNumEstados * max_T];

CalcXi( Xi[s], max_T );

CalcGamma( Gamma[s], max_T, Xi[s] );

}

// Entrenamiento de la matriz A;

for( i = 0; i < m_nNumEstados; i++ )

Page 40: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

220 APENDICE B. CODIGO EN C++

{

for( j = 0; j < m_nNumEstados; j++ )

{

gamma_sum = 0.0;

xi_sum = 0.0;

for( s = 0; s < nSec; s++ )

{

siz = (int)Secs[s].size();

//if( siz <= 1 ) continue;

for( t = 0; t < siz-1; t++ )

{

gamma_sum += Gamma[s][max_T * i + t];

xi_sum += Xi[s][(i*m_nNumEstados + j)*max_T + t];

}

}

A[m_nNumEstados * i + j] += xi_sum;

Aden[m_nNumEstados * i + j] += gamma_sum;

}

}

// Entrenamiento de los vectores B y pi

for( i = 0; i < m_nNumEstados; i++ )

{

gamma_sum = 0.0;

for( s = 0; s < nSec; s++ )

{

pi[i] += Gamma[s][max_T*i];

siz = (int)Secs[s].size();

for( t = 0; t < siz; t++ )

{

gamma_sum += Gamma[s][max_T*i + t];

}

}

for( k = 0; k < m_nNumElementos; k++ )

{

gamma_sum_cond = 0.0;

for( s = 0; s < nSec; s++ )

Page 41: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.6. HMM.CPP 221

{

siz = (int)Secs[s].size();

for( t = 0; t < siz; t++ )

{

if( Secs[s][t] == k )

gamma_sum_cond += Gamma[s][max_T*i + t];

}

}

B[m_nNumElementos*i + k] += gamma_sum_cond;

Bden[m_nNumElementos*i + k] += gamma_sum;

}

}

// Division

k = m_nNumEstados;

pi_sum = (real)0.0;

for( i = 0; i < k; i++ )

{

pi_sum += pi[i];

}

for( i = 0; i < k; i++ )

{

pi[i] /= pi_sum;

}

k = m_nNumEstados * m_nNumEstados;

for( i = 0; i < k; i++ )

{

if( Aden[i] != 0.0 )

A[i] /= Aden[i];

}

k = m_nNumEstados * m_nNumElementos;

for( i = 0; i < k; i++ )

{

if( Bden[i] != 0.0 )

B[i] /= Bden[i];

}

// Comprobacion

tempPi = m_prPi;

tempA = m_prA;

Page 42: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

222 APENDICE B. CODIGO EN C++

tempB = m_prB;

m_prPi = pi;

m_prA = A;

m_prB = B;

P2 = 0.0;

for( s = 0; s < nSec; s++ )

{

Observacion( Secs[s] );

real Prob = Probabilidad();

int SecSize = (int)Secs[s].size();

P2 += Prob;

}

if( P2 > P )//|| numPasos < 1000 )

{

pi = tempPi;

A = tempA;

B = tempB;

}

else

entrenando = false;

// Comprobacion de resultado valido (para depuracion).

NotReal( P2 );

numPasos++;

}

delete tempPi;

delete tempA;

delete tempB;

for( s = 0; s < nSec; s++ )

{

delete Gamma[s];

delete Xi[s];

}

delete Gamma;

Page 43: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.6. HMM.CPP 223

delete Xi;

}

void HMM::CalcGamma( real *gamma, int max_T, real *xi )

{

int i, j, t;

int T = (int)m_Sec.size();

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return;

if( !xi )

{

xi = new real[m_nNumEstados * max_T];

CalcXi( xi, max_T );

}

else

{

if( !m_prAlfa )

CalcAlfa();

if( !m_prBeta )

CalcBeta();

}

for( t = 0; t < T-1; t++ )

{

for( i = 0; i < m_nNumEstados; i++ )

{

gamma[i*max_T + t] = 0.0;

for( j = 0; j < m_nNumEstados; j++ )

{

gamma[i*max_T + t]

+= xi[(i*m_nNumEstados + j)*max_T + t];

}

}

}

for( i = 0; i < m_nNumEstados; i++ )

{

Page 44: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

224 APENDICE B. CODIGO EN C++

gamma[i*max_T + T-1] = m_prBeta[i*T + T-1];

}

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return;

}

void HMM::CalcXi( real *xi, int max_T )

{

int i, j, t;

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return;

// Se calculan las variables de avance y retroceso si no se ha

// hecho ya.

if( !m_prAlfa )

CalcAlfa();

if( !m_prBeta )

CalcBeta();

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return;

int T = (int)m_Sec.size();

real suma;

int indice;

for( t = 0; t < T-1; t++ )

{

suma = 0.0;

for( i = 0; i < m_nNumEstados; i++ )

{

for( j = 0; j < m_nNumEstados; j++ )

{

indice = (i*m_nNumEstados + j)*max_T + t;

Page 45: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.6. HMM.CPP 225

xi[indice] = m_prAlfa[i*T + t]

* m_prA[i*m_nNumEstados + j]

* m_prB[j*m_nNumElementos + m_Sec[t+1]]

* m_prBeta[j*T + t+1];

suma += xi[indice];

}

}

for( i = 0; i < m_nNumEstados; i++ )

{

for( j = 0; j < m_nNumEstados; j++ )

{

indice = (i*m_nNumEstados + j)*max_T + t;

if( suma == 0.0 )

xi[indice] = 0.0;

else

xi[indice] /= suma;

}

}

}

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return;

}

void HMM::EntrenarSecuencia( vector<int> &Sec )

{

bool entrenando = true;

real P, P2;

Observacion( Sec );

P = Probabilidad();

while( entrenando )

{

printf( "%f\n", P );

Paso_Baum_Welch();

Page 46: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

226 APENDICE B. CODIGO EN C++

P2 = Probabilidad();

if( P2 > P )

P = P2;

else

entrenando = false;

}

}

void HMM::Save( string &filename )

{

fstream file;

file.open( filename.c_str(),

ios::out | ios::trunc | ios::binary );

if( !file.is_open() )

return; // ERROR!!!

Save( file );

file.close();

}

void HMM::Save( fstream &file )

{

file.write( (char *)&m_nNumElementos, sizeof(int) );

file.write( (char *)&m_nNumEstados, sizeof(int) );

file.write( (char *)&m_nTipo, sizeof(int) );

file.write( (char *)m_prA,

sizeof(real)*m_nNumEstados*m_nNumEstados );

file.write( (char *)m_prB,

sizeof(real)*m_nNumEstados*m_nNumElementos );

file.write( (char *)m_prPi, sizeof(real)*m_nNumEstados );

}

void HMM::Load( string &filename )

{

fstream file;

file.open( filename.c_str(), ios::in | ios::binary );

Page 47: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.6. HMM.CPP 227

if( !file.is_open() )

return; // ERROR!!!

Load( file );

file.close();

}

void HMM::Load( fstream &file )

{

int newID;

bool load_matrices;

if( m_prA )

delete m_prA;

if( m_prB )

delete m_prB;

if( m_prPi )

delete m_prPi;

if( m_prAlfa )

delete m_prAlfa;

if( m_prBeta )

delete m_prBeta;

file.read( (char *)&m_nNumElementos, sizeof(int) );

file.read( (char *)&m_nNumEstados, sizeof(int) );

file.read( (char *)&m_nTipo, sizeof(int) );

int longA = m_nNumEstados * m_nNumEstados;

int longB = m_nNumEstados * m_nNumElementos;

m_prA = new real[longA];

m_prB = new real[longB];

m_prPi = new real[m_nNumEstados];

file.read( (char *)m_prA, sizeof(real)*longA );

file.read( (char *)m_prB, sizeof(real)*longB );

file.read( (char *)m_prPi, sizeof(real)*m_nNumEstados );

}

Page 48: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

228 APENDICE B. CODIGO EN C++

bool NotReal( real r )

{

string sR;

char cR[256];

sprintf( cR, "%f", r );

sR = cR;

return( sR == "1.#INF00" ||

sR == "-1.#INF00" ||

sR == "1.#IND00" ||

sR == "-1.#IND00" ||

sR == "1.#QNAN00" ||

sR == "-1.#QNAN00" );

}

Page 49: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.7. SOUNDCAPTURE.H 229

B.7. SoundCapture.h

#ifndef __SOUNDCAPTURE_H__

#define __SOUNDCAPTURE_H__

#include <dsound.h>

#include "Common.h"

#define FREQUENCY 22050

#define BITSPERSAMPLE 16

#define SAMPLE short int

//#define FREQUENCY 11025

//#define BITSPERSAMPLE 8

//#define SAMPLE BYTE

class CSoundCapture

{

//! \brief Instancia unica de la clase.

//!

//! La clase sigue el patron \a singleton. Esto quiere decir

//! que durante la ejecucion de la apliacacion solo existira

//! una instancia de esta clase, \a CSoundCapture::m_pInstance.

static CSoundCapture *m_pInstance;

//! Dispositio de captura de audio de Direct Sound.

IDirectSoundCapture8 *m_pDSC;

//! Buffer del dispositivo de captura de audio.

IDirectSoundCaptureBuffer8 *m_pDSCBuffer;

//! Numero de notificaciones para el \a buffer de captura.

int m_iNotificaciones;

//! \a Handle de notificacion para el \a buffer.

HANDLE *m_phNotificationEvent;

//! Datos de las notificaciones de posicion del \a buffer de

//! lectura.

DSBPOSITIONNOTIFY *m_pDSBPosNotify;

//! Estructura de descripcion de la onda de audio.

WAVEFORMATEX m_wfx;

//! Estructura de descripcion del buffer de captura.

DSCBUFFERDESC m_dscbd;

Page 50: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

230 APENDICE B. CODIGO EN C++

//! Variable para controlar el punto de lectura sobre el buffer.

DWORD m_dwNextOffSet;

//! Bloque de memoria donde se almacenan los datos capturados

//! hasta el momento.

BYTE *m_pbStoredData;

//! Longitud (en bytes) del bloque almacenado en

//! \a m_pbStoredData.

unsigned int m_uiStoredDataLength;

//! Constructor.

//!

//! El constructor es privado porque la clase sigue el patron

//! \a singleton. La instancia se crea la primera vez que se

//! llama al metodo GetSoundCapture() y se devuelve la misma

//! instancia en cada llamada posterior al mismo metodo.

CSoundCapture();

//! Destructor.

//!

//! El destructor es privado para seguir el patron

//! \a singleton. La instancia se destruye con el metodo

//! ReleaseSoundCapture().

~CSoundCapture();

//! \brief Inicializacion del sistema de grabacion.

//!

//! @return Ver la documentcion de DirectX para referencias

//! a \a HRESULT.

HRESULT Initialize();

//! Almacena los datos obtenidos del buffer de lectura en el

//! array de analisis

void StoreCapturedData();

public:

//! \brief Devuelve la instancia unica de la clase.

//!

//! Si es la primera vez que se llama al metodo crea la

//! instancia y la devuelve.

static CSoundCapture *GetSoundCapture();

Page 51: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.7. SOUNDCAPTURE.H 231

//! Destruye la instancia unica de la clase.

static void ReleaseSoundCapture();

//! Comienza la captura de audio

void Record();

//! Captura un bloque de 1000 muestras a traves del dispositivo

//! configurado.

void CaptureBlock();

//! Detiene la captura de audio.

void Stop();

//! Longitud del bloque almacenado.

//!

//! @return La longitud del bloque capturado en bytes.

int GetLength();

//! Obtener el bloque capturado.

//!

//! @return El puntero al array de la se~nal.

real *GetCaptured();

//! Uso provisional.

DWORD m_CapturePosition;

//! Uso provisional.

DWORD m_ReadPosition;

};

#endif //__SOUNDCAPTURE_H__

Page 52: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

232 APENDICE B. CODIGO EN C++

B.8. SoundCapture.cpp

#include "SoundCapture.h"

// El puntero a la instancia unica se inicia a NULL.

CSoundCapture *CSoundCapture::m_pInstance = NULL;

CSoundCapture *CSoundCapture::GetSoundCapture()

{

// Si no existe aun una instancia de la clase se crea.

if( !m_pInstance )

m_pInstance = new CSoundCapture;

// Se devuelve la unica instancia de la clase.

return m_pInstance;

}

void CSoundCapture::ReleaseSoundCapture()

{

// Si existe la instancia, se elimina y se inicia el puntero a NULL

if( m_pInstance )

{

delete m_pInstance;

m_pInstance = NULL;

}

}

CSoundCapture::CSoundCapture()

{

// Se ponen los punteros de los datos almacenados a NULL para

// no intentar llamar a ’delete’ sobre un puntero no iniciado.

m_pbStoredData = NULL;

m_uiStoredDataLength = 0;

m_pDSBPosNotify = NULL;

m_pDSC = NULL;

m_pDSCBuffer = NULL;

m_phNotificationEvent = NULL;

HRESULT hr;

Page 53: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.8. SOUNDCAPTURE.CPP 233

// Construccion y configuracion de los elementos necesarios para

// realizar la captura de audio.

hr = Initialize();

// TODO: Actuar sobre el error.

if( hr != DS_OK )

return;

}

CSoundCapture::~CSoundCapture()

{

m_pInstance = NULL;

// Liberar memoria y recursos

if( m_pbStoredData )

delete m_pbStoredData;

if( m_pDSBPosNotify )

delete m_pDSBPosNotify;

if( m_pDSC )

m_pDSC->Release();

if( m_phNotificationEvent )

delete m_phNotificationEvent;

}

HRESULT CSoundCapture::Initialize()

{

HRESULT hr;

DSCCAPS Caps;

int i;

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

// Crear dispositivo de captura de sonido de DirectX9 //

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

// Para comprender el funcionamiento de este metodo lease

// el capıtulo de la ayuda del SDK de DirectX 9.0:

// DirectSound->Using DirectSound->Capturing Waveforms

hr = DirectSoundCaptureCreate8( NULL, &m_pDSC, NULL );

if( hr != DS_OK )

Page 54: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

234 APENDICE B. CODIGO EN C++

{

return hr; // ERROR

}

// Comprobacion de la capacidades del dispositivo de captura

// (estructura DSCCAPS).

Caps.dwSize = sizeof( DSCCAPS );

hr = m_pDSC->GetCaps( &Caps );

if( hr != DS_OK )

{

return hr; // ERROR

}

// Estructura de definicion del formato de captura de audio.

m_wfx.cbSize = 0;

m_wfx.nAvgBytesPerSec = FREQUENCY * (BITSPERSAMPLE / 8);

m_wfx.nBlockAlign = BITSPERSAMPLE / 8;

m_wfx.nChannels = 1;

m_wfx.nSamplesPerSec = FREQUENCY;

m_wfx.wBitsPerSample = BITSPERSAMPLE;

m_wfx.wFormatTag = WAVE_FORMAT_PCM;

// Estructura de descripcion del buffer de captura

m_dscbd.dwSize = sizeof(DSCBUFFERDESC);

m_dscbd.dwFlags = 0;

// Buffer de 2 segundos

m_dscbd.dwBufferBytes = m_wfx.nAvgBytesPerSec * 2;

m_dscbd.dwReserved = 0;

m_dscbd.lpwfxFormat = &m_wfx;

m_dscbd.dwFXCount = 0;

m_dscbd.lpDSCFXDesc = NULL;

IDirectSoundCaptureBuffer *pDSCB;

// Creacion del buffer de captura ’pDSCB’

hr = m_pDSC->CreateCaptureBuffer( &m_dscbd , &pDSCB, NULL );

if( hr != DS_OK )

{

return hr; // ERROR

}

// Peticion de la iterfaz del buffer de captura de DirectX 8

Page 55: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.8. SOUNDCAPTURE.CPP 235

// en m_pDSCBuffer

hr = pDSCB->QueryInterface( IID_IDirectSoundCaptureBuffer8,

(LPVOID*)&m_pDSCBuffer );

if( hr != DS_OK )

{

return hr; // ERROR

}

// Obtencion de la interfaz de notificacion.

IDirectSoundNotify8 *pDSNotify;

hr = pDSCB->QueryInterface( IID_IDirectSoundNotify8,

(LPVOID *)&pDSNotify );

if( hr != DS_OK )

{

return hr; // ERROR

}

// Definicion de las notificaciones que hara el sistema al

// ir recorriendo el buffer de captura. Actualmente no se usan

// en las pruebas pero se mantiene para facilitar su uso en el

// futuro.

m_iNotificaciones = 4;

m_pDSBPosNotify = new DSBPOSITIONNOTIFY[m_iNotificaciones];

m_phNotificationEvent = new HANDLE[m_iNotificaciones];

// Crear eventos

for( i = 0; i < m_iNotificaciones; i++ )

m_phNotificationEvent[i] =

CreateEvent( NULL, TRUE, FALSE, NULL );

// Descripcion de las notificaciones.

for( i = 0; i < m_iNotificaciones; i++ )

{

m_pDSBPosNotify[i].hEventNotify = m_phNotificationEvent[i];

m_pDSBPosNotify[i].dwOffset =

( ( m_wfx.nAvgBytesPerSec / 2 )

* ( i + 1 ) ) - 1 ;

if( m_pDSBPosNotify[i].hEventNotify == NULL )

{

hr = GetLastError();

Page 56: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

236 APENDICE B. CODIGO EN C++

return hr; // ERROR

}

}

// Determinacion de las posiciones de notificacion.

pDSNotify->SetNotificationPositions( m_iNotificaciones,

m_pDSBPosNotify );

// Liberar interfaces

pDSNotify->Release();

pDSCB->Release();

// Si ha llegado hasta aquı no ha habido ningun error

return DS_OK;

}

void CSoundCapture::Record()

{

HRESULT hr;

// Punto de lectura al inicio del buffer.

m_dwNextOffSet = 0;

// Comienzo de la grabacion.

hr = m_pDSCBuffer->Start( DSCBSTART_LOOPING );

}

void CSoundCapture::CaptureBlock()

{

HRESULT hr;

static int iLastReadPos = -1;

bool bDone = false;

int next = (m_dwNextOffSet + 4000) % m_dscbd.dwBufferBytes;

while( !bDone )

{

hr = m_pDSCBuffer->GetCurrentPosition( &m_CapturePosition,

&m_ReadPosition );

Page 57: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.8. SOUNDCAPTURE.CPP 237

if( hr != DS_OK )

{

// Error en GetCurrentPosition

}

// Si el ındice ’next’ esta casi al final del buffer y la

// posicion de lectura ha vuelto ya al principio del mismo

// se corrige next para ver la distancia real entre ellos.

if( ( (int)m_ReadPosition < iLastReadPos ) &&

( next > (int)( m_dscbd.dwBufferBytes /2 ) ) )

{

next -= m_dscbd.dwBufferBytes;

}

// Se guardan los datos capturados cuando la posicion de

// lectura esta pos delante de ’next’ y no esta ‘next‘ al

// principio del buffer y el punto de lectura al final;

// este tiene que dar la vuelta y volver al principio.

if( (int)m_ReadPosition > next &&

!( (int)m_ReadPosition > (2 * m_dscbd.dwBufferBytes / 3)

&& next < m_dscbd.dwBufferBytes / 3 ) )

{

StoreCapturedData();

bDone = true;

}

iLastReadPos = m_ReadPosition;

}

}

void CSoundCapture::Stop()

{

HRESULT hr;

// Almacena los datos obtenidos desde la ultima llamada

// a GetBlock()

hr = m_pDSCBuffer->Stop();

}

void CSoundCapture::StoreCapturedData()

Page 58: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

238 APENDICE B. CODIGO EN C++

{

HRESULT hr;

//DWORD capturePosition, readPosition;

void *pCapturedData1, *pCapturedData2;

DWORD capturedDataLength1, capturedDataLength2;

DWORD blockLength;

BYTE *pbStoredDataAux;

hr = m_pDSCBuffer->Lock( m_dwNextOffSet, 4000, &pCapturedData1,

&capturedDataLength1, &pCapturedData2,

&capturedDataLength2, 0 );

if( hr != DS_OK )

{

//cout << "Error en Lock" << endl;

}

pbStoredDataAux = m_pbStoredData;

// Longitud del nuevo bloque.

blockLength = capturedDataLength1 + capturedDataLength2;

m_pbStoredData = new BYTE[m_uiStoredDataLength + blockLength];

// Recolocar la marca de offset para la proxima captura.

m_dwNextOffSet += blockLength;

m_dwNextOffSet %= m_dscbd.dwBufferBytes;

if( pbStoredDataAux )

{

memcpy( m_pbStoredData, pbStoredDataAux,

m_uiStoredDataLength );

delete pbStoredDataAux;

}

if( pCapturedData1 )

memcpy( m_pbStoredData + m_uiStoredDataLength,

pCapturedData1, capturedDataLength1 );

if( pCapturedData2 )

memcpy( m_pbStoredData + m_uiStoredDataLength +

Page 59: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.8. SOUNDCAPTURE.CPP 239

capturedDataLength1, pCapturedData2,

capturedDataLength2 );

hr = m_pDSCBuffer->Unlock( pCapturedData1, capturedDataLength1,

pCapturedData2, capturedDataLength2 );

if( hr != DS_OK )

{

//cout << "Error en Unlock" << endl;

}

m_uiStoredDataLength += blockLength;

}

int CSoundCapture::GetLength()

{

return m_uiStoredDataLength / ( BITSPERSAMPLE / 8 );

}

real *CSoundCapture::GetCaptured()

{

int iLength = m_uiStoredDataLength / ( BITSPERSAMPLE / 8 );

SAMPLE *pCap = (SAMPLE *)m_pbStoredData;

real *prCap = new real[iLength];

for( int i = 0; i < iLength; i++ )

{

prCap[i] = pCap[i];

}

return prCap;

}

Page 60: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

240 APENDICE B. CODIGO EN C++

B.9. SoundCaptureLink.h

#ifndef __SOUNDCAPTURELINK_H__

#define __SOUNDCAPTURELINK_H__

#include "..\Application\Common.h"

class CSoundCapture;

class CSoundCaptureLink

{

CSoundCaptureLink();

~CSoundCaptureLink();

//! Instancia de la clase \a CSoundCapture a la que enlaza.

static CSoundCapture *m_pSoundCapture;

//! Instancia unica de esta clase.

static CSoundCaptureLink *m_pInstance;

public:

//! \brief Devuelve la instancia unica de la clase.

//!

//! Si es la primera vez que se llama al metodo crea la

//! instancia y la devuelve.

static CSoundCaptureLink *GetSoundCaptureLink();

//! Destruye la instancia unica de la clase.

static void ReleaseSoundCaptureLink();

//! Comienza la captura de audio

void Record();

//! Captura un bloque de 1000 muestras a traves del dispositivo

//! configurado.

void CaptureBlock();

//! Detiene la captura de audio.

void Stop();

//! Longitud del bloque almacenado.

//!

//! @return La longitud del bloque capturado en bytes.

Page 61: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.9. SOUNDCAPTURELINK.H 241

int GetLength();

//! Obtener el bloque capturado.

//!

//! @return El puntero al array de la se~nal.

real *GetCaptured();

};

#endif //__SOUNDCAPTURELINK_H__

Page 62: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

242 APENDICE B. CODIGO EN C++

B.10. SoundCaptureLink.cpp

#include "SoundCaptureLink.h"

#include "..\Application\SoundCapture.h"

CSoundCaptureLink *CSoundCaptureLink::m_pInstance = NULL;

CSoundCapture *CSoundCaptureLink::m_pSoundCapture = NULL;

CSoundCaptureLink::CSoundCaptureLink()

{

m_pSoundCapture = CSoundCapture::GetSoundCapture();

}

CSoundCaptureLink::~CSoundCaptureLink()

{

}

CSoundCaptureLink *CSoundCaptureLink::GetSoundCaptureLink()

{

if( !m_pInstance )

m_pInstance = new CSoundCaptureLink();

return m_pInstance;

}

void CSoundCaptureLink::ReleaseSoundCaptureLink()

{

CSoundCapture::ReleaseSoundCapture();

m_pSoundCapture = NULL;

delete m_pInstance;

m_pInstance = NULL;

}

void CSoundCaptureLink::CaptureBlock()

{

m_pSoundCapture->CaptureBlock();

}

real *CSoundCaptureLink::GetCaptured()

Page 63: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.10. SOUNDCAPTURELINK.CPP 243

{

return m_pSoundCapture->GetCaptured();

}

int CSoundCaptureLink::GetLength()

{

return m_pSoundCapture->GetLength();

}

void CSoundCaptureLink::Record()

{

m_pSoundCapture->Record();

}

void CSoundCaptureLink::Stop()

{

m_pSoundCapture->Stop();

}

Page 64: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

244 APENDICE B. CODIGO EN C++

B.11. PhonRec.h

#ifndef __PHONREC_H__

#define __PHONREC_H__

#include "Common.h"

#include "HMM.h"

using namespace std;

//! \brief Fonema.

//!

//! Esta clase representa un fonema de un idioma concreto en el

//! sistema de reconocimiento de voz. El fonema se caracteriza por

//! las secuencias correspondientes al analisis de la se~nal de audio

//! de las distintas pronunciaciones introducidas. Tras el

//! entrenamiento correspondiente estas caracterısticas se plasman

//! en el Modelo Oculto de Markov (HMM) asociado.

class CPhonRec

{

//! Modelo Oculto de Markov asociado a la pronunciacion.

HMM m_HMM;

//! Nombre del fonema.

string m_sPhon;

//! Etiqueta para el elemento.

string m_sLabel;

//! Valor medio del logaritmo de la probabilidad para el modelo

//! de este fonema.

real m_rProbAverage;

//! Secuencias correspondientes a las distintas pronunciaciones

//! asociadas al fonema.

vector< vector<int> > m_vviUtterances;

public:

//! \brief Constructor.

//!

//! @param sPhon Nombre del fonema.

Page 65: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.11. PHONREC.H 245

//! @param sLabel Etiqueta del fonema.

CPhonRec( string &sPhon, string &sLabel );

//! \brief Constructor.

//!

//! @param filename Nombre del archivo.

CPhonRec( string &filename );

//! \brief Constructor.

//!

//! @param file Origen de datos del archivo desde el que se

//! quiere cargar el elemento.

CPhonRec( fstream &file );

//! Destructor.

~CPhonRec();

//! \brief Obtener el nombre del fonema.

//!

//! @return Instancia \a string con el nombre del fonema.

string GetPhonName();

//! \brief Obtener la etiqueta del fonema.

//!

//! @return Instancia \a string con la etiqueta del fonema.

string GetPhonLabel();

//! \brief A~nadir pronunciacion.

//!

//! A~nade una secuencia de observacion referente a una

//! pronunciacion del fonema en estudio.

//! @param vUtterance Secuencia de observacion.

void AddUtterance( vector<int> &vUtterance );

//! \brief Evaluar pronunciacion.

//!

//! Evalua la probabilidad de que la secuencia dada corresponda

//! con el fonema que representa esta instancia.

//! @param vUtterance Secuencia de observacion.

//! @return Logaritmo de la probabilidad de ocurrencia de la

//! secuencia de entrada.

real LogEvaluateUtterance( vector<int> &vUtterance );

//! \brief Evaluar pronunciacion.

//!

//! Evalua la probabilidad de que la secuencia dada corresponda

Page 66: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

246 APENDICE B. CODIGO EN C++

//! con el fonema que representa esta instancia.

//! @param vUtterance Secuencia de observacion.

//! @return Probabilidad de ocurrencia de la secuencia de

//! entrada.

real EvaluateUtterance( vector<int> &vUtterance );

//! \brief Entrenamiento del modelo de markov del elemento.

void TrainUtterances();

void SetAverage( real rAverage );

//! \brief Guarda el termino en el archivo especificado.

//!

//! @param filename Nombre del archivo con la ruta completa.

void Save( string &filename );

//! \brief Guarda elemento y sus datos en el archivo

//! especificado.

//!

//! @param file Origen de datos del archivo.

void Save( fstream &file );

//! \brief Carga el fonema desde el archivo especificado.

//!

//! @param filename Nombre del archivo con la ruta completa.

void Load( string &filename );

//! \brief Carga el fonema y sus datos desde el archivo

//! especificado.

//!

//! @param file Origen de datos del archivo.

void Load( fstream &file );

};

#endif //__PHONREC_H__

Page 67: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.12. PHONREC.CPP 247

B.12. PhonRec.cpp

#include "PhonRec.h"

CPhonRec::CPhonRec( string &sPhon, string &sLabel )

{

m_sPhon = sPhon;

m_sLabel = sLabel;

m_rProbAverage = 0.0f;

}

CPhonRec::CPhonRec( string &filename )

{

Load( filename );

m_rProbAverage = 0.0f;

}

CPhonRec::CPhonRec( fstream &file )

{

Load( file );

m_rProbAverage = 0.0f;

}

CPhonRec::~CPhonRec()

{

}

string CPhonRec::GetPhonName()

{

return m_sPhon;

}

string CPhonRec::GetPhonLabel()

{

return m_sLabel;

}

void CPhonRec::AddUtterance( vector<int> &vUtterance )

{

m_vviUtterances.push_back( vUtterance );

}

Page 68: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

248 APENDICE B. CODIGO EN C++

real CPhonRec::LogEvaluateUtterance( vector<int> &vUtterance )

{

real prob = m_HMM.Probabilidad( vUtterance );

if( prob != 0 )

{

prob = log10(prob);

prob = (prob-m_rProbAverage);

}

else

prob = -100000000;

return prob;

}

real CPhonRec::EvaluateUtterance( vector<int> &vUtterance )

{

return m_HMM.Probabilidad( vUtterance );

}

void CPhonRec::TrainUtterances()

{

m_HMM.EntrenarGrupo( m_vviUtterances );

}

void CPhonRec::SetAverage( real rAverage )

{

m_rProbAverage = rAverage;

}

void CPhonRec::Save( string &sFilename )

{

fstream file;

file.open( sFilename.c_str(),

ios::binary | ios::trunc | ios::out );

if( !file.is_open() )

return; // ERROR!

Save( file );

Page 69: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.12. PHONREC.CPP 249

file.close();

}

void CPhonRec::Save( fstream &file )

{

SaveString( m_sPhon, file );

SaveString( m_sLabel, file );

int n = (int)m_vviUtterances.size();

file.write( (char *)&n, sizeof(int) );

for( int i = 0; i < n; i++ )

{

SaveIVector( m_vviUtterances[i], file );

}

m_HMM.Save( file );

}

void CPhonRec::Load( string &sFilename )

{

fstream file;

file.open( sFilename.c_str(), ios::binary | ios::in );

if( !file.is_open() )

return; // ERROR!!

Load( file );

file.close();

}

void CPhonRec::Load( fstream &file )

{

int n, i;

vector<int> v;

LoadString( m_sPhon, file );

LoadString( m_sLabel, file );

file.read( (char *)&n, sizeof(int) );

Page 70: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

250 APENDICE B. CODIGO EN C++

for( i = 0; i < n; i++ )

{

LoadIVector( v, file );

m_vviUtterances.push_back( v );

}

m_HMM.Load( file );

}

Page 71: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.13. WORDREC.H 251

B.13. WordRec.h

#ifndef __WORDREC_H__

#define __WORDREC_H__

#include "Common.h"

#include "LangRec.h"

using namespace std;

class CWordRec

{

//! Palabra.

string m_sWord;

//! Lista de fonemas que forman la pronunciacion de la palabra.

vector<CPhonRec *> m_vPhons;

//! Grupo de fonemas del espa~nol.

CLangRec *m_pLangRec;

real *m_prProbability;

int *m_piIndex;

//! \brief Trascripcion fonetica de la palabra en espa~nol.

//!

//! Realiza la trascirpcion fonetica de la palabra segun las

//! reglas del espa~nol. Crea ası la lista de fonemas (CPhonRec)

//! correspondientes a la pronunciacion de aquella.

void PhoneticTrascription();

//! \brief Construye la matriz de probabilidades acumuladas.

//!

//! Este metodo privado se apoya en el algoritmo de Viterbi para

//! obtener la probabilidad de que una palabra esta pronunciada

//! en una secuencia. La matriz posee la probabilidad de que un

//! determinado fonema se termine de pronunciar en un

//! determinado \a frame. Con la distribucion de los anteriores

//! que hace maxima esta distribucion. En otra matriz se

//! almacena para cada paso la distribucion de dichos fonemas.

void ConstructProbMatrix( vector<int> &vUtterance );

Page 72: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

252 APENDICE B. CODIGO EN C++

//! \brief Probabilidad de ocurrencia de una secuencia.

//!

//! Este metodo devuelve la probabilidad de ocurrencia de una

//! subsecuencia para un fonema concreto de la palabra que se

//! esta estudiando.

//! @param fon Indice del fonema en la palabra.

//! @param i Primer elemento de la subsecuencia dentro de la

//! secuencia \a vUtterance.

//! @param f Ultimo elemento de la subsecuencia dentro de la

//! secuencia \a vUtterance.

//! @param vUtterance Secuncia de la que se extrae la

//! subsecuencia.

//! @return El logaritmo de la probabilidad de ocurrencia de la

//! subsecuencia.

real LogProbability( int fon, int i, int f,

vector<int> &vUtterance );

public:

//! \brief Constructor.

//!

//! @param sWord Nombre del elemento.

//! @param pLangRec Puntero a la intsnacia de la clase de

//! definicion de idioma.

CWordRec( string &sWord, CLangRec *pLangRec );

//! Destructor.

~CWordRec();

//! Devuelve el elemento en una instancia \a string

string GetWord();

//! \brief Evaluar pronunciacion.

//!

//! Evalua la probabilidad de que la secuencia dada corresponda

//! con la palabra que representa esta instancia.

//! @param vUtterance Secuencia de observacion.

real EvaluateUtterance( vector<int> &vUtterance );

};

#endif //__WORDREC_H__

Page 73: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.14. WORDREC.CPP 253

B.14. WordRec.cpp

#include "WordRec.h"

CWordRec::CWordRec( string &sWord, CLangRec *pLangRec )

{

m_pLangRec = pLangRec;

m_sWord = sWord;

m_prProbability = NULL;

m_piIndex = NULL;

PhoneticTrascription();

}

CWordRec::~CWordRec()

{

if( m_prProbability )

delete m_prProbability;

if( m_piIndex )

delete m_piIndex;

}

string CWordRec::GetWord()

{

return m_sWord;

}

real CWordRec::EvaluateUtterance( vector<int> &vUtterance )

{

int nFrames, nPhon;

string filename;

fstream file;

nPhon = m_vPhons.size();

nFrames = vUtterance.size();

if( nPhon == 1 )

{

real prob = LogProbability( 0, 1, nFrames-1, vUtterance );

Page 74: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

254 APENDICE B. CODIGO EN C++

return prob;

}

ConstructProbMatrix( vUtterance );

if( !m_prProbability )

{

return -100000000;

}

int i = m_piIndex[ (nPhon * nFrames) - 1 ];

int j = nFrames-1;

real prob = LogProbability( nPhon-1, i, j, vUtterance );

real rProb = m_prProbability[ (nPhon * nFrames) - 1 ];

for( int n = nPhon - 2; n >= 0; n-- )

{

j = i-1;

i = m_piIndex[n*nFrames+j];

prob = LogProbability( n, i, j, vUtterance );

}

return rProb;// / nPhon;

}

void CWordRec::PhoneticTrascription()

{

char *pcWord;

int siz = (int)m_sWord.size();

int i;

pcWord = new char[siz+1];

memcpy( pcWord, m_sWord.c_str(), siz+1 );

strlwr( pcWord );

for( i = 0; i < siz; i++ )

{

if( pcWord[i] == ’~N’ )

pcWord[i] = ’~n’;

}

Page 75: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.14. WORDREC.CPP 255

//m_vPhons.push_back( m_pLangRec->GetPhonByLabel(".pau") );

for( i = 0; i < siz; i++ )

{

char s = pcWord[i+1];

char t = pcWord[i+2];

switch( pcWord[i] )

{

case ’a’:

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("a") );

break;

case ’e’:

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("e") );

break;

case ’i’:

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("i") );

break;

case ’o’:

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("o") );

break;

case ’u’:

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("u") );

break;

case ’b’:

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("b") );

break;

case ’c’:

if( s == ’h’ )

m_vPhons.push_back(

m_pLangRec->GetPhonByLabel("ts") );

else if( s == ’e’ || s == ’i’ )

m_vPhons.push_back(

m_pLangRec->GetPhonByLabel("z") );

else

m_vPhons.push_back(

m_pLangRec->GetPhonByLabel("k") );

break;

case ’d’:

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("d") );

break;

case ’f’:

Page 76: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

256 APENDICE B. CODIGO EN C++

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("f") );

break;

case ’g’:

if( s == ’e’ || s == ’i’ )

m_vPhons.push_back(

m_pLangRec->GetPhonByLabel("x") );

else

{

m_vPhons.push_back(

m_pLangRec->GetPhonByLabel("g") );

if( s == ’u’ && ( t == ’e’ || t == ’i’ ) )

i++;

}

break;

case ’h’:

break;

case ’j’:

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("x") );

break;

case ’k’:

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("k") );

break;

case ’l’:

if( s == ’l’ )

{

m_vPhons.push_back(

m_pLangRec->GetPhonByLabel("j") );

i++;

}

else

m_vPhons.push_back(

m_pLangRec->GetPhonByLabel("l") );

break;

case ’m’:

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("m") );

break;

case ’n’:

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("n") );

break;

case ’~n’:

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("ny") );

Page 77: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.14. WORDREC.CPP 257

break;

case ’p’:

if( !(s == ’s’ && i == 0) )

m_vPhons.push_back(

m_pLangRec->GetPhonByLabel("p") );

break;

case ’q’:

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("k") );

if( s == ’u’ )

i++;

break;

case ’r’:

if( s == ’r’ || i == 0 )

{

m_vPhons.push_back(

m_pLangRec->GetPhonByLabel("rr") );

if( s == ’r’ )

i++;

}

else

m_vPhons.push_back(

m_pLangRec->GetPhonByLabel("r") );

break;

case ’s’:

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("s") );

break;

case ’t’:

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("t") );

break;

case’v’:

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("b") );

break;

case ’w’:

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("u") );

break;

case ’x’:

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("k") );

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("s") );

break;

case ’y’:

if( s == ’a’ || s == ’e’ || s == ’i’

Page 78: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

258 APENDICE B. CODIGO EN C++

|| s == ’o’ || s == ’u’ )

m_vPhons.push_back(

m_pLangRec->GetPhonByLabel("j") );

else

m_vPhons.push_back(

m_pLangRec->GetPhonByLabel("i") );

break;

case ’z’:

m_vPhons.push_back( m_pLangRec->GetPhonByLabel("z") );

}

}

//m_vPhons.push_back( m_pLangRec->GetPhonByLabel(".pau") );

delete pcWord;

}

void CWordRec::ConstructProbMatrix( vector<int> &vUtterance )

{

int nPhons = (int)m_vPhons.size();

int nFrames = (int)vUtterance.size();

// Arrays para el tama~no maximo o mınimo de cada fonema

int *minLen = new int[nPhons];

int *maxLen = new int[nPhons];

int *sumMin = new int[nPhons];

int *sumMax = new int[nPhons];

int i, j, k, i1, i2;

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return;

// Se dan los valores a las longitudes maximas y mınimas

// de cada fonema.

for( i = 0; i < nPhons; i++ )

{

if( m_vPhons[i] == NULL )

{

maxLen[i] = 20;

minLen[i] = 0;

Page 79: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.14. WORDREC.CPP 259

}

else

{

maxLen[i] = 16;

minLen[i] = 3;

}

}

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return;

// Se calculan las posiciones maxima y mınima de cada fonema en

// funcion de las longitudes maximas y mınimas.

sumMin[0] = minLen[0];

sumMax[0] = maxLen[0];

for( i = 1; i < nPhons; i++ )

{

sumMin[i] = sumMin[i-1] + minLen[i];

sumMax[i] = sumMax[i-1] + maxLen[i];

}

if( m_prProbability )

{

delete m_prProbability;

m_prProbability = NULL;

}

if( nFrames > sumMax[nPhons-1] )

return;

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return;

// Inicializamos las matrices que indican la Distorsion

m_prProbability = new real[ nPhons * nFrames ];

if( m_piIndex )

delete m_piIndex;

Page 80: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

260 APENDICE B. CODIGO EN C++

m_piIndex = new int[ nPhons * nFrames ];

float mf, aux;

int mi;

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return;

int j1, j2;

// Para cada segmento excepto el ultimo

for( i = 0; i < nPhons-1; i++ )

{

j1 = sumMin[i];

j2 = min( sumMax[i], nFrames-1 );

// Para cada punto posible de fin del segmento

for( j = j1; j <= j2; j++ )

{

if( i == 0 )

i1 = 1;

else

i1 = max( j-maxLen[i]+1, sumMin[i-1]+1 );

if( i == 0 )

i2 = 1;

else

i2 = min( j-minLen[i]+1, sumMax[i-1]+1 );

mf = -100000000;

mi = i1;

// Entre todos los puntos de inicio posible

for( k = i1; k <= i2; k++ )

{

aux = LogProbability( i, k, j, vUtterance );

if( i != 0 )

aux += m_prProbability[(i-1)*nFrames + k-1];

Page 81: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.14. WORDREC.CPP 261

// Tomamos aquel de probabilidad acumulada mayor.

if( aux > mf )

{

mf = aux;

mi = k;

}

}

m_prProbability[i*nFrames + j] = mf;

m_piIndex[i*nFrames + j] = mi;

}

}

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return;

// Ultimo Segmento

mf = -100000000;

i1 = max( nFrames - maxLen[nPhons-1], sumMin[nPhons-2] + 1 );

i2 = min( nFrames - minLen[nPhons-1], sumMax[nPhons-2] + 1 );

mi = i1;

for( k = i1; k <= i2; k++ )

{

aux = LogProbability( nPhons-1, k, nFrames-1, vUtterance );

aux += m_prProbability[(nPhons-2)*nFrames + k-1];

// Tomamos aquel de probabilidad acumulada mayor.

if( aux > mf )

{

mf = aux;

mi = k;

}

}

m_prProbability[(nPhons*nFrames) - 1] = mf;

m_piIndex[(nPhons*nFrames) - 1] = mi;

Page 82: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

262 APENDICE B. CODIGO EN C++

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return;

delete minLen;

delete maxLen;

delete sumMax;

delete sumMin;

}

real CWordRec::LogProbability( int fon, int i, int f,

vector<int> &vUtterance )

{

vector<int> subUtterance;

real probSum = 0.0;

real prob = 0.0;

real relprob = 0.0;

int numPhons = m_pLangRec->GetNumPhons();

int numFrames = (int)vUtterance.size();

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return 0.0;

if( fon < 0 || fon >= numPhons || i < 0 || i >= numFrames

|| f < 0 || f >= numFrames || f <= i )

return 0.0;

subUtterance.insert( subUtterance.begin(), vUtterance.begin()+i,

vUtterance.begin()+f+1 );

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return 0.0;

prob = m_vPhons[fon]->LogEvaluateUtterance( subUtterance );

// Control de lagunas de memoria en modo debug.

if( !_CrtCheckMemory() )

return 0.0;

Page 83: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.14. WORDREC.CPP 263

return prob;

}

Page 84: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

264 APENDICE B. CODIGO EN C++

B.15. LangRec.h

#ifndef __LANGREC_H__

#define __LANGREC_H__

#include "Common.h"

#include "PhonRec.h"

//! \brief Grupo de fonemas pertenecientes a un idioma.

//!

//! Esta clase almacena un conjunto de fonemas correspondientes

//! a un idioma para el sistema de reconocimiento de voz.

//! Cada elemento (clase CPhonRec) esta represenado por un nombre,

//! una etiqueta y lo mas importante su Modelo Oculto de Markov

//! caracterıstico (clase HMM).

class CLangRec

{

//! Nombre del idioma.

string m_sName;

//! Vector de fonemas incluidos.

vector<CPhonRec *> m_vpPhons;

public:

//! \brief Constructor vacio

CLangRec();

//! \brief Constructor cargando el contenido desde disco.

//! @param filename Nombre del archivo con la ruta completa.

CLangRec( const string &filename );

//! \brief Constructor cargando el contenido desde disco.

//! @param file Origen de datos del archivo desde el que se

//! quiere cargar.

CLangRec( fstream &file );

//! \brief Destructor

~CLangRec();

//! \brief A~nade un fonema a la configuracion de un idioma.

//!

//! @param sPhon Nombre del fonema.

//! @param sLabel Etiqueta del fonema.

//! @return El puntero a la instancia de la clase CPhonRec que

Page 85: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.15. LANGREC.H 265

//! se ha a~nadido.

CPhonRec *AddPhon( string &sPhon, string &sLabel );

//! \brief A~nade un elemento nuevo cargando sus datos desde

//! disco.

//!

//! @param filename Nombre del archivo del que se quiere cargar

//! el fonema.

//! @return El puntero a la instancia de la clase CPhonRec que

//! se ha a~nadido.

CPhonRec *AddPhon( string &filename );

//! \brief A~nade un elemento nuevo cargando sus datos desde

//! disco.

//!

//! @param file Origen de datos del archivo del que se quiere

//! cargar el fonema.

//! @return El puntero a la instancia de la clase CPhonRec que

//! se ha a~nadido.

CPhonRec *AddPhon( fstream &file );

//! \brief Obtener el numero de fonemas del idioma.

//!

//! @return Entero con el numero de elementos.

int GetNumPhons();

//! \brief Obtener fonema.

//!

//! @param index Indice del elemento en la lista de fonemas.

//! @return Puntero a la instancia CPhonRec del elemento de

//! ındice \a index. Devuelve NULL si el ındice esta fuera de

//! rango.

CPhonRec *GetPhon( int index );

//! \brief Obtener fonema.

//!

//! @param sLabel Etiqueta del fonema que se quiere obtener.

//! @return Puntero a la instancia CPhonRec del elemento de

//! etiqueta \a sLabel. Devuelve \a NULL si no esta contenido

//! en el grupo de fonemas de este idioma.

CPhonRec *GetPhonByLabel( const string &sLabel );

//! \brief Guarda el diccionario en el archivo especificado.

Page 86: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

266 APENDICE B. CODIGO EN C++

//!

//! @param filename Nombre del archivo con la ruta completa.

void Save( const string &filename );

//! \brief Guarda el diccionario en el archivo especificado.

//!

//! @param file Origen de datos del archivo.

void Save( fstream &file );

//! \brief Carga el diccionario desde el archivo especificado.

//!

//! @param filename Nombre del archivo con la ruta completa.

void Load( const string &filename );

//! \brief Carga el diccionario desde el archivo especificado.

//!

//! @param file Origen de datos del archivo.

void Load( fstream &file );

};

#endif //__LANGREC_H__

Page 87: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.16. LANGREC.CPP 267

B.16. LangRec.cpp

#include "LangRec.h"

CLangRec::CLangRec()

{

m_sName = "Espa~nol";

}

CLangRec::CLangRec( fstream &file )

{

Load( file );

}

CLangRec::CLangRec( const string &filename )

{

Load( filename );

}

CLangRec::~CLangRec()

{

for( int i = 0; i < (int)m_vpPhons.size(); i++ )

{

delete m_vpPhons[i];

}

m_vpPhons.clear();

}

CPhonRec *CLangRec::AddPhon( string &filename )

{

CPhonRec *pPhon = new CPhonRec( filename );

m_vpPhons.push_back( pPhon );

return pPhon;

}

CPhonRec *CLangRec::AddPhon( fstream &file )

{

CPhonRec *pPhon = new CPhonRec( file );

Page 88: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

268 APENDICE B. CODIGO EN C++

m_vpPhons.push_back( pPhon );

return pPhon;

}

CPhonRec *CLangRec::AddPhon( string &sPhon, string &sLabel )

{

CPhonRec *pPhon = new CPhonRec( sPhon, sLabel );

m_vpPhons.push_back( pPhon );

return pPhon;

}

int CLangRec::GetNumPhons()

{

return (int)m_vpPhons.size();

}

CPhonRec *CLangRec::GetPhon( int index )

{

if( index < 0 || index >= (int)m_vpPhons.size() )

return NULL;

else

return m_vpPhons[index];

}

CPhonRec *CLangRec::GetPhonByLabel( const string &sLabel )

{

for( int i = 0; i < (int)m_vpPhons.size(); i++ )

{

if( m_vpPhons[i]->GetPhonLabel() == sLabel )

return m_vpPhons[i];

}

return NULL;

}

void CLangRec::Save( const string &filename )

{

Page 89: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.16. LANGREC.CPP 269

fstream file;

file.open( filename.c_str(),

ios::binary | ios::trunc | ios::out );

if( !file.is_open() )

return; // ERROR!

Save( file );

file.close();

}

void CLangRec::Save( fstream &file )

{

int iSize = (int)m_vpPhons.size();

SaveString( m_sName, file );

file.write( (char *)&iSize, sizeof(int) );

for( int i = 0; i < iSize; i++ )

{

m_vpPhons[i]->Save( file );

}

}

void CLangRec::Load( const string &filename )

{

fstream file;

file.open( filename.c_str(), ios::binary | ios::in );

if( !file.is_open() )

return; // ERROR!!

Load( file );

file.close();

}

void CLangRec::Load( fstream &file )

{

int iSize, i;

Page 90: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

270 APENDICE B. CODIGO EN C++

LoadString( m_sName, file );

file.read( (char *)&iSize, sizeof(int) );

for( i = 0; i < iSize; i++ )

{

AddPhon( file );

}

}

Page 91: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.17. DICTREC.H 271

B.17. DictRec.h

#ifndef __DICTREC_H__

#define __DICTREC_H__

#include "Common.h"

#include "LangRec.h"

#include "WordRec.h"

//! \brief Diccionario de terminos identificables.

//!

//! Esta clase almacena un conjunto de palabras identificables

//! mediante el sistema de reconocimiento de voz.

class CDictRec

{

//! Nombre del diccionario.

string m_sName;

//! Nombre del archivo del que se cargan los fonemas del idioma

//! empleado.

string m_sLangRecFile;

//! Grupo de fonemas del idioma empleado.

CLangRec *m_pLangRec;

//! Vector de elementos identificables.

vector<CWordRec *> m_vpWords;

public:

//! \brief Constructor dando la instancia de la clase de

//! configuracion del idioma.

//! @param name Nombre que se quiere dar al diccionario.

//! @param pLangRec Puntero a la instancia de la clase de

//! configuracion del idioma.

CDictRec( const string &name, CLangRec *pLangRec );

//! \brief Constructor indicando la coniguracion del idioma.

//! @param name Nombre que se quiere dar al diccionario.

//! @param sLangRecFile Puntero a la clase de configuracion del

//! idioma.

CDictRec( const string &name, const string &sLangRecFile );

//! \brief Constructor cargando el contenido desde disco.

Page 92: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

272 APENDICE B. CODIGO EN C++

//! @param filename Nombre del archivo con la ruta completa.

CDictRec( const string &filename );

//! \brief Constructor cargando el contenido desde disco.

//! @param file Origen de datos del archivo desde el que se

//! quiere cargar el diccionario.

CDictRec( fstream &file );

//! \brief Destructor

~CDictRec();

//! \brief A~nade una palabra nueva al diccionario de terminos

//! identificables.

//!

//! @param sWord Palabra a a~nadir.

//! @return El puntero a la instancia de la clase CWordRec que

//! se ha a~nadido.

CWordRec *AddWord( string &sWord );

//! \brief Obtener el numero de terminos en el diccionario.

//!

//! @return Entero con el numero de elementos en el diccionario.

int GetNumWords();

//! \brief Obtener una palabra del diccionario.

//!

//! @param index Indice del elemento en la lista de terminos.

//! @return El puntero a la instancia de la clase CWordRec de

//! ındice \a index.

CWordRec *GetWord( int index );

//! \brief Obtener una palabra del diccionario

//!

//! @param sWord Palabra que se quiere encontrar.

//! @return Puntero a la instancia CWordRec de la palabra

//! \a sWord.

CWordRec *GetWord( const string &sWord );

//! \brief Identificacion de un termino.

//!

//! Identifica a que elemento del diccionario pertenece (con

//! mayor probabilidad) la secuencia de observacion dada.

//! @param vSecuence Secuencia del elemento a identificar.

//! Esta secuencia se obtiene del analisis de la se~nal de voz

//! (clase CSignal) y posterior clasificacion de los

Page 93: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.17. DICTREC.H 273

//! vectores de coeficientes cepstrales obenidos (clase

//! CFuzzyCMeans).

//! @return Puntero a la instancia CWordRec de la palabra que

//! se estima se ha identificado en la secuencia.

CWordRec *Identify( vector<int> &vSecuence );

//! \brief Guarda el diccionario en el archivo especificado.

//!

//! @param filename Nombre del archivo con la ruta completa.

void Save( const string &filename );

//! \brief Guarda el diccionario en el archivo especificado.

//!

//! @param file Origen de datos del archivo.

void Save( fstream &file );

//! \brief Carga el diccionario desde el archivo especificado.

//!

//! @param filename Nombre del archivo con la ruta completa.

void Load( const string &filename );

//! \brief Carga el diccionario desde el archivo especificado.

//!

//! @param file Origen de datos del archivo.

void Load( fstream &file );

};

#endif //__DICTREC_H__

Page 94: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

274 APENDICE B. CODIGO EN C++

B.18. DictRec.cpp

#include "DictRec.h"

CDictRec::CDictRec( const string &name, CLangRec *pLangRec )

{

m_sName = name;

m_sLangRecFile = "";

m_pLangRec = pLangRec;

}

CDictRec::CDictRec( const string &name, const string &sLangRecFile )

{

m_sName = name;

m_sLangRecFile = sLangRecFile;

m_pLangRec = new CLangRec( sLangRecFile );

}

CDictRec::CDictRec( const string &filename )

{

Load( filename );

}

CDictRec::CDictRec( fstream &file )

{

Load( file );

}

CDictRec::~CDictRec()

{

for( int i = 0; i < (int)m_vpWords.size(); i++ )

{

delete m_vpWords[i];

}

if( m_sLangRecFile != "" )

delete m_pLangRec;

}

CWordRec *CDictRec::AddWord( string &sWord )

{

Page 95: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.18. DICTREC.CPP 275

CWordRec *pWord;

pWord = new CWordRec( sWord, m_pLangRec );

m_vpWords.push_back( pWord );

return pWord;

}

int CDictRec::GetNumWords()

{

return (int)m_vpWords.size();

}

CWordRec *CDictRec::GetWord( int index )

{

if( index >= 0 && index < (int)m_vpWords.size() )

return m_vpWords[index];

else

return NULL;

}

CWordRec *CDictRec::GetWord( const string &sWord )

{

for( int i = 0; i < (int)m_vpWords.size(); i++ )

{

if( m_vpWords[i]->GetWord() == sWord )

return m_vpWords[i];

}

return NULL;

}

CWordRec *CDictRec::Identify( vector<int> &vSecuence )

{

real maxProb = -1.0;

real prob;

int i, maxI = -1;

for( i = 0; i < (int)m_vpWords.size(); i++ )

{

prob = m_vpWords[i]->EvaluateUtterance( vSecuence );

Page 96: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

276 APENDICE B. CODIGO EN C++

if( prob>maxProb )

{

maxProb = prob;

maxI = i;

}

}

return m_vpWords[maxI];

}

void CDictRec::Save( const string &filename )

{

fstream file;

file.open( filename.c_str(),

ios::binary | ios::trunc | ios::out );

if( !file.is_open() )

return; // ERROR!

Save( file );

file.close();

}

void CDictRec::Save( fstream &file )

{

int numWords, i;

SaveString( m_sName, file );

SaveString( m_sLangRecFile, file );

numWords = (int)m_vpWords.size();

file.write( (char *)&numWords, sizeof(int) );

for( i= 0; i < numWords; i++ )

{

SaveString( m_vpWords[i]->GetWord(), file );

}

}

void CDictRec::Load( const string &filename )

Page 97: C´odigo en C++ - Servidor de la Biblioteca de …bibing.us.es/proyectos/abreproy/3851/fichero/PFC-B.pdf · B.3. SIGNAL.H 187 //! @return Devuelve el t¶ermino en¶esimo de una ventana

B.18. DICTREC.CPP 277

{

fstream file;

file.open( filename.c_str(), ios::binary | ios::in );

if( !file.is_open() )

return; // ERROR!!

Load( file );

file.close();

}

void CDictRec::Load( fstream &file )

{

int numWords, i;

string sWord;

CWordRec *pWord;

LoadString( m_sName, file );

LoadString( m_sLangRecFile, file );

m_pLangRec = new CLangRec( m_sLangRecFile );

file.read( (char *)&numWords, sizeof(int) );

m_vpWords.clear();

for( i = 0; i < numWords; i++ )

{

LoadString( sWord, file );

pWord = new CWordRec( sWord, m_pLangRec );

m_vpWords.push_back( pWord );

}

}