QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 2059|回复: 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. 引言
      P5 v# Q8 q5 j: o/ y: [) c; \  之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。
    % M4 q1 [4 n9 f. f0 X
    1 y9 d* U2 E3 \- a  然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。0 S0 ^' V  `6 w" ]; |
    8 a7 E- i" Z( M: b6 }! K8 V, I
    2. 代码介绍
      w' S+ G$ T" `" K# k  e  原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:8 [1 G( r' j+ f% C! b1 v) L$ K
    function [mcSignals,setup] = multichannelSignalGenerator(setup)
    $ u) r$ A/ n* {+ ?. Z
    + l( q9 J& u3 G6 ^$ B
    . E, [" L3 _) L. g% E%-----------------------------------------------------------------------7 A" u6 \! G$ ?; v
    %  Producing the multi_noisy_signals for Mic array Beamforming.) h: J$ V% L8 m1 G
    %
    " m) p  M6 U1 |& T; V%  Usage:  multichannelSignalGenerator(setup), \2 Y  G' h: C4 M& k
    %         
    , ~* M- b; c5 ^5 b4 J%        setup.nRirLength : The length of Room Impulse Response Filter
    " Y; W# l+ c3 x" C, c%        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default
    7 x! ~0 H; t, Z' C  F%        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order.9 E$ ~. |2 P6 V+ [
    %        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.
    ' Z( ^8 `+ ~7 _2 V%           
    5 h; w  q( d: M: ?7 J%        setup.nSensors : The numbers of the Mic
    % Y1 b. b# r, w. n( r/ U# }  Y%        setup.sensorDistance : The distance between the adjacent Mics (m)- i5 c/ [" |4 _8 V0 y( s- P
    %        setup.reverbTime : The reverberation time of room
    : x" Y% x( j! X1 ~%        setup.speedOfSound : sound velocity (m/s)
    ; F- p( m9 }% c$ J9 b# e( U%
    6 b/ M# O' }. b  {# _% k6 a7 c4 J( D! l%        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'
    1 D5 S; w# k* A' c%        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.: W& q6 _  |! S; R; }
    %        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.6 e7 G6 T: }. f9 ]6 @
    %! M, e! r/ [4 e& N6 w$ `1 K3 ^( h
    %        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).           ' w2 Q* z: Y1 K) d3 \$ X4 {
    %        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m).
    , x7 X/ y  ^1 u%        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m). * C) J2 C; P: V- N
    %& y% T4 o! N+ v0 s
    %        srcHeight : The height of target audio source
      \8 r8 ~' R3 m%        arrayHeight : The height of mic array
    7 J/ i) a+ g- O! k' e$ A4 ]%! M4 r. s9 w' p3 N* O
    %        arrayCenter : The Center Postion of mic array $ T1 r, z. Y' J+ n1 _
    %
    ' |! c$ ~: H1 W) p' Q0 p9 s8 k8 m%        arrayToSrcDistInt :The distance between the array and audio source on the xy axis. {6 D' L' \" A6 u) p4 E* g
    %3 Z" w  r$ a! F: ]
    %                        2 M* R: C$ b  O+ s5 l
    %9 w0 r9 D1 N" o& k* ]% \7 T# V
    %
    % F6 n/ C5 l- y% I' j7 R  [%         ; x, |) I! n; c6 P
    %: o3 X. N4 x$ G( x' ~" a7 w
    %  How To Use : JUST RUN
    4 T$ p2 L+ K9 u! \%' q$ ?1 k# q- i
    %  
    # g8 D4 j/ W' S  _  k0 C7 I* l%   
    # Y' Q0 w$ c* s! d% Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),; e9 @; q% _) h9 [# ?) F5 C
    %            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.24: f- m# I0 o' h  \! d# O- s  P9 ~
    %
    . Z, d* U) y* W- s5 f" w% Copyright (C) 1989, 1991 Free Software Foundation, Inc.
    / e( G6 H( x+ s9 K, u4 Z: A%-------------------------------------------------------------------------
    ; S! C; s1 `& ]
    - z: R: x8 s% c( x) S3 h, h7 \* j( H; _1 P& s' e
    ! V& I7 A1 A2 l) x
    addpath([cd,'\..\rirGen\']);9 P$ S! s% `7 y8 W, f% @
    % K  C7 O0 s9 ?5 Y% N6 r
    %-----------------------------------------------initial parameters-----------------------------------2 g' R. `+ A& ~

    5 X/ X% B$ Y) A7 c: B5 jsetup.nRirLength = 2048;
    8 J  T  y- H& o/ i+ y! x# z7 c1 _5 ?setup.hpFilterFlag = 1;2 G1 R. Z- x4 u8 a: K
    setup.reflectionOrder = -1;1 Q1 g9 h7 ^6 A9 N
    setup.micType = 'omnidirectional';" X+ l- J0 P% V/ y9 n% C: s
    setup.nSensors = 4;
    8 u3 ^3 I7 H) Q3 m3 p* \setup.sensorDistance = 0.05;+ }  p4 v) s% f# c
    setup.reverbTime = 0.1;3 m9 J+ `/ b3 o, m1 d. e
    setup.speedOfSound = 340;
    5 r9 M5 d; U* I9 i1 C. G3 t' u+ |
    setup.noiseField = 'spherical';
    % x. i1 S$ A  b4 J" osetup.sdnr = 20;: t% F. K/ }# b( o/ H
    setup.ssnr = 25;
    * V% C# v- i, a% Y" A
    ' R8 ^! Y+ ]$ w. V1 ysetup.roomDim = [3;4;3];/ C( p: `/ i1 p4 b- b: I
    & Y  T) f7 S0 a7 V4 U
    srcHeight = 1;( @/ \: o. b" x% L- h( `7 Q
    arrayHeight = 1;
    . ?3 l& E; r8 @& p2 i4 o) W: k
    $ i5 m9 U4 Y4 |/ ~+ aarrayCenter = [setup.roomDim(1:2)/2;1];  j5 N9 l/ W3 o' K; `1 a

    0 _# S3 v* g2 Z% j0 {2 harrayToSrcDistInt = [1,1];
    6 g9 u: @+ W; k+ [1 E! U3 q4 v, D" Y' t8 p0 Q1 n% P4 ?& L
    setup.srcPoint = [1.5;1;1];
    $ V: K& O! a8 Z$ U9 S% c5 P. L$ e0 T' P
    setup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);7 F9 l. k! A" Z
    ( ~" Y2 q6 r1 m" i% R& c* P4 b: V* R# N3 V
    4 B7 X2 O, k  w: M& W6 [" Z* G8 s
    [cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');
    1 f- B  N, U- I/ v2 y+ \$ _6 u, O0 \! s; N) o: M5 ?
    %---------------------------------------------------initial end----------------------------------------  [4 h' |6 ?8 j' O/ U" I1 `3 w
    4 {7 U. u' E. m- k  Y* I$ D+ p

    6 I+ @7 l( I7 r, c& J' s5 `# z  y( b' y, @  @/ Y
    %-------------------------------algorithm processing--------------------------------------------------
    4 q+ m% w8 u$ R0 e0 v1 p8 w) A" \0 k; V  p- P7 Y# k
    if setup.reverbTime == 0,
    . A1 V7 d* [) P) k( G1 w+ N. Q/ E    setup.reverbTime = 0.2;
    % n+ s8 j3 G$ |! z: P2 b7 J' D( ~; I    reflectionOrder = 0;6 A5 F# n0 D' V/ Y7 \
    else
    , ?2 ?  j/ d& [    reflectionOrder = -1;9 P. d. [3 u/ m' x- L5 J7 Y
    end
    : D3 U" B+ ~" o$ g3 p1 {: D
    . P7 K! O( T  @/ Z7 {" M4 B+ \rirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',...1 A0 \4 R3 r2 B' [* a- q) X7 M8 i
        setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);; D* D$ P6 c6 k1 l  B
    ( n4 V1 R+ f7 I- |, T
    for iSens = 1:setup.nSensors,
    % g  {- h  X( H! s/ i8 k* Y& `    tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);$ Z$ P5 o( }+ F( a: v/ F; E/ J: ~! S# Z
    end
    7 w" d. e$ d+ }/ H3 q% t6 c3 PmcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;* Z6 H2 d! k, y- e# h
    setup.nSamples = length(mcSignals.clean);
    : e0 r% y% I5 Y& s
    3 w! K; G8 x  v9 [9 ImcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);) Q! M2 f( P9 Y0 E% @- n

    1 K5 N. @$ x" }+ P$ p%-------produce the microphone recieved clean signals---------------------------------------------; o& Y+ H4 c. \' \; j* o

    % \3 v( w9 l; f/ j) w# f) Smic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold. B$ @# V0 h( y$ i+ v
    mic_clean2=10*mcSignals.clean(:,2);" H9 ^  I( Q, f* o4 L: I
    mic_clean3=10*mcSignals.clean(:,3);2 s* d# I/ V& k7 t/ q
    mic_clean4=10*mcSignals.clean(:,4);
    % T& D% ^# O9 T% B* P7 laudiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);
    & U7 L, O) n- Q& a2 m8 r, Saudiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);
    ! O' J2 a. V$ t3 _audiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);9 i/ b* P5 G9 T, d" j  D
    audiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);
    9 G. G" S' m6 I9 [6 b2 U/ K* q0 B# K" K* V" g* P  h$ @* }+ e
    %----------------------------------end--------------------------------------------------
    2 R4 p, _+ q6 S; k1 C2 {0 E0 g, |  W/ [
    addpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);
    ( m- P" \- X; L
    7 E* {! Q; N  e! W& }& wcleanSignalPowerMeas = var(mcSignals.clean);* k) P0 _  e* b8 ^. ]- [( \9 _; P# T3 a
    , ?8 g% T+ I9 e1 B

    : I% L) E- E3 dmcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...& r: l+ ^! X* Y: b
        setup.speedOfSound,setup.noiseField);% C% a$ i/ \$ Y& ^- N
    diffNoisePowerMeas = var(mcSignals.diffNoise);6 s" N7 c4 p; j% `
    diffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);
    ' N2 r& N0 _- ~! ~' p+ s8 l0 S$ ]mcSignals.diffNoise = mcSignals.diffNoise*...
    1 M( Q% U7 r1 m2 W2 B0 F    diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));# R$ c4 y+ _7 J- X

    6 E% _6 Y2 {4 G/ k6 ^  M7 kmcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);5 E7 E1 v+ W+ ^* @5 O. H3 F5 T: @
    sensNoisePowerMeas = var(mcSignals.sensNoise);& Q' f! J) b0 \* g* D; `9 j8 ?( h: J
    sensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);2 \4 K4 s) \: R! G
    mcSignals.sensNoise = mcSignals.sensNoise*...
    5 A% z7 Q2 N5 `0 M8 l# `    diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));2 K; G7 X) c( W' T

    8 d" ]9 u0 l. _$ z6 T! C/ @mcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;" b6 F, U* ]* _; R. ^% \
    mcSignals.observed = mcSignals.clean + mcSignals.noise;  q) w/ t: _: Z( @: `0 h7 w) M+ e6 j) s

    5 @0 B+ g( i3 k+ ?+ z- h* }%------------------------------processing end-----------------------------------------------------------% l! B4 r: a2 r1 x

    : v" S2 A4 |; |1 V
    4 m0 m: X5 h. g: A1 k. k% t
    1 ]6 J1 L3 r- c9 B. c9 x
    2 k" W& U2 N- h2 I  e8 G%----------------produce the noisy speech of MIc in the specific ervironment sets------------------------
    ( }. H! c1 @- h" g$ @" `8 d: ^6 L
    ) U1 ]7 j* p' U9 Hnoisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold
    5 A- r' }( |2 t2 Q1 ~1 [noisy_mix2=10*mcSignals.observed(:,2);* L4 n: J: G5 h1 _+ d
    noisy_mix3=10*mcSignals.observed(:,3);
    & I9 |, o" ~( [6 `' p& enoisy_mix4=10*mcSignals.observed(:,4);
    5 _! a6 j7 S% pl1=size(noisy_mix1);: C; t6 S1 f% V% T
    l2=size(noisy_mix2);
    3 J, P1 h6 f& Y; Y- k& p( ]l3=size(noisy_mix3);
    " `3 I% q) V. a+ Z, _  cl4=size(noisy_mix4);! S% Z4 _: m5 `
    audiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);
    * C& o$ G: Q8 i% d5 f! a& Daudiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);1 o+ X7 D4 O: e; V2 x
    audiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);' E6 a! W' W! O0 h0 W$ `! O
    audiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);" {9 j3 U6 m2 t
    3 z( e# G3 b6 T: V
    ' N6 [; h7 f3 B, _' f6 o
    %-----------------------------end-------------------------------------------------------------------------
    ) v, n2 `! }9 D; M- g这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。- e2 F& z7 G1 J/ y! s% a: o
    直接把它们替换成你想要处理的音频文件即可。
    ( j% C: H# w  T4 i  f
    & d7 h% @7 b, q* [5 r  除此之外,还有一些基本实验环境参数设置,包括:麦克风的形状为线性麦克风阵列(该代码只能对线性阵列进行仿真建模,并且还是均匀线性阵列,这个不需要设置);麦克风的类型(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)。
    : p5 ~1 b$ h" j3 k9 F$ x4 |( u6 B$ V9 `6 o. G
    6 b! }* B+ f8 ]
    / u6 q+ a$ d6 m0 V$ b, D
    图1 麦克风类型图
    " p$ b) N$ E0 n$ t- n
    : N5 f3 i* f/ B+ m$ P$ {  F图二 房间的坐标系
    7 I  [; G5 w% `+ O, }
    4 _2 @* L% q7 l6 ^6 H  以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。. G+ B( J& x9 ^3 K2 s* y: P8 ^
    ————————————————
    0 D- e3 d  e5 G9 y* I$ c' C版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。8 K2 f  ~0 Z; p! T
    原文链接:https://blog.csdn.net/zhanglu_wind/article/details/79674998
    1 h; I7 j  @7 O: }0 Z. I
    / t8 [* k8 _- H' ^+ z' U& K+ R* ^) ~: m& m0 u
    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, 2024-4-19 17:01 , Processed in 0.276600 second(s), 50 queries .

    回顶部