QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3388|回复: 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. 引言
    1 f1 I% s( L" c/ b  之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。
    5 L  P8 v0 J5 h$ o: d: b$ F8 b$ C- W* W: |! J
      然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。, V, d# H% f& W* [
    ( n6 y5 q- ^0 d. C, x6 E
    2. 代码介绍
    0 {- x" p1 ]- R; L7 z6 k  原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:
    8 L7 o* [5 i) C% {7 A' l( g' Ufunction [mcSignals,setup] = multichannelSignalGenerator(setup), V8 ~) H; F; o; C8 P6 `

    % A' |8 z# h4 q* K3 k
    & l! U4 Y/ G. m+ U1 x! |%-----------------------------------------------------------------------# y3 J; Q3 Y0 u$ L) g% r' i! L
    %  Producing the multi_noisy_signals for Mic array Beamforming.
    / v' ~6 S6 k; G0 x% Y% 6 J5 @! T/ R. d; W9 ~
    %  Usage:  multichannelSignalGenerator(setup)
    6 o' \7 e8 r" X%         - d1 L/ x- o! {6 M6 h) f
    %        setup.nRirLength : The length of Room Impulse Response Filter
    3 p. }/ J, }' v; ^0 ~%        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default% N, K, ]6 k' e0 {  T
    %        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order.. Q0 \' O; T0 S5 x4 G# I
    %        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.
    * e. g$ m% q! u8 y%           * O: G' g) R8 c; L$ `. G- c
    %        setup.nSensors : The numbers of the Mic+ {& P* Q+ Y6 t: V& Y- t: B
    %        setup.sensorDistance : The distance between the adjacent Mics (m)  K9 V. C3 Z8 H5 R
    %        setup.reverbTime : The reverberation time of room3 m. Y8 C7 x- S; `  ]* P
    %        setup.speedOfSound : sound velocity (m/s), `& h$ W+ I1 b4 x: [; N) F
    %
    $ n9 L, w9 ^  i$ y3 C5 p3 |" c%        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'
    ( D4 V4 ^8 Q/ p. Y%        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.
    5 L4 `+ T* s8 H+ R5 p%        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.5 K( p" L  X8 K9 D/ ]/ Y
    %
    " q) F9 R- k. ~4 V2 \+ @# a& ^%        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).           
    # Z. R% Q, V/ u' C* y. e- Y%        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m).
    : ]* d7 X/ E, n; ?$ Q$ Z( A9 S%        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m). & ?5 L* u  x7 ~# E& [
    %, j6 x$ B' r- X6 }& `
    %        srcHeight : The height of target audio source
    0 |; u) |5 b' S5 H" J6 j, ?4 K8 l6 j1 A%        arrayHeight : The height of mic array
    0 u( R. p6 {' z%
    6 ?+ [1 b3 ?! S( e%        arrayCenter : The Center Postion of mic array
    $ e9 \6 T: i6 O" F6 Z8 ]- d%
    ( ?; i1 t6 F$ l' B0 A" H7 S%        arrayToSrcDistInt :The distance between the array and audio source on the xy axis
    6 M. D) a( Y3 [%
    - z& u* t/ w9 w4 a5 S8 `2 ]6 Z%                        ; r4 I7 G" V; m' J% g6 E& y# Q) S# [! i
    %0 H) n! U  |' \* F" `) W# Q- D6 x7 M
    %% j/ n5 X! D$ I: E
    %         . d5 h. x$ M: o- h0 ^/ o5 Q
    %1 m% N- R7 z. ~; W; X
    %  How To Use : JUST RUN
    8 e6 b: b  Z$ j) i+ a/ {%
    & [0 Y: L3 ~& F' o6 i1 ]%  
      b. V7 _; d' P5 w: j5 N/ s, k) r& p%   
    ) W9 K4 x& C1 ?8 c. n+ Y/ }% Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),
    7 Y6 S- h# b- u; V' d2 w- q%            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.24
    + p" i# [8 d" K. I3 ?%
    9 Y% D1 j/ G# X- v% Copyright (C) 1989, 1991 Free Software Foundation, Inc.
    - R5 ?. b- X! l) Y%-------------------------------------------------------------------------; G; Z+ I$ A  J$ o: G
    . P! E' ^6 i, V

    0 p4 k7 d1 @; z0 h$ h  x; z$ ]2 @
    ) R- J/ [/ E; w+ s% A# e( @addpath([cd,'\..\rirGen\']);
    & o1 v  S6 |9 w5 K9 l  a0 n$ Q3 o8 S$ D" v% @" a
    %-----------------------------------------------initial parameters-----------------------------------
    ' n. T. c: r# T% b* a& N, P% b. {4 C; J; v9 L4 K  i) j
    setup.nRirLength = 2048;) U) R# d( [/ F  k
    setup.hpFilterFlag = 1;
    0 C" f2 k) o) ^( ^0 [/ {( dsetup.reflectionOrder = -1;
    6 E) e* X- B! W9 N2 Ysetup.micType = 'omnidirectional';
    $ ]  \$ s* _2 {5 @' l( esetup.nSensors = 4;( r1 p  |5 J# w* @  N
    setup.sensorDistance = 0.05;+ t+ ]! |1 u9 u4 g% ?8 g
    setup.reverbTime = 0.1;6 @9 L' S' I4 t- d2 `5 r( s1 Q
    setup.speedOfSound = 340;3 t# t& Q' G1 \- U
    - }9 u* Z, o$ v5 X, Y8 [' V
    setup.noiseField = 'spherical';
    ! V4 q8 l, z7 o; U% Qsetup.sdnr = 20;
    7 P$ L' B$ R4 y8 q0 Vsetup.ssnr = 25;% F# C. l9 z6 r8 y' [- s* v
    6 C) i* |* o  r9 l/ A
    setup.roomDim = [3;4;3];, V% N( I9 Y4 a  A3 g3 L# r

    * @4 O2 ^# X* w+ AsrcHeight = 1;
    " V* D1 t" o( V" ~1 narrayHeight = 1;5 l" o" r8 b) J) M( O' i  Q

    + s% E1 l5 P, k' B9 R6 z/ _arrayCenter = [setup.roomDim(1:2)/2;1];
    4 c& w5 P# p1 m3 F, O; s9 T- N
    8 c7 ]) G8 T, ?% A4 TarrayToSrcDistInt = [1,1];; n0 ?/ I$ K! V+ d- e/ X
    4 T! v( W, i: ^. O; l$ B/ ]1 f% r- d
    setup.srcPoint = [1.5;1;1];, L8 W, c  h( j

    0 W9 k$ f# U1 I( e* Esetup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);) v5 w9 b, O& L

    ( ?4 @! W; |0 q
    . a6 P1 A2 h, H7 M3 [4 l, I6 ~[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');
    1 P, @& K$ ]" V7 J* Z  ?6 p- U7 v$ U* a& Q+ o0 `
    %---------------------------------------------------initial end----------------------------------------
      \+ f# N  c6 K% b
    0 s0 `3 {- @$ t( Y7 O$ \
    3 I6 B5 r; n  D' H7 c) m$ o/ [5 }
    . m& J' ~" F' T" h. Z%-------------------------------algorithm processing--------------------------------------------------5 k% V$ |# }" l. I9 a& i$ {

    2 I3 Y  Z6 [+ V: x" T! t$ T3 _& G1 `if setup.reverbTime == 0," R, K  W' Z: B* O5 }$ N8 v. K: q- R
        setup.reverbTime = 0.2;, j8 V' C: p$ L2 x; l. r
        reflectionOrder = 0;
    / z' e. A* L% d- lelse: a" C6 I" t* l# V
        reflectionOrder = -1;$ p/ v0 h+ @% |5 ^  N0 V' @
    end3 w, o- D1 Y7 B% ~8 E" T

    7 ?- [* |! h" L- \( m( s# hrirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',...0 _# Y/ `& P5 d# D4 g) l4 F
        setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);6 o) w3 A8 \: N* e9 ^+ _3 ^

    2 i5 |' a% y8 G* l, L' `( a' nfor iSens = 1:setup.nSensors,& \9 t6 v$ d5 q* q: B5 F
        tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);
    + P& A! {8 `  n$ y+ [end
    : a! _$ H$ N0 H/ D+ J/ smcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;4 j/ y" F, C2 h' c( y+ _! g/ J
    setup.nSamples = length(mcSignals.clean);- t# C: s" ~; l! ~; |: h  c( L

    ( o% I5 O6 [7 n7 zmcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);2 ^( r" g9 Y" ]2 G* P- W
    , h" d  \. ^0 w% k& D, O' U
    %-------produce the microphone recieved clean signals---------------------------------------------
    * V: ?4 c; E) \# r; m& E4 ~. z7 c6 l2 p) j+ g1 k0 c( g- e
    mic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold
    0 {$ [  f9 o! V1 N1 \3 K- D1 omic_clean2=10*mcSignals.clean(:,2);6 N! `4 b& ?9 c! M2 U
    mic_clean3=10*mcSignals.clean(:,3);
    5 M+ E0 z! e5 Y# N) `+ \mic_clean4=10*mcSignals.clean(:,4);0 Q1 \9 L* y6 C1 U5 s" ]2 M
    audiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);
    5 Z- l% I& H* z# G) i! Q7 R8 Daudiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);! `# {; ~; L" D$ _& T# n
    audiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);
    ( W5 g6 s+ n$ a# m0 aaudiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);0 u' C, _4 L" Y; u( z4 ~- ~6 N' T* A& v

    , J1 R: h$ [4 P: ?$ c/ {, W/ P9 Q%----------------------------------end--------------------------------------------------
    ( H# _- d4 T3 d2 P6 J( j  W8 v- E/ l, B
    addpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);
    " m; u, {6 n- [, u3 b
    % n: L/ M. R- J7 g* a/ scleanSignalPowerMeas = var(mcSignals.clean);* X: Y) A) r. A1 y5 {& ]( ~* ?

    & X$ N! f, i/ D$ q0 Y( B2 |: X! e: T" b( ?* q
    mcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...
    + x6 ]7 |0 J5 H9 Q    setup.speedOfSound,setup.noiseField);
    2 M+ g+ @; K1 TdiffNoisePowerMeas = var(mcSignals.diffNoise);7 u- P# e2 W2 g- R* M# h5 m. G
    diffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);
    # h; K+ M* _$ p' _mcSignals.diffNoise = mcSignals.diffNoise*...
    ; z: Y9 w0 S& Q0 Y$ b# R    diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));
    - C3 z- C( E2 z) G$ l! m7 ~9 S- m/ |4 V
    mcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);8 k& R5 a+ {7 K0 V4 i
    sensNoisePowerMeas = var(mcSignals.sensNoise);
    5 \! B6 f' j8 E6 H2 `$ o" S* fsensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);. X& Q: ]1 h- C) D1 t
    mcSignals.sensNoise = mcSignals.sensNoise*...
    5 V' R: B" L9 G6 |3 U& O! _; W    diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));2 R# i7 N# ]+ c) t& v2 _( G
    ' C) t  a9 ?5 j
    mcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;8 r4 {" h! y7 F. H% ]
    mcSignals.observed = mcSignals.clean + mcSignals.noise;
    0 I- S6 l/ i3 b8 t8 T- X4 ~. N! }2 \$ F1 [
    %------------------------------processing end-----------------------------------------------------------: f( x0 t' Q: H3 X8 S) T2 ^/ D

      K: @4 k5 ], b! m/ @9 c& z2 H9 T0 D, @8 O9 b

    0 i6 j: ]6 l  ~+ B+ x% C
    ) q3 x" I+ R, Z  t%----------------produce the noisy speech of MIc in the specific ervironment sets------------------------* ~# n3 ]2 M, h5 D
    , R& ^' W  }" W! G
    noisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold
    9 Y( A5 c* ^; q1 Ynoisy_mix2=10*mcSignals.observed(:,2);
    9 {8 G3 W' U1 w# F( a1 v+ x! @noisy_mix3=10*mcSignals.observed(:,3);
    , {* v6 j( \: A& U. _noisy_mix4=10*mcSignals.observed(:,4);3 i- |8 d6 y' G
    l1=size(noisy_mix1);
    # x& B5 _2 K5 p3 n! kl2=size(noisy_mix2);
    ; G0 B' `2 ]" j. Al3=size(noisy_mix3);
    ) l3 `+ X! m6 W* D2 h0 b2 Hl4=size(noisy_mix4);  p. ~2 K; z" @; |6 W$ j
    audiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);
    # u$ P& Z7 b. R' naudiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);0 y! f( V/ b2 R( i+ C4 H: ]; x8 }
    audiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);
    / Y. t# l) R: m' B; `7 D9 Kaudiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);5 P% |1 R4 M) k- s

    : c+ X) v6 n8 A' N. O. H( C. w7 C( a/ X$ a( _- m
    %-----------------------------end-------------------------------------------------------------------------9 S; X! q! C7 i
    这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。
    7 |- Y9 M3 J, J  L* {0 ?! ], x直接把它们替换成你想要处理的音频文件即可。
    . i3 |2 e8 \. H. V
    % Y1 D7 x% ?1 O: 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)。
    6 S: Y0 J( B  X3 Z6 h, }& y6 c# r- i  q! }. X% ~% n

    3 p, y1 g1 ?0 J2 c$ _. K1 Y6 q
    - D: A7 E* W3 X8 j图1 麦克风类型图
    . q& b0 B/ q0 p! ]( O; |8 K# ~$ v$ N  b. i: k! b+ y
    图二 房间的坐标系
    8 ^' a( B( c/ N$ i% z  T1 _! g; P; ~5 K
      以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。
    ' ~( m+ t1 H) b) J0 U1 Y' i! F- o+ P————————————————5 s. v/ E8 a: K, p: D6 Y* Y
    版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。! S9 r: ^+ B0 f  A( k
    原文链接:https://blog.csdn.net/zhanglu_wind/article/details/79674998' H3 \9 ^/ D* ]

      W: S  r. P; O: X( X; {9 X1 F% V. g1 Q  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-9-8 13:43 , Processed in 0.444185 second(s), 51 queries .

    回顶部