Referencia de la Clase ParamDeltas

Clase para el cálculo sistemático y eficiente de derivadas de parámetros. Más...

#include <deltas.h>


Métodos públicos

 ParamDeltas ()
 ParamDeltas (INT Ndeltas, INT *windowSize, INT Ndim)
 ~ParamDeltas ()
void Initialize (INT Ndeltas, INT *windowSize, INT Ndim)
 Cambia el tamaño del buffer.
void Push (const DOUBLE *e)
 Añade un nuevo vector de parámetros a los buffers de cálculo.
INT Delay () const
 Devuelve el retardo de cálculo.
INT Ndim () const
 Devuelve la dimensión de los parámetros.
INT Ndeltas () const
 Devuelve el número de deltas calculadas.
void Get (DOUBLE *e) const
 Devuelve un vector de parámetros con sus deltas.

Métodos protegidos

void Populate (const DOUBLE *e)
 Popula el primer buffer.

Atributos protegidos

std::vector< buffer2Dm_vDeltaBuffers
 Buffers usados para el cálculo de derivadas.
std::vector< buffer2Dm_vMemBuffers
 Buffers usados para recordar muestras pasadas.
INT m_Ndim
 Número de dimensiones de los parámetros (sin deltas).
bool m_bInit
 Variable interna para saber si el objeto está inicializado.
DOUBLE * m_pdDiff
 Buffer temporal para cálculo de derivadas.


Descripción detallada

Supongamos que tenemos un archivo de audio que queremos parametrizar. Supongamos asímismo que tenemos una función que, dada una trama de muestras, genera un vector de parámetros. Y por último, supongamos que queremos añadir a esa parametrización información dinámica: derivadas.

El esqueleto de la parametrización sería algo así (por supuesto, el código es muy mejorable, pero sirve para el ejemplo):

        INT frameLen = 80:          //Tamaño de la ventana de trama en muestras
        INT npars = 10;             //Número de parámetros
        INT ndeltas = 2;            //Número de derivadas a calcular (deriv. y aceleraciones)
 
        //array para recoger una trama de muestras
        DOUBLE* frame = new DOUBLE [frameLen];
 
        //array para recoger un vector de parámetros (sin deltas)
        DOUBLE* params = new DOUBLE [npars];
        
        //array para recoger las derivadas de los parámetros
        DOUBLE* deltaparams = new DOUBLE [npars];
        
        //array para recoger un vector de parámetros junto con las deltas (concatenadas)
        DOUBLE* finalparams = new DOUBLE [npars*(ndeltas+1)];
        
        for (INT i = 0; i < Nframes(); ++i)
        {
            frame = GetFrame(i);
            params = GetParams(frame);
 
            //Calculamos las primeras derivadas y las añadimos a los parámetros
            deltaparams = GetDeltas(params);
            finalparams = Catenate(params, deltaparams);
 
            //Calculamos las segundas derivadas y las añadimos a los parámetros
            deltaparams = GetDeltas(deltaparams);
            finalparams = Catenate(finalparams, deltaparams);
 
            //Hacemos algo con los parámetros
            DoSomething(finalparams);
        }

Salvo por un pequeño detalle. Si se quiere calcular la delta de una trama de forma precisa, es necesario disponer de una ventana de tramas por delante y por detrás de la trama actual. En modo gráfico:

        trama ->      i-3    i-2    i-1     i     i+1    i+2    i+3
                       *      *      *      *      *      *      *
        ventana ->         \----------------------------------/
                                            |
                                            *
        delta ->                            i

Dicho de otra forma, para calcular la delta de la trama i-ésima, es necesario que el puntero del archivo esté leyendo la trama i+2 (en este ejemplo). Esto tiene varias implicaciones:

Todo esto se complica de sobremanera si estamos calculando deltas de deltas: El retardo del cálculo se acumula, cada delta puede tener ventanas de tamaño diferente, necesitas varias memorias (una para cada delta y otra para las muestras sin deltas), etc.

Bien, pues esta clase te permite abstraerte de (casi) todo esto. Lo único que debes tener en cuenta es que existe un retardo entre la trama que le das y la delta que te devuelve. Pero incluso este retrardo te lo calcula él de forma automática.

