QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3393|回复: 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. 引言
    $ g7 p- k1 _3 t$ O' U  之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。
    5 q: ]/ f. m7 Z# V& p! E( [
    . A) D$ C$ T) k0 @' @4 ?  然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。
    1 B  d2 [0 ~0 V. y5 t1 W; }9 f
    4 k: s& F, F7 W' C7 [  {2. 代码介绍( Y5 i' m- R% X7 B
      原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:
    * v' V4 e4 w5 E$ gfunction [mcSignals,setup] = multichannelSignalGenerator(setup)
    3 W0 a' L2 {& G: n/ U' B8 F/ l: S1 Q2 K' F+ Y: c( Z( W. T

    0 y1 k3 F6 @6 P- c) b  b%-----------------------------------------------------------------------
    4 Q+ n/ P7 x. B. {6 k# J( P5 N; W: @6 a%  Producing the multi_noisy_signals for Mic array Beamforming.1 L* j5 A* J: C% \+ V5 S
    % - [) Y+ a) p. o- C' i
    %  Usage:  multichannelSignalGenerator(setup)
    + y, x; r% y  y4 B" u%         
    0 f7 g3 `$ s- S9 W: |%        setup.nRirLength : The length of Room Impulse Response Filter% t" I9 r/ J2 I
    %        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default3 p1 Z: c) e9 L: H" ]; o  p
    %        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order./ s7 q1 e- }: }' @4 i  \9 P
    %        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.
    ' i, J5 z  A6 N0 z3 X( t- N%           6 e2 w) h/ @* C. m- r( x5 z
    %        setup.nSensors : The numbers of the Mic& q7 @- e9 D2 U9 C7 c8 _; u
    %        setup.sensorDistance : The distance between the adjacent Mics (m)5 w$ C9 s& m( M: z( ^2 m( [" t
    %        setup.reverbTime : The reverberation time of room* j# v8 [5 g! U/ O6 s, |
    %        setup.speedOfSound : sound velocity (m/s)
    ' U7 r3 g6 {9 f8 K%
    3 H9 m6 w  e6 }%        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'
    ! @& m$ D! L9 C* S: I" ~( C" e3 Z3 k%        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.
    ) F. J/ B  [6 d0 [$ |- a' Q%        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl." D) f% p0 t+ c: P" h1 O
    %
    ; d0 n  N* `7 [4 j( e0 G+ R%        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).           
    5 n" T: }) {& I4 ~# I! L%        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m). 4 ~1 s% f* `, F" b  S
    %        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m). 6 z4 ~- c$ h2 L3 ?& m- i5 u
    %5 X- y7 F7 e. d5 P) Y9 O
    %        srcHeight : The height of target audio source+ S: c4 [# Q! G' ^( {
    %        arrayHeight : The height of mic array
    0 y6 Y1 Q1 p+ q7 n- V. \! u%; t3 B8 {, \+ M+ q: |4 o5 J
    %        arrayCenter : The Center Postion of mic array
    & M- K; g9 ?/ x5 Z9 B: l%8 x7 |5 {" G% w# x3 f* E
    %        arrayToSrcDistInt :The distance between the array and audio source on the xy axis9 f, t, U( a5 i) x/ F7 ^
    %
    : h3 _9 N6 A7 d7 p%                       
    4 @; r+ U% J! O7 B%
    ; `& g" {, E7 y. A# \( O%( T: J% [& S/ K
    %         
    ! F8 u- m" ~& _%
    3 L: v: G* r5 j0 t%  How To Use : JUST RUN
    " O$ l" t, h# g  h  s%
    / i& F0 s0 m- {# p$ F%  . Z3 [2 X- R: H
    %   , W- J2 |5 k! J1 _# z
    % Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),
    ( n2 V  r; J8 T# A* L. V. o%            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.247 O( K7 f# U" ^. j
    %5 U5 r5 c" H/ u
    % Copyright (C) 1989, 1991 Free Software Foundation, Inc.
    , n, |+ K/ v% q" K0 f3 Y. U& a%-------------------------------------------------------------------------# e9 B8 Q: J; L& y

    , x3 C4 P: a, u/ T% l
      }1 Z/ T6 o: S
    ; Y; A. m" H" p# r/ Daddpath([cd,'\..\rirGen\']);
    * ]" M# m' Y9 ^5 X& X- a! A$ h# e6 k. R
    %-----------------------------------------------initial parameters-----------------------------------/ }4 q2 a4 }. H/ e9 c4 P
    8 ]6 Q* g, l+ a" k0 P! \* Y2 p8 }$ X1 s
    setup.nRirLength = 2048;, P/ g$ d  B0 c0 e
    setup.hpFilterFlag = 1;
    4 B) t" y8 L8 y0 J6 t8 C1 usetup.reflectionOrder = -1;) Z' l. k5 s: x" Y
    setup.micType = 'omnidirectional';
    ) V: f0 m6 |+ s  E* x3 e) L; |( n5 Ssetup.nSensors = 4;' i3 v" K4 p" _- e' b
    setup.sensorDistance = 0.05;
    8 B1 K; Q8 U& J& Z7 H1 {% o% Esetup.reverbTime = 0.1;
    6 \6 t( k7 G, ^9 L. tsetup.speedOfSound = 340;
    * h( i0 v# A$ j# Z/ k9 b0 C7 t5 A; D) F/ ^) \
    setup.noiseField = 'spherical';4 o3 @1 I7 c; V7 V0 C
    setup.sdnr = 20;
    7 ]7 w( F: v" N( v5 I( i6 _# Q+ v, psetup.ssnr = 25;: K% r" d, U" a# t$ c- A( f& O

    0 |2 o# i9 |7 t* I, qsetup.roomDim = [3;4;3];1 P4 F9 t- R! v; c
    ' ^4 \! k& l$ X
    srcHeight = 1;0 G: |4 o! `: J! H1 V  C5 N) M4 G
    arrayHeight = 1;& G. h, X  Y, W: T* D6 u

    " q5 f; `6 e  TarrayCenter = [setup.roomDim(1:2)/2;1];7 c& m9 a' y/ b; i1 u: v

    + {) D( k% N( Z1 i$ n. BarrayToSrcDistInt = [1,1];9 I: q4 \$ a9 w. q
    3 @9 c; g5 s& ?6 \; p8 Z, q
    setup.srcPoint = [1.5;1;1];
    & j; N5 w, |& w( i6 W1 n" y+ r/ `: ^% k
    setup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);8 r( T( @1 \. w
    1 A' r2 C5 [0 d
    6 U/ y# C( `; c9 U5 _: I& ]& u
    [cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');& h+ b- o$ Z8 v+ D
    & H& X+ B  Y& y) c+ m" n
    %---------------------------------------------------initial end----------------------------------------* R" H) B. T" u5 J' c6 H9 J

    & j) C- ~( u- X& {* P7 u# g3 Q  G: R1 Z3 a' q3 H& P# W

    . _$ A  K, _9 v8 u7 l; H%-------------------------------algorithm processing--------------------------------------------------
    $ C' F- |% \$ `9 c* {. c. X/ W
    ! T+ a! F9 n# {! f# p" Zif setup.reverbTime == 0,
    ; ~$ o( C5 \3 c, E2 d1 L# t    setup.reverbTime = 0.2;
      K1 P9 k) G2 P9 H2 B    reflectionOrder = 0;' T8 r( ?' R* n3 y6 |
    else# A7 p6 z3 I) ]$ r$ v4 V
        reflectionOrder = -1;
    ( Q. G: a8 d( d' C' n, l8 R  D, X$ Pend
    % f# _3 f) o$ J
    8 t4 ]! ~  v7 x! i% z2 M/ ErirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',...2 Y$ P+ m* k/ e' ^
        setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);! t6 ~0 K! [$ I. H8 y

    . _7 h; H2 v2 P" `: y5 }, F( Xfor iSens = 1:setup.nSensors,
    - B% v) B/ \/ O5 V2 r; u* g" `    tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);
    & p$ I, ?" b1 v1 V8 k. n5 y2 q8 `1 Fend
    5 b% v/ Y7 L  [, ymcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;
      s5 Y1 R, s- h0 J6 c) t1 K  jsetup.nSamples = length(mcSignals.clean);  x5 R8 s% r! W6 j
    - O# y) R3 v1 w) a
    mcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);
    9 I; J0 H% y2 t' I+ i, [
    1 k5 n  _' J! E5 @# Z. b%-------produce the microphone recieved clean signals---------------------------------------------
    1 ]! J; r$ O! P% a5 x$ X' ^; l. d! \3 V: n) k
    mic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold' b- B, o& a- ^% v  Q( z* z7 V
    mic_clean2=10*mcSignals.clean(:,2);1 ~; f" c$ j* B" I. h
    mic_clean3=10*mcSignals.clean(:,3);# q  G+ c0 c$ F+ R" Y0 n
    mic_clean4=10*mcSignals.clean(:,4);6 j1 Z  m# l) H' m
    audiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);7 Z7 Z: T$ A/ r; d" v
    audiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);0 r2 T2 K) X3 i. H. d
    audiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);- Q. n* `$ P; Y- a4 B' V
    audiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);
    7 e3 o' m  K& \. B# d" `. _6 Z. f6 j, b- p3 b! @9 b' z- Q
    %----------------------------------end--------------------------------------------------1 o: S2 A6 c6 l9 T. Y# X" v
    ( I' l1 K3 b8 X- e! f: w5 H1 Y
    addpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);0 V$ p+ \, x4 j0 h1 G6 A7 J% o2 Z

    6 m' B+ l& x* E0 n/ BcleanSignalPowerMeas = var(mcSignals.clean);2 H7 y" d) K. h: H) l+ f
    1 M+ c/ f* B  B6 z
    . X: |$ u  n* \& u' s3 T/ X8 \
    mcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...
    4 f# O  P/ M% F  S9 g/ v+ _5 H! h, x    setup.speedOfSound,setup.noiseField);- C$ L& |$ g/ e7 `% k* P
    diffNoisePowerMeas = var(mcSignals.diffNoise);* O) k! p0 i& [% V
    diffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);
    $ W2 D* i/ H0 n' D! H4 f6 ymcSignals.diffNoise = mcSignals.diffNoise*...5 f1 A5 n  U* f; f
        diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));8 @& }" r$ n& g& l8 S8 w) s/ M

    - Y1 D4 I/ a/ H2 fmcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);" I5 P) B# u5 v+ I
    sensNoisePowerMeas = var(mcSignals.sensNoise);
    + s* N+ R" y; f1 W/ U3 {) DsensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);
    % A# c: z! c/ WmcSignals.sensNoise = mcSignals.sensNoise*.../ B& ]- w8 X* I6 N9 J
        diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));
    ' ?# t& W. x) H3 H  J& d
    ( I, R! w# N5 j# m% P2 s( m9 p% r7 ~mcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;; ^3 U& ?& l' ^
    mcSignals.observed = mcSignals.clean + mcSignals.noise;
    ) m! m, S  n; ]) ?  C3 G/ K
    , h: }+ b5 v4 Q%------------------------------processing end-----------------------------------------------------------( ]5 u5 S. D/ h: M

    3 h7 A, }" w" m& G: R/ D2 G& z7 }/ f' ?# W1 H. P

    9 B! f; ?$ M) t! J+ {$ _! O9 O/ o6 q$ k* q
    %----------------produce the noisy speech of MIc in the specific ervironment sets------------------------
    & a2 o' _; V! m; a5 |& H& Y, ?/ O- H. M- |  r
    noisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold
    * C4 g2 m) ^9 a* m+ g- wnoisy_mix2=10*mcSignals.observed(:,2);: g* {# X2 S! j
    noisy_mix3=10*mcSignals.observed(:,3);6 C2 _4 ?, b4 d9 ?8 T; f) R$ b8 A
    noisy_mix4=10*mcSignals.observed(:,4);
    5 H% t, ]% M/ ^' G1 T1 Rl1=size(noisy_mix1);/ A; F# ^! C! m3 I5 W& u" c) J
    l2=size(noisy_mix2);
    + X! [9 M0 U, ?, U# ?l3=size(noisy_mix3);
    . b) \5 |, Q! F! f& V" v+ ml4=size(noisy_mix4);
    4 W% v  g5 F4 i+ y8 {$ f2 raudiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);
    5 w* T/ M- T. @! f, X. r  b+ E* vaudiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);( u5 b+ @( ]  q( G2 Z
    audiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);
    8 |. ^& m1 Y* p$ W* X; Y4 L- q. ^$ ]: @audiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);
    ) Y) g; X- z7 b2 S4 v0 N5 W3 d' l
    8 R* B! h1 T/ b0 `; G
    %-----------------------------end-------------------------------------------------------------------------
    ; i: m9 x; S, c# z8 H5 {5 W0 B2 q这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。7 ?) w3 c3 V4 }
    直接把它们替换成你想要处理的音频文件即可。% ]3 \: u& |) c3 D# {$ T4 n( w
    1 l; g! W4 c! [# R! i$ [
      除此之外,还有一些基本实验环境参数设置,包括:麦克风的形状为线性麦克风阵列(该代码只能对线性阵列进行仿真建模,并且还是均匀线性阵列,这个不需要设置);麦克风的类型(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)。% x1 W( _. r; D( Q! b9 i0 f9 Z
    ; [9 l( N& A5 }8 q( M, f0 T

    " k9 L/ ~9 T4 O. C4 P' G. e2 J7 @& w$ C: A+ e; Q( t% Q8 R- w) i: T
    图1 麦克风类型图
    : a( {9 Z; Q( ~2 V
    . a' d. r. i9 B, l- g图二 房间的坐标系
    6 d/ S8 J% d" W, ~' ~0 U
    9 T& B- C/ h& C  以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。
    ! I0 u  d1 j5 O/ {& m————————————————
    - s6 X' D2 Y. K* p* o  n8 r; i+ [版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    ; b: t, E2 i* Y4 F原文链接:https://blog.csdn.net/zhanglu_wind/article/details/79674998% N7 t  U( a( h4 I5 d
    / b: I- H( K6 C

    ; i) a  u* ]+ D( I$ D/ i3 V! o' h
    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-9 12:18 , Processed in 0.336647 second(s), 51 queries .

    回顶部