最近一直致力于语音增强方面的工作,主要是增强目标位置发出的语音信号,削弱环境噪音。这里面最有效的方法就是波达方向估计和波束增强了。本篇主要介绍波达方向估计,其包含很多种算法:capon music RSS GCC等。我这里主要是使用GCC算法,我的麦克阵列使用的是双麦克,8cm距离。以下是我写的C语言版本,由于是第一版,所以比较粗糙,不过性能还是稳定的,角度误差在20°左右,希望能帮到大家:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include<string.h>
#include<fftw3.h>
#include<math.h>
#include"tool_spline.h"
#define PI 3.1416
typedef struct PCM PCM;
typedef struct Matrix Matrix;
typedef struct X X;
typedef struct conj_X conj_X;
typedef struct max_index max_index;
typedef struct doa_res doa_res;
// 读取文件后,文件内容和文件长度
struct PCM {
int* data;
int length;
};
// 把两个麦克的数据组成矩阵
struct Matrix {
int * m[2];
int length;
};
// fft变换后,二维的频率数据
struct X {
fftw_complex* x[2];
};
// X数据的复数共轭
struct conj_X {
fftw_complex* x[2];
};
// 求取最大值和最大值的索引
struct max_index {
double data;
int index;
};
// 最终角度的数据和长度
struct doa_res {
double* data;
int n_blocks;
};
// 读取文件
PCM readPCM(char* file_path) {
FILE* file;
const int MAX_END = 2;
const int MAX_START = 0;
file = fopen(file_path, "rb");
if (file == NULL) {
printf("open file failed. file_path is :%s\n", file_path);
PCM cur_pcm = { NULL,0 };
return cur_pcm;
}
fseek(file, 0L, MAX_END);
int file_len = ftell(file);
unsigned char* origin_data = (unsigned char*)malloc(file_len + 1);
int* data = (int*)calloc(file_len / 2, sizeof(int));
fseek(file, 0L, MAX_START);
fread((char*)origin_data, 1, file_len, file);
origin_data[file_len] = '\0'; // 空字符,表示字符串的结束
int count = 0;
for (int i = 0; i < file_len - 1; i += 2) {
data[count++] = (int)((origin_data[i + 1] << 8) | origin_data[i]);
}
fclose(file);
free(origin_data);
origin_data = NULL;
struct PCM cur_pcm = { data, file_len / 2 };
return cur_pcm;
}
// 合成二维矩阵
Matrix getMatrix(char* file_path1, char* file_path2) {
PCM data1 = readPCM(file_path1);
PCM data2 = readPCM(file_path2);
// 如果两个pcm文件长度不同,我们以短的作为标准
if (data1.length > data2.length) {
data1.length = data2.length;
}
else if (data1.length < data2.length) {
data2.length = data1.length;
}
Matrix cur_m;
for (int i = 0; i < 2; i++) {
cur_m.m[i] = (int*)calloc(data1.length , sizeof(int));
}
memcpy(cur_m.m[0], data1.data, data1.length*sizeof(int));
memcpy(cur_m.m[1], data2.data, data1.length*sizeof(int));
cu