? ? ? ? 對(duì)音頻數(shù)據(jù)進(jìn)行處理時(shí)經(jīng)常會(huì)對(duì)mic陣列的選擇有很多特殊要求,當(dāng)原始錄取的音頻陣列排布有問(wèn)題時(shí),會(huì)進(jìn)行一些軟件的處理,使陣列排布達(dá)到一定的要求。
1.回聲消除對(duì)麥克陣列的特殊要求
2.原始音頻MIC陣列排布處理
? ? ? ? ?對(duì)于4ch音頻數(shù)據(jù)而言,麥克陣列排列要求為mic1、mic2、ref1、ref2,但是通過(guò)tinycap采集的原始音頻數(shù)據(jù)的陣列排布為ref1、null、mic1、mic2,倆路mic分別對(duì)應(yīng)左右mic的音頻攝入,需要對(duì)mic陣列進(jìn)行一定處理。
? ? ? ? check相關(guān)原始音頻pcm文件,ref通道攝入的是喇叭對(duì)應(yīng)的音頻,收集到的是設(shè)備播放音樂(lè)的聲音,同時(shí)mic通道也會(huì)攝入設(shè)備播放的音樂(lè)聲音,需要通過(guò)回聲消除處理對(duì)設(shè)備音進(jìn)行一定的處理。
?
? ? ? ? 針對(duì)麥克陣列排布不符合規(guī)定的代碼端處理,調(diào)整排列架構(gòu)符合要求。
struct pcm *pcm_open(unsigned int card, unsigned int device,
unsigned int flags, struct pcm_config *config)
{
struct pcm *pcm;
struct snd_pcm_info info;
struct snd_pcm_hw_params params;
struct snd_pcm_sw_params sparams;
char fn[256];
int rc;
LOG("pcm_open card %d device %d channel %d period_size %d period_count %d format %d\n", card, device ,config->channels, config->period_size, config->period_count, config->format);
...
...
if(card == 0 && device == 2 && config->rate == 64000){
char *buffer;
unsigned int ch1_first = 0, ch3_first = 0, i = 0;
buffer = malloc(sizeof(char)*8);
for(i = 0; i < 10 && ch1_first < 2 && ch3_first < 2; i++){
pcm_mmap_read(pcm, buffer, 8);
/* LOG("buffer[2] = 0x%x. buffer[3] = 0x%x buffer[6] = 0x%x. buffer[7] = 0x%x",
*(buffer+2), *(buffer+i+3), *(buffer+6), *(buffer+7)); */
if((*(buffer+2) == 0x00)&&(*(buffer+3) == 0x00))
ch3_first++;
if((*(buffer+6) == 0x00)&&(*(buffer+7) == 0x00))
ch1_first++;
}
if(ch3_first > ch1_first){
LOG("start channel ch3/4, do the conversion\n");
printf("start channel ch3/4, do the conversion\n");
pcm_mmap_read(pcm, buffer, 4);
} else {
LOG("start channel ch1/2 \n");
}
free(buffer);
}
LOG("pcm_open done pcm->fd = %d\n", pcm->fd);
return pcm;
}
????????相關(guān)代碼執(zhí)行l(wèi)og
? ? ? ? 調(diào)整后的音頻pcm文件
?文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-403788.html
?3.音頻數(shù)據(jù)采樣精度、回采通道復(fù)用處理
? ? ? ? 原始錄取出來(lái)的音頻數(shù)據(jù)采樣精度為16bit,采樣頻率為16khz,且ref2因?yàn)橛布O(shè)計(jì)為null。為滿足麥克陣列的要求需對(duì)這樣的音頻數(shù)據(jù)進(jìn)行應(yīng)用層的處理,采樣精度:16bit -> 32bit,第二路回采信號(hào)復(fù)用第一路回采信號(hào)。
? ? ? ? 處理代碼如下:
//2mic: 4c 16k 16bit -> 4c 16k 32bit(copy 3ch -> 4ch)
public static byte[] addCnFor2MicN4(byte[] data) {
byte[] cpy=new byte[data.length*2];
int j=0;
//mic1 mic2 ref ref
while(j<data.length/8) {
cpy[16*j]=00;
cpy[16*j+1]= 00;
cpy[16 * j + 2] = data[8 * j +0];
cpy[16* j + 3] = data[8 * j +1];
cpy[16*j+4]=00;
cpy[16*j+5]= 00;
cpy[16 * j + 6] = data[8 * j +2];
cpy[16* j + 7] = data[8 * j +3];
cpy[16*j+8]=00;
cpy[16*j+9]= 00;
cpy[16 * j + 10] = data[8 * j +4];
cpy[16* j + 11] = data[8 * j +5];
cpy[16*j+12]=00;
cpy[16*j+13]= 00;
cpy[16 * j + 14] = data[8 * j +4];
cpy[16* j + 15] = data[8 * j +5];
j++;
}
return cpy;
}
? ? ? ? ?以下是一些項(xiàng)目中用到的對(duì)音頻數(shù)據(jù)進(jìn)行處理的方法:
//6mic 8ch 32bits
private byte[] addCnForMutiMic(byte[] data) {
int datasize=data.length;
byte[] newdata=new byte[datasize*2];//double to 16bit -> 32bit
int j=0;
int k=0;
int index= 0;
int step = datasize/2;
while(j<step) {
for (int i=1; i<9;i++) {
k = 4*j;
index= 2*j;
newdata[k]=00;
newdata[k+1]=00;
newdata[k+2]=data[index];
newdata[k+3]=data[index+1];
j++;
}
}
data = null;
return newdata;
}
//4mic 8ch->6ch
private byte[] adapeter4Mic(byte[] data) {
// int size = ((data.length/8)*2)*6;
int size = (data.length/8)*6;
byte[] cpy=new byte[size];
int j=0;
while(j<data.length/16) {
cpy[12 * j + 0] = data[16 * j +0];
cpy[12* j + 1] = data[16 * j +1];
cpy[12 * j + 2] = data[16 * j +2];
cpy[12* j + 3] = data[16 * j +3];
cpy[12 * j + 4] = data[16 * j +4];
cpy[12* j + 5] = data[16 * j +5];
cpy[12 * j + 6] = data[16 * j +6];
cpy[12* j + 7] = data[16 * j +7];
cpy[12 * j + 8] = data[16 * j +12];
cpy[12* j + 9] = data[16 * j +13];
cpy[12 * j + 10] = data[16 * j +14];
cpy[12* j + 11] = data[16 * j +15];
j++;
}
return cpy;
}
//4mic:8ch -> 6ch
private byte[] adapeter4Mic32bit(byte[] data) {
// int size = ((data.length/8)*2)*6;
int size = (data.length/8)*6*2;
byte[] cpy=new byte[size];
int j=0;
while(j<data.length/16) {
cpy[24 * j + 0] = 0x00;
cpy[24* j + 1] = 0x01;
cpy[24 * j + 2] = data[16 * j +0];
cpy[24* j + 3] = data[16 * j +1];
cpy[24 * j + 4] = 0x00;
cpy[24* j + 5] = 0x02;
cpy[24 * j + 6] = data[16 * j +2];
cpy[24* j + 7] = data[16 * j +3];
cpy[24 * j + 8] = 0x00;
cpy[24* j + 9] = 0x03;
cpy[24 * j + 10] = data[16 * j +4];
cpy[24* j + 11] = data[16 * j +5];
cpy[24 * j + 12] = 0x00;
cpy[24* j + 13] = 0x04;
cpy[24 * j + 14] = data[16 * j +6];
cpy[24* j + 15] = data[16 * j +7];
cpy[24 * j + 16] = 0x00;
cpy[24* j + 17] = 0x05;
cpy[24 * j + 18] = data[16 * j +12];
cpy[24* j + 19] = data[16 * j +13];
cpy[24 * j + 20] = 0x00;
cpy[24* j + 21] = 0x06;
cpy[24 * j + 22] = data[16 * j +14];
cpy[24* j + 23] = data[16 * j +15];
j++;
}
return cpy;
}
//6mic 16bit-> 2mic 32bit
private byte[] addCnFor2Mic(byte[] data) {
byte[] cpy=new byte[data.length];
int j=0;
//mic1 mic2 ref ref
while(j<data.length/16) {
cpy[16 * j] = 00;
cpy[16 * j + 1] = (byte) 1;
cpy[16 * j + 2] = data[16 * j + 0];
cpy[16 * j + 3] = data[16 * j + 1];
cpy[16 * j + 4] = 00;
cpy[16 * j + 5] = (byte) 2;
cpy[16 * j + 6] = data[16 * j + 2];
cpy[16 * j + 7] = data[16 * j + 3];
cpy[16 * j + 8] = 00;
cpy[16 * j + 9] = (byte) 3;
cpy[16 * j + 10] = data[16 * j + 12];
cpy[16 * j + 11] = data[16 * j + 13];
cpy[16 * j + 12] = 00;
cpy[16 * j + 13] = (byte) 4;
cpy[16 * j + 14] = data[16 * j + 14];
cpy[16 * j + 15] = data[16 * j + 15];
j++;
}
return cpy;
}
4.回聲消除效果
? ? ? ? 經(jīng)過(guò)回聲消除之后輸出的音頻數(shù)據(jù)是16k、16bit、單聲道數(shù)據(jù),經(jīng)過(guò)與之前的pcm文件對(duì)比可以看出數(shù)據(jù)的音樂(lè)聲音被消除,基本只留下了之前mic聲道里面說(shuō)話的聲音。
?
總結(jié)
? ? ? ? 回聲消除和噪聲抑制都是音頻處理中必須要進(jìn)行的一些過(guò)程,這篇只是對(duì)這些處理之前的音頻數(shù)據(jù)進(jìn)行轉(zhuǎn)化的內(nèi)容進(jìn)行一下說(shuō)明,回聲消除與噪聲抑制的具體處理涉及到算法的優(yōu)化與解決,很難搞!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-403788.html
到了這里,關(guān)于Audio-音頻降噪、回聲消除處理的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!