数学建模社区-数学中国

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

作者: 浅夏110    时间: 2020-5-15 15:10
标题: 麦克风阵列仿真环境的搭建
1. 引言% i* J' Q& @; R
  之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。: o: G) n- O- x; X% }! g
6 f4 g4 D3 P; n
  然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。
. w% {+ x7 l) a' {; ^
$ m. |# E7 x" t) {2. 代码介绍. j- F+ \  K7 P/ O0 o
  原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:
, ~0 e4 G% [1 t0 n# U: K$ P1 A. \function [mcSignals,setup] = multichannelSignalGenerator(setup)
7 E* g# C- ^8 s3 Z9 ]9 R; ~5 A: u6 Z  e) J0 Y7 V' |8 z% H& Z

7 H: `- ~6 g2 N& S6 Y4 a2 n, f3 e. ^%-----------------------------------------------------------------------
1 q% m# W1 P/ E3 d. p%  Producing the multi_noisy_signals for Mic array Beamforming.% n' {/ ^9 E% p: c
% 9 z! L/ [6 j7 P" c
%  Usage:  multichannelSignalGenerator(setup)) l: Y, T, ?9 c8 \/ t
%         ( a( j& l; L! Z; x( I$ z+ |
%        setup.nRirLength : The length of Room Impulse Response Filter& c! a/ h6 v4 ^2 W1 @
%        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default
& S& n6 b- G; A%        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order./ r  k4 L0 ~5 o
%        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.. [/ E) I& l# X! i! A& |8 f3 S
%           
" `$ S3 G; `+ U5 D' E%        setup.nSensors : The numbers of the Mic3 |8 H- C2 y' l; @9 M
%        setup.sensorDistance : The distance between the adjacent Mics (m), \# E5 k! g4 D, v( v/ @0 x
%        setup.reverbTime : The reverberation time of room: O" I9 _! i4 `
%        setup.speedOfSound : sound velocity (m/s)
& h: |2 d# j' G7 N: ~/ H%4 K6 {1 o' t- x  o
%        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'
7 V0 G( }9 e3 M- i%        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.& H( _* T& F+ m
%        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.+ F4 A) L: X; O- F
%
' [" t+ Y9 h/ u%        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).           
+ N- v7 Q- s! ^  s! \# l, W%        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m). & a: E( }& k  d. ~
%        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m).
; P  R3 |! g4 G4 o  I  d# b%: D5 r% d0 \$ i; ~
%        srcHeight : The height of target audio source8 t' G. X2 E4 g3 J" w
%        arrayHeight : The height of mic array
. W4 v% k/ C) h7 ^6 p5 H) A%7 C& v5 u; o7 x, ^% z
%        arrayCenter : The Center Postion of mic array
7 Y' r7 Z" F$ G  u" r; \+ |%
0 {- ~  M0 g8 d8 w%        arrayToSrcDistInt :The distance between the array and audio source on the xy axis) F: l7 c. |8 V6 @5 w) i# \9 D
%
6 z5 Q8 G9 Z6 C* {2 w: `& p%                        5 Y( z; `0 o" p; @5 c: b! l
%
* r: S; x& a; {( U: K; @%# }" T* `. E( i; {6 r+ T1 g
%         
3 c7 ^$ Z2 H5 F6 q. E! H%; I; H1 Y/ p5 G
%  How To Use : JUST RUN+ T: S# i% T1 I5 \) t
%
* h: A" h9 c8 [) B$ G' ?%  
/ P; _- G- t. F* {6 a( ^6 q/ b%   
% r4 }8 u3 N1 s& H% j, p, l% Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),* Z4 d/ N( T# f$ \
%            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.24- Q5 \) u# e- e
%8 P8 G4 m) f1 N8 c! g# q# e
% Copyright (C) 1989, 1991 Free Software Foundation, Inc.
) W2 X2 @6 Y5 J' ?% J* q* b%-------------------------------------------------------------------------( l0 h( ]  C, m" `2 q

4 s/ {6 _1 f5 V; c' Z9 ^7 p0 a! v9 {2 ~/ a

9 J$ {) n, {( h+ i: r& y8 i4 |addpath([cd,'\..\rirGen\']);" I3 K5 ]0 |9 S! @9 K! H$ q
: W7 y; E9 J, L3 g, }& e
%-----------------------------------------------initial parameters-----------------------------------
5 l  F- K: E; s' {% m4 t: e" @7 F- U3 c/ Z6 O5 w3 O3 c4 p
setup.nRirLength = 2048;8 o: o1 ]6 p. m6 u, Q1 o; }
setup.hpFilterFlag = 1;
/ W# R- n# T7 [8 ^setup.reflectionOrder = -1;/ p* w5 g7 _9 a" s6 m+ p
setup.micType = 'omnidirectional';! M9 }9 j# i, F' _4 E' R
setup.nSensors = 4;" Y6 P' V/ D) G- Y: n
setup.sensorDistance = 0.05;  W6 K, F% q4 `8 S4 D2 D4 x) C
setup.reverbTime = 0.1;
1 E/ n0 h1 h9 u! h$ P% usetup.speedOfSound = 340;
7 U% p* u. G; u  s" C+ M3 \4 D! E
setup.noiseField = 'spherical';
% U; O& p! n( s" Rsetup.sdnr = 20;2 r0 U1 n6 f; ?, [4 G0 |
setup.ssnr = 25;
, L% k+ H6 C2 a$ K1 w" R+ L0 c
  y* @, C* ~, k' O+ _/ {0 [setup.roomDim = [3;4;3];
$ W7 V3 D8 {$ m2 R* e$ t' _& a$ L8 R- O/ t/ p1 g8 Q
srcHeight = 1;& F' T+ l6 b, |2 U& F/ e
arrayHeight = 1;( k$ S; V. f, M; H) V# v
- W  e: M- c8 W  R" U. T8 F, ^3 _& P
arrayCenter = [setup.roomDim(1:2)/2;1];. t) S' [2 H8 O! k0 J; |( r

- b9 `3 |  F: OarrayToSrcDistInt = [1,1];7 U2 X$ b3 |$ Q/ z9 g) F
' ]; h/ x$ d# K
setup.srcPoint = [1.5;1;1];
5 s/ e4 x2 i* N& E: I& e- w. R/ `* z
setup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);' \3 o8 _. |& e7 i4 X' [/ T! M
; J, W' v+ G" N/ V! X/ x

9 t' `2 R" N+ u' x: m+ W3 _. t[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');
4 ^+ A  c5 J# n/ n/ \/ {/ U$ G" i& @
, @& j- Y; w2 r( Q# F% K3 u- z%---------------------------------------------------initial end----------------------------------------, _; ?: N" n/ _* L5 x0 b! e3 N

  S' o8 P' L: J9 b5 C8 Q6 r( y' ~0 x  V+ o% t3 M
5 c& z+ t! L0 {) i+ A* W; G
%-------------------------------algorithm processing--------------------------------------------------! z& b# `5 A) j3 n2 x" P

: @4 Q% o* L2 U! m+ yif setup.reverbTime == 0,, H& u6 P; Q1 m
    setup.reverbTime = 0.2;6 l% F/ I$ |& B
    reflectionOrder = 0;
: z$ N# Q2 V, J0 zelse
: D- I2 s; u8 r3 c* ?8 x  m& l    reflectionOrder = -1;
8 Q2 T2 T* q  g9 dend( V# Q7 Z" q# @+ V
/ U; E7 C9 Y% a- d2 x  O' k
rirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',...
. N/ k9 J7 I, D: q# b    setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);4 |0 j6 f9 b% x( x

# h( P8 N" l& e4 S# |: Ufor iSens = 1:setup.nSensors,* W2 C1 M* t+ ?4 B( B
    tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);
* V8 n- x5 V8 [end7 l# A/ k) D0 |  x# e: d
mcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;
8 P9 ~* P6 D% Q6 e, k. ?% Isetup.nSamples = length(mcSignals.clean);
  i8 a! [1 v2 f0 s$ J9 ]0 d2 \+ C  r0 N. r; i
mcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);
8 a' @3 y* u" K/ Z1 K  ], g/ d: W1 T
+ I5 \& `5 Z9 ?%-------produce the microphone recieved clean signals---------------------------------------------
. L9 \+ {9 U+ Z& d# a7 ]  \5 _, r% r0 R; V7 O
mic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold
% ]. t( u, d3 @2 `' Y8 jmic_clean2=10*mcSignals.clean(:,2);
/ T$ n( {0 c6 O$ {# u! Kmic_clean3=10*mcSignals.clean(:,3);* o. W+ g1 |% @2 Z8 b4 H/ x- x8 a
mic_clean4=10*mcSignals.clean(:,4);2 T% d% v8 ^% y$ o4 g. U* j$ M) U
audiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);. t0 J* T2 B1 [. b# ]
audiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);
# c9 E' S9 a/ G+ d. zaudiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);% m# y( }2 Y: d0 u1 U
audiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);
. `3 F/ F) x# V3 @0 H
' L5 s$ ?7 c( W5 R2 X%----------------------------------end--------------------------------------------------
5 S; e* h3 O: u* f& e# Z, l" r, A9 r1 k
addpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);7 I  h9 o9 f& m# B

/ F' m  q, _: T( l* T& }$ h7 L* GcleanSignalPowerMeas = var(mcSignals.clean);4 v% v+ z+ `+ w  U! {( A

! C+ B! B! N' O% }2 ~, P5 q9 m9 g. |+ d2 D" ~) Z
mcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...
5 t7 D5 o$ \3 ^0 c- t, ~    setup.speedOfSound,setup.noiseField);
. }( l1 J+ J. }- [diffNoisePowerMeas = var(mcSignals.diffNoise);) u6 N, a! F1 T! y8 [+ o' w7 h
diffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);
4 O$ {2 G/ g& nmcSignals.diffNoise = mcSignals.diffNoise*...
1 G. a) V" O2 _" D0 u% x    diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));/ e3 g2 R& e0 d1 U5 @% u' B- M7 Y

/ N% W  u7 L0 u, w) ^# C8 \mcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);9 M) D: C) d8 a) @/ ^
sensNoisePowerMeas = var(mcSignals.sensNoise);
6 @/ e/ `; I- Z: x* l+ m- FsensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);
: E) V6 ~/ S' [3 emcSignals.sensNoise = mcSignals.sensNoise*...
, U8 T* K* Q! ?8 {    diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));- b4 N' Y) M( Z- O1 S8 x& b, W

' W8 J& F/ h3 i( E, xmcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;$ ~1 t4 G: f' f
mcSignals.observed = mcSignals.clean + mcSignals.noise;2 }7 e& I% Z9 \* F9 ]( P" I  u1 q

6 C0 t5 p/ f2 o%------------------------------processing end-----------------------------------------------------------5 x# _/ _$ p, @6 P( h
% w  V. `- c; f. ]: p! i
$ u7 [* n7 d! n4 V( |+ k

! j! g2 u2 N1 J
/ Q8 N" E/ z/ d) ?; t" R%----------------produce the noisy speech of MIc in the specific ervironment sets------------------------% a; p. ?7 o; ?7 W

, c: a; N4 k4 J, P& C+ v# enoisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold" I' P6 I5 Y4 S
noisy_mix2=10*mcSignals.observed(:,2);
+ l* H7 q0 q& d3 lnoisy_mix3=10*mcSignals.observed(:,3);3 P1 p- G' w: ^' V" {; v4 e' ]& M0 Y0 P
noisy_mix4=10*mcSignals.observed(:,4);* u( L0 W  M9 ^! V! F1 M
l1=size(noisy_mix1);
9 C6 d, D  V- z& ^0 ~1 A- Ol2=size(noisy_mix2);
; o; b" Q; P. w2 I2 al3=size(noisy_mix3);
! ^) c3 k: {# i) I. xl4=size(noisy_mix4);
$ k7 c8 ~) k/ Y, ?# ^# {audiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);( r( \, \) ^9 S8 h
audiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);
+ f; D" \+ c0 b+ aaudiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);
) J  L$ y* e4 j) Y  u. kaudiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);
2 U! p( r0 M) _7 K" C, V  s; O# I* e% ?/ l$ Q0 s
% Y) H) P, z2 V' i
%-----------------------------end-------------------------------------------------------------------------
9 U# i5 s$ L: G这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。
3 ]* y' ^* p  b& q6 {直接把它们替换成你想要处理的音频文件即可。( S, y$ i0 j4 j7 u( V, w  y9 ]
& ^4 Y0 n& m. i1 V! V) X. W1 S
  除此之外,还有一些基本实验环境参数设置,包括:麦克风的形状为线性麦克风阵列(该代码只能对线性阵列进行仿真建模,并且还是均匀线性阵列,这个不需要设置);麦克风的类型(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)。
$ E  \! ?, Q# y4 |( U9 }
& Q2 p/ c5 G$ w3 Y1 l: x7 Q( q0 A* b* \+ F4 W
: |% ~, `3 M) O8 L4 R7 G0 K
图1 麦克风类型图- L# C- X( Y4 K
# s  L' y# A) K% k8 {- U) Y
图二 房间的坐标系
/ p: e7 n/ A' z3 z* f) S8 L5 o: \: t  p* u2 }% s: O
  以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。8 O9 U; W- v/ y. L
————————————————
2 w: e, S( I  a# w版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
8 a4 m% {, y7 t6 o原文链接:https://blog.csdn.net/zhanglu_wind/article/details/79674998
" F% B3 ?. e0 D6 H. Y* y2 ~) W5 t* S1 ?. Y# S1 Z& J  [
1 \6 e+ x% S, K% v4 T- q  t





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