📄 extcaracteristicas.java
字号:
/*
* ExtCaracteristicas.java
*
* Created on 9 de marzo de 2008, 02:10 PM
*
*/
package rah;
import java.awt.*;
import java.util.*;
public class ExtCaracteristicas {
private double[] datosVoz;
private int ancho;
ProcesamientoSenhal ProcDSenhal;
private double[][] mInversa;
private int P=14;
private double[] a = new double[P];
public ExtCaracteristicas(double[] dxVoz,int ancho){
ProcDSenhal=new ProcesamientoSenhal(dxVoz,ancho);
this.datosVoz=dxVoz;
this.ancho=ancho;
}
//********************** MFCC ***********************************************************
//H(k)
public double[] obtenerH(int fm0,int fm,int fm1){
int j=0;
double[] H=new double[fm1-fm0];
for(int k=fm0;k<fm1;k++)
{
double valor=0;
if(k<fm0 || k>fm1)
{
valor=0;
}
if(k>=fm0 && k<=fm)
{
valor=(double)(k-fm0)/(double)(fm-fm0);
}
if(k>fm && k<=fm1)
{
valor=(double)(fm1-k)/(double)(fm1-fm);
}
H[j]=valor;
j++;
}
return H;
}
public double[][] obtenerMFCC(double[] dxVoz,int longVent,int desp){
double[][] MFCC=new double[39][dxVoz.length/desp];
int fs=dxVoz.length;
int i,j,k,cMFCC=0;
for (i=0;i<dxVoz.length-(desp+longVent);i+=desp)
{
//Obtengo ventana
double[] ventana=new double[longVent];
k=0;
for(j=i;j<i+longVent;j++)
{
ventana[k]=dxVoz[j];
k++;
}
//Calculo FFT de la ventana
double[] ventana2=ProcDSenhal.ventanamiento(ventana,0.46);
double[] FFT_Vent=ProcDSenhal.obtenerFFT(ventana2);
//Utilizo solo la mitad del vector FFT_Vent
int N=FFT_Vent.length;
//*****************************************************************
// Cambiando a Dominio Mel
int indice=FFT_Vent.length/2;
double f=(indice*fs)/N;
double B=1127*Math.log(1+(f/700.0));
int rango=(int)(B/14.0);
int[] vIndices=new int[14];
//*****************************************************************
// Encontrando la inversa al dominio Mel
k=0;
for(j=0;j<B-rango;j+=rango)
{
double invB=700*(Math.exp(j/1127.0)-1);
vIndices[k]=(int)((invB*N)/fs);
k++;
}
//*****************************************************************
// Calculando la suma de la energia en cada filtro
double[] S=new double[14];
int s=0;
for(j=1;j<vIndices.length-1;j+=1)
{
double[] H=obtenerH(vIndices[j-1],vIndices[j],vIndices[j+1]);
// System.out.println("Longitud del filtro H= "+H.length);
/*
//Se sumariza con cada filtro
*/
double suma=0;
int m=vIndices[j-1];
for(k=0;k<H.length;k++)
{
double valor=Math.pow(FFT_Vent[m],2.0)* H[k];
suma=suma+Math.log(valor+0.00005);
m++;
}
S[s]=suma;
s++;
}
//*********************************************************************************
// Obteniendo la transformada del coseno que seria el Cepstrum de la frecuencia Mel
double[] C=new double[14];
for(j=0;j<S.length-1;j++)
{
double suma=0;
for(k=0;k<S.length;k++)
{
suma=suma+S[k]*Math.cos(((Math.PI*(j+1))/S.length)*(k+0.5));
}
C[j]=suma;
//System.out.println("Cepstrum "+j+" = "+C[j]);
}
double[] dC=new double[18];
double[] ddC=new double[16];
// Calculo de DELTAS y DOBLES DELTAS
for(j=0;j<C.length;j++)
{
int cdC=j+2;
int cddC=j+1;
dC[cdC]=C[j];
ddC[cddC]=C[j];
}
//******************************************************************
// LLENADO DE LA MATRIZ MFCC
for(j=0;j<39;j++)
{
if(j<13)
{
MFCC[j][cMFCC]=C[j];
continue;
}
if(j>=13 && j<26)
{
k=j-13;
int cdC=k+2;
MFCC[j][cMFCC]=(dC[cdC-2]-8*dC[cdC-1]+8*dC[cdC+1]-dC[cdC+2])/12.0;
continue;
}
if(j>=26 && j<39)
{
k=j-26;
int cddC=k+1;
MFCC[j][cMFCC]=ddC[cddC-1]-2*ddC[cddC]+ddC[cddC+1];
continue;
}
}
// for(j=0;j<39;j++)
// {
// System.out.println("MFCC para la columna "+cMFCC+" = "+MFCC[j][cMFCC]);
// }
//*****************************************************************
cMFCC++;
}
return MFCC;
}
//*********************** CMN **********************************************************
/*
En una parametrizaci髇 basada en coeficientes cepstrales, una se馻l ,
es dividida en cortas ventanas de tiempo ( ~=20 ms), de la cual son extra韉os
un cierto n鷐ero de coeficientes cepstrales. Para ello se busca que los par醡etros MFCC
tengan una media igual a 0. CMN se basa en sustraer para cada coeficiente cepstral
extra韉o la media de dicho coeficiente a lo largo de toda la se馻l. De esta forma se
reduce la distorsi髇 introducida por elementos de variaci髇 lenta, como por ejemplo
ruido estacionario
*/
public double[][] CMN(double[][] MFCC){
int f=MFCC.length;
int c=MFCC[0].length;
int i,j;
for(i=0;i<f;i++)
{
double media=0;
for(j=0;j<c;j++)
{
media+=MFCC[i][j];
}
media=media/c;
for(j=0;j<c;j++)
{
MFCC[i][j]-=media;
}
}
return MFCC;
}
//************************ LPCC *********************************************************
public double[][] obtenerLPCC(double[] dxVoz,int longVent,int desp){
int i,j,k;
double[][] LPCC=new double[P][dxVoz.length/desp];
double[][] matrizR = new double[P][P];
double[][] vectorR = new double[P][1];
boolean band=true;
int cLPCC=0;
for (i=0;i<dxVoz.length-(desp+longVent);i+=desp)
{
//Obtengo ventana
double[] ventana=new double[longVent];
k=0;
for(j=i;j<i+longVent;j++)
{
ventana[k]=dxVoz[j];
k++;
}
double[] ventana2=ProcDSenhal.ventanamiento(ventana,0.46);
matrizR = obtenerMatAutocorrelac(ventana2,P,P);
vectorR = obtenerMatAutocorrelac(ventana2,P,1);
band = obtenerMatrizInversa(matrizR);
// if (band == true){
a = multiplicarMatVect(mInversa,vectorR);
a=Cepstrum(a);
for(j=0;j<P;j++)
{
LPCC[j][cLPCC]=a[j];
}
cLPCC++;
//}
}
return LPCC;
}
public double[][] obtenerMatAutocorrelac(double[] m,int f,int c){
double[][] R = new double[f][c];
double[] r = new double[f+1];
int i,j,k;
for(i=0; i<=f; i++){
r[i] = 0;
for(j=0; j<m.length-i; j++){
r[i] = r[i] + m[j]*m[j+i];
}
}
if(c>1)
for(i=0; i<f; i++){
R[i][i] = r[0];
k=1;
for(j=i+1; j<c; j++){
R[i][j] = r[k];
R[j][i] = R[i][j];
k=k+1;
}
}
else
for(i=0; i<f; i++){
R[i][0] = r[i+1];
}
return R;
}
public boolean obtenerMatrizInversa(double[][] m){
int tamanyoM = m.length;
mInversa = new double[tamanyoM][tamanyoM];
int i,j,k,ubicPiv;
double v1,v2,pivote,v;
boolean tieneMI = true;
for(i=0; i<tamanyoM; i++){
mInversa[i][i]=1;
}
for(i=0; i<tamanyoM; i++){
pivote = m[i][i];
ubicPiv = i;
for(j=i+1; j<tamanyoM; j++){
if( m[j][i] > pivote ){
pivote = m[j][i];
ubicPiv = j;
}
}
if( i != ubicPiv){
for(j=0; j<tamanyoM; j++){
v = m[i][j];
m[i][j] = m[ubicPiv][j];
m[ubicPiv][j] = v;
v = mInversa[i][j];
mInversa[i][j] = mInversa[ubicPiv][j];
mInversa[ubicPiv][j] = v;
}
}
if( pivote != 1){
for(j=0; j<tamanyoM; j++){
m[i][j] = m[i][j]/pivote;
mInversa[i][j] = mInversa[i][j]/pivote;
}
}
for(j=i+1; j<tamanyoM; j++){
if(m[j][i] != 0){
pivote = m[j][i];
for(k=0; k<tamanyoM; k++){
m[j][k] = (m[i][k]* -pivote) + m[j][k];
mInversa[j][k] = (mInversa[i][k]* -pivote) + mInversa[j][k];
}
}
}
if( m[i][i] == 0){
System.out.println("NO tiene Matriz Inversa");
tieneMI = false;
}
}
if(tieneMI == true){
for(i=tamanyoM-1; i>-1; i--){
for(j=i-1; j>-1; j--){
if(m[j][j] != 0){
pivote = m[j][i];
m[j][i] = (m[i][i] * - pivote) + m[j][i];
for( k=0; k<tamanyoM; k++){
mInversa[j][k] = (mInversa[i][k] * - pivote) + mInversa[j][k];
}
}
}
}
}
return tieneMI;
}
public double[] multiplicarMatVect(double[][] A, double[][] B){
double[] C = new double[A.length];
double s;
int i,j;
for(i=0; i<A.length; i++){
s=0;
for(j=0; j<A.length; j++){
s = s + A[i][j]*B[j][0];
}
C[i] = s;
}
return C;
}
public double[] Cepstrum(double[] a)
{
double[] c=new double[a.length];
int p=c.length;
c[0]=a[0];
// 1<n<=p
for(int n=2;n<=p;n++)
{
double suma=0;
for(int k=1;k<n;k++)
{
suma+=(1-(double)(k/n))*a[k-1]*c[(n-k)-1];
}
c[n-1]= suma+ a[n-1];
}
return c;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -