QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3337|回复: 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. 引言
    - m. k7 V) A. N9 Z/ f  之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。& S- U( p0 x6 o

    : v# Q8 U) T3 [7 `6 I  然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。- c/ W) s1 e2 J" K; G. l1 t

    2 }1 ^8 P% {7 [% k! h2. 代码介绍' C: x$ {. r' C6 u8 t
      原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:
    ; Y3 Y/ W) ~) Q3 p, M5 S, [$ gfunction [mcSignals,setup] = multichannelSignalGenerator(setup)2 y7 l' X' d- i# a0 l8 B+ q
    4 l& i; M, g5 l! B# h

    : y( `# |# U2 g5 {%-----------------------------------------------------------------------" o# u2 e5 B6 X9 n& |  L( ]" g
    %  Producing the multi_noisy_signals for Mic array Beamforming.
    6 i0 R* q' N* G0 j% }9 g8 H" u% ; F% F& T: C* z% o( R! E& I3 {6 W- v
    %  Usage:  multichannelSignalGenerator(setup)
    7 {9 ?0 n# F- n9 F%         * \2 W2 ], S2 H7 n) U8 ?4 |
    %        setup.nRirLength : The length of Room Impulse Response Filter
    , Y  Y9 e% h) l0 {! p  j5 e( F%        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default$ y6 k  S7 p# t% L  T
    %        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order.
    0 N0 P5 @) [' J$ L: D/ Y* \1 D- v2 o# i% `%        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.
    - |/ f4 P4 V( q%           
    , z8 j9 s! q/ ^! y$ Z. a, n%        setup.nSensors : The numbers of the Mic0 J/ u" _7 {0 }* i. N- T7 ]0 j
    %        setup.sensorDistance : The distance between the adjacent Mics (m)
    0 F+ ^5 C0 s( F%        setup.reverbTime : The reverberation time of room4 ]5 Z  t# R9 S' Y/ L' Y
    %        setup.speedOfSound : sound velocity (m/s)
    ) C$ ^7 |; M# y: o%
    , E$ N2 y* A) D9 B+ A; C%        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'+ S1 F) U; m, p5 K
    %        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.' V  r, i) v6 u
    %        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.
    : V% l$ v1 M6 n9 x%
    ) K9 z/ y' o5 w%        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).           & N- W& b2 l2 m) j
    %        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m). 4 W4 t, M2 f1 B
    %        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m). " l  G( }, K% o" q
    %- }7 B# u$ l2 N. y+ P0 h
    %        srcHeight : The height of target audio source
    & F6 ~* ~, [. l0 I; d%        arrayHeight : The height of mic array
    8 T+ r9 F7 K  L1 E%8 ]# V& J2 u* {1 M6 |0 f
    %        arrayCenter : The Center Postion of mic array
    6 I0 g( d/ w: g$ u- N%) N2 \: J8 H% T3 _" @" ?& j- Q
    %        arrayToSrcDistInt :The distance between the array and audio source on the xy axis1 ^" Z& c. U  u1 Y
    %2 b1 h# {" N! j/ \) {7 ~3 [, ~2 _
    %                        , }" ?0 p2 F; I; @* ?* |: |6 w/ j
    %
    ; S6 d4 {. J- a/ P3 E1 I& L5 M% Y7 Y%
    * m1 H4 ?" ^. y  [6 H3 K9 p! V%         
    , b; E4 t) i& v%
    5 j( v6 O. M& `; D%  How To Use : JUST RUN
    1 ?( V2 q5 D+ W4 h- A; i%
    2 b+ G7 B* h+ e3 R! H. i%  1 R" d  \7 {* [! z& c. j
    %   , b. a) P+ n- l+ q. k
    % Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),
    ! W* w/ Y( w6 C2 @3 y%            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.24: i& W, t/ D$ v1 }. E; B: a
    %) y9 A7 {" x" `. j3 h
    % Copyright (C) 1989, 1991 Free Software Foundation, Inc.
    0 |( v. c8 G: G; C& H8 C5 B%-------------------------------------------------------------------------
    8 r+ B9 r8 x" f8 K. }) Y  }3 W9 C! V2 a3 g0 J3 k9 `

    8 F4 a( z1 v8 Z2 U! I$ N3 ?4 i1 [) }4 V$ o9 m2 F, f1 U6 N) l1 Q
    addpath([cd,'\..\rirGen\']);6 E( K: @% a5 q* t

    - k( ^/ x/ [& }; l%-----------------------------------------------initial parameters-----------------------------------0 o8 h7 A, g. \1 N5 U) z1 K0 I4 V
    ) x) U, ]) V1 B, o3 o. a; [) `6 ]
    setup.nRirLength = 2048;
    * j/ R% H% h& l3 }setup.hpFilterFlag = 1;
    - ~; i9 X$ ]6 s% @2 X. P* Y/ T) tsetup.reflectionOrder = -1;
    $ _4 y1 O6 u# ^setup.micType = 'omnidirectional';4 h( ]. E* e/ m
    setup.nSensors = 4;
    2 W5 }7 H4 e- e- ^setup.sensorDistance = 0.05;
      y& e1 G3 f$ @. Y/ F1 Jsetup.reverbTime = 0.1;$ ]! c1 r' l6 F: O
    setup.speedOfSound = 340;
    - e# u- K% t4 y. ~" t0 Q6 [$ g% Z$ D
    setup.noiseField = 'spherical';; w; j! y( w, Q, K- [/ [
    setup.sdnr = 20;) I& P3 p6 ^$ y" S* a0 o8 e
    setup.ssnr = 25;
    - W5 g8 W5 j" p0 n. Q
    ! n; _" k! U  d/ G: M) r* dsetup.roomDim = [3;4;3];. Q% O! [7 o; h. b9 D

    , n+ j/ k; k2 w+ U, jsrcHeight = 1;+ E( m: i0 C6 Z% f. C% d; T
    arrayHeight = 1;
    % Z1 l1 o$ ]+ v3 `
    ( x! C  ?& Y4 G! ^# k! EarrayCenter = [setup.roomDim(1:2)/2;1];
    " @* \3 {3 C* X5 O- `& Y6 E0 m8 t8 x
    arrayToSrcDistInt = [1,1];& i+ y* Y8 w2 Z$ {

    $ d6 `3 G! ~% O, ~setup.srcPoint = [1.5;1;1];! q/ G6 R. e' G2 K# J1 z
    ' H/ Z3 G( s2 Q/ t1 ]+ |5 l$ [
    setup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);, t( c8 j* X) H; X9 f% c
    # k- e* }" P! d  v: o. n
    3 c) y& P( N+ ?5 h
    [cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');
    8 C# d9 r  Y8 W# C* t( k9 G* m& O* Y, K4 `+ x4 Q  z) m
    %---------------------------------------------------initial end----------------------------------------
    " ^8 b7 X$ h/ g; ^- i2 g
    5 J) s9 l8 K* }: z. X: Q& Z/ e/ P) F! q4 }
    ! V$ Y! R8 q8 ]$ a& d
    %-------------------------------algorithm processing--------------------------------------------------3 ~" s$ \5 O) a  b
    . H7 K( P# j2 ~# x! }0 C
    if setup.reverbTime == 0,
    + {. z9 O" \4 m5 ~! \. e, I, b    setup.reverbTime = 0.2;
    9 ~2 n. I3 v7 w" ]- O8 U    reflectionOrder = 0;5 V  B# C4 j% V% [( v
    else
    8 d* A4 p4 O' W4 W    reflectionOrder = -1;7 l7 @! v5 [4 j7 C$ ]) l
    end
    ; L8 n  H& @6 b/ N
    0 d6 o. c  u8 y, x% ]1 L7 ]! xrirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',...
    # w. V% v( F' z+ r! O2 b    setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);
    9 W& b6 ~# o+ h: p8 o# F
    % D/ Q4 o8 g) }for iSens = 1:setup.nSensors,
    ! p# y( a! B8 [$ M    tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);7 M# o4 j& X+ I5 [9 J9 d! w) g
    end
    8 b3 p, h# W" ?9 Y2 G6 Y2 ?mcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;; Q8 K" g1 f% `  R- F% z! [" R2 J
    setup.nSamples = length(mcSignals.clean);
    * J. S. o2 Z4 u5 R
    ! z3 h8 C9 n% v+ ?* UmcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);
    ; w& a( f" Q8 u* o1 W% f5 A# o
    ! k# m  w7 k: u8 m. A%-------produce the microphone recieved clean signals---------------------------------------------% v: t4 o9 a6 P4 \' b* D
    0 Z9 P4 i' f. f( i
    mic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold
    ' m' X5 q5 l% ~/ o. U. B: nmic_clean2=10*mcSignals.clean(:,2);
    $ O& k- R  S0 y1 ~+ @& i9 K, Qmic_clean3=10*mcSignals.clean(:,3);+ L& g9 z2 l( y
    mic_clean4=10*mcSignals.clean(:,4);
    * x2 @+ b' J; Y9 A( C1 g& [6 Y7 Laudiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);
    # x! y( c; e- {) f+ paudiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);
    7 @0 ]$ c6 \3 ?+ d6 ^, w! L( jaudiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);
    " s; m8 n$ P4 p# t- v1 I' taudiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);
      I4 B- ?0 y, m6 u( P- _( x3 e. o" _
    %----------------------------------end--------------------------------------------------
    3 U& M8 O/ L& m' T" n
    4 ~/ |: U$ }  P: w2 _: Oaddpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);- \3 m, C$ R, A* Z$ A
    6 _% Q  v+ J/ r2 j2 L
    cleanSignalPowerMeas = var(mcSignals.clean);; |+ d& \! G* k2 k# q
    $ K6 y/ i- R7 Z- I* X
      x  I  G6 T" Q" F
    mcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...
    / E4 l" Z  O% u# K" t    setup.speedOfSound,setup.noiseField);
    ) Y, _# V# T3 E/ x( i  @% Y8 OdiffNoisePowerMeas = var(mcSignals.diffNoise);" ^% ?+ L# M' e4 h: `7 a
    diffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);' Y/ Z+ F' ^5 n1 u: V3 q+ e$ c
    mcSignals.diffNoise = mcSignals.diffNoise*.../ ]- c9 ?1 Q, Q1 J9 l  N- J
        diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));
    . {+ }  p1 c8 \  J) e/ O7 i1 S) E, a" I& H) L
    mcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);+ T) _, k3 C1 I9 p! B& K, A- H% h- Z
    sensNoisePowerMeas = var(mcSignals.sensNoise);
    2 Y4 L' E' N& x  L/ Q3 S: {! x: psensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);
    9 h& r+ k" c5 qmcSignals.sensNoise = mcSignals.sensNoise*...# K$ l+ x, d- `
        diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));+ M% f/ m* |) q' N4 H
    ; n7 E( u* y( N. H, M+ S
    mcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;
      m; e+ O, E4 R8 L+ SmcSignals.observed = mcSignals.clean + mcSignals.noise;
    9 {1 e' p3 G5 F$ v0 Z9 H7 A6 T* j
    %------------------------------processing end-----------------------------------------------------------
    7 L: x. A3 R4 k6 ?
    7 H7 G& ?8 Z- L$ A3 B8 [" T2 C
    5 X4 N$ _7 ~! _; P9 f. u% p+ J
    8 E6 p8 |: c5 l  z* m1 y' \
    %----------------produce the noisy speech of MIc in the specific ervironment sets------------------------$ {6 E) V. `; Y" I% A  i

    + O6 F7 `! o! D9 O  b& ]noisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold, \' p. R% a& b. [# z% h6 m4 n9 D
    noisy_mix2=10*mcSignals.observed(:,2);
    0 _6 v! L  q' L+ Rnoisy_mix3=10*mcSignals.observed(:,3);5 ]2 t0 |( H  f% f& p+ s
    noisy_mix4=10*mcSignals.observed(:,4);4 W+ c% b, [7 L
    l1=size(noisy_mix1);6 f! m% a/ g* p& h/ Y' e( H8 y
    l2=size(noisy_mix2);( U% {1 L$ v  Z
    l3=size(noisy_mix3);
    1 S, U* H: Z, Z& l  d' u8 k( Tl4=size(noisy_mix4);+ _9 Y; d' j) b# p
    audiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);
    4 M- N8 u% w2 f. I3 Taudiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);
    # p/ X: \9 f: x3 e9 q' j" @' \5 Kaudiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);
    $ E( j( a, E( _; ~: i( Uaudiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);
    8 c* y% _. ^( Y7 o. M$ u* `
    5 a6 ]9 r- E* A5 Y8 p$ `
    6 Q. O% M# X1 O4 G7 P& @%-----------------------------end-------------------------------------------------------------------------  G* E$ e; H1 O7 `0 S! Q7 r
    这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。
    & d$ J: q. X$ ^+ h9 i直接把它们替换成你想要处理的音频文件即可。( h6 Q0 g* ^, M  s- h

    3 |5 ?* m' h( w0 |7 i  除此之外,还有一些基本实验环境参数设置,包括:麦克风的形状为线性麦克风阵列(该代码只能对线性阵列进行仿真建模,并且还是均匀线性阵列,这个不需要设置);麦克风的类型(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)。
    $ x, N. @# s# `. q9 y4 O6 n5 I' f) t

    ) f8 ^, [' s. Q! p
    ) F& a: Y/ E, B0 q* c图1 麦克风类型图* Y6 j+ a6 w* s$ B- a: C

    3 ~0 o& Z3 m" G$ m图二 房间的坐标系9 G8 T- _! v0 m% m
    / s- D2 C2 i5 H
      以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。
    / ]% F5 A6 C  t* y————————————————7 U9 l- Z& {7 s. s+ n  f; O
    版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    . O/ Z& O4 y8 A  b0 {7 ^原文链接:https://blog.csdn.net/zhanglu_wind/article/details/796749982 h9 h2 E1 w, J. f# P

    ! x1 W7 Z4 o  {0 C
    ! O0 l  o) f4 i! S! ~
    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-6-9 18:33 , Processed in 1.664362 second(s), 51 queries .

    回顶部