El ejemplo anterior, utilizando esta clase, sería algo así como:

        INT frameLen = 80:          //Tamaño de la ventana de trama en muestras
        INT npars = 10;             //Número de parámetros
        INT ndeltas = 2;            //Número de derivadas a calcular (deriv. y aceleraciones)
        INT wins [] = {2, 3};       //Tamaño de las ventanas para cálculo de deltas (en tramas)
 
        //Este objeto se encarga de todo el cálculo de deltas
        ParamDeltas deltas (ndeltas, wins, npars);
 
        //array para recoger una trama de muestras
        DOUBLE* frame = new DOUBLE [frameLen];
 
        //array para recoger un vector de parámetros (sin deltas)
        DOUBLE* params = new DOUBLE [npars];
        
        //array para recoger un vector de parámetros junto con las deltas (concatenadas)
        DOUBLE* finalparams = new DOUBLE [npars*(ndeltas+1)];
        
        for (INT i = 0; i < Nframes()+deltas.Delay(); ++i)
        {
            //Estamos leyendo más allá del fichero. No debemos hacerlo
            //Si i >= NFrames(), símplemente se repite la última muestra
            if (i < NFrames())
                frame = GetFrame(i);
            params = GetParams(frame);
 
            //Metemos los parámetros en el sistema
            deltas.Push(params);
 
            //El valor devuelto por el sistema no tiene sentido hasta que no hayamos
            //metido deltas.Delay() tramas
            if (i < deltas.Delay())
                continue;
 
            //Recuperamos la trama con deltas
            //Será la trama i-deltas.Delay()
            deltas.Get(finalparams)
 
            //Hacemos algo con los parámetros
            DoSomething(finalparams);
        }

La clase automáticamente repite la primera trama al principio del fichero, con lo que es capaz de calcular la delta de la primera trama. Con respecto a la última trama, como no hay forma de que la clase sepa que es la última, pues ya nos encargamos nosotros, repitiendo la última trama Delay() veces.

Hay que tener en cuenta que Get() devuelve el vector con deltas para la trama i-Delay(). Si i<Delay(), entonces estamos recuperando una trama que en realidad no existe. El objeto está sin inicializar del todo, y sólo devuelve mierda.

Por último, si no se quiere que se repitan la primera y última trama (es decir, si podemos soportar no calcular deltas al principio y final del archivo), se puede hacer así:

        INT frameLen = 80:          //Tamaño de la ventana de trama en muestras
        INT npars = 10;             //Número de parámetros
        INT ndeltas = 2;            //Número de derivadas a calcular (deriv. y aceleraciones)
        INT wins [] = {2, 3};       //Tamaño de las ventanas para cálculo de deltas (en tramas)
 
        //Este objeto se encarga de todo el cálculo de deltas
        ParamDeltas deltas (ndeltas, wins, npars);
 
        //array para recoger una trama de muestras
        DOUBLE* frame = new DOUBLE [frameLen];
 
        //array para recoger un vector de parámetros (sin deltas)
        DOUBLE* params = new DOUBLE [npars];
        
        //array para recoger un vector de parámetros junto con las deltas (concatenadas)
        DOUBLE* finalparams = new DOUBLE [npars*(ndeltas+1)];
        
        for (INT i = 0; i < Nframes(); ++i)
        {
            //Ahora ya no leemos más allá del final del archivo
            frame = GetFrame(i);
            params = GetParams(frame);
 
            //Metemos los parámetros en el sistema
            deltas.Push(params);
 
            //Descartamos 2*deltas.Delay(), ya que así nos aseguramos que las deltas
            //obtenidas se hayan calculado sin repetir la primera trama
            if (i < 2*deltas.Delay())
                continue;
 
            //Recuperamos la trama con deltas
            //Será la trama i-deltas.Delay()
            //Sólo que ahora i={2*deltas.Delay(),...,Nframes()}, lo que significa
            //que sólo tenemos tramas completas en el rango i={deltas.Delay(),...,Nframes()-deltas.Delay()}
            deltas.Get(finalparams)
 
            //Hacemos algo con los parámetros
            DoSomething(finalparams);
        }

Algoritmo

Esta clase calcula las deltas como la pendiente de la recta de regresión de una ventana centrada en la trama i. Digamos que estas ventanas tienen semi-anchura N. Es decir, la anchura total de la ventana es de 2N+1.

Esto significa que para calcular la derivada de la trama i es necesario conover las tramas i-N hasta i+N.

Bien, supongamos ahora que no sólo calculamos las diferencias, sino también aceleraciones. Las aceleraciones se calculan como la pendiente de la recta de regresión de las derivadas, en otra ventana de tamaño M (posiblemente diferente a N)

