数学建模社区-数学中国
标题:
麦克风阵列仿真环境的搭建
[打印本页]
作者:
浅夏110
时间:
2020-5-15 15:10
标题:
麦克风阵列仿真环境的搭建
1. 引言
$ @$ X5 }0 n8 [' m' P( }+ P& Y; ?
之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。
/ B6 n& M7 g% ^& d
% t: {/ W$ A/ W
然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。
1 z6 r* v( l( a7 q; P
$ }: f( |, z+ P( ^* M
2. 代码介绍
4 p6 u% x+ v3 ?$ [" u0 G; A
原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:
O6 G2 C. D9 f* M* K3 p8 @3 J
function [mcSignals,setup] = multichannelSignalGenerator(setup)
. D) h$ Y/ x7 l9 T D
( f t. S7 t" e
# P& T# ~, l/ y# b, `% Y
%-----------------------------------------------------------------------
) y _3 V9 M6 v+ p e7 m
% Producing the multi_noisy_signals for Mic array Beamforming.
+ \, _7 }. h- {7 ?# Y. ?7 t( J
%
+ c* u* c5 C. ~5 D
% Usage: multichannelSignalGenerator(setup)
U4 a0 N& \( @! p! o# M
%
3 j! a/ O, X$ g8 \( L
% setup.nRirLength : The length of Room Impulse Response Filter
X1 \+ m$ K! o1 }$ G, F
% setup.hpFilterFlag : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default
; B7 Q$ d2 M* s; O
% setup.reflectionOrder : reflection order, default is -1, i.e. maximum order.
7 t% k/ A7 |# d8 n( o
% setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.
, d ]2 a2 _- }1 ^
%
* T3 ?2 v5 r) V
% setup.nSensors : The numbers of the Mic
0 {# }" E) r. A. B& m1 h& R: o0 ^
% setup.sensorDistance : The distance between the adjacent Mics (m)
, n/ D) B: l1 H
% setup.reverbTime : The reverberation time of room
* n! D" p1 ~8 n! o
% setup.speedOfSound : sound velocity (m/s)
# H6 P7 |2 U m' u
%
1 F7 L1 x6 c) d1 U* w5 o' N
% setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'
: x1 B! y" y& x! o
% setup.sdnr : The target mixing snr for diffuse noise and clean siganl.
9 X0 ^4 d8 M3 k" P5 s
% setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.
) j+ ~2 u* U- V1 W8 n1 M
%
/ |7 m8 U; v; q
% setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).
% s% J+ S7 w2 J6 r1 l; k
% setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m).
% [$ {$ r [3 {: j) ~4 W0 x
% setup.srcPoint : 3 x M array, the rows specifying the (x,y,z) coordinates of the audio source postion (m).
8 n; w6 \( }6 s, p9 d' u1 e
%
, e3 H9 @- r" N5 J( g1 i' _8 O
% srcHeight : The height of target audio source
0 @: }) [6 C3 h; t2 C
% arrayHeight : The height of mic array
$ f8 o( V7 ^ x( k
%
2 j; p1 v. q9 L4 N" s7 |, I* ~
% arrayCenter : The Center Postion of mic array
' I5 k6 J) T6 n$ _0 z
%
! W$ N6 M; c: `
% arrayToSrcDistInt :The distance between the array and audio source on the xy axis
' z+ p9 z$ \ T1 H( W
%
$ w) M( J$ l, y+ u$ r
%
& y& k: o! x5 j/ S) ~
%
6 E& h7 P+ u( j' m% i# l
%
4 o* G' D* I6 N; |
%
( S- y H& u9 Y( j' O0 t
%
' G: r2 C0 K5 m8 w$ i# j" |( A
% How To Use : JUST RUN
. z7 d0 Z+ ?& X4 w
%
, K' A! }" Z/ }6 U M0 K0 H
%
8 @6 ]+ \- P* j6 Z
%
* u5 `. U( w0 b" h& W; U( \' p
% Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),
8 o" X% v& L; R
% slightly modified by Wind at Harbin Institute of Technology, Shenzhen, in 2018.3.24
2 |$ N3 v# I& |5 S7 I. Z# k
%
3 w0 ~8 v( x, U
% Copyright (C) 1989, 1991 Free Software Foundation, Inc.
. J L' k$ `, ]6 |; k. ?
%-------------------------------------------------------------------------
' }% O O& E6 K: H
; G+ M/ D9 h) ~
$ q. z$ h( K9 u# A' E% _' i A
0 i+ d4 [$ N3 f* \+ F \
addpath([cd,'\..\rirGen\']);
/ v9 y. d2 j* R6 {
+ H4 ]/ g% w8 p5 Y4 a
%-----------------------------------------------initial parameters-----------------------------------
$ l1 i: o9 ?/ _# F- f
) h; y( D2 M& V! J( n
setup.nRirLength = 2048;
1 y/ |/ D: P: H' ]; p5 e7 x
setup.hpFilterFlag = 1;
' y( D; D8 o: D! U, r( J
setup.reflectionOrder = -1;
0 S5 G4 W4 I# m; W4 c
setup.micType = 'omnidirectional';
; @( Q5 m# M& m" ~0 d) h
setup.nSensors = 4;
# I# W5 D& w9 @
setup.sensorDistance = 0.05;
9 [/ k, \* f) S
setup.reverbTime = 0.1;
: f' G3 F9 k" i8 j8 X
setup.speedOfSound = 340;
" w6 W4 o% u- ~" z/ u, ~0 E, K a7 W
% | d- Y8 d# v+ Z* \
setup.noiseField = 'spherical';
g) L' H% S: a: L) S
setup.sdnr = 20;
6 ?) d3 W, C+ ~$ ?. k/ ?
setup.ssnr = 25;
" H+ u% `( f# A3 X' M5 }
) U. ^5 N" O$ u" h3 u; ^3 _
setup.roomDim = [3;4;3];
+ Z. o/ v! F$ h! t( M
0 q9 `& o* z7 \- L
srcHeight = 1;
6 R1 N& Q) K$ o; d1 a# Q
arrayHeight = 1;
& ^- x7 p D# B1 |3 c* f; p
" T% A; f, a3 y, n s
arrayCenter = [setup.roomDim(1:2)/2;1];
, h7 t$ t& e( p' ~! V2 z4 w. _& v
' q6 b! \- x3 m" T" d
arrayToSrcDistInt = [1,1];
, Q0 V# ^2 D3 W* l
8 x5 Y" ~# ~5 g+ c7 f7 Y6 g4 E. F
setup.srcPoint = [1.5;1;1];
' C5 E2 I r4 q8 R1 p* Y+ L
& x( F( ^- `9 f6 R
setup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);
# N) T) ]/ y% P7 W
1 x- \. P+ C5 t+ P' t& Y' D$ i
0 B8 k0 g" c/ {, d# r( g
[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');
7 y0 f& ^ M2 b2 |* R
' A E% W' z4 ?. h1 y K: u
%---------------------------------------------------initial end----------------------------------------
) L; L3 ?. P, j. ^3 M+ H: A& w6 r
, G( Q. B5 w+ K6 b2 E
! j3 s: F3 ?) j/ P
! t/ c4 P" b( j9 {: F
%-------------------------------algorithm processing--------------------------------------------------
" o X, Q4 |1 d2 f( \
2 X$ l6 Z- k+ U; p
if setup.reverbTime == 0,
- d" h5 n( L9 V6 ]
setup.reverbTime = 0.2;
1 G0 u0 Z. W& o* u1 O
reflectionOrder = 0;
2 j, I# F6 h/ s0 ]* `
else
# {6 @; P6 E* g& |& o
reflectionOrder = -1;
$ `! ]% N& F( ^" @3 }" r1 {5 |
end
8 o: x+ R9 O* W9 z* y
7 o6 J8 S" a M" ^- i
rirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',...
) b. h% R8 t% T! R& @ r
setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);
0 j+ I0 i9 Q0 Z. @0 Q
: q6 `6 p- ?3 l( M! O, v
for iSens = 1:setup.nSensors,
- c/ B; b2 K! L+ I+ D& u
tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,
',cleanSignal);
. `! N" c ?% C* R
end
9 r4 o2 t1 i; G
mcSignals.clean = tmpCleanSignal(setup.nRirLength:end,
;
& g$ E# Y2 S3 v+ a0 g! h
setup.nSamples = length(mcSignals.clean);
8 q% Y0 [* X2 o4 ?* q) m$ J: i3 v
) Q B4 C" A! e, w* ~! V7 T
mcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);
9 J+ h7 {9 q, A1 g1 ]8 i
, R& p7 N- o% P1 _" t+ `
%-------produce the microphone recieved clean signals---------------------------------------------
9 d1 O5 L! q) ^$ [7 G0 N2 S
& q+ L, T+ P: P# C
mic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold
5 }0 L5 J# _# F0 z
mic_clean2=10*mcSignals.clean(:,2);
/ O( Q1 |4 }# J
mic_clean3=10*mcSignals.clean(:,3);
) y7 U9 V' G e0 |; n/ q# ^7 S3 t
mic_clean4=10*mcSignals.clean(:,4);
$ _) \* }2 n! L. X3 P0 j
audiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);
! X' r9 F0 m) v& e0 v3 X
audiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);
8 B2 X. n/ [% C7 I
audiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);
. Y) F9 m" ]6 ]! h) R' r2 Z$ {% j
audiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);
& t- r, |) r' G5 s5 s
M" M Q& z" Z3 n4 h
%----------------------------------end--------------------------------------------------
# R$ h0 ~* L* X3 N I8 t
& X5 q; i5 o7 e2 j# I2 H) N
addpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);
$ E9 y9 E% C( L5 z4 Q/ M" e3 P' J
7 P* m5 L+ y! x6 P! D& `7 e
cleanSignalPowerMeas = var(mcSignals.clean);
+ E% H6 q2 e) X5 ?* Q; z, h
* h$ F, w4 l% J2 B( @+ u: r' [: [
3 ?1 L* y! E& I6 t( D4 }( C d
mcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...
4 `% e% C; b# j* G+ o0 I
setup.speedOfSound,setup.noiseField);
* l6 W' x& k/ ?0 {. b5 z+ d
diffNoisePowerMeas = var(mcSignals.diffNoise);
8 `( O+ J. H2 a. x! z. }
diffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);
1 }2 v- k! s& a3 K' L
mcSignals.diffNoise = mcSignals.diffNoise*...
+ C( x1 A$ `9 E
diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));
& O# f6 n# r5 v s9 k
1 ^2 e0 P& f7 ]2 F5 M4 @3 s* i
mcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);
8 X8 w0 G( T) _. o' v* n
sensNoisePowerMeas = var(mcSignals.sensNoise);
2 D) W' _5 x8 u
sensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);
7 Q* V6 ?. O+ i7 e4 v
mcSignals.sensNoise = mcSignals.sensNoise*...
$ |! r6 _' m/ Z% K7 |5 {8 ^9 C. Z# _
diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));
% ?3 E+ v7 A( I- j3 S% E1 k
1 c0 P5 j7 O B, `+ I0 `' f
mcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;
7 z8 m9 y& F0 A: k, h8 J, Y8 {7 i
mcSignals.observed = mcSignals.clean + mcSignals.noise;
% H8 G F3 u: M5 n, P" K0 H' s
4 T3 I1 ~7 T" r- x: p5 z I
%------------------------------processing end-----------------------------------------------------------
8 s1 X3 x! }. \( H$ O* x4 a9 T t
1 B8 W. c8 e$ Z' |( M, ]
9 U( W* l6 z$ i1 G! X* J9 `
Z5 @ @/ F' b& w' F$ p
1 f% @+ c' c# v5 c" }
%----------------produce the noisy speech of MIc in the specific ervironment sets------------------------
% m- T( e9 t" F5 T# L; h
+ s" m, M6 T4 g3 x+ E& x; x3 W
noisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold
) Z! e( o* ~& F
noisy_mix2=10*mcSignals.observed(:,2);
! _; A9 x/ S' r/ s; R$ q7 N: c
noisy_mix3=10*mcSignals.observed(:,3);
2 o/ V! S9 B- M# J; `
noisy_mix4=10*mcSignals.observed(:,4);
' r5 I6 `, J9 o/ H0 c/ o5 T& r! ~
l1=size(noisy_mix1);
, h( Z5 \$ F5 Y6 r2 I
l2=size(noisy_mix2);
5 j& A$ I9 L1 k* r. g& ]; C
l3=size(noisy_mix3);
6 I- Y. o+ ~; z
l4=size(noisy_mix4);
& o6 `# s3 Z1 T7 Z& f4 ?
audiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);
- w, o/ c1 }3 V5 p. o
audiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);
) |- v0 u& _# v. \
audiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);
2 E) R' V* n6 A( F# \( W+ `! E
audiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);
. x1 u- J, X6 a2 o
; u7 {+ b# C5 n
/ e! O5 n; R) b6 w; \
%-----------------------------end-------------------------------------------------------------------------
% R/ _- C/ K9 z! d q, K/ S
这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。
7 W5 o& u( c, p9 v4 w( q2 M5 n
直接把它们替换成你想要处理的音频文件即可。
; D% V" r7 i* ~( F8 _# l+ Z! l
7 G4 ~ t8 d' ]: A1 H! |5 n: C* g9 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)。
8 n, a! W$ \1 ?" o" j% K( k
) Y8 v& a5 H ?) J6 C/ ?
. N% o1 d# Q$ Y1 a- X9 ?$ N
* ?& g1 A- ~# A( g# Z
图1 麦克风类型图
" m; G* V4 _" F) A
. l8 t& B4 o( U$ \
图二 房间的坐标系
/ o, A( u& M% b
$ f; b/ \3 ^5 y+ C' f
以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。
0 N5 ?5 w T) W$ ^& |6 g C
————————————————
2 c4 v# [6 {# J* ^( m7 ?( g! ?
版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
( W; l8 v- c: l; b. d
原文链接:https://blog.csdn.net/zhanglu_wind/article/details/79674998
6 H `6 \2 w+ A+ D6 a% V
1 P! O8 o4 i' w
$ i; c3 `1 `3 T4 K! h/ ]
欢迎光临 数学建模社区-数学中国 (http://www.madio.net/)
Powered by Discuz! X2.5