QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3397|回复: 0
打印 上一主题 下一主题

麦克风阵列仿真环境的搭建

[复制链接]
字体大小: 正常 放大
浅夏110 实名认证       

542

主题

15

听众

1万

积分

  • TA的每日心情
    开心
    2020-11-14 17:15
  • 签到天数: 74 天

    [LV.6]常住居民II

    邮箱绑定达人

    群组2019美赛冲刺课程

    群组站长地区赛培训

    群组2019考研数学 桃子老师

    群组2018教师培训(呼伦贝

    群组2019考研数学 站长系列

    跳转到指定楼层
    1#
    发表于 2020-5-15 15:10 |只看该作者 |正序浏览
    |招呼Ta 关注Ta |邮箱已经成功绑定
    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
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信
    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2026-9-10 22:22 , Processed in 2.273729 second(s), 52 queries .

    回顶部