- 在线时间
- 791 小时
- 最后登录
- 2022-11-28
- 注册时间
- 2017-6-12
- 听众数
- 15
- 收听数
- 0
- 能力
- 120 分
- 体力
- 36451 点
- 威望
- 11 点
- 阅读权限
- 255
- 积分
- 13896
- 相册
- 0
- 日志
- 0
- 记录
- 1
- 帖子
- 616
- 主题
- 542
- 精华
- 12
- 分享
- 0
- 好友
- 225
TA的每日心情 | 开心 2020-11-14 17:15 |
|---|
签到天数: 74 天 [LV.6]常住居民II
 群组: 2019美赛冲刺课程 群组: 站长地区赛培训 群组: 2019考研数学 桃子老师 群组: 2018教师培训(呼伦贝 群组: 2019考研数学 站长系列 |
1. 引言
5 ^* ?0 d4 y- c9 {9 @ 之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。
3 |+ s9 y- X9 I- p7 h$ T- s3 q3 u' q
然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。- v/ j3 f$ w7 }4 r: ^
1 X: g' n& u! o) `; S
2. 代码介绍
, t& F& _- r0 l4 D8 T$ e: b 原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:0 r9 V' T- u3 Z u6 ?
function [mcSignals,setup] = multichannelSignalGenerator(setup)
. J/ D9 X6 u( g; E. ^' u/ J8 r
; |0 E W# B3 _. C1 S9 T% ?* k1 [
+ X) [2 i o3 g0 f. K) S; q2 T%-----------------------------------------------------------------------/ Q0 ^3 f$ Z" j" o: y% o
% Producing the multi_noisy_signals for Mic array Beamforming.
; r9 Z5 _1 z7 c: K" B( d% * C* c7 W7 r; K6 H$ O
% Usage: multichannelSignalGenerator(setup)8 o/ k8 K& H4 q( l3 v, D: [
% $ @6 h: |, f) C1 |1 A
% setup.nRirLength : The length of Room Impulse Response Filter
/ Y, J+ u9 k1 h( S% setup.hpFilterFlag : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default+ H% h2 }( r' s6 a8 l1 `" G* b8 }
% setup.reflectionOrder : reflection order, default is -1, i.e. maximum order.
1 p8 c) x4 X1 F4 j3 P ^1 X0 h% setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.9 Q# R+ m: M/ S! m/ d7 k
%
7 g1 K, b7 W* j& D) m9 C! B! m% setup.nSensors : The numbers of the Mic4 f$ }% {1 p k" b" D2 U9 K3 ?7 ^7 u5 j
% setup.sensorDistance : The distance between the adjacent Mics (m)1 @) [. u. `+ y/ M% D' j; ^
% setup.reverbTime : The reverberation time of room
( ?6 J* Z0 A# [4 R4 `7 H% setup.speedOfSound : sound velocity (m/s)
" \4 T" y4 w! f, j/ n%! p( q7 H. B: z+ G2 `1 G& ]
% setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'2 y: \# [+ P5 f% _ b* R
% setup.sdnr : The target mixing snr for diffuse noise and clean siganl.- T) T" w5 K7 W' J' b5 w6 l
% setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.6 M2 z7 C3 b3 C$ Q- w
%( @; ?7 |, p6 @5 _
% setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m). 0 k7 Q# n7 l- F3 \. x
% setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m).
( J# G3 ]1 f' ^+ D- S6 E4 I+ S% setup.srcPoint : 3 x M array, the rows specifying the (x,y,z) coordinates of the audio source postion (m). 7 P6 }% s# }* w2 \- K
%
" P$ D) Z' j/ X- @' m8 z% srcHeight : The height of target audio source) |8 ~7 U5 q$ d* B; _& a
% arrayHeight : The height of mic array2 @5 i! |& B2 [5 c* w! Z2 T
%! z4 t* e7 {; Q1 ^9 T% }/ @5 V" B
% arrayCenter : The Center Postion of mic array 3 [. [8 L3 r. I$ G. }3 N9 b
%
" k4 O$ S X& O; i" @% arrayToSrcDistInt :The distance between the array and audio source on the xy axis9 I1 ^7 Y6 l' p; k6 U" }2 ]
%
) c# t e! `" v: d& V7 [%
. E; @% I7 D& R' M, @5 d%
( g( }3 l2 i& t9 ]# ^: V%) e5 T9 f+ W3 W1 }9 O0 O9 A, N
%
6 B' b# y) ^0 F; h; m2 h R1 p%
& A: M& c; j; T% How To Use : JUST RUN
9 R4 J! t' n1 g# w# }3 s%+ J) @5 F$ q% Q$ C, `0 P% P- Z2 L
% 1 V0 d. O% c9 ^) ~
%
! |5 i" O2 a' D- X7 g% Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),
8 J# y1 K0 |# p0 {% d1 a; b( [' q% slightly modified by Wind at Harbin Institute of Technology, Shenzhen, in 2018.3.24
8 s0 q9 S2 F" r) \" v! z ~) t%
* f7 V, g( {1 c* l7 d% Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|7 Y. _0 R3 Y%-------------------------------------------------------------------------
4 m2 L) y. M2 M0 c" |7 T) \7 s1 K, w6 C+ Y
# ]+ {. b) Q! Y$ T9 ?, }* o* a' z- h; Z4 P0 H9 @( K
addpath([cd,'\..\rirGen\']);
6 C* u/ z7 I7 E. D3 V3 w- v
9 ` X* P( h2 M" k4 ~: e/ m" i, @%-----------------------------------------------initial parameters-----------------------------------5 m+ F, F, z7 O9 v- q. a& N# S
& ^8 H n) p9 esetup.nRirLength = 2048;) M9 b! w4 Z% U8 M. J
setup.hpFilterFlag = 1;
/ f% M+ B0 C4 Dsetup.reflectionOrder = -1;2 F; q" _' l! }, _: h
setup.micType = 'omnidirectional';" {6 p! q# @8 m& ?0 r+ }
setup.nSensors = 4;8 @3 Q: g+ m( N. x% R7 S, S
setup.sensorDistance = 0.05;
* F7 Q! I2 h3 d# [9 Y! ~* N. Gsetup.reverbTime = 0.1;* f4 O9 V5 e$ A! L, o5 C4 T
setup.speedOfSound = 340;
" @! ~( ]8 f y7 b6 _* |7 t0 ]
9 g$ T- {) A& ~% [; }: J% v7 ]3 fsetup.noiseField = 'spherical';$ ^$ r% @9 V j4 Q
setup.sdnr = 20;8 e, O' ?) E5 c& j+ n8 |3 J
setup.ssnr = 25;( d7 @) u/ A4 D; E% w
/ |7 t; y6 ]( y' t7 e% P5 Psetup.roomDim = [3;4;3];
5 G- e) t" c: m0 x. J% S& @( `4 ^0 j [1 \
srcHeight = 1;2 x/ }6 K m7 G5 D: h6 d
arrayHeight = 1;
& a) y" ]( U3 J- E$ W; h# }/ {* k7 t- R" X M% {
arrayCenter = [setup.roomDim(1:2)/2;1];
" X7 N& \/ ^$ s8 S; d3 z1 R+ e+ u, |% o! Y: p3 ]( a) x
arrayToSrcDistInt = [1,1];
3 D2 F' l! a* ]
3 O; B2 O3 y; m' N7 l; \6 dsetup.srcPoint = [1.5;1;1];
' v# _) G* c. G' I% z" ?3 G
$ S% O2 J `% I/ s. G! v! {setup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);
) Y) t- j% J1 F7 M: q
* v. I* T* e+ {% Z: j5 b% I6 h, ?. v
[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');$ Y7 ~+ b8 `8 K' _
' G; w2 R8 g4 o) C$ T6 J: M%---------------------------------------------------initial end----------------------------------------
4 ~7 q/ a, R8 v7 g1 t# O. N" t& \+ x4 Z* n. n
9 w+ A; h( k8 o- m6 U9 r9 M) x$ e: @- l/ s
%-------------------------------algorithm processing--------------------------------------------------
3 x: O5 L8 z, o; H$ R! R( ?! J$ }1 `* u3 f, U+ }8 m; O
if setup.reverbTime == 0,
( Y. Q8 \2 g. k, x7 ]2 | setup.reverbTime = 0.2;
2 o$ c; Q X' b, X reflectionOrder = 0;7 x# H. B" I- n* W4 B$ n
else% z7 i. A3 l7 M+ ]; ^1 Q, A4 A
reflectionOrder = -1;
/ O2 K! Q' P7 w) p5 @ p: send
1 w* N: V: L% Y7 j/ @' F6 K( k( p* W+ v/ @
rirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',...
4 M/ E' Q/ T2 U* ^, e8 @ setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);$ D( D( _0 D1 V# A& k/ Y. H
/ E+ P; n ?" I. I2 _: N; q$ u
for iSens = 1:setup.nSensors,
, v3 M2 k' p. f! v* ~9 k tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens, ',cleanSignal);' P4 W! b1 A# ?' w% W& G& j$ s
end% k* R* |, P: {9 Y$ b \) g4 l
mcSignals.clean = tmpCleanSignal(setup.nRirLength:end, ;7 f C* H* T- C" L* m
setup.nSamples = length(mcSignals.clean); K; z e. s! `3 V3 X8 D) {
# J2 c- w) `1 K( T8 a& GmcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);
' B6 P* s; ], B8 W2 Q! J
}6 f7 _/ r4 x3 M( N+ s) g' v%-------produce the microphone recieved clean signals--------------------------------------------- f; O. F- |0 n& g# j
- A8 z% l. \/ b4 J/ O4 w0 E2 R
mic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold' N- a6 x) A# u! f
mic_clean2=10*mcSignals.clean(:,2);
7 D8 F: g1 I' j2 pmic_clean3=10*mcSignals.clean(:,3);
, L% `% @* d+ z' Dmic_clean4=10*mcSignals.clean(:,4);
6 e( w, a+ `# j$ p# m% gaudiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);1 B& |- r- F) a! u+ g) b
audiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);
8 `& B$ ]+ h* n- q& `$ u$ H0 }. Naudiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);
+ m! n" C" ^( u) ^- H+ W# zaudiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);' {0 t0 h" |3 u' Z& ~0 w. U
' U/ V/ u, j) j; a! T* E3 P6 o%----------------------------------end--------------------------------------------------
3 a# r6 p* \7 B% P7 t5 V4 }9 @8 j; N- k- m0 z" K% d9 q
addpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);! H5 T, X8 m1 Y- B% g; C
" j' n2 M& f' K- K9 B" ]" v
cleanSignalPowerMeas = var(mcSignals.clean);( \1 X) f# v7 J" v3 N- U* L
7 z/ ?! n" `" P
, _1 Q& h; s& {& G5 C2 T5 ?
mcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...* }4 z0 K) N1 _) r) s8 c
setup.speedOfSound,setup.noiseField);
1 c, Y: ^9 ~4 z; |diffNoisePowerMeas = var(mcSignals.diffNoise);, H9 {& A0 G: s0 n- y
diffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);& k+ T5 w5 Z* ^# F4 e
mcSignals.diffNoise = mcSignals.diffNoise*...
+ b& I' T6 l. N' ~( \" ]2 ~0 \ diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));
9 B% ?! a* W' w o) |- S( j: D5 x
% N$ W/ N8 A( G0 {mcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);
7 K8 s( i% W& y1 _* S W1 z' y& FsensNoisePowerMeas = var(mcSignals.sensNoise);
) \. ~# I8 d' y; }0 jsensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);
. G# C s. }! u* i4 J' BmcSignals.sensNoise = mcSignals.sensNoise*...0 V+ j5 Q- Y$ j3 A2 u! a
diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));
( `3 ?) o2 d' E/ h( i3 d7 i# s( p: n! I; P. ]! }0 Y, \
mcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;# R: a J9 x! O. l; B: e. O
mcSignals.observed = mcSignals.clean + mcSignals.noise;1 b; c4 W& X9 {
( Q5 Q' r' t+ v, F) ~
%------------------------------processing end-----------------------------------------------------------& H1 k2 Z: _& g' [$ X# l9 \# Y
( `4 E) u8 g& S8 @- c! A$ j! h" y' W
. _* m+ _, F. u# k& q$ K3 {
* N8 Z2 o8 s, Q% g4 ^2 s, @: @, G
: {9 N m8 w; o6 f6 v' ]%----------------produce the noisy speech of MIc in the specific ervironment sets------------------------9 `0 q% o" W2 o. W
0 Y1 u z% ^6 J3 @' u! u8 l" \' Tnoisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold0 t' E) R- F \& O% e: E
noisy_mix2=10*mcSignals.observed(:,2);
7 |) x8 P% N5 |5 ^! C4 Knoisy_mix3=10*mcSignals.observed(:,3);
: y6 }( w# `6 ~4 Q) F$ enoisy_mix4=10*mcSignals.observed(:,4);/ V1 l, B# j u* k
l1=size(noisy_mix1);
* O5 `& ?( o/ C; U& A4 o G9 g) Dl2=size(noisy_mix2);- Z8 V" w: @- |! y
l3=size(noisy_mix3);
& |' Q/ o2 Q9 ], z/ Cl4=size(noisy_mix4);* B2 ]+ R2 ^5 ^3 A7 Z, q! q
audiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);
! ]' {% P8 i) A; U! X& R8 ]0 vaudiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq); f) o2 Z) g6 m3 f
audiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);
% R5 @; w* U! h8 H( d. Daudiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);8 f3 p7 K$ M& l2 {4 ~% G& r
& a' j5 E0 z f) K: y }" ^- C4 K8 S c
%-----------------------------end-------------------------------------------------------------------------( Q/ @% J: E% v& s% S
这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。
0 k! O% X( o- G6 l3 L& d" C) @$ Z' u% m直接把它们替换成你想要处理的音频文件即可。* k: H' M; \5 Z+ T$ u* E
; q" _3 I. _& q0 R {/ G) 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)。
9 R7 ?1 o* t& f$ ]
8 J; Q/ V: P) v3 Q9 y, F7 ], v![]()
2 Z) h% r& |; I; g* Z2 G0 U7 e- N5 e, B( Y5 x7 r
图1 麦克风类型图
2 s+ c* G8 B* y6 [3 @& F$ s![]()
0 Q* @# m. ]2 R% N图二 房间的坐标系
+ ]) k( S, T" K+ z$ q6 y& j5 t
: E; g) B. N" h3 p 以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。
6 t- P! v* D' `7 H1 G! V y————————————————$ T, o4 K H8 s/ a0 H% i1 w% m9 `# _
版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
- `' {* i/ i, J5 j2 t6 y原文链接:https://blog.csdn.net/zhanglu_wind/article/details/79674998" [# S% }/ s+ L
! _8 ^6 a5 K1 h J
. X* [! I0 L2 { |
zan
|