QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3336|回复: 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 g: m6 m6 M: a  K2 f8 A$ }6 J  之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。3 u" |) f+ _4 x3 ~
    ! f/ p; h/ A' Y3 K
      然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。: P3 W2 N$ `& O  |- N
      Y' I5 P8 _" p7 E+ z& o' C
    2. 代码介绍
    ( W+ Z) A$ u6 o4 p  原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:7 ~* Y0 U% h7 _
    function [mcSignals,setup] = multichannelSignalGenerator(setup)' y0 V, T/ n' B; i4 ~" B
    ) {/ i6 @/ Z3 Y3 l  I. f5 }
    1 h/ J- R! V! i7 c0 D% P
    %-----------------------------------------------------------------------
    / G$ p+ K  O* K%  Producing the multi_noisy_signals for Mic array Beamforming.' ], u# z' ]6 z' \
    %
      g1 o$ j: [) c9 Q" B/ n# J%  Usage:  multichannelSignalGenerator(setup)+ x; @% H; ?4 b5 A6 W( |) C8 C
    %         % J" e  J' ]6 X0 Z
    %        setup.nRirLength : The length of Room Impulse Response Filter& p0 d; [- K7 j" \. f  r
    %        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default
    & N% @9 `5 {( x: M# m1 x" z  Y" C%        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order.+ e+ z  a) H8 S
    %        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.& o: \; I2 |, N3 J; g$ r/ t
    %           
    & {/ |( ?8 C/ Q9 {* G: c- n" N%        setup.nSensors : The numbers of the Mic
    * F# u# G% _. q3 i5 `%        setup.sensorDistance : The distance between the adjacent Mics (m)
    - N! \. ]8 h! D  _%        setup.reverbTime : The reverberation time of room
    * U4 u# x6 K) Y* L9 `%        setup.speedOfSound : sound velocity (m/s): e* T+ f, C2 r2 a0 _
    %. x# p1 D' C' ~8 G
    %        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical', k9 X3 k3 Z9 f$ s+ S# {& D
    %        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.- @$ _. Z9 T$ y# _: `6 T
    %        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.8 ~5 J* ]: p$ I/ @3 W( H+ E5 j
    %" j3 u4 j4 c. C
    %        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).           
    / ~3 W* S2 _; T. o%        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m). 6 t1 T( \7 T; H0 \( W
    %        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m).
    7 W% R1 b! Y# `$ u: E%1 g7 X' A0 q# ~4 h, l% a: i' L2 `1 U
    %        srcHeight : The height of target audio source  w( ~* w" H4 U
    %        arrayHeight : The height of mic array
    . a5 W/ `9 n5 T' x) k%
    ; v8 S4 @0 D1 r; n, O%        arrayCenter : The Center Postion of mic array 1 U1 u. M4 E9 e" s
    %
    $ E; P' m. j/ L; j7 l%        arrayToSrcDistInt :The distance between the array and audio source on the xy axis5 ]8 m. c2 V% I- o
    %) P1 y" r& G% p( {1 o
    %                        8 o; d( j- N$ A2 P8 N5 [# M: y
    %
    1 A" g0 e3 N6 [8 Z7 A. @9 d0 M%
      D5 A. Q; u# \/ y- @5 u) K& b. m( R%         
    5 S9 J( N( d7 |1 \%
    ( u9 ~0 u# g7 x, l# T6 p%  How To Use : JUST RUN4 n& ]& J1 m1 s4 W6 `
    %) n7 B4 ?7 e2 {( y7 \0 C7 f" |, y
    %  
    & G6 S* a, D3 r9 |6 j& y# I%   
    4 l5 W) ^/ J" Q: Q7 Y% Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),& O5 @% N; t  L( b/ v( V5 I9 X
    %            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.24
    . L& Z. w! ~" y% |/ [8 J* S2 X%
    4 C7 l$ V+ b, R% Copyright (C) 1989, 1991 Free Software Foundation, Inc.
    ( c0 B5 f: W. {& \% R( c! H%-------------------------------------------------------------------------+ I; b9 z5 M: Q1 _9 {
    ) W( J, l# m6 k) y
    % A7 m; R# G& `+ t7 n

    ! ]' V* k$ ^# }' G3 Waddpath([cd,'\..\rirGen\']);
    : R) i: d" a9 r/ B4 r" G; ~  c4 H
    ! k) l5 k  G4 E; N% S1 ~%-----------------------------------------------initial parameters-----------------------------------# H2 L. k  w9 D/ k% ~; n, B
    : S: p  Q6 k; u- Q0 t9 H, P! Y# y
    setup.nRirLength = 2048;
    ) c, e5 y' |- A7 o4 t# _setup.hpFilterFlag = 1;
    & Y. Z) b. V- E( G! k" _6 I- wsetup.reflectionOrder = -1;
    , _2 I. z' {. \  I; c7 qsetup.micType = 'omnidirectional';
    " ]1 E; W5 T# z' j7 }7 ksetup.nSensors = 4;
    % K. w' m* @$ \7 ?3 }setup.sensorDistance = 0.05;# d& h- Z1 D6 Y) d: s9 u  R
    setup.reverbTime = 0.1;6 J7 m4 z5 T: P. z
    setup.speedOfSound = 340;
    " W8 L# a% l* r# v2 C
    % T0 d- q# H* _: z  {: C& X% Isetup.noiseField = 'spherical';7 C/ h( `6 h: T4 W" f
    setup.sdnr = 20;  M# N  C; [! f7 u9 l, Z5 E9 d
    setup.ssnr = 25;
    " Y* p0 z; m" D- y, M' p) H( f, e/ r7 d
    setup.roomDim = [3;4;3];- e) E/ k% ]" c1 m
    & A( N' d  `$ p6 I) x
    srcHeight = 1;7 l  a, N2 [* {4 @) i9 w  x" h
    arrayHeight = 1;7 X3 S$ e6 a  E

    : p5 W* E% Q$ C7 u3 c3 z! parrayCenter = [setup.roomDim(1:2)/2;1];
    # T- J) D4 r- A3 V7 U; o8 |- ?& B( q0 {0 D( O- o7 ]1 x: s/ e# ], [% V
    arrayToSrcDistInt = [1,1];  G+ ?  k1 R4 g) O/ o; M7 }% E
    . k7 Z4 x. [/ u9 x- C
    setup.srcPoint = [1.5;1;1];) S) D8 _5 W$ [% u

    ) }5 a1 s1 A# e1 Z8 n: l0 w. Rsetup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);
    ; \( u/ ^* r4 D5 {" [
    ; ^6 p- V# ^) k  L6 Q, S& E' H- i0 d* l1 P: `+ |; @' W, l
    [cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');% M; w2 Y& }& s$ N& q

    8 B- g# }; q! g" W2 p9 K%---------------------------------------------------initial end----------------------------------------
    . x! t' Q( `. c6 y' N5 S1 y" W0 p7 V9 j
    & P! Z1 C' H1 A4 R
    , H& A5 u* D' h
    %-------------------------------algorithm processing--------------------------------------------------
    9 m$ n, z& D& f# N; K
    6 z' _) @4 h1 @- S6 Lif setup.reverbTime == 0,1 t0 m0 C) |, Y4 w' [& W7 M8 |
        setup.reverbTime = 0.2;
    / w  G( E7 u" M    reflectionOrder = 0;
    3 R# ?# Z5 f- V* c2 @- ?& K5 welse) P8 a+ I: ?1 R7 E8 \
        reflectionOrder = -1;" y; D/ o! P: k$ G0 m: u$ e
    end
    : b  A) X/ g* @9 F" r; y* j
      e6 O* _6 f  |! ?rirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',.../ ^. s" E$ D- l0 q7 z: w5 r
        setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);
    # n3 I* Z1 |9 u$ {# K/ Q$ o" _! N7 F# n6 U
    for iSens = 1:setup.nSensors,  J* _" j( ^9 Q) {+ w9 U
        tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);3 @. T* Y4 y; _# e
    end
    3 @. G2 y! m, R% Z; g+ BmcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;
    % |2 Z1 P' k  G4 r/ Y* ?setup.nSamples = length(mcSignals.clean);
    7 `4 g, Z* G1 b) x! U6 ?7 P5 ~/ z1 k2 h
    mcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);2 Q* {! ?4 r, i
    5 Y+ {3 o8 A6 ]- _
    %-------produce the microphone recieved clean signals---------------------------------------------
    ; I: ?$ S; k* `4 V# _5 W- l1 e: A% t* ^/ P
    mic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold  Q) B6 r/ c0 a3 n) d
    mic_clean2=10*mcSignals.clean(:,2);
    2 Q6 k( }* b# {$ P8 Smic_clean3=10*mcSignals.clean(:,3);
    4 v& q. c, @- i% W; n9 Vmic_clean4=10*mcSignals.clean(:,4);0 _9 Q4 E. f; b5 F* E8 r+ C$ c
    audiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);
      b: H0 S$ L6 `$ I9 C* F8 Waudiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);
    4 t  S2 }% u# Q7 c* E1 iaudiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);5 e& |' c6 K7 x" d/ a
    audiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);
    * O  O. C' N& @6 Q% S* {3 S8 ^' Y6 T! T( N, c! d+ ?$ g! e
    %----------------------------------end--------------------------------------------------7 o8 i; I: s6 q
    8 X- o1 T' ]% D3 P; d( S5 y7 Y
    addpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);
    + S; b+ f: I6 c
    & h# B' x; p) R: Q5 y" ucleanSignalPowerMeas = var(mcSignals.clean);
    ; d' l0 y/ t9 D' K+ h+ w- H  \* l; ^( a; o4 O8 v

    6 a1 h/ o1 P! T8 @  [! WmcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...
    % G) Z+ k% V) W    setup.speedOfSound,setup.noiseField);
    4 S( t% d3 w& S7 s9 g. adiffNoisePowerMeas = var(mcSignals.diffNoise);2 a% h* S1 u% [$ o4 I0 N, A; n
    diffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);. P# {5 m* O! X; F* d  Y  i
    mcSignals.diffNoise = mcSignals.diffNoise*...
      b, P0 O( x9 F    diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));. P) `% C" Z4 @
    ! H  d9 O2 p; z
    mcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);5 c2 T( g5 k" r+ j  z1 [; d
    sensNoisePowerMeas = var(mcSignals.sensNoise);
    3 n# E2 m/ ~" @8 q3 YsensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);
    - T# w- }9 ~2 S, cmcSignals.sensNoise = mcSignals.sensNoise*...' O0 c0 G6 u- C# d) b
        diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));( E5 M/ S  @+ [) Y9 w$ l
    0 `; q: o! D5 v$ E. A7 @3 `6 U
    mcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;
    8 b5 s+ i1 _" w7 |" tmcSignals.observed = mcSignals.clean + mcSignals.noise;
    # m, {4 x/ E% p# B( U+ w) E7 v$ l1 I& i, T. h' X/ P) f
    %------------------------------processing end-----------------------------------------------------------
    9 `0 Z% t& m. M
    , |: v8 u* i. ~9 v! o& Q  G* Y' U+ O. |. P! P* t& d! ?) O
    3 K/ J6 j. a4 P: L
    ) E! [9 T/ O, X: z  Y
    %----------------produce the noisy speech of MIc in the specific ervironment sets------------------------. r6 a& T" P( S) [3 H
    " c# X+ B( l3 [3 ~: X7 J. w
    noisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold4 w2 u9 k) V2 \. I5 }) D5 M
    noisy_mix2=10*mcSignals.observed(:,2);* Y; `/ j$ T  E: @4 I" A
    noisy_mix3=10*mcSignals.observed(:,3);
    ) z3 T; R3 c8 V* s6 |noisy_mix4=10*mcSignals.observed(:,4);
    2 [: F) ^# ~6 H( s5 Pl1=size(noisy_mix1);
    6 v5 ^- |  |: ]! ~# l# J- X* ll2=size(noisy_mix2);
    4 N$ e/ C* i: dl3=size(noisy_mix3);+ A" |' d# d$ u
    l4=size(noisy_mix4);' ~) ^2 `' k, X5 S+ u
    audiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);+ A- u  I$ k) i) f3 y" }( w
    audiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);
    & {% Q2 g# j# ]) w: Gaudiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);
    7 @9 j, d  k1 [+ E. Q) }audiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);* W" N+ V, \! L' _1 q
    - h: G; g. j: x" {2 `8 e
    7 u. P* \. h2 o
    %-----------------------------end-------------------------------------------------------------------------
    & k, q4 }" R& Z1 l$ {! G! y+ E* t这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。4 m- i, ]+ q8 p
    直接把它们替换成你想要处理的音频文件即可。# h4 t& w' c. i0 n& j
    ( M$ }1 W8 ]2 }7 U* n' 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)。
    3 O% y+ x" @7 {  E# x" I
    ) f% c  z2 a: M+ L- I5 E: |7 w
    4 v* z8 \6 X4 a
    % T2 T* F+ l! C/ t% x& h. d$ S( e图1 麦克风类型图
    - ?# p! [/ J, l/ g7 D) a
    ) y$ M- r5 P/ K5 j图二 房间的坐标系7 b- U% C) R7 W$ P/ f( `" l
    & [% C& S; ^: o% r. y: ?
      以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。$ A. ?8 H$ t/ B; x$ ~
    ————————————————/ V: y4 @* Q, v& V* V
    版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    # o8 I! `. [3 d4 S: `, G7 j# U. h原文链接:https://blog.csdn.net/zhanglu_wind/article/details/796749981 i. g2 a- Y& Y  R$ j6 `( c

    . {. Y( F8 l( V. R
    3 c- S2 O% I$ R" J0 _6 b+ 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-9 17:20 , Processed in 1.366130 second(s), 51 queries .

    回顶部