Y podríamos calcular terceras, cuartas... diferencias. Digamos que la semi-anchura de cada una de las ventanas es N[j] para la derivada j-ésima. Entonces se puede demostrar que el retardo total en el cálculo (o lo que es lo mismo, cuánto por delante de la trama i debemos estar leyendo el archivo para poder calcular TODAS las derivadas de i) es igual a la suma de todas las semi-ventanas: delay = sum(N[j]).

Definición en la línea 224 del archivo deltas.h.


Documentación del constructor y destructor

ParamDeltas::ParamDeltas (  )  [inline]

Definición en la línea 242 del archivo deltas.h.

ParamDeltas::ParamDeltas ( INT  Ndeltas,
INT *  windowSize,
INT  Ndim 
) [inline]

El número de deltas puede ser 0, pero ninguna ventana puede ser ni cero ni negativa, o se provoca un ASSERT.

Ndeltas = 0 se trata como un caso especial

Definición en la línea 254 del archivo deltas.h.

ParamDeltas::~ParamDeltas (  )  [inline]

Definición en la línea 258 del archivo deltas.h.


Documentación de las funciones miembro

void ParamDeltas::Initialize ( INT  Ndeltas,
INT *  windowSize,
INT  Ndim 
)

El número de deltas puede ser 0, pero ninguna ventana puede ser ni cero ni negativa, o se provoca un ASSERT.

Ndeltas = 0 se trata como un caso especial

Parámetros:
Ndeltas  Número de deltas a calcular
windowSize  Tamaño de la ventana para el cálculo de cada delta
Ndim  nº de dimensiones de los parámetros (sin deltas)

Definición en la línea 95 del archivo deltas.cpp.

void ParamDeltas::Push ( const DOUBLE *  e  ) 

Parámetros:
e  Vector a añadir. Debe tener Dim() elementos

Definición en la línea 137 del archivo deltas.cpp.

INT ParamDeltas::Delay (  )  const [inline]

Definición en la línea 271 del archivo deltas.h.

INT ParamDeltas::Ndim (  )  const [inline]

Definición en la línea 277 del archivo deltas.h.

INT ParamDeltas::Ndeltas (  )  const [inline]

Definición en la línea 283 del archivo deltas.h.

void ParamDeltas::Get ( DOUBLE *  e  )  const

<Memoria donde escribir el vector. Debe tener Ndim()*(Ndeltas()+1) elementos

Devuelve un vector completo con deltas. Cuidado, ya que el vector devuelto tiene un retardo de Delay() tramas con respecto al último vector insertado con Push(). Dicho de otra manera, en el siguiente código:

        INT ndeltas = 2;
        INT wins [] = {2, 3};
        INT dim = 10;
        ParamDeltas deltas (ndeltas, wins, dim);
 
        DOUBLE* frame = new DOUBLE [dim];                       //Trama sin deltas
        DOUBLE* deltaframe = new DOUBLE [(ndeltas+1)*dim];      //Trama con deltas
 
        for (int i = 0, i < Nframes(); ++i)
        {
            //Recogemos una trama
            frame = GetFrame(i);
            deltas.Push(frame);
            deltas.Get(deltaframe);
        }

Cuando metemos al sistema la trama i mediante un Push(), Get() nos devuelve la trama i-Delay().

Definición en la línea 186 del archivo deltas.cpp.

void ParamDeltas::Populate ( const DOUBLE *  e  )  [protected]

Cuando llega la primerísima trama, esta función se encarga de llenar el buffer [0] (el de las muestras sin deltas). En realidad lo llena por completo excepto la última posición, de la cual ya se encarga Push()

Definición en la línea 205 del archivo deltas.cpp.


Documentación de los campos

std::vector<buffer2D> ParamDeltas::m_vDeltaBuffers [protected]

Definición en la línea 298 del archivo deltas.h.

std::vector<buffer2D> ParamDeltas::m_vMemBuffers [protected]

Definición en la línea 299 del archivo deltas.h.

INT ParamDeltas::m_Ndim [protected]

Definición en la línea 300 del archivo deltas.h.

bool ParamDeltas::m_bInit [protected]

Definición en la línea 301 del archivo deltas.h.

DOUBLE* ParamDeltas::m_pdDiff [protected]

Definición en la línea 302 del archivo deltas.h.


La documentación para esta clase fue generada a partir de los siguientes ficheros:

Generado el Thu Mar 11 18:59:28 2010 para AhoLib por  doxygen 1.5.6