数学建模社区-数学中国

标题: 麦克风阵列仿真环境的搭建 [打印本页]

作者: 浅夏110    时间: 2020-5-15 15:10
标题: 麦克风阵列仿真环境的搭建
1. 引言% Y" f+ Y6 [; B& d
  之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。
% ?) u2 W# @: O. b! f1 ?1 r& W3 L1 c6 M
  然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。
' g1 k: {$ Y* o) g4 k) S' Q& U
5 M. `* w7 w$ G9 g0 ^2. 代码介绍6 N% |6 V9 L: C% h
  原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:
  T1 N+ O  o' r' X: Z0 f. Cfunction [mcSignals,setup] = multichannelSignalGenerator(setup)
) ^: L" [/ L4 P" O* f4 l! G8 I! |7 v  S7 \. d# r6 L. t7 r
! L3 K/ O1 Q3 c; ]+ N8 K3 J
%-----------------------------------------------------------------------
8 m' V( o* z: Y, q, Y! c: B2 w%  Producing the multi_noisy_signals for Mic array Beamforming.. p0 K' T$ c" i, [
%
* L7 w; I$ N. u%  Usage:  multichannelSignalGenerator(setup)9 w$ U: j1 a) s' z2 g7 k
%         
- g- t7 w, c8 c4 a%        setup.nRirLength : The length of Room Impulse Response Filter
8 T( {+ R6 g- c& F& l# K; z2 M%        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default6 z9 E. e" x* n$ h1 S0 E
%        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order.( `2 W  Q- g6 H+ \
%        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.5 d9 Z0 [* ~6 Q, P- w6 ^! W! f% `
%           
8 H" n2 o& o% q! R5 v: a%        setup.nSensors : The numbers of the Mic
( [. D2 s6 y1 q# b( s  t%        setup.sensorDistance : The distance between the adjacent Mics (m)
" q1 p5 a- `3 l' \%        setup.reverbTime : The reverberation time of room
9 f; f+ M# m9 i; c1 I%        setup.speedOfSound : sound velocity (m/s)
: B& p7 W& P% `7 `%
+ Q9 h* G4 D0 b+ Y%        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'6 L6 K& F# F7 K& _% `
%        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.
" ?/ G) i3 W6 c%        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.
3 l: @) _2 |( M0 x%
' s: G* v; u1 A/ J%        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).           
* f7 T: G7 `* c8 N. C%        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m). , u0 A( G9 U8 B  u# i1 Z5 u
%        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m).
: z1 |/ q7 E' ~* {0 Q& M$ Q%
9 _  ?1 b! [9 u$ N%        srcHeight : The height of target audio source. x) _& J: u! X$ ^# ^- ]4 y
%        arrayHeight : The height of mic array: o' A* g# P; L# f" W/ @$ m/ L
%
; ?5 Z8 f* |, z2 _: N%        arrayCenter : The Center Postion of mic array
8 h" d4 C: Z$ V1 _) ~- V%
& s/ k3 q  |  U1 l2 n% N: H. X%        arrayToSrcDistInt :The distance between the array and audio source on the xy axis0 \6 j1 O; t! U& `  ]( M  l
%
: i- n, j5 v$ k3 ]. y4 }1 _%                        & F5 L* m+ `7 v8 K) b8 z1 F& P$ g
%
) a# E# z0 d$ H%% l$ @% L; r; x- L4 g) ]
%         - W- r- }0 c4 y; ^
%! W' N- N) \' V
%  How To Use : JUST RUN
7 K# A2 p1 c0 u2 Z5 |" f8 }%
* Q9 [+ e- h3 [%  0 t1 g8 I3 d+ p" G
%   , R' {8 U% T5 X& p; {0 D/ S2 r
% Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),
1 l4 `% ~, W/ C6 F2 `%            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.24
  y6 L: }& @4 o0 u" ^1 J" ~! L1 \%" {6 J3 M8 P" o4 ~0 r
% Copyright (C) 1989, 1991 Free Software Foundation, Inc.
" \8 G9 r( V0 V( }2 s%-------------------------------------------------------------------------) e4 B" J# j# q6 \, b
2 [* r% i1 g3 C: D
4 H$ ]2 X  X& g- \6 I- ~0 E* O

: Y7 {9 l" n) {: K/ M  maddpath([cd,'\..\rirGen\']);
4 z6 p0 V; }8 [  g) i: c; T: W, t( V! s1 z' M1 _/ y
%-----------------------------------------------initial parameters-----------------------------------
% ^6 K0 {+ H, R- [5 h& R4 Z% D0 o; v) Z* _7 g, l
setup.nRirLength = 2048;' l/ y) K& N. Y, }% W
setup.hpFilterFlag = 1;. u8 W5 J! ^! K
setup.reflectionOrder = -1;5 m: |6 \  L! r4 P* f3 v! G
setup.micType = 'omnidirectional';
. m% J) s" |% I2 Ysetup.nSensors = 4;
' p* E% H, g" l1 Msetup.sensorDistance = 0.05;- s+ s" _" y0 {/ ~# ~+ \
setup.reverbTime = 0.1;! f. d! C, j: o0 a9 x/ T
setup.speedOfSound = 340;
0 X. t5 M- [5 N1 n1 P- E5 m2 R
1 {" Z$ n( P* r7 ]8 \setup.noiseField = 'spherical';/ Z# ^9 z* n- u  k4 ?0 D
setup.sdnr = 20;
( L4 r* t; t! |! v2 t. Isetup.ssnr = 25;
/ Z- D4 X4 H( Y5 u& e5 {; d1 x# R* m& F# @
setup.roomDim = [3;4;3];5 B+ r: \/ F- ]) a1 p
+ E8 P. M$ Q. H6 U) X& a) X
srcHeight = 1;" s! A1 u" n+ ^' E6 J
arrayHeight = 1;$ x9 |& Q1 @7 R( v9 d% `8 ^, z
  g% I/ F8 P# ~( z' o# K5 V* K0 D
