QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3346|回复: 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. 引言
    $ \$ Z, X( j- B* x1 [" O2 G7 c  之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。3 E4 q1 j0 n9 H: z4 E9 X
    ' G" n' j" G* Q
      然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。* V' ~0 B; J+ j' ~. A" D
    6 a) y8 l, _/ x  W2 ~2 y
    2. 代码介绍
    9 U( [& m4 d  y0 W2 G( v  原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:
    - a* `$ {" m! l7 N2 Ifunction [mcSignals,setup] = multichannelSignalGenerator(setup)
    ; Q4 I5 K: Q& v/ t8 u* H6 _: M. _% V4 W; ~) v) Q2 ?
    ) E! W; S9 ]( d0 u* D3 T! A  _" J
    %-----------------------------------------------------------------------7 _( S( {) k0 i* _
    %  Producing the multi_noisy_signals for Mic array Beamforming.* l: ?+ [% F& d3 {5 o/ }
    %
    1 a( k: C( a: X6 W0 ?3 B%  Usage:  multichannelSignalGenerator(setup)- L) R* m) C: [
    %         
    & h6 G, B) m2 v3 Q# m. s" n9 o%        setup.nRirLength : The length of Room Impulse Response Filter% n1 a! v( h* M) }7 h
    %        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default/ T: H8 _% i$ t- X
    %        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order., s* h+ p3 \: ~
    %        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.
    7 g8 G* {% l7 b%           
    . `0 R+ R4 O; P$ B%        setup.nSensors : The numbers of the Mic& ]0 d( L' E9 U
    %        setup.sensorDistance : The distance between the adjacent Mics (m)
    - f" |0 S: f5 _7 D- ^' u) O%        setup.reverbTime : The reverberation time of room4 W8 m/ t; z, s; }: C
    %        setup.speedOfSound : sound velocity (m/s)
    - x& m$ b; h% n- E%
    " J$ q7 i' j( ~* @%        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'
    ( G& G1 V5 n3 @" W2 A%        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.& y( T& N9 U$ s# \9 T; n  B) X
    %        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.
    ( E/ ]" B( M! H  M% T( v& K8 E# o; ^%8 A0 j! ~) f, h+ G
    %        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).           
    ' g' z8 @9 t; S9 g5 `%        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m).
    ( ?4 |5 E( F- j+ @, q! z. b9 H! z%        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m). # h7 |* {: O% ]8 y' A
    %
    ( r2 l# l) {/ `  ]%        srcHeight : The height of target audio source
    * U! j! _) Z; {) a$ K' \% d1 [%        arrayHeight : The height of mic array
    # {) \; V& ]5 n$ r- P$ _& }0 W%7 y3 h- Z+ P8 l; W" ?- h( a
    %        arrayCenter : The Center Postion of mic array # ^" j5 E) I# \( t7 i
    %
    & t; J- x9 [( d2 u9 C# N, k%        arrayToSrcDistInt :The distance between the array and audio source on the xy axis
    2 g; @  y8 v+ B  S& g/ X8 X3 z%
    9 {2 h6 `$ E2 v# y; m1 L%                        3 o3 W! A  ]1 f' u! J& Z, ]
    %4 d* g9 A& P+ A" O& _
    %3 ]& G7 d* W. k; V+ W( r: v
    %         ; ~, n; c# N% |7 @9 k
    %
    * h0 I" e* k9 d' ^9 B( O5 A3 V%  How To Use : JUST RUN* p- s3 _* w/ e
    %7 W0 h9 F; j2 |
    %  
    8 }! b, h( e  A8 F1 U) x* A%   
    . v& H, Y$ E- [! x4 r3 ~% Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),+ @" x# E& Y& q  p: _7 L
    %            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.248 q) Z; y& r2 v: {+ C0 X5 {+ y$ P
    %2 ^4 e8 s, _6 _
    % Copyright (C) 1989, 1991 Free Software Foundation, Inc.
    ) ?5 z+ ~  w8 e' V$ w/ g%-------------------------------------------------------------------------6 k7 ]" e0 \1 j: L5 w: c1 b
      c# l- n4 m, a% g4 G5 A5 t  o( ^# R
    ' {4 Q3 O* F. ^& r' c

    . E9 {  N$ j1 x; Laddpath([cd,'\..\rirGen\']);1 M2 A7 ]5 Z7 K) t2 o' T6 b. f9 |; ^
    2 Y& [6 Z( }/ g3 s; |; ]* G& i, x
    %-----------------------------------------------initial parameters-----------------------------------
    # F* i5 g8 m# M5 R9 U: `+ \& l! I- d; I
    setup.nRirLength = 2048;
    " O- h8 H* v" z. msetup.hpFilterFlag = 1;" h4 h" `; T# D4 m. g1 n
    setup.reflectionOrder = -1;
    ( q. L0 P. Z- O# s. Zsetup.micType = 'omnidirectional';
    , I( S& }. q8 _setup.nSensors = 4;" D. D) m2 }$ Y) @
    setup.sensorDistance = 0.05;
    1 X' u% B* t) u0 O! S' Nsetup.reverbTime = 0.1;4 w* z( S3 ]5 O' x
    setup.speedOfSound = 340;$ R- t; }2 L$ U! e' `1 T5 k4 _: K* o
    1 @2 b/ P, @1 ?& @3 F  `) k
    setup.noiseField = 'spherical';
    . q8 e! V9 Q. C7 E& Jsetup.sdnr = 20;
    3 z1 s# ?/ B; s% R9 ssetup.ssnr = 25;( ?0 h5 H, E) v6 t' T
    % g3 T6 J* p. Q* O( [3 Y
    setup.roomDim = [3;4;3];/ N, l  h7 C# t1 Y; w+ ]" L, [: K

    9 a* F) }# X2 y( X0 a: q  CsrcHeight = 1;
    * p0 `: ^& ~* ^' L& @# b6 V+ _6 k2 U5 }arrayHeight = 1;6 X# S; l  _2 o9 k+ A

    3 I* w1 `% J( e" g2 U; jarrayCenter = [setup.roomDim(1:2)/2;1];
    ' A8 I" P) y3 B6 H+ u" b2 l8 {/ M0 |( Z$ I4 E
    arrayToSrcDistInt = [1,1];
    - @& ]. e9 n  [. ]" N0 h1 ]3 Q  I6 R- z7 t- ?" ~
    setup.srcPoint = [1.5;1;1];
    & D. u* G. G# b  M) v5 D
    7 _( c; h( d. a% o6 Q' Ssetup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);
    : _3 O. V4 `# m, e: m$ I9 Y/ _% U: u* Z
    . ~8 l# |; m: }! Q+ f3 _2 ?
    [cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');
    , }$ `- ?8 {( j2 i1 e( `- D9 p7 f9 F; n, r$ Y( d$ f) P$ }5 ^
    %---------------------------------------------------initial end----------------------------------------1 E5 D2 |6 v9 p6 N- M- f

    ' v' @' L; k' ]0 P  X9 y
      X( C' c% H3 V$ L1 V
      E, o- `. C# q5 b%-------------------------------algorithm processing--------------------------------------------------
    3 [. J  p! X. K) `$ z, g) n: h( \5 {3 ~1 q& ]
    if setup.reverbTime == 0,
    7 B1 v0 N! K! \4 H! y    setup.reverbTime = 0.2;
    ' A& O4 w7 a4 I) I    reflectionOrder = 0;
      X6 A. F! z- m% `0 o- h* z- lelse1 E# O) Q0 j1 o! _$ M
        reflectionOrder = -1;1 l7 ^7 `5 s6 Q* D7 v1 C
    end
    , X: B5 [3 j; B! H# y% _6 ^! ^1 u) \2 T: b( i9 ?6 @
    rirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',...
    $ v& A+ ~# x  D0 U% x' L7 p& h    setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);- n! D1 D( O( o, ~4 H
    8 \6 i( L7 Z- Z( O
    for iSens = 1:setup.nSensors,$ t; m1 W* I0 I6 U: V& g: B( m
        tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);" b/ w7 G! F* _* Y% R
    end6 k! ?0 ]! C4 T$ @5 S) R* Z! g
    mcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;4 h9 k) U/ G" i' N8 m$ G* o6 [' }
    setup.nSamples = length(mcSignals.clean);
    ( d; d1 |- t7 X, ]* V2 F% _' e' |  ~( p" r
    mcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);
    * k" {# |; M# Q) K! ?4 t" X, E# g
    %-------produce the microphone recieved clean signals---------------------------------------------
    # s& b2 P+ ^' u& q! W/ M
    / L. Y' ?  }$ P* `7 |mic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold( j: d9 T# S- x. n
    mic_clean2=10*mcSignals.clean(:,2);
    5 ?: B& i" m% `# {7 v3 @mic_clean3=10*mcSignals.clean(:,3);
    $ |' T0 r$ T9 f/ \; Q9 h+ wmic_clean4=10*mcSignals.clean(:,4);- X5 o9 i5 x. q4 `
    audiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);
    4 f9 v7 w. U+ m8 H5 u% Saudiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);; ~3 _5 l6 G% v" M" ^+ ^. w6 S" G8 W8 j
    audiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);
    ) U( c4 v0 R1 E  Caudiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);' v3 h. R0 Q0 q/ `4 P

    $ p5 c% r# C: ~7 L8 j%----------------------------------end--------------------------------------------------
    , W: J9 H% @$ d9 _  k$ u3 d$ l
    * K& N. Y7 Y. {addpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);8 ]: J5 p1 f. {& |+ @
    / m7 Z% ]; @: G" d* G7 I
    cleanSignalPowerMeas = var(mcSignals.clean);
    % T* @. D7 u0 B+ P: f) Q4 h
    & R1 h- Z( X, S) t5 f) I7 p" A( `
    - ~# f9 W5 r0 W7 [1 FmcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...
      S/ Q7 v3 J. _2 ?  d1 ~; A2 \    setup.speedOfSound,setup.noiseField);7 X2 ^! _# Z7 a" c5 _0 m' _& H! f! H  K
    diffNoisePowerMeas = var(mcSignals.diffNoise);; [0 n! l1 p+ f
    diffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);
    , ~8 Z* j' o( Z, b  s0 B" nmcSignals.diffNoise = mcSignals.diffNoise*...
    0 s) Z9 n: i% {! ~) ?1 S/ g    diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));
    ' i. J; L! [8 K2 |* x$ M" z+ l( U( j$ [5 Y4 N
    mcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);
    - j9 ]( U% C1 r- h# QsensNoisePowerMeas = var(mcSignals.sensNoise);
    " Q5 g5 v0 z- ~- b1 TsensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);
    - J1 p8 V4 p+ t) j: e* ]mcSignals.sensNoise = mcSignals.sensNoise*...
    1 {; T. ]4 R/ ?0 d  M# Y, j3 s    diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));
    % K% |8 s6 {2 s, M  {; |: m+ A% p/ }9 S- L8 v
    mcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;
    1 }7 m) N5 G+ ]. j9 _mcSignals.observed = mcSignals.clean + mcSignals.noise;  N* ?& Q$ _2 i
    ( f/ u' T9 t: l$ p1 y
    %------------------------------processing end-----------------------------------------------------------8 k) i0 d! P8 w+ l0 R  }
    # j0 w: b2 Y: [# f9 A

    - j5 h. ?$ P# J/ H* R1 x! \5 k* D, ]* }( N3 x" u; L* u2 T
    # q8 g/ H' E: o# b& Y, \1 }
    %----------------produce the noisy speech of MIc in the specific ervironment sets------------------------
    + i2 y- z+ O& o
    $ j. _7 U: U9 p4 l: e8 a# ^& knoisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold( ^. J" j6 p. F0 m6 d
    noisy_mix2=10*mcSignals.observed(:,2);6 H, g  Z: t0 p, `  Q) N# |
    noisy_mix3=10*mcSignals.observed(:,3);
    & i) s: N. }& u& Unoisy_mix4=10*mcSignals.observed(:,4);
    ! E) i! h- w9 k% k! Y- p& ~4 z, ql1=size(noisy_mix1);6 _5 y; V9 E1 O9 r" w1 [
    l2=size(noisy_mix2);
    $ F7 y4 C3 ?! G, }( |l3=size(noisy_mix3);2 D) I+ ]+ X; s/ F8 K( U
    l4=size(noisy_mix4);
    . h4 p. E* g& Y" ]' maudiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);
    * o; `+ ~/ T5 T& E( T+ xaudiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);
    - H$ T/ T& [/ Waudiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);
    0 ~- a4 Z9 z! T* V" G- B% f7 l7 q) haudiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);5 ]/ @$ e& s) i7 q) \

    ' R/ I9 O3 {! `" c' `9 S- ~& n/ m" l1 Z$ u2 O, D2 R9 `9 N
    %-----------------------------end-------------------------------------------------------------------------
    / F) [& \' ]: d5 u) B! r5 y' J这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。* b$ x$ ?$ l" j+ s/ f% p3 H* P
    直接把它们替换成你想要处理的音频文件即可。
    - d1 q- h" G1 p5 s0 W9 i5 t3 Q- P: S  [- w# U, _+ ~) I( Q
      除此之外,还有一些基本实验环境参数设置,包括:麦克风的形状为线性麦克风阵列(该代码只能对线性阵列进行仿真建模,并且还是均匀线性阵列,这个不需要设置);麦克风的类型(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)。* V7 g' f& A0 R+ G  E/ u: g+ t2 q

    $ u( f$ \. G# W# [+ M
    ' D6 n* E- s0 A- |2 z  w6 ~4 m
    / q( M9 n! R5 Y1 Z9 E图1 麦克风类型图
    / c* K5 u2 ~$ ?6 H3 W. m0 [1 b. s3 O  s7 `1 r+ _: y& B# W
    图二 房间的坐标系
    . u+ _# Q' A  y1 T, |4 p8 G: `  y6 O, V
      以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。* W% {) G% {# [9 _: p% B( o. `
    ————————————————! D2 R7 L0 d: ?, t# ?
    版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    7 u$ ?' W6 P( T" f原文链接:https://blog.csdn.net/zhanglu_wind/article/details/79674998+ P/ c6 {" ~6 X( ~4 P7 }6 Q

    1 ?' d2 f, m& a8 Z0 P. @+ U* g0 n& p1 T% o, W' J- z+ d" P% G
    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-15 21:33 , Processed in 0.713247 second(s), 50 queries .

    回顶部