- 在线时间
- 791 小时
- 最后登录
- 2022-11-28
- 注册时间
- 2017-6-12
- 听众数
- 15
- 收听数
- 0
- 能力
- 120 分
- 体力
- 36450 点
- 威望
- 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. 引言
( e' X% P$ n+ t 之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。
6 l8 h- N3 g7 C# v0 v0 `, e+ C9 L/ s7 F
然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。2 R# S# d$ A0 b7 l0 O
/ E4 Z$ ~4 o" [. @/ ]7 c2. 代码介绍/ n- ?0 h; S) e/ w! {
原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:
, |! e$ X+ U* n3 J: A# R7 Nfunction [mcSignals,setup] = multichannelSignalGenerator(setup)
& K+ L7 x- g* |! k1 b3 x9 b5 g. @. I( `5 z9 h) A* C/ x% Y
7 |- }& c, \- i/ d% a+ u# t%-----------------------------------------------------------------------1 y5 T( V7 b- f# g
% Producing the multi_noisy_signals for Mic array Beamforming.
1 G0 N- N7 E% K$ {5 }2 g2 m% : X% w) T1 R) s! ^+ H; G
% Usage: multichannelSignalGenerator(setup)
: b8 v/ l0 ?3 g%
8 q; j6 }. Y7 \2 N$ x, H% \. ~% setup.nRirLength : The length of Room Impulse Response Filter" m/ L- c( X! b) D$ r
% setup.hpFilterFlag : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default) o$ B- R$ `2 M) b
% setup.reflectionOrder : reflection order, default is -1, i.e. maximum order.5 y) @9 _# ?. j% \- K- ?8 b$ Z) v7 }
% setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.% k6 m/ N2 }6 `! r5 ]) I
%
. P( e4 ~+ b! x1 b% setup.nSensors : The numbers of the Mic" w0 m( r' v2 g
% setup.sensorDistance : The distance between the adjacent Mics (m)! x7 V9 k. l3 u% c- ?$ d
% setup.reverbTime : The reverberation time of room
; }% q) O9 p. F5 N4 @ a$ g1 u% setup.speedOfSound : sound velocity (m/s)! [0 o: ], E5 i- P6 d/ S
%
$ e: {1 X( z: G) w# N; u$ O4 e3 C% setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'1 T; g6 R7 P/ e% \/ }% J# F* U
% setup.sdnr : The target mixing snr for diffuse noise and clean siganl." S6 N4 N: J* p8 x- S5 l: {6 h( A
% setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.: @5 O6 I- N, G% f, s4 k# ]& b. {/ Y
%$ F7 x; ?7 c* w. a! {
% setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).
) F/ S! B/ [ Y R; ]% setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m). - h5 W2 P( r# e! `
% setup.srcPoint : 3 x M array, the rows specifying the (x,y,z) coordinates of the audio source postion (m).
+ l1 b, G$ Q( I- l%7 p) z' Z$ R4 M0 N7 X1 w/ W
% srcHeight : The height of target audio source
* I ~4 k0 Q, c+ d4 C% arrayHeight : The height of mic array9 R& [! v, b5 ^0 b" N
%, E- g0 }, O# h$ A& a1 u( L* q
% arrayCenter : The Center Postion of mic array
0 x# {2 c) v j2 B" Z E%
1 U2 p( { c- |3 Y% g. Z% arrayToSrcDistInt :The distance between the array and audio source on the xy axis! ~4 y+ }6 v: @ E( H# z
%
$ v) y: C6 L# `% c% 5 \ C' w$ R( g! L! z1 u+ j- ~; M: n3 f
%$ z2 y1 \% H# b3 _
%
( A9 B2 \& @( R% s* x9 p3 _8 R% % V: m3 D/ n, j7 y
%$ T: [' i9 S$ x
% How To Use : JUST RUN: w3 g; \1 `7 H8 @+ N
%7 a* b/ u5 V0 b3 _9 X8 l2 T
% ) g2 ^% O1 ^, m# i% w
% ; f( d! }- b( a: V( {
% Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),
& g4 X: k9 |. l# B3 \% K8 k5 q% slightly modified by Wind at Harbin Institute of Technology, Shenzhen, in 2018.3.24
- L9 z- L3 U4 r# h( X; @+ K5 z%
$ {& @0 d+ b0 g% Copyright (C) 1989, 1991 Free Software Foundation, Inc.3 h& r4 `7 U( j( k, S5 v; k
%-------------------------------------------------------------------------
- L3 w3 H" ?' V) x% s8 [2 m* m0 t1 e. @! S
' f8 y$ A& o7 `: R! C5 q" y- O* w8 H9 D2 q9 X) U& K4 {+ s
addpath([cd,'\..\rirGen\']);+ M! P# F5 f! P# u4 u0 j
' o% V7 V: y' R# P' { W# R9 t) C9 E%-----------------------------------------------initial parameters-----------------------------------
# G+ N6 Z) U' A# W j: o6 ]
9 [) v8 ^4 p: d) u! b; isetup.nRirLength = 2048;
" F; L9 W) w$ p- t9 \# Z: wsetup.hpFilterFlag = 1;+ b% N5 F! ?; N: ]# S
setup.reflectionOrder = -1;2 {$ j# h6 S8 s# D( c) A4 k
setup.micType = 'omnidirectional';9 ~1 C& \6 f, d2 P- W
setup.nSensors = 4;$ E2 V) b% I9 z! D0 ^, g J% ] |
setup.sensorDistance = 0.05;
9 m+ a; G( A7 tsetup.reverbTime = 0.1; a$ J; d, |. e2 \ k2 R% W: h
setup.speedOfSound = 340;; _7 h9 x1 T. Y1 [( ~4 q6 w
) V$ B& k3 ^) a$ q" P( ^0 M+ C6 Osetup.noiseField = 'spherical';7 ?4 o( Y* f' G: I, P+ k$ q9 S
setup.sdnr = 20;' o- c9 q5 z3 f8 b( B+ { ] Z
setup.ssnr = 25;* @5 D: s, `- n/ E
. U' h' P- V. z7 J! d# s7 V* @setup.roomDim = [3;4;3];$ P" v/ S, v6 s& G8 @ ~( W" q- M
- w. X% E1 A3 h' ?4 j, v0 i$ o) v+ z( SsrcHeight = 1;
. H" ~( y& z; `% `, ^% parrayHeight = 1;
o( x9 k4 F6 F6 V( z% c* I
1 s+ ~: @ ~3 p/ G+ n! r( U( l' D* tarrayCenter = [setup.roomDim(1:2)/2;1];1 v8 q; ^5 [: t3 k
% j3 t$ c1 v0 K/ m/ A; j
arrayToSrcDistInt = [1,1];
% k, y: j( h- D8 K. j% H$ |$ r# d8 c3 Y; O: B
setup.srcPoint = [1.5;1;1];
- o0 i0 k$ ]( H
, Z) q: ~: P- u% U+ p% k, o2 Esetup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);
9 S( q: z( i4 Z4 C3 d. m+ W
4 X9 M0 D0 w, y; m
* }* L; I6 }) b1 q[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');
/ `3 w5 s& ~& `% H6 o) p* V& u; I& A8 ^
; P2 o5 y$ v8 Y5 x$ H%---------------------------------------------------initial end----------------------------------------1 q$ {$ P! c8 a% f$ h
* e5 \" @( I& K8 l* u: y: X
( N- A& }4 @: p; S& p
0 J n- ]( [; Y- [- r5 F& x+ h% c
%-------------------------------algorithm processing--------------------------------------------------
1 R9 z, `7 r: {' o( B: v
' Q- Q) y; }2 C, d. c6 i7 tif setup.reverbTime == 0,6 J8 W7 l: v- s {# V; k
setup.reverbTime = 0.2;) W: ]% t D) s2 E; M
reflectionOrder = 0;4 K: m- {% [; i; H: E
else6 h( s% S. S' g1 ?
reflectionOrder = -1;# h4 g$ ]. ~" O, I
end$ R4 l3 @3 u" V- \
1 R* S0 ]# W% D* UrirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',...) y: W: q; W# Q8 X) v7 H
setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);
2 M9 _9 I( j2 k6 G" i3 {
+ e# g) z( D2 |& a1 ?, M* H; Afor iSens = 1:setup.nSensors,
. H: n" J9 V# t: d" Q* Q/ N tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens, ',cleanSignal);
& k; t9 u) O5 p' w8 H6 T! Kend
2 _, s& R8 U' C: g' vmcSignals.clean = tmpCleanSignal(setup.nRirLength:end, ;
2 I6 R; z2 Q0 [2 d/ {, ~setup.nSamples = length(mcSignals.clean);
* X8 ^+ _' w% {: s# R4 H2 ]% [* ?7 b, _( w# J, J/ ?
mcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);
/ R2 z2 L' m& F. E6 ]7 f7 C% ^! |+ ?7 M7 b5 j8 j% U$ I
%-------produce the microphone recieved clean signals---------------------------------------------: Z0 f( Y0 H) r& a3 N
, r9 Q s& R& \3 {/ i4 X
mic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold
4 I. T4 L: o! r7 S/ |mic_clean2=10*mcSignals.clean(:,2);
' _2 } H& C* r& d/ f1 Hmic_clean3=10*mcSignals.clean(:,3);
G+ ?& c' X- n$ Umic_clean4=10*mcSignals.clean(:,4);5 H7 k% N& j C, j4 ?' B
audiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);% h1 ^: _! p5 t
audiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);; V' \0 F9 C* s% x H- G$ Q5 m) P* F
audiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);
, f; b4 k. q9 p. j5 z I4 zaudiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);
; \2 k8 }" h! ?. i' O- _" I
, }3 x! O. P2 b' u3 z%----------------------------------end--------------------------------------------------
4 B; x5 ?$ B' X4 c" k; D9 q& x+ N! l& e8 l6 f4 I4 I
addpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);7 ^" ~$ S6 k8 p& j2 [3 J
, N8 j3 ?. o5 U4 g3 ~! ^7 B- Q7 C
cleanSignalPowerMeas = var(mcSignals.clean);7 v/ x& _8 n' T: v- b5 ]( c
' |0 w7 A+ s4 }! @4 a
; Y. C( U3 h% Y. ]! G, f9 K! w3 f
mcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...0 ]. d$ A* s7 A1 }/ Y- D
setup.speedOfSound,setup.noiseField);7 P2 I2 ~* B# c. L
diffNoisePowerMeas = var(mcSignals.diffNoise);
" Z) ~" u8 n/ n0 m0 CdiffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);
1 G. {, [, @1 b+ F e- p; L% H0 CmcSignals.diffNoise = mcSignals.diffNoise*...
/ f4 I! Z+ [* b4 [ diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));9 F4 ?- d5 s/ T# k: Y$ m4 S: T4 b0 P
/ Q# d$ Q# z3 v+ k2 Q" `mcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);
) {- L( ~1 K$ n5 {7 t2 X5 Z+ psensNoisePowerMeas = var(mcSignals.sensNoise);
$ _: O: P Q& f4 z( JsensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10); _5 t3 X1 w1 p
mcSignals.sensNoise = mcSignals.sensNoise*...; I5 s# Y4 ~+ [: r
diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas)); |, t1 A6 G' `& ~- }
% S5 y3 M- f ?# W& ]
mcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;; y% g% M# @ y6 q" a
mcSignals.observed = mcSignals.clean + mcSignals.noise;6 O3 Q1 t9 l, _- G) V
5 y& c) y. T2 `%------------------------------processing end-----------------------------------------------------------" B) I( G8 `) i$ V; A
2 X% j% Z# M4 p# q4 O! p0 }% D) S- ]
3 p( T4 i9 B# y0 k) V" m/ V# p* c- E4 n, x& h' G9 x2 P+ H
T' s1 _& ]2 x0 v# Q6 p%----------------produce the noisy speech of MIc in the specific ervironment sets------------------------' H" c% M. W% X
: e1 Z& H+ h& }2 _4 p4 j2 l/ snoisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold
! k9 Y* x3 Y. }7 U, ~! Qnoisy_mix2=10*mcSignals.observed(:,2);
. j5 c. u; W8 G# J3 A' n( @6 D) f5 b3 Ynoisy_mix3=10*mcSignals.observed(:,3);
M4 z2 {& L5 E- {1 Gnoisy_mix4=10*mcSignals.observed(:,4);: S' q# J/ H7 H2 z' P! D2 n4 q) ^
l1=size(noisy_mix1);
" j) Z6 J" Q& g( Sl2=size(noisy_mix2);( ^+ `. D! }6 }1 J
l3=size(noisy_mix3);7 e+ a) v* c; `* U# ^
l4=size(noisy_mix4);7 `) u$ s3 \2 H1 _. [
audiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);
! \5 q! U" X% u5 x8 p. {$ N) ?audiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);
9 o0 A% n. S* O7 c, l- | w& B, Q& Vaudiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);4 D+ {0 j' i7 b1 |& t! p' d* [9 H
audiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);
, ^2 \; R2 V+ L
" A$ u0 H7 [6 l2 O0 L) F) y A$ R \7 |
%-----------------------------end-------------------------------------------------------------------------
; ?1 B- ]2 t& J/ ?& \- m这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。; Q2 K0 s1 k1 ^
直接把它们替换成你想要处理的音频文件即可。% z! f1 b6 `7 m
0 @# @) G4 `! 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)。6 \. ^' |2 ~ I, c( o
2 z4 K/ a, [& m# G m2 w2 t- J4 s$ ~8 _ B) L1 q: q
8 i' K' ?0 }' N" \ o1 W* W
图1 麦克风类型图
4 m6 V- N% A/ ]; A ( E, Y7 Z* I; k" Y( T
图二 房间的坐标系4 ]3 I/ Z& {) ~" B7 b5 o
8 Y g; v" d3 Z 以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。
& C8 h* u, y* V/ B7 ~. X————————————————
, p' I' b. G& ?0 A3 h& c版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。8 D+ {7 w5 j7 [
原文链接:https://blog.csdn.net/zhanglu_wind/article/details/79674998
, {1 P; c5 j1 B; m+ U
$ v% l; p N* ^9 l* |; N7 K) O4 x8 V
|
zan
|