1. 引言 1 U- i. q( R3 Q8 H2 O: r. `5 k 之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。2 h. m7 a3 O8 Q3 u* X
$ V/ \$ a. {0 ]) N
然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。5 R6 u8 v6 l# `! c
5 ~. [) A' v& D/ z- E
2. 代码介绍 3 d3 N, z7 H" x$ E6 \ J" l 原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下: # A) F4 T. }" @ pfunction [mcSignals,setup] = multichannelSignalGenerator(setup)/ F1 D8 N) |8 m- i6 G- k. v9 v
B2 f7 d5 ~# A/ e. v2 R& E0 c5 @6 k
%-----------------------------------------------------------------------$ x4 [# a" M0 k% q; S2 T- n
% Producing the multi_noisy_signals for Mic array Beamforming.; E$ W @0 s) s- i/ B
% ) H7 N$ ~! H! f* o @% Usage: multichannelSignalGenerator(setup) ! q: U2 j' `1 h6 h# p/ l S+ I% : H' u2 Y: Y/ I+ G; `8 _% setup.nRirLength : The length of Room Impulse Response Filter+ I' M* A0 g; g _3 I
% setup.hpFilterFlag : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default1 N' o9 d. l+ f9 {
% setup.reflectionOrder : reflection order, default is -1, i.e. maximum order. - O' a6 z5 ^- }. d3 u& h% setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional. 9 R! Z6 h7 r+ s3 _( v8 V- d% 9 G! R& e; [3 H( J( G0 ^% setup.nSensors : The numbers of the Mic1 r6 l1 b- E: q5 s& r0 V$ o
% setup.sensorDistance : The distance between the adjacent Mics (m) " @8 e( ?1 u* X/ R% setup.reverbTime : The reverberation time of room . X2 p9 V5 A6 N2 s) I5 ?% setup.speedOfSound : sound velocity (m/s) 0 O" s0 b* Z- I6 ]% 0 P3 E a! j; L$ e% setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical' 0 U" h( o; d* k2 p% setup.sdnr : The target mixing snr for diffuse noise and clean siganl.: T% h, F! Q, o; a1 A" X
% setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl. - B( j0 S, ]8 _) x$ S% k% . b: A9 j6 }% C' R% setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m). : R" j* @; A1 n4 r% setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m). 6 L0 A+ b; B3 H9 W% setup.srcPoint : 3 x M array, the rows specifying the (x,y,z) coordinates of the audio source postion (m). 0 o! U: |+ X* l4 i%: ~" O- r6 `2 J* _8 N
% srcHeight : The height of target audio source; K" R, ]0 C5 @( v5 {1 M6 R7 k
% arrayHeight : The height of mic array 8 M; w" q% t+ B7 o4 P) }%1 \; e& m q7 i: N; k
% arrayCenter : The Center Postion of mic array $ R+ o6 e2 ]- a5 e%9 q3 o7 t* U! h
% arrayToSrcDistInt :The distance between the array and audio source on the xy axis7 Y- a, J2 r, b6 E! t
% - e9 ?: Q( V3 H! o% - \0 a: ]# R+ J: h H |( X2 W$ c7 B2 C; O
%7 C4 R, r) Y4 j: U/ F* m
%0 u9 A" ?6 U- p- Q
% $ R9 {( E+ F4 L% V( U8 a& [: O
% 8 F. M7 D" k% B% How To Use : JUST RUN, |: @- }% K4 X# s9 s
% 8 c" m3 F0 u2 @% 9 C" I8 \, |' G7 n2 [; F% - I+ j& W; f) V6 g; w: t% Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),6 C8 P4 o2 O1 v5 c' S' ?
% slightly modified by Wind at Harbin Institute of Technology, Shenzhen, in 2018.3.24 2 m$ w+ w2 u" Z1 D4 m) a% O6 g' p5 n2 x* a6 f
% Copyright (C) 1989, 1991 Free Software Foundation, Inc. # Q; Q# W7 T( d1 z4 V%-------------------------------------------------------------------------: W" e3 N( |; y/ n$ a
$ R; w6 u' K ~( a& w* a
2 e l5 J- T# W. T
7 n! M; B' N8 Z% n6 g! A
addpath([cd,'\..\rirGen\']); ) J5 C3 B2 h$ M4 Q4 E& z g2 F6 S$ z, N5 _) Y# x
%-----------------------------------------------initial parameters-----------------------------------9 ]; H+ b% V) |8 D5 s
) B+ V# F# E" M, I+ G$ ]
setup.nRirLength = 2048; 4 ^' L7 ?$ f9 J" T( }setup.hpFilterFlag = 1; / M, N' d$ a; ?' H+ Tsetup.reflectionOrder = -1;& v9 r5 @" X. e1 d* G
setup.micType = 'omnidirectional';& b! g1 S0 F( s- o# `6 l
setup.nSensors = 4; 8 i& J) z1 ` b/ M/ }3 S }/ o" Jsetup.sensorDistance = 0.05; ' N) M4 @8 B; I, o0 n6 lsetup.reverbTime = 0.1; - _' V2 `7 q! W3 z4 @) usetup.speedOfSound = 340;' V) m1 _) L8 u, a
: \: m3 J* D5 V. I' d
setup.noiseField = 'spherical'; ! [' g# U: \ Z% H+ c0 L: @setup.sdnr = 20; m5 _/ t6 g# v8 w+ f7 N9 ?' J
setup.ssnr = 25; + |1 N: i) i$ y/ ~1 [ ; w2 `' `/ E2 T$ Rsetup.roomDim = [3;4;3];! Y/ L1 m- q- W2 i
0 u0 P* f4 Q/ J- j8 G& s
srcHeight = 1;4 n: l( C" p7 M+ u4 P- k
arrayHeight = 1; 5 `5 t4 s+ b0 t; D; d7 N5 O( ], m) X1 y& {! w" U
arrayCenter = [setup.roomDim(1:2)/2;1]; , X9 }5 I! E, H! B , c% ~/ b+ l$ C2 m. d4 u& o4 z7 varrayToSrcDistInt = [1,1];9 H; w, e9 I8 \) R% Y0 K7 s" K+ S
; D0 B4 N" }+ K; Isetup.srcPoint = [1.5;1;1]; ' [. r. N( p# Z; e0 U0 T- f+ {6 g r& U. z
setup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight); 9 m% \0 {! X9 u- T( z 5 F$ D9 s; }0 Q/ V- f s4 r# r. s' P, A9 Y H( H' t1 B$ t
[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'); 1 d% O! O ~; R; f7 k& b, }- L. `" b; l# \0 D4 e% U
%---------------------------------------------------initial end---------------------------------------- & e; e; B& _. H4 E+ d0 p l2 m! {: O. ?; X5 A0 g" l5 [
2 X7 L |2 A, q1 ~3 z7 I" l7 |$ t& R" Y/ W% ^
%-------------------------------algorithm processing--------------------------------------------------8 v- f# g- C ]3 b
2 _* B, ~: M" B, ^: j$ Y& z8 Tif setup.reverbTime == 0, 7 j# ]7 z. j" R+ v setup.reverbTime = 0.2; ( [( h3 ~6 U4 O Q" O9 d reflectionOrder = 0;4 i' p; Z8 r3 f9 Y2 j
else $ |' w! I* b/ J+ u% z reflectionOrder = -1;( E8 A. Y; A. e1 ]9 d' o
end9 ?2 e$ `% n/ `9 ?
8 m" d5 x1 D) M# M" [; z
rirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',... 7 z; j4 p. Y0 C7 d% H% t setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);3 l* x/ O5 B/ L' v. b; \. C
% D- k8 l7 O. p) J0 A1 |* D
for iSens = 1:setup.nSensors, - g2 j3 H/ v6 F' ^* _/ j* d! m) o tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);2 L5 g# P* V% [
end 1 i1 U# p5 r6 c2 {: T$ JmcSignals.clean = tmpCleanSignal(setup.nRirLength:end,; / n& @1 E1 V, S! Xsetup.nSamples = length(mcSignals.clean);- [4 j# l3 N' {7 n3 C }
! \) S) r$ U; A0 A- T9 |mcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean); ' Z3 b" f/ C1 e3 @6 g: U3 {+ c% S' R S R4 ~
%-------produce the microphone recieved clean signals--------------------------------------------- , i' d9 W7 c9 H @- t; s4 O" H" I3 f4 @' u: N2 l
mic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold, [4 d$ z* E5 A- ^" `
mic_clean2=10*mcSignals.clean(:,2); 4 v; H9 L% |, r/ D9 a# ymic_clean3=10*mcSignals.clean(:,3);" b+ A) ~+ T: Z' K6 n: o
mic_clean4=10*mcSignals.clean(:,4); 7 j3 Z+ f. v$ O: d+ _audiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);7 ^0 {, F/ P) r g! M4 f
audiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);5 q) b# G" E0 C4 w' w* |. g" Q
audiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq); & o+ ]' s h2 O" z2 [audiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);1 p2 W# t- O6 G0 ?( @$ d7 _
9 o, G5 ?6 l Z5 G) x7 z%----------------------------------end--------------------------------------------------6 n9 k8 U& {* ]% r: [5 X