arrayCenter = [setup.roomDim(1:2)/2;1];! K; Y+ P7 g( t$ b3 t! L

) X( A* H  K: d, r1 d; n$ \) J( \( }arrayToSrcDistInt = [1,1];1 e. k5 ^0 @6 M% r1 n
8 \' k$ J5 l. c! u0 L. D
setup.srcPoint = [1.5;1;1];
- S' C4 y" B* A+ A! y: I* t+ i! t0 E8 ?5 w  w$ I0 z% S" M* H. x
setup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);% k6 {' G) S1 T+ t" ^# b
8 H* e" J/ C, \0 w5 M- `

* l! P. h* \8 j% _5 }: R0 H; \[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');
/ o7 s, K+ F3 f9 f: B& R5 ^- J
5 C, U' K# n: K0 }! {* R%---------------------------------------------------initial end----------------------------------------! @6 N. W" \: ]0 N* |
  Q' Y$ s) L) E$ [. a- t* S7 n
, f" Y/ {" A) q

) B, \( F9 Q9 C& X%-------------------------------algorithm processing--------------------------------------------------7 f  ?7 v- ?+ S+ T: r- ?; @/ m

6 N! q3 ]) v& o# Pif setup.reverbTime == 0,
" p; A( ?( t* C9 R$ e    setup.reverbTime = 0.2;/ A1 h2 Y8 h8 p8 X
    reflectionOrder = 0;
8 F, \5 U  ?' ~/ h" \else; \' W. e" E) j/ O
    reflectionOrder = -1;: z& n4 y  @+ k. u: O8 c6 X: E1 ?8 {
end+ j8 S6 l4 ]8 v3 H: j* @

1 I. q* }5 J& m# D" SrirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',.../ v) M' }! J: X% y$ X
    setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);) }" t; Q" f. q# U1 C

( x8 T; S- g" I' M$ w0 M0 afor iSens = 1:setup.nSensors,
& K% h$ n0 u0 ~. {    tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);" v, c5 t5 Q% S! w# n
end- m, o: A; e& e! Y7 [
mcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;
5 \8 _7 C- j1 K( [1 P$ A- F5 hsetup.nSamples = length(mcSignals.clean);& b- j* v4 y) |* a& U8 U$ N9 R% w, I9 T

; l" [2 Q* y, S9 _- w' k; dmcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);
/ I2 X# J3 Y- D# G
" G* v, H) V& h% D' [$ L3 ^" X2 k%-------produce the microphone recieved clean signals---------------------------------------------
! o/ o: S7 s9 D$ b( V( ]5 t8 e2 o. {1 m9 l& ~; }
mic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold
( s$ A3 ^1 v" ^% \mic_clean2=10*mcSignals.clean(:,2);
0 x5 `7 s7 j# c2 n8 l/ }# Y: C9 O2 Wmic_clean3=10*mcSignals.clean(:,3);3 D0 D4 H2 V6 u) h3 u
mic_clean4=10*mcSignals.clean(:,4);/ K! |. S2 r* L' j  @, q. ?
audiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);
4 j1 H5 W. c. B) {& b3 m. Raudiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);# A: f; q6 F2 R& m+ Z( P
audiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);* U! r9 z' V0 o+ e/ b: k
audiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);% ]2 @6 ~  `& p) j7 j, \
- c9 s6 d% }6 ]
%----------------------------------end--------------------------------------------------  v1 l; t( J! W, p! }1 L

8 s. k( u' \/ H" xaddpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);, y9 B1 o, i6 u

) F. J, Z4 R& scleanSignalPowerMeas = var(mcSignals.clean);
+ u2 i& H. d; @) v5 ~) T$ {: Y
& y% U5 Z$ h/ l
( N5 o2 ?/ Z" m) x7 X# ymcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...1 C% x/ i% N% F$ u8 {
    setup.speedOfSound,setup.noiseField);
# Y6 [6 L- o8 Y  e. ediffNoisePowerMeas = var(mcSignals.diffNoise);$ E  ~# q9 z. k: u
diffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);1 l  Q6 t( @' n
mcSignals.diffNoise = mcSignals.diffNoise*...: J- A8 l9 W. \8 j! M, \
    diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));7 z5 O6 P8 u  g7 u7 L
7 [: |3 B7 u1 w6 z% V6 H
mcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);
. D6 H  X- E) I5 r$ b: h* csensNoisePowerMeas = var(mcSignals.sensNoise);
  |/ z: b+ X1 R+ U6 `sensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);+ W. ?) d. n  [; z) ~* ]
mcSignals.sensNoise = mcSignals.sensNoise*...
' a/ u0 }5 z: t" k; m: B& Z    diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));$ v. C% R4 ?. t/ r

% D: h9 u  T8 h& \+ fmcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;
7 y0 n' U  X7 A( x, l- SmcSignals.observed = mcSignals.clean + mcSignals.noise;
1 A9 D; ^8 x) A( n4 a/ w) B0 [; X, b0 M* |( |$ O7 }
%------------------------------processing end-----------------------------------------------------------, p. r+ A7 I: D. u* L5 ]2 J0 G

& D, k5 M# F/ p0 R0 X
5 m) e+ g; ~8 W
, L' ?. j7 I* f: \+ @' p: T7 s4 ]/ w; D0 q9 S9 Y' N
%----------------produce the noisy speech of MIc in the specific ervironment sets------------------------9 F) j% L9 D7 M! M

8 U$ k: \% Z4 r( F' ?9 hnoisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold
7 G' t' k8 J% K: c9 ynoisy_mix2=10*mcSignals.observed(:,2);
9 v1 P$ N" K- O% r% v7 G+ M5 F' ^# Lnoisy_mix3=10*mcSignals.observed(:,3);
1 ~- K1 k/ f8 i0 `: x: L6 wnoisy_mix4=10*mcSignals.observed(:,4);
" P; n: j; c2 m' A* E- ?& il1=size(noisy_mix1);
( m( C3 c( `3 {$ o$ al2=size(noisy_mix2);
9 ^  U4 O9 N8 d% Al3=size(noisy_mix3);$ _: i  M/ w* _1 F  D; J6 f
l4=size(noisy_mix4);
! a1 V+ Z: y& W$ Y" \% l1 Caudiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);
$ z! u* |; k( A  ^- Iaudiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);, S+ f& y* j1 Q, o$ i0 O
audiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);* j6 O; F) l6 u% v" A+ ~
audiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);0 H) ]! [7 W4 l- u- T9 S
& [0 d( d1 {- W8 _2 [

# ]% k. N  t5 \/ l; Z2 y; ^%-----------------------------end-------------------------------------------------------------------------" z; _, ~) F9 t8 i. L
这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。% s# ^0 h3 _  H% b9 d
直接把它们替换成你想要处理的音频文件即可。1 v2 }$ r% a, o+ b0 W+ o9 {

2 R: i8 |. u* e6 z9 V  除此之外,还有一些基本实验环境参数设置,包括:麦克风的形状为线性麦克风阵列(该代码只能对线性阵列进行仿真建模,并且还是均匀线性阵列,这个不需要设置);麦克风的类型(micType),有全指向型(omnidirectional),心型指向(cardioid),亚心型指向(subcardioid,不知道咋翻译,请见谅) , 超心型(hypercardioid), 双向型(bidirectional),一般默认是全指向型,如下图1所示;麦克风的数量(nSensors);各麦克风之间的间距(sensorDistance);麦克风阵列的中心位置(arrayCenter),用(x,y,z)坐标来表示;麦克风阵列的高度(arrayHeight),感觉和前面的arrayCenter有所重复,不知道为什么还要设置这么一个参数;目标声源的位置(srcPoint),也是用(x,y,z)坐标来表示;目标声源的高度(srcHeight);麦克风阵列距离目标声源的距离(arrayToSrcDistInt),是在xy平面上的投影距离;房间的大小(roomDim),另外房间的(x,y,z)坐标系如图2所示;房间的混响时间(reverbTime);散漫噪声场的类型(noiseField),分为球形场(spherical)和圆柱形场(cylindrical)。/ z7 Y) S3 t" E' Z: A

( c" ]9 j9 T, m: `  [' I5 \5 d" ?9 I9 ^

* j' F" w' O  L+ e8 i) W5 ]4 }图1 麦克风类型图
8 {. `$ \9 z6 P' r
; J) ~' J" T& b/ H( i* R  }/ R图二 房间的坐标系3 _) _, q) k, d# |0 x* v. a
* J3 S' R* ]% M6 q- N3 {
  以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。2 L' M1 r( ^8 M
————————————————& k! Z2 @1 q% g0 y0 a3 e7 A5 }
版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
5 h0 L) y" @( b1 T4 g9 B原文链接:https://blog.csdn.net/zhanglu_wind/article/details/79674998
6 [9 W7 i2 P% j. w- N) X1 [) M' |: {; s6 I8 i: `8 k

6 E  N$ w# F- z% I' ]7 x) c




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5