数学建模社区-数学中国

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

作者: 浅夏110    时间: 2020-5-15 15:10
标题: 麦克风阵列仿真环境的搭建
1. 引言
) L, u8 h- y# M0 I0 f  之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。( H  `3 g+ K/ ]) i, i

- V" i6 K" J% @4 Z  然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。
5 o: ?# r6 h& N2 M, Y( I1 S7 c, L; U* \6 o
2. 代码介绍# \2 f1 j+ @& H( F. R5 y
  原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:
5 @8 h5 t0 `; l$ M! {function [mcSignals,setup] = multichannelSignalGenerator(setup)
- Y! x/ J% I- y7 {7 A
( A6 _+ Y8 a! S5 v
4 h/ Y5 c. z" U% h%-----------------------------------------------------------------------
7 q2 I) X* Y$ Z9 F; _/ ]1 Q$ h3 S%  Producing the multi_noisy_signals for Mic array Beamforming.7 O* c* q4 ]( q0 J
%
3 {+ {% a! w- N1 o7 R8 R%  Usage:  multichannelSignalGenerator(setup)6 F3 h; r: r& i/ d0 X3 W+ Y  A" m
%         , W1 u1 q1 e# X
%        setup.nRirLength : The length of Room Impulse Response Filter
! L3 w7 o6 s8 n* k; v1 A%        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default
2 g) [' D$ |4 f7 Z: T% l/ K" D5 Y%        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order./ G, R: ^' m) R2 O/ f. m
%        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.& ]0 x4 O) F) s) M2 q2 r+ L0 E
%           
; Y: h) L- V/ p/ Z) u: d+ [) L%        setup.nSensors : The numbers of the Mic
' ~4 x2 C/ a. E& {  y* _2 e3 r%        setup.sensorDistance : The distance between the adjacent Mics (m), |% U) x/ M0 P7 v9 q3 ?& L
%        setup.reverbTime : The reverberation time of room
% g* Q6 Y0 ~4 ~) i/ J8 n" D  n%        setup.speedOfSound : sound velocity (m/s)1 [8 \7 y  u) K
%
9 X/ r/ F4 J! Q/ n%        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'
7 y: f, Q" W# g" v, g%        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.
' }7 D+ A& A9 u1 f9 H% K%        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.
. u1 T  I7 x7 @! L8 a%
& y6 {/ _6 g; n9 e9 g! q9 {8 }%        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).           
1 ?; }( n/ w. M( E8 N%        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m). & ^' p( ?! ~5 ~; ~7 I9 N4 _
%        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m). ) }! m! |/ a7 ^# ^
%( ~4 m+ @9 h7 q* U5 B
%        srcHeight : The height of target audio source
$ |4 I+ B- \* ?! f! V7 G2 C%        arrayHeight : The height of mic array$ B: p' x' g+ ^9 c3 T
%
& }  y' w/ u+ h2 p$ f: q$ e  K5 C%        arrayCenter : The Center Postion of mic array # f  i- l% r% ?. ?. Y/ E
%, T7 p7 x& X4 C- H
%        arrayToSrcDistInt :The distance between the array and audio source on the xy axis
2 P/ C6 p! ?: G%+ W8 P- ]( ^5 [- B; m+ s" I
%                        . Q6 p* A' Z/ _  T6 l
%; @  r! [. n8 _; f
%1 i* s. D6 B0 i* ]" N
%         3 Z* ^: J* z, J8 q4 R
%- B, O$ ]5 e- T3 u" c  T
%  How To Use : JUST RUN
2 [6 i/ ^7 S+ M4 X%, O5 ]( y! S9 F* X3 M
%  
0 ]! k  b0 E: l2 w. z' n; E& i%   ! l$ ?. n5 ~9 u* a. e5 P0 x
% Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),
6 T8 d. e3 X+ e: ^% {%            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.24: e2 ~3 d3 R6 {( n. }  h$ O
%0 @) l0 B; y& S
% Copyright (C) 1989, 1991 Free Software Foundation, Inc.
% u) l, E7 E# \3 e8 ^%-------------------------------------------------------------------------% S- |+ X1 E2 R* m7 ]2 Y  r
: |8 y" T) q4 v* j
9 ^4 `" W% r# ~/ E7 y# u2 ~

5 U; E! p% v: l& ~addpath([cd,'\..\rirGen\']);* C: X9 k1 y2 T  n& M
2 A7 Y8 n) ^( j/ \# S9 P( x( {9 U2 _
%-----------------------------------------------initial parameters-----------------------------------
* G: [" u4 O& f! `8 H# N* X" D/ x3 d; F
setup.nRirLength = 2048;
0 C8 y0 M/ g6 t1 b) isetup.hpFilterFlag = 1;. [8 _) @+ F4 v, f" M
setup.reflectionOrder = -1;
) S' I" _5 Y1 i5 {& M$ esetup.micType = 'omnidirectional';
) J8 o% k. Q7 N9 {: Wsetup.nSensors = 4;
8 Y# y5 a, L2 N) G/ W7 G* ysetup.sensorDistance = 0.05;! \" X  y  e+ I) x+ @6 N/ I; n6 f
setup.reverbTime = 0.1;) _  K3 p% n; p8 q* K) q& @
setup.speedOfSound = 340;# N4 ~# [2 b+ h8 o% }. ]( r
- [8 Q* H, B& G: v4 Q, C5 {, V
setup.noiseField = 'spherical';
* }& E: ?% @" g8 F0 Wsetup.sdnr = 20;& J2 F4 ^8 s7 g  U  a
setup.ssnr = 25;
* q$ i9 Q4 I  ]1 }  [2 b* P; Y- I$ X
  h6 `7 v0 z7 Q+ N' \& f2 Zsetup.roomDim = [3;4;3];
8 c7 c% _  r! B* U2 @6 x: h: u9 ?4 m& B' t# q
srcHeight = 1;8 g4 d* H# a0 P2 m* D1 k. B
arrayHeight = 1;
/ U' K& y" |# n0 u7 `
! ^( D' r/ C3 U: LarrayCenter = [setup.roomDim(1:2)/2;1];6 u5 P+ @- g# o$ H/ }: p

+ b9 b: n$ W4 J) p6 S0 RarrayToSrcDistInt = [1,1];' |, r- G% g7 L
+ _, q" b* c2 v
setup.srcPoint = [1.5;1;1];
5 p( _1 I+ s2 s+ z  E  i: m( S: j) r2 X  `! d. H1 f) ?3 X
setup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);0 i8 {* E  W: v

- W) \- R0 M. @; U1 D5 a
* `5 Y, N2 L& n1 R- x[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');7 ~0 [* Q$ }2 d  ^, ~, o; _# _
4 S3 F4 S9 {1 `6 A" u; y; X+ N
%---------------------------------------------------initial end----------------------------------------
; T& `$ ~3 x) k
4 s  i4 F5 |' w4 L" X; N
2 M6 S5 `2 Y. b8 V
# a4 I3 T& s& g%-------------------------------algorithm processing--------------------------------------------------# C; Q# G* I( R5 t2 ~
; {8 j$ {  @3 E/ \. [9 [
if setup.reverbTime == 0,7 d5 ^+ n: P1 B8 c/ @8 W1 s" B
    setup.reverbTime = 0.2;
: w6 F, C, U  P) x    reflectionOrder = 0;7 P# ]2 w9 D% d3 X! Q% E( b
else
4 j  ^" ]% {9 F8 }    reflectionOrder = -1;! j) z% y. B: [2 s4 q; S
end; Z4 j/ G' x, p

4 }$ I6 X3 I  B, B1 ^1 trirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',.../ g; ^* f) f& Y! i! [) }# [' H
    setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);
0 P' U4 Z, @$ l! r8 W3 A
# K4 x9 q; v8 Cfor iSens = 1:setup.nSensors,
  d  f$ ^) J: t: x/ V4 P    tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);/ M3 i, C7 P5 m1 L
end- W7 z# _1 s9 A% {+ Q# Z5 T
mcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;
% l" [9 \9 a) C3 U8 P& ^- Vsetup.nSamples = length(mcSignals.clean);2 c6 `9 d3 @2 V# a- v4 ]" n

* Z# q% h2 \, q6 W9 _. smcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);
9 q* t- i7 J7 B" a3 x- K; B" ~* l3 T, {- ^/ ]7 G
%-------produce the microphone recieved clean signals---------------------------------------------
8 I% N3 O5 A5 N
2 Y6 _! j; j& r( v/ jmic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold* o8 C' P5 e! ~; Y8 N) ^9 `) q7 d
mic_clean2=10*mcSignals.clean(:,2);) e, B1 Y( M8 x
mic_clean3=10*mcSignals.clean(:,3);
- A* y8 Z4 Y5 m, P: |! Imic_clean4=10*mcSignals.clean(:,4);( J5 X1 o6 J1 a9 [0 m# U0 \
audiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);
- P% V8 [7 {7 |  d1 ?audiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);
$ E) V6 g% z' B- q3 Iaudiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);
% \9 M0 {1 ~5 x$ oaudiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);* e0 _# Q3 K# f6 X. M' o) T$ T
2 Z9 h8 }, X8 h6 N0 c
%----------------------------------end--------------------------------------------------
  c: X1 N* K5 v- o
0 U$ V" `  F0 Y8 Eaddpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);
- }, @  w! l2 |5 q. i5 P# V0 F& T
# m9 I- q; x, {9 s# @cleanSignalPowerMeas = var(mcSignals.clean);+ o% w9 n/ M- ?: j$ N) W, U

9 w! w" R, a; x
6 ^' c, |) q" `! ZmcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...
" u& q" `# t/ o+ j& D/ C    setup.speedOfSound,setup.noiseField);
5 {' s3 U" R! w6 h$ F. X1 t: e/ vdiffNoisePowerMeas = var(mcSignals.diffNoise);
$ a3 t0 d3 H# j' @& _2 vdiffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);
8 X6 r4 {' r/ l. B  ]' G6 V6 W" h) xmcSignals.diffNoise = mcSignals.diffNoise*...
% g* g9 ~4 A7 _. t! p4 l+ t    diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));9 A8 J0 l  `: o. k& C8 x: ~
& h+ R' W) t4 N  I3 @# y: n9 O8 U% U9 L' K
mcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);- K* J6 w5 ~( P6 i( {4 K
sensNoisePowerMeas = var(mcSignals.sensNoise);
2 ~/ U, l* m% W; GsensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);
8 R& e- p5 b( c: o& pmcSignals.sensNoise = mcSignals.sensNoise*..." z5 t3 ^4 u! E2 n$ v; ]
    diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));( z; Q' x" F- ^% t% E- z6 o

8 E& C( ?! \( s. c* Q7 ~$ i3 mmcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;) k6 B2 W/ e' \$ }
mcSignals.observed = mcSignals.clean + mcSignals.noise;
9 Y/ \: [' u( d. A
% F. |. ^) k+ V! t" i+ B%------------------------------processing end-----------------------------------------------------------
. C8 E4 S  J) [; E3 _" V
* s5 x( m6 c& s) H; P% g+ D! X* ~# J& q6 b8 L# _& x7 {0 F
3 m+ v! \$ `4 N7 Z. r0 \: R
3 N0 J) n4 U$ L$ d
%----------------produce the noisy speech of MIc in the specific ervironment sets------------------------
6 y. h  K& q" ]6 B: O% Z% h' y* k
# X" j) C; i9 S" R# _noisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold
$ g! {' g5 f! T8 U) Cnoisy_mix2=10*mcSignals.observed(:,2);! l* F5 K2 ~) i; T
noisy_mix3=10*mcSignals.observed(:,3);
: I- r2 k0 s; \9 C9 lnoisy_mix4=10*mcSignals.observed(:,4);
+ P. T( s! I: ^( K# e0 ]l1=size(noisy_mix1);' Q6 f; z$ P# J
l2=size(noisy_mix2);
' L3 a, I0 Y2 M- }0 Gl3=size(noisy_mix3);- I" u6 y3 a3 @+ d/ z; m  Q2 P$ A
l4=size(noisy_mix4);
: T+ E& r! O, R7 Q0 [) faudiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);7 @8 ]+ c) H8 P4 a3 Q* |
audiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);+ J. l: [# D. s$ }
audiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);0 T: L; U9 _9 N) w1 r
audiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);
7 L- R; O  M' H$ I& a. ?! o5 G& ^8 K8 ]1 X* ^$ F* r) F7 G% y

' f6 I% u( {* C  [' _%-----------------------------end-------------------------------------------------------------------------0 Q' B0 P" O) ?1 X. [6 b/ Y$ }0 {2 E
这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。
1 u" G9 k$ {9 B% [8 [/ Y直接把它们替换成你想要处理的音频文件即可。
5 h2 C- P) E0 [( P$ g! U$ s$ b. F  ?/ d$ j1 N
  除此之外,还有一些基本实验环境参数设置,包括:麦克风的形状为线性麦克风阵列(该代码只能对线性阵列进行仿真建模,并且还是均匀线性阵列,这个不需要设置);麦克风的类型(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)。
! q3 x, c. S' ~- ]
0 R" ~1 }  g; e! a" n, i
- ~' ?2 {/ E2 d  j+ U
( N% {0 a& f: z2 d+ O% h) {图1 麦克风类型图. e0 \" F' V( O5 o" o2 |7 b) O

' x% G& B- j2 t# V/ o4 k7 `图二 房间的坐标系
' e  R+ C3 M! h2 q' A1 B( C  l4 @
7 l5 q8 j7 w3 o0 o& L  以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。
4 X5 \( J) V9 r————————————————3 a! X9 {6 R7 g" F' `5 I
版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
5 `! ^6 H! A5 L) Q- q1 G原文链接:https://blog.csdn.net/zhanglu_wind/article/details/796749988 X  @8 ~3 o2 }" H( @! b- N& e
& m: t- U% |" I- _3 A8 y

) e9 B% Y& X4 z+ O3 b




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