QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3307|回复: 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. 引言( ^  d1 C  }8 l* W# y2 z
      之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。1 D! t% N1 L8 W) I

    * x4 F5 ]0 H9 |7 ^  然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。3 M( v" E  d! W/ p- C3 }

    ) E0 |- H7 r& M) |1 H2. 代码介绍
    $ s1 E: R/ [3 Q* L  原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:7 F, a1 \. S( z
    function [mcSignals,setup] = multichannelSignalGenerator(setup)
    7 \. P+ Q/ m! d- X* ~  L
    ' y3 \$ q, U  K7 U0 t7 Q: E/ j( d' j; j" D5 ?+ {
    %-----------------------------------------------------------------------# g0 z% j5 k) t
    %  Producing the multi_noisy_signals for Mic array Beamforming.
    / x( a" ]/ j, E( \+ `6 C3 z3 K# ^%
    6 h- f( B: Y) O% [% U! D* p/ H%  Usage:  multichannelSignalGenerator(setup)
    3 }  z  E! Q2 m8 o2 O0 h$ Z%           H8 H* x, o/ V* ?" e9 H% J, W4 {
    %        setup.nRirLength : The length of Room Impulse Response Filter
    ! d1 Z$ o+ c! ?) x4 P%        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default
    4 u" j# J  {5 E2 v& _0 [+ [%        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order.# A  A5 X! J2 @6 q" t
    %        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.* k& x. \- E* H  J
    %           $ t% _6 D( l) C4 b' u( T
    %        setup.nSensors : The numbers of the Mic
    : E9 o- R$ \: ^" f! M. c1 m%        setup.sensorDistance : The distance between the adjacent Mics (m)
    $ ]8 a7 t. s& v) Y& f7 ^%        setup.reverbTime : The reverberation time of room# N% P* `! ]3 R9 M! P
    %        setup.speedOfSound : sound velocity (m/s)
    ( T. C( B+ o3 |. K%3 H* _6 k* t. D2 T6 I- @
    %        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'1 \1 `* m( L, x4 `5 Q
    %        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.4 q- i. e( N, I. A
    %        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.
    4 j, X9 n! [4 ^7 M; k7 ^; H%: x% i4 a# a7 E/ Z6 K* l
    %        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).           2 Y" @& d6 Y. V0 D6 P8 [
    %        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m). 2 s$ y4 H' K; X0 A6 o
    %        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m).
    $ Q/ c4 H0 V' m+ W+ p; x%4 G& F; F8 k/ C. b& _
    %        srcHeight : The height of target audio source
    0 U& v/ z1 l3 I4 V%        arrayHeight : The height of mic array
    7 H% N' Q" q1 F6 U, i- E2 t6 ]%9 l) T) S1 q3 D9 ~# n, I
    %        arrayCenter : The Center Postion of mic array
    / D# V% [0 A& t4 ?, \. U/ r%1 N5 q. P* H& F  o* n
    %        arrayToSrcDistInt :The distance between the array and audio source on the xy axis7 E7 n) f; Z) a
    %9 h# y3 _$ y+ E7 F$ B! V+ j. Q3 @1 x
    %                        1 H! y7 ^! a% Y# [5 n- e
    %
    0 R- e8 s0 v: Z" P5 ^%
    6 n" t" _7 o, W! ]%         9 Z0 I- ^4 n/ _5 X  f. }7 Z
    %
    . g) R; d$ b1 E2 W%  How To Use : JUST RUN& c+ t2 O: Q% Z& C0 q
    %
    ' ^6 Y) t( n9 n5 k  g%  
    * q1 F% Z5 n9 M2 _%   
    ) a! B: u$ \9 Z' @! J% e% Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),
    % a6 e; k$ f# h4 o% a, S%            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.24; Q! ~+ X" _' S+ {% B" `3 I
    %
    ; x- g" h4 O" A$ g# Z- \6 U% Copyright (C) 1989, 1991 Free Software Foundation, Inc.2 P9 E1 d  Y0 z3 u( R! A
    %-------------------------------------------------------------------------! P5 o+ r5 T! V, p' C- P
    " m) p1 ]& q. q; N5 X% ^. E0 h
    - n' P3 _: ?! Q4 K* u' ]+ I8 L

    0 X$ v1 ]2 v  J1 Caddpath([cd,'\..\rirGen\']);5 R( L6 g8 L: s3 B

    & t  Q; E: n* O: ~5 o%-----------------------------------------------initial parameters-----------------------------------
    ! J5 D4 z% d7 Y8 M6 J# B
    0 r+ J9 P( _7 ]' X& m- \3 tsetup.nRirLength = 2048;% _, }' u2 V; V$ t9 w' h2 ]: O
    setup.hpFilterFlag = 1;& G  }* _0 P2 x. Z, |* a+ \2 I
    setup.reflectionOrder = -1;
    4 s2 W  z& l1 I( Z) u! i# Zsetup.micType = 'omnidirectional';5 a- y! d6 ?0 n: L& M- p
    setup.nSensors = 4;
    ) ?( n  N# O5 C& E- vsetup.sensorDistance = 0.05;
    . `$ \. l1 r, S5 _. ~setup.reverbTime = 0.1;! a  q, q; x. ~2 \6 s
    setup.speedOfSound = 340;
    & v( U4 M  D# s* |
    & o7 O/ ^2 p! ^' h9 {setup.noiseField = 'spherical';* L7 R0 Z9 N4 S5 N2 l8 j
    setup.sdnr = 20;& ^# i% _$ A3 q8 f# S, d2 I
    setup.ssnr = 25;) H% g" e8 {3 w- R+ ~1 s

    ' d4 _: u  }; E0 ]setup.roomDim = [3;4;3];' ?. o7 k( L3 [8 p3 `% N: V
    " m0 |. H6 ]  D$ E
    srcHeight = 1;6 X  d# B+ s- r) {& D! k; q
    arrayHeight = 1;9 H2 M3 @3 Z$ g. t" j2 |
    ( F8 ~, u* n7 }0 K$ k
    arrayCenter = [setup.roomDim(1:2)/2;1];0 v7 x4 S$ Q( K' n* x$ ^# W

    / w* v% ~3 o% U$ S7 {* D- @( j) D1 t5 f2 ]arrayToSrcDistInt = [1,1];
    6 M6 m! J0 |3 ^) a2 G, h# J( }0 J/ t
    setup.srcPoint = [1.5;1;1];
    0 l# e& _9 V; K/ y9 t6 m* T: P$ @9 U: L: v
    setup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);
    ( [& l  @, K- k% t1 S0 }! w+ |0 {5 Y! c& o9 c: }. Q
    8 m( o/ @$ B4 a+ b% J
    [cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');" c4 n# Z1 K0 Z5 P1 _

      R) m. S5 ^1 L$ v% p" C%---------------------------------------------------initial end----------------------------------------
    5 {6 ?2 b2 K5 G  H7 X0 \( j
    0 m5 I+ @- m& s4 a, u: y1 P
      W$ @2 s# t' L; p/ V, Q4 H1 s5 k& X( h3 z/ [! R9 Q
    %-------------------------------algorithm processing--------------------------------------------------/ O% k. b% E, Q3 z6 x9 o

    6 W7 B- F/ P8 ]if setup.reverbTime == 0,$ l, C) @2 o* o# ~4 W: U
        setup.reverbTime = 0.2;
    . I# v4 q8 S. _0 t0 a# {- v% @4 L" _0 n0 J    reflectionOrder = 0;$ T2 x5 [3 W3 C/ _' x% R" @1 A
    else
    8 i3 Q5 U6 ~( f& j! o) v. B7 ?( _    reflectionOrder = -1;9 ]- t3 A% X: T2 k( U- p& o) L
    end
    3 ^( H) Z2 I# c8 b. p# J; y' b- }' M$ F6 Y, s) d
    rirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',...
    ( k: B) f' J: ]5 s* S9 |$ e5 q2 A/ r    setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);6 F. h/ F, E5 o9 }& t. p

    - U# A! Y8 l" a0 u7 E+ }7 t+ tfor iSens = 1:setup.nSensors,+ \, a( a3 Y( E  E6 u) ~
        tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);: P% B4 N8 E- Q( l1 ^1 h- J
    end
    - T# Q- Q2 s- G6 MmcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;. i( y  @7 s, H( t
    setup.nSamples = length(mcSignals.clean);6 |8 t( b) }+ o  e+ Q$ D
    0 t$ e2 K, X& K% ^& U! {, }
    mcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);
    ) X5 Z/ H/ ^2 D, U$ {: X5 J" q0 a8 i2 P6 S. l% V
    %-------produce the microphone recieved clean signals---------------------------------------------
    ( E2 V% ~2 H9 K2 K6 d- P" O
    9 S0 n$ w; O( ^% G' ~+ Qmic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold  }8 c0 s9 E( N2 `
    mic_clean2=10*mcSignals.clean(:,2);
    4 {8 a* }/ Z: b) {4 e0 Q7 s( A, xmic_clean3=10*mcSignals.clean(:,3);7 f" d! P- f+ X5 R, P
    mic_clean4=10*mcSignals.clean(:,4);9 l' @# w% R' s, w
    audiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);
    ' ], s7 d1 q6 F% Z3 qaudiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);
    ' k( D6 k! q" x! b" \audiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);; ~1 \0 V/ b- c6 @5 p
    audiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);
    ( w7 b! Y" p" _4 Z4 _/ B- P$ x; I" s
    %----------------------------------end--------------------------------------------------( O3 o  Z, w5 j7 ], k

    : G* ~, h3 z) j% y1 Yaddpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);
    + y$ w- E( c4 n4 u  H; S# {3 I$ ^/ Q* h
    1 z5 R  m1 `  X, d5 KcleanSignalPowerMeas = var(mcSignals.clean);$ P& T0 u0 d- T) @- W4 t

    ' f( z) ?/ E) b% Y3 s. P3 }. [8 o" J- W
    mcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...
    & W( J! y: c) w* `/ y" K    setup.speedOfSound,setup.noiseField);
    8 v( |6 i  f; s5 C5 c" kdiffNoisePowerMeas = var(mcSignals.diffNoise);* E4 T; n. W& R, ]
    diffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);: i, W4 c" F) E2 X8 A
    mcSignals.diffNoise = mcSignals.diffNoise*...
    2 J3 ^. @% G' E3 c/ r2 L5 @    diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));
      A+ o/ _- N  S$ f
    * F& E* m  J9 ~( Q7 p. w8 f% C8 jmcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);5 @) ^! A8 I  M; z( B$ {4 ]1 ^  G
    sensNoisePowerMeas = var(mcSignals.sensNoise);
    * ]9 a9 N0 `' M7 BsensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);
      D$ E# m$ m9 i( pmcSignals.sensNoise = mcSignals.sensNoise*...$ d* k+ k" a6 o: F' a
        diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));! z' Y8 W1 k# h$ t5 k9 Q+ I) u
    / w) q0 s, P2 a# e6 Z: H' s$ \, o
    mcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;1 D3 y& X: {0 t& b3 [" ]
    mcSignals.observed = mcSignals.clean + mcSignals.noise;$ k% x! n6 ?- F6 r

      C7 \+ B. U+ _7 f%------------------------------processing end-----------------------------------------------------------9 F; |" Y; E. x, R0 L* [

    ! l; v9 A8 S) ~  E3 Z& n4 d& Y7 f# |

    6 F5 l6 M. p$ M: n% L& Q$ S' O$ o9 @. y: [3 ~$ q
    %----------------produce the noisy speech of MIc in the specific ervironment sets------------------------
    7 H. f1 g, M: E) `* L: v' F4 M1 t3 D4 H
    noisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold  V+ t! W4 s& [6 `+ q
    noisy_mix2=10*mcSignals.observed(:,2);
    - c& i8 O- L/ onoisy_mix3=10*mcSignals.observed(:,3);$ z* n1 {9 |. K& \
    noisy_mix4=10*mcSignals.observed(:,4);( [! ~$ O+ B( n2 N! @. `7 N% Q% H
    l1=size(noisy_mix1);/ l$ l! c% V- m2 m$ p6 [9 V+ R
    l2=size(noisy_mix2);2 [4 e  U) H. k& @- H5 m1 p
    l3=size(noisy_mix3);' \7 L# p; }& t2 Z
    l4=size(noisy_mix4);% }6 K7 b% C# N6 L; L
    audiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);1 ~# e8 d' c# ^' ~
    audiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);
    0 ]$ |7 b8 K# yaudiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);
    $ }0 D; r2 v5 q6 Haudiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);) h/ S  o( W0 K# t7 H
    8 V2 _+ [! U/ F+ l, H1 Y" U

    - E5 n% C( U) i; s$ m" u%-----------------------------end-------------------------------------------------------------------------
    5 X0 W$ X' V+ @1 ?! o' }" A* e这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。
    % b! v" W! L, h& y) X直接把它们替换成你想要处理的音频文件即可。: g- D, J" f" R. J( G: A" G; ]

    ' z) h4 \: b, p, F* {  除此之外,还有一些基本实验环境参数设置,包括:麦克风的形状为线性麦克风阵列(该代码只能对线性阵列进行仿真建模,并且还是均匀线性阵列,这个不需要设置);麦克风的类型(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)。7 X7 Z" ^3 @; K4 Z

    : U$ @  A: h  @1 \, T
    - h, a$ \+ \3 E& S" {" m2 {% ~: s5 O4 n  M- S& O, Q' r9 Q3 h( g8 n
    图1 麦克风类型图7 n) r: z" U8 G6 C7 {

      U1 u1 p+ O+ H4 g4 d$ R3 f图二 房间的坐标系
      N5 e" M, E" e( w# P  f$ h+ C! U; I$ y& E0 [. T  Q
      以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。
    % g1 b. R) S1 `% j( I$ @! t, t2 t————————————————; h; \  u5 Q+ O; v2 v
    版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。' V  Y2 v" o) H4 w
    原文链接:https://blog.csdn.net/zhanglu_wind/article/details/79674998
    + a0 U- d" z$ z! o% P. Y4 f3 {
    3 L8 F% E4 J& u) `: j
    " q: f2 b8 X4 b
    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-4-20 21:18 , Processed in 0.423492 second(s), 50 queries .

    回顶部