QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3368|回复: 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. 引言
    # v( a$ ~+ A  @! \6 c  之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。% m3 u+ `* ^2 w' ~( f5 l& E
    0 v0 E2 n" Z3 n# m: Z' R# ^
      然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。( ?- `: p2 ]: U0 c/ {
    - l0 C- G2 L% P" F9 v# e
    2. 代码介绍5 k; i5 a' h+ x/ p  _5 w( r
      原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:/ T( ]2 i: o2 G6 D1 y% w( a
    function [mcSignals,setup] = multichannelSignalGenerator(setup)
    - M# ^8 S6 v! k& O. {
    ! X" b% n+ }6 e- t& ?
    ) \: l( E% C& V%-----------------------------------------------------------------------1 Y" O2 s$ X; o, ^
    %  Producing the multi_noisy_signals for Mic array Beamforming.9 o$ G8 j  U5 E9 ~/ n, l6 o5 o
    % ; Y& H" E1 N/ w4 ~2 s
    %  Usage:  multichannelSignalGenerator(setup)
    : F) H: a" U+ a' c) g  q! z%         
    ) L  j; H- x1 B/ j- m- Z9 d. ?" }) n" S) k%        setup.nRirLength : The length of Room Impulse Response Filter
    , s' Y' I5 V  |" X2 T; S; I%        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default
    ! G; h  L# J. O' v3 d9 U%        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order.
    * c3 J, z3 \+ g%        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.
    9 W7 b' y& k  ?! c; L: d: A) o%           , R" H4 h8 r7 `: v; R& }- K
    %        setup.nSensors : The numbers of the Mic
    % l* E* S3 t4 f  @! o%        setup.sensorDistance : The distance between the adjacent Mics (m)
    ) ~5 S$ e6 D; N# c  k1 [%        setup.reverbTime : The reverberation time of room
    & ?+ _, Z/ d% y0 u" |1 I%        setup.speedOfSound : sound velocity (m/s)
    . l. k% j# s: L- n%
    # k: N4 z' ~3 k: _  d%        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'- L* |; g, {" f: i
    %        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.
    ! Y* z$ W( ]/ A4 Z%        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.
    + p2 C2 P7 G; |  D$ G( B+ m; t' j%- a4 Y! z6 d2 y
    %        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).           
    ' L' k) x2 q" A" e8 g%        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m). 1 R* P0 d+ e, X  }3 Y, F
    %        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m).
    4 X1 u. y: |& ]4 T4 V4 ]5 ?%
    4 x4 A( t( m9 r4 V3 C2 k%        srcHeight : The height of target audio source' p3 J* a5 V$ ~$ P8 W5 x
    %        arrayHeight : The height of mic array
    + m. T+ R2 H* f) m. K2 p3 M  _, C' S%- J% |* P7 `6 r
    %        arrayCenter : The Center Postion of mic array
    : @" y. C$ ]& {+ g8 \; m%& s. H' @0 s0 I5 V9 J7 \% L* i( V
    %        arrayToSrcDistInt :The distance between the array and audio source on the xy axis
      M( U9 x- e) f, d" F5 e%3 c9 S1 \$ e, ?7 ~3 Q: \8 L2 b
    %                       
    # d& `/ {9 @! l$ `. `%" o/ g9 P$ G! V1 u' L
    %  G* U* b, H' w' F. k! R3 o1 p* w6 `5 z
    %         
    " `- I- a: h& G9 |- d4 f/ x+ g%
    % s: l8 ]! F* w- l& Q5 ^) G7 E%  How To Use : JUST RUN
    : w" R4 ?- t4 M2 f# D; `$ a%
    8 W, v1 v- E$ ?2 Q  s%  6 y1 I* h# E, }6 e/ W4 u1 p
    %   - J5 O  \/ j& u9 Y# I5 N) }
    % Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),$ T" q: j. s) |- b8 I& c
    %            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.24
    ! f1 U% u) X4 M! q1 `%) u5 L& D  |: y! i2 N$ P$ W
    % Copyright (C) 1989, 1991 Free Software Foundation, Inc.
    ; ]; P- B' d1 C7 }% @( i& V. z( N%-------------------------------------------------------------------------$ q  g# @* _) F& w

    7 \+ D# _4 |# W1 R& ~4 }( Z; c' P7 U' J  U1 g' X0 a5 f
    5 W5 L/ ~9 W! N+ t% y# U
    addpath([cd,'\..\rirGen\']);
    + f( W9 L# P" L0 Y
    0 o. j' w) ?1 \( b%-----------------------------------------------initial parameters-----------------------------------; g. \! o! E( U: b3 K

    + S6 k, F1 q# Q" J. Asetup.nRirLength = 2048;
    8 L, T- d$ D1 S% V. x! q" E$ Wsetup.hpFilterFlag = 1;
    + a% ~: i  J5 Bsetup.reflectionOrder = -1;
    . i& t+ q& t3 x* I: S0 h7 H4 {setup.micType = 'omnidirectional';" [( M7 ?" X% p6 j
    setup.nSensors = 4;
    9 R% r6 o1 x7 |4 @setup.sensorDistance = 0.05;6 {% J, k* }0 E) P9 G  d0 X
    setup.reverbTime = 0.1;
    : f/ H# X% G/ G: i* J) V6 psetup.speedOfSound = 340;
    4 f6 O) W: t5 S& @
    6 z) x9 B( W: ?+ D% dsetup.noiseField = 'spherical';
    $ W6 h- o1 ~1 D" Q4 C6 Psetup.sdnr = 20;9 p  Q8 L4 q2 K" c
    setup.ssnr = 25;) g/ w( ^( O; p! a; G% e

    # H8 g5 m7 O) @$ Lsetup.roomDim = [3;4;3];
    $ |+ u- `/ D1 l% u. l
    9 L( k7 f, C+ Q0 [! l1 ^' esrcHeight = 1;
    0 i/ |9 {4 h; v+ Q9 {! varrayHeight = 1;0 N; j5 r8 Q0 c9 J! s. R
    - b% @0 k" ?( }; n$ a
    arrayCenter = [setup.roomDim(1:2)/2;1];% f' d9 H* w9 [& n$ @

    9 e/ `+ }+ z4 |( VarrayToSrcDistInt = [1,1];; s9 S9 Q" I! H4 x( f

    : [3 z$ A% [) G! K, z- g7 lsetup.srcPoint = [1.5;1;1];2 o1 @4 f; |+ M. w) W/ U! k. u" g! [
    ( t( I5 X0 Y2 z) O0 F
    setup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);, E3 n$ D: u: E" J( x- v1 ?
    0 E! q8 O, ?) n. [

    + E' {  i/ ]' h& j2 D/ O; j: i[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');) j# ^2 B, i+ t( J# J2 ~4 R) X

    & v) `2 H0 r2 ~%---------------------------------------------------initial end----------------------------------------
    5 u% ~( z+ V, v' {& K6 ?1 z" y; s6 w1 d$ \
    + I* w2 p) ]' T! V$ X# j; E# z2 j

    * V, _$ W5 d# f, H%-------------------------------algorithm processing--------------------------------------------------
    ' O- k+ |5 g* w; f* O
    : \. o4 w# A* xif setup.reverbTime == 0,. B2 N6 ?- J5 H7 I' {
        setup.reverbTime = 0.2;
    " U( i5 |* e. W1 w/ ]& K    reflectionOrder = 0;+ Y; Q6 F/ J; y8 ^' _1 Z# J% q
    else
    $ X: J7 b: N5 u4 k! G1 H0 r  j    reflectionOrder = -1;1 g0 r+ z) ^. l/ I( A2 o
    end8 N  F/ k% B- s3 `$ M$ U
    $ W& r5 D# N) g7 w5 p; a
    rirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',...* E+ Y$ Y) `5 ]5 p  b" ^
        setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);
    4 x. ]7 b8 ?8 i. W# Y+ C. m; L+ _/ ?- C0 \% D/ y! _4 F
    for iSens = 1:setup.nSensors,
    ; @2 L) H; ~* P0 L, \1 [3 o    tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);; F- a8 n) j0 K2 ?) Q0 N6 Z
    end
    1 s+ q8 x; ], w  L5 ZmcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;
    9 A- v& j# m' \1 O1 Qsetup.nSamples = length(mcSignals.clean);2 B. g3 O- e, x$ u( o

    " |; v* p/ H- F: ]4 ~! d4 EmcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);
    % Y7 Q3 F6 M2 n+ `' E. A& s8 A  `  v
    %-------produce the microphone recieved clean signals---------------------------------------------
    ) Z1 Q4 V7 l% B4 B& s1 Q, d. n, z1 `& I, ~7 i) [% [
    mic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold
      M- j* Y, b, u0 s" |: _1 i; }5 E" @mic_clean2=10*mcSignals.clean(:,2);0 L; T! q+ s& ~1 r
    mic_clean3=10*mcSignals.clean(:,3);2 n. H) B6 ~1 ?9 j. z# H- ?$ @
    mic_clean4=10*mcSignals.clean(:,4);
    ( ?! j5 z# V) B1 Uaudiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);3 O% G! }7 W3 T8 p
    audiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);* ~) D! E2 H, s8 u; ~. Q7 m
    audiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);
    8 q! Z) }4 ~# ^3 Q# J0 E5 maudiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);
    # H/ j2 i5 m" D
    ( {6 s( l0 F7 f" w5 E0 \3 a- C' \, }. ~%----------------------------------end--------------------------------------------------, v7 _& m+ T+ H6 O/ b: u9 L7 r
      ^" L2 }! H% k0 e" k9 {
    addpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);
    ) U" N/ @' U0 p6 g( s( S
    ; u4 m) O8 `: v8 Y8 pcleanSignalPowerMeas = var(mcSignals.clean);7 v" w5 J+ m/ H+ O6 L4 {, ?+ ^

    : Y7 \5 r, p7 f: A$ }0 x, U; l+ q* R  k, t' D! S* R7 u
    mcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...2 E" ~  P2 \% }) F* w; N
        setup.speedOfSound,setup.noiseField);
    ' }5 y* M1 H3 g( Q- Q2 qdiffNoisePowerMeas = var(mcSignals.diffNoise);3 G4 w* T9 O3 c3 O. _
    diffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);
    6 v) ]) L6 {; b. ymcSignals.diffNoise = mcSignals.diffNoise*...
    ! Y; Y+ v0 X- Q/ o6 N    diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));
    7 l% |. V1 c( w) b. M& `
    3 x! Z- t- X  L" ymcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);% Y- Z+ A* m* ]! N  N
    sensNoisePowerMeas = var(mcSignals.sensNoise);
    , E" o/ b* u4 @sensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);
    5 J6 J7 }( O& pmcSignals.sensNoise = mcSignals.sensNoise*...
    ) C+ ^; {$ N& s2 y- Y    diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));$ U  r2 q7 P% X
      J( C5 {+ W' ^3 C
    mcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;
    ; |( `2 n& i0 o- H- rmcSignals.observed = mcSignals.clean + mcSignals.noise;. Q! X) l. i! G, @/ H+ Y

    8 P% Y" V- Y& c, m4 x%------------------------------processing end-----------------------------------------------------------" P9 P4 t# K( J# s* C  b

    . W# o- L7 V8 v6 f" Q
    * _* E; L6 u2 c6 U
    " x$ B/ Z+ ?: \- g1 {9 X4 a
    * m% X, h( i7 M% f( E2 c%----------------produce the noisy speech of MIc in the specific ervironment sets------------------------1 {/ l+ l# `8 z, U9 \' T7 z4 @
    / ^' f! n# Q9 c0 t- X3 d
    noisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold& F7 d+ v7 Z5 X  F& A* i0 h8 V% B& b
    noisy_mix2=10*mcSignals.observed(:,2);! d: g. A* C" b  \; O
    noisy_mix3=10*mcSignals.observed(:,3);
    / H5 b6 i" P% y3 U& A4 _4 jnoisy_mix4=10*mcSignals.observed(:,4);( ~- C( r5 O: d2 ^+ e& q+ Y
    l1=size(noisy_mix1);
    7 U, I: f* a6 M4 N3 J0 H% Il2=size(noisy_mix2);
    + c3 X& X. l8 }l3=size(noisy_mix3);
    ; @8 Q9 M9 @% rl4=size(noisy_mix4);1 T+ s5 ?" @7 N6 b" `  o0 \( B
    audiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);: k3 G$ r6 h' Z
    audiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);
    6 f' N8 |% o/ {# @8 I5 iaudiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);3 y, {) n' j( U4 A9 g  n* o
    audiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);
    # u; y+ Z7 V% R% _5 N& p4 C+ Z; N" ~- x2 q! F

    ( p6 y8 v% Q% k) R) J9 L/ s8 m" B! k/ i%-----------------------------end-------------------------------------------------------------------------! Q6 f4 ]3 c( p8 k: |8 v
    这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。
    % x# ^$ {; S/ }直接把它们替换成你想要处理的音频文件即可。/ ?" @( e8 x) z5 L

    2 l0 I2 \( C0 }1 y  除此之外,还有一些基本实验环境参数设置,包括:麦克风的形状为线性麦克风阵列(该代码只能对线性阵列进行仿真建模,并且还是均匀线性阵列,这个不需要设置);麦克风的类型(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)。
    * z, u3 H- ?& ?& S; }2 X; ~: C% e: M1 ?5 H

    * q9 ^5 \% Y$ @" i% l( {( Q
    2 }4 @# m9 o0 f1 _, |, H# I图1 麦克风类型图
    8 k% f3 T& o. h( m- _
    . y- l: m( q7 A) c' l图二 房间的坐标系
    4 Y& \4 L2 ?. H( B/ R9 [6 ]$ ~, h( _5 f
      以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。
    * C8 g0 b  F$ D3 ^6 G" H% ]————————————————5 A  P% n4 P$ ]0 w$ [/ w2 l
    版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。6 I6 E4 w) b8 Z' ~$ Q
    原文链接:https://blog.csdn.net/zhanglu_wind/article/details/79674998# r4 e( u/ f% b; F7 V- B

    % o, \; y- u3 A, u! P0 D: Y4 N1 P. U7 V2 h/ I# K
    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-7-25 02:17 , Processed in 0.405439 second(s), 51 queries .

    回顶部