QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3305|回复: 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. 引言% G0 R. g; W, M0 j6 T5 S# D8 i1 [! {
      之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。
    - D: }/ D% e- R4 b' O1 H8 k. v
    3 K5 [) ~' k* v7 a- g  然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。
    5 A& l0 @/ b2 B. @1 V. T# _4 I5 e' z% U, a0 s: A# \; Y
    2. 代码介绍% b+ c& L9 y9 `  g- q' x. J( w% x
      原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:
    4 Z" ~  d$ J" C  Z, E  l1 k4 Hfunction [mcSignals,setup] = multichannelSignalGenerator(setup)
    + ]' w1 c( U: ?) f' c3 c, [. y+ n+ k1 R
    3 @8 r+ ?* q' a& ]$ R
    %------------------------------------------------------------------------ u! w2 N% f; ^8 ^- A. C
    %  Producing the multi_noisy_signals for Mic array Beamforming.; I9 u" [0 q) W) }% x8 @% Q
    % - K& T" x! n) K2 i% F/ S" l
    %  Usage:  multichannelSignalGenerator(setup)
    : B3 W- s$ e4 H3 i" l4 |%         
    : a, S! j6 }) Q" d%        setup.nRirLength : The length of Room Impulse Response Filter
    % i. U, v6 P) W& k%        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default" _( R8 t" R* V6 j2 y' W3 @
    %        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order.
    - R% a5 q& w4 z+ y: d" O%        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.; D3 Z# l1 }1 ~' X( U
    %           
    ! u: {$ C8 T/ ~%        setup.nSensors : The numbers of the Mic4 P$ p7 @" [/ _
    %        setup.sensorDistance : The distance between the adjacent Mics (m)
    " A0 k& C. ^1 J# U* G& C! l' |%        setup.reverbTime : The reverberation time of room/ @1 @; U8 {8 X: b
    %        setup.speedOfSound : sound velocity (m/s)
    5 u1 h0 K3 S. a7 ~%& K+ d& N! H, G, ]0 ?3 w3 b2 V
    %        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'
    ; F4 i& u" F/ S%        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.9 L. j! U- T% @7 e  {' v5 v
    %        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.2 z' ~$ A7 t) h  z9 ]' q) p8 O: w; B
    %
    4 E7 X% p; y4 b) V" F9 F( o%        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).           
    * `8 w' H6 K  M$ S%        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m).
    " S8 f$ V& k/ Y% i6 U9 I%        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m). - _2 \+ g( ^1 }3 Z6 X; H/ R2 b
    %
    ) r" G" X' Y$ }# P( e2 g9 K2 Z%        srcHeight : The height of target audio source4 u) Q/ Z& g2 z+ K$ D' v
    %        arrayHeight : The height of mic array
    8 p6 s4 D" V, H%
      Q% n9 Z. ]2 u" y% `0 z%        arrayCenter : The Center Postion of mic array
    & o- j5 q& j! I0 x1 a%) S, s4 J; ]; T7 d& c+ A
    %        arrayToSrcDistInt :The distance between the array and audio source on the xy axis
    1 y" y* q* ]. S" o6 l9 l3 a" G%  O% l$ B% L9 D# h- x
    %                        " N+ Y/ g) r8 Y7 B) S3 ]% f
    %7 }7 ^8 c& I5 Z
    %8 J; G3 I' P* c, K' G
    %         
    - h( g: E3 t; a' ~( F; B. L3 r%
    8 |; ^" j, X4 s( L. Q%  How To Use : JUST RUN$ \' T3 b# d& |6 c# f1 _8 h
    %6 _, W3 p" B; G4 r
    %  
    " ~  e% Z4 e& L$ r2 z# b& J* V%   0 X; n7 E' n- o  L
    % Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),
    2 ?+ v) \* b4 _1 \: u- o%            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.24
    # }6 |; B) w0 k) M%' C* s* }& \( \4 C3 d
    % Copyright (C) 1989, 1991 Free Software Foundation, Inc.
    , `* u4 m6 ~, b5 O  _3 g  M%-------------------------------------------------------------------------
    : v# \  ~& L+ z2 V7 k/ {
    , _9 [' N$ n2 b7 Z' t$ \9 U- u# F% Y+ k

    . o5 w3 K/ V2 O' j# L+ l. C6 saddpath([cd,'\..\rirGen\']);
    4 ~+ R8 F- x3 i: N, k0 c& T3 w% j' t6 k/ }+ O8 s! @
    %-----------------------------------------------initial parameters-----------------------------------
    ( \8 x/ N; |/ w+ X4 f# z! ^2 U" ?+ y* W% V
    setup.nRirLength = 2048;9 S  b' v7 B" a8 L, {
    setup.hpFilterFlag = 1;- A# p$ a/ Y8 V/ X4 i' s
    setup.reflectionOrder = -1;4 ^: _4 _- N6 E4 Z
    setup.micType = 'omnidirectional';
      ]: d6 @; h7 |8 \+ i( h2 o+ Esetup.nSensors = 4;0 E0 A* D2 @) x) H. h1 J& X
    setup.sensorDistance = 0.05;2 P9 `/ ~/ O+ i7 ^' U( m7 G6 ~  w- |
    setup.reverbTime = 0.1;
    / ~1 R' x3 j5 h5 [4 o  K4 Lsetup.speedOfSound = 340;
    $ I: B: Z+ A: `2 m8 C9 T
    7 K& a/ Z  ^0 Q& g# B( b# Dsetup.noiseField = 'spherical';
    ! ?! y) ~- C. O  r4 wsetup.sdnr = 20;
    " n. P3 ]/ c) hsetup.ssnr = 25;$ a0 C) _' w/ _$ B$ ]' F$ @
    1 }7 Y2 U! X1 L. S8 A' R+ {* D% h
    setup.roomDim = [3;4;3];8 j2 V  k' B  Z  e! N. p+ _
    , ?* m$ D/ |4 Q. l) L7 E8 B- N
    srcHeight = 1;1 B3 _8 u( ?0 I$ }. e
    arrayHeight = 1;/ h3 f5 j# S" m7 R/ i3 @
    " h+ ~) L& b& L: F% ^* k' J( p
    arrayCenter = [setup.roomDim(1:2)/2;1];& B8 m* Y0 }5 }2 e9 U
    , ^+ {* g2 j3 `; ^+ _
    arrayToSrcDistInt = [1,1];
    & q+ h8 M& {% W8 z. u- Y8 L* R- {+ P/ ?+ G  V7 h* q
    setup.srcPoint = [1.5;1;1];
    7 C3 l: m2 f7 P* ]' @! N5 i) X$ g$ Z% ?% _. \8 n
    setup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);, j- R& H  p. V

    ) A3 h0 C- z( M2 X- ?$ l* `# X" y+ w) L& U$ U+ R( K
    [cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');
    . P6 m6 H2 p6 w* n, i7 ]
    . r8 f1 }+ E$ m%---------------------------------------------------initial end----------------------------------------
    9 w6 q# y: x) _+ o$ m+ r9 k) C* ]
    ' L+ P+ T) S8 |" ^$ y/ ]
    ( `9 y+ w5 B1 H8 x# G0 `
    %-------------------------------algorithm processing--------------------------------------------------2 ]9 N+ a5 q* j0 m

    ! S4 j$ {5 R9 o: j1 A( nif setup.reverbTime == 0,! h+ O/ {2 T! S+ T7 Q3 j0 i
        setup.reverbTime = 0.2;
    $ h( b* }: S9 L1 c% j+ P+ K    reflectionOrder = 0;
    9 ?# i: W! ]4 q) F/ b/ B- belse8 D1 x; W- S" L! S$ V
        reflectionOrder = -1;
    . Q& c, \- g6 t6 iend
    : Q0 v- @: v+ P$ V# \' B5 n0 d9 D, u& U/ f) S: ]- m
    rirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',...
    ) k( w% j- S+ k- s- A/ i: B- a, j# A    setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);
    1 |7 Z' T& Y+ d* O1 v6 s
    : J5 J+ ^  A' Qfor iSens = 1:setup.nSensors,
    ! B; T, k0 `& F; Z: F8 R    tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);
    , ~. }- D3 u9 ?end
    ) P: Z7 K; F. d% \: f/ emcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;8 M/ c" Y. }& e( @* s7 r' {
    setup.nSamples = length(mcSignals.clean);$ [0 G! e8 D* W7 i1 D
    % u6 Y! L$ S) d2 Y+ q" A
    mcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);% N( H. W( {" x+ I+ P

    $ \) S- V  n' J%-------produce the microphone recieved clean signals---------------------------------------------
    ; p# \; A, h0 @* S/ h, q: A" x3 C0 |( }4 j' t7 e! c
    mic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold
    / G. S" y/ W3 t1 @( u. Dmic_clean2=10*mcSignals.clean(:,2);' v6 Q7 l# t4 i7 R; m) g+ ]
    mic_clean3=10*mcSignals.clean(:,3);+ _* d3 Z' T1 w
    mic_clean4=10*mcSignals.clean(:,4);' l+ e% {7 u* R7 \2 O6 D: d
    audiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);* m% a( j  x8 m
    audiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);
    . X9 x: g, L  z( S& M) g" qaudiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);
    # B) }6 n) S% H# R+ e8 maudiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);, e$ N: B% Z& [7 [, z8 J# g( f

    + n: G0 ]+ s- N%----------------------------------end--------------------------------------------------! Z0 q$ s  O! T0 J

      V+ Q) m+ J/ \1 ~addpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);3 ]0 W: H6 @' m% j
    + r! R9 B, V: {" @( c- e8 _
    cleanSignalPowerMeas = var(mcSignals.clean);+ p! E% D: c. o: i. w; E

    4 ?# S* D9 z3 S) ~4 T' [& D
    ! ~* P, I# c3 f+ N* r6 `% o& RmcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...
    + [, V) B. C7 }    setup.speedOfSound,setup.noiseField);" T, h& B, }5 \3 j3 u( Q9 `2 ~
    diffNoisePowerMeas = var(mcSignals.diffNoise);
    " c, Y; C2 r6 L0 H" v+ m) f& K" g8 W- fdiffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);
    8 s; K$ s: [/ M$ H2 w  t- GmcSignals.diffNoise = mcSignals.diffNoise*...
    5 p2 A. g! g5 t' y' S    diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));
    ) U! Q" _" g1 C0 F3 Y" B* }
    6 a, f3 D& m# I- V/ {) LmcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);4 Y, k8 d, g* h9 P; `
    sensNoisePowerMeas = var(mcSignals.sensNoise);
    8 c. V$ [# [; r9 ^, q/ Y, \4 o' ?* VsensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);
    + c4 g1 `# h8 a: r) hmcSignals.sensNoise = mcSignals.sensNoise*...5 m9 ^& N# q# y" x1 Z5 G
        diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));
    0 {& }6 V9 P' ~  J4 w, X: w) E
    . s2 i/ U2 G' S& e6 JmcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;
    8 e- T0 M5 ^' Z, QmcSignals.observed = mcSignals.clean + mcSignals.noise;0 y  c8 |6 u2 _1 L  @$ i
    # a- R" k  q8 L
    %------------------------------processing end-----------------------------------------------------------% v3 v6 @, ^) Q+ {4 K* \# y* ^
    ) B1 ?; x7 x! N+ H$ }
    0 k" _2 N, e' J: v

    2 T1 k. d9 S3 N5 N: @2 ~  K) P4 u
    %----------------produce the noisy speech of MIc in the specific ervironment sets------------------------1 ]5 t  \- L7 ?6 r& I: b7 M1 g2 o
    8 c. f( S% ?8 [# N' t
    noisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold9 n6 |2 S5 |. r2 S5 V, c
    noisy_mix2=10*mcSignals.observed(:,2);
    7 f( l  n* R8 V  }9 x  D5 ]noisy_mix3=10*mcSignals.observed(:,3);
    & o2 x: f' S1 ~. V/ P) ~; e3 N0 Knoisy_mix4=10*mcSignals.observed(:,4);
    ( a. h: ]! y. O7 sl1=size(noisy_mix1);
    3 E: }8 d9 E. x. K3 X% Rl2=size(noisy_mix2);
    $ t# n" _6 g; A5 w4 ~: al3=size(noisy_mix3);5 ^( r' m& S1 x8 W% {# i. H
    l4=size(noisy_mix4);8 b" D& k! K& F0 q1 z# l
    audiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);. ]" t7 k$ w8 j3 R
    audiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);
    ' E  z$ w" D) l5 R. ]/ r  Yaudiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);) p. p1 s$ |  c% y' v
    audiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);5 M" K7 G3 M5 g9 q1 N
    / y" L. w5 Y1 b" X5 e4 W

    ) c2 m! n. k/ Q4 u%-----------------------------end-------------------------------------------------------------------------
    / l3 E% Z1 X: m+ S' U9 [这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。
    $ n7 C, K4 S- [  z直接把它们替换成你想要处理的音频文件即可。( f; |+ D7 b  A- e

    % ~+ C4 r5 p5 R1 P  除此之外,还有一些基本实验环境参数设置,包括:麦克风的形状为线性麦克风阵列(该代码只能对线性阵列进行仿真建模,并且还是均匀线性阵列,这个不需要设置);麦克风的类型(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)。
    " i/ ]9 K  j& u0 y" H) P( G% r2 X- ?: q6 P, U
    $ o) M$ h0 C# S+ @( X* F+ s

    ' ?8 ^+ y$ C$ o- N图1 麦克风类型图* Y1 \4 e) K+ r/ e8 P& J

    * C( u5 D3 r  U% a; D$ V. s) @图二 房间的坐标系
    - _/ _! E/ p+ n1 \+ T3 h
    . a+ |. b$ r# G' T( s! E  以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。
    9 g& y' A" J2 B5 r————————————————
    ; V6 Q8 W+ i0 U! C) E( d$ q3 l版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    - N$ p8 V9 p: }% t2 r8 {3 h6 u( Q原文链接:https://blog.csdn.net/zhanglu_wind/article/details/79674998
    ; E, z- _" D4 d6 z; o3 v9 R. r, O% D" j# o

    , X! l. L( r8 D
    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-4-20 11:56 , Processed in 0.311161 second(s), 50 queries .

    回顶部