QQ登录

只需要一步,快速开始

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

    . @9 R/ Z! {9 q8 B1 K  然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。
    4 q) E' M/ b5 l5 n8 z: a9 W
    : @) }; H4 v8 j2 ]0 L. L" o" |- b2. 代码介绍
    ( W0 M6 s7 X: i3 v9 N4 N  原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:9 X- s+ |) F7 ~! b5 e( y, ~9 j; P$ A
    function [mcSignals,setup] = multichannelSignalGenerator(setup)
    6 c% j' Q4 I+ R0 N- O$ f) T
    ( a$ |" j& R. x# X2 \" F4 m' ?) S9 ?1 O5 j/ X/ ?. S: m' v7 O
    %-----------------------------------------------------------------------( y" Y+ W9 ?4 @- `* i
    %  Producing the multi_noisy_signals for Mic array Beamforming.6 ?7 M) Q- m6 n2 k
    %
    8 O; z0 _* h- a%  Usage:  multichannelSignalGenerator(setup)$ j5 A8 Y6 T) i# y: C; d
    %         
    / U8 V( t7 [5 ?. M1 B%        setup.nRirLength : The length of Room Impulse Response Filter( s6 ?# p' Q/ j
    %        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default, @& h1 I# e" f2 Y  l5 e% C* Z
    %        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order.
    3 f+ _; ^8 S- A3 L%        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.6 |; h+ r( o* H: `) ^' _
    %           
    ! o* H: u4 T8 Q3 P7 T%        setup.nSensors : The numbers of the Mic
    ) ]- C( S* R2 K0 {%        setup.sensorDistance : The distance between the adjacent Mics (m)
    4 p9 h; K8 _6 R4 {- X%        setup.reverbTime : The reverberation time of room3 N: x: ~) Z) C* k
    %        setup.speedOfSound : sound velocity (m/s)( {5 c. A: y% `
    %
    & B+ l, N" @& g# b) U6 w2 s. O%        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'
    - k; n1 s- C. H; t1 x0 ~%        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.& h! B/ g) c% P" s! M) m' n% J9 D
    %        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.
    9 H' t- d# T) f& d% B$ x, e%5 H5 v2 u% Q+ a$ o
    %        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).           
    * F+ V9 e( @1 f1 i- ?. y9 x%        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m).
    $ Z0 T1 Y0 ?* I' a: F$ O* N+ t%        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m).
    ; e, f$ A- o& I' }1 m) @2 ~6 }, T%+ T) y4 u: u- M# h
    %        srcHeight : The height of target audio source. ?2 v2 P; P) _1 _3 v
    %        arrayHeight : The height of mic array3 o2 g; o( T  o
    %4 B1 D! T9 O! D! o% S
    %        arrayCenter : The Center Postion of mic array , j9 m; A7 Z9 S: j. X
    %
    / `2 w9 j, b3 F%        arrayToSrcDistInt :The distance between the array and audio source on the xy axis' w+ \9 h: L  z) [. T) z+ @
    %' m# p; v& a  h" M. z* B
    %                       
    " x4 F/ i8 l4 h, {- A%& v  G: ^$ ^- c& q! l
    %. P  `6 o4 K, E8 `; @  U, b* J
    %         ; s, @, U' z. b$ p8 Z
    %$ q' c1 d$ h4 F; W
    %  How To Use : JUST RUN
    3 v* z2 S" `2 A6 y%
    4 K  l/ B2 R5 a+ L$ o+ Z%  & e2 v% B# }3 |. H; Z' G
    %   
    / \0 \- F0 A# C7 e4 V% Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),; d2 L9 H* w7 g
    %            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.24
    , V9 ]5 I0 q1 Y) G7 L%
    6 ?, Y+ X# ?! i% n6 X% Copyright (C) 1989, 1991 Free Software Foundation, Inc.
    + ]1 J' K( K( g" ?( ^%-------------------------------------------------------------------------6 G0 o& n. [; R' F( i) ^

    0 x! g2 V( g: C" D4 _: k; X6 `8 u$ J) z2 g; {& o

    3 l8 ?" F( T# r( v: Q2 [addpath([cd,'\..\rirGen\']);
    7 H6 @) }! n8 Z- Z3 G, p9 e; w8 K" Y2 X8 @: c5 J& L# ]
    %-----------------------------------------------initial parameters-----------------------------------& t$ j, V8 D2 V; T  L2 l
    6 X2 e1 _1 V2 x+ u
    setup.nRirLength = 2048;4 H# j" P, B4 U  N1 {' g
    setup.hpFilterFlag = 1;
    : y1 a$ z# b8 H3 y7 ?+ Ysetup.reflectionOrder = -1;3 G. ], W: Q; z6 @, G
    setup.micType = 'omnidirectional';9 U) V. h. G! T
    setup.nSensors = 4;$ g4 p+ a2 @" V
    setup.sensorDistance = 0.05;! h* i& g+ C$ p  M
    setup.reverbTime = 0.1;
    : C" D' S, g* Xsetup.speedOfSound = 340;
    0 V1 k2 f; S) s/ T1 y" q) \  g
    % z: b6 J3 Y7 m$ t& G2 xsetup.noiseField = 'spherical';2 J; ?( l/ p% {0 m- y
    setup.sdnr = 20;& B, B7 s& |8 R5 F5 v( G" j
    setup.ssnr = 25;
    ) W4 {0 A/ y3 D' L/ y( Z1 |& i4 c; ^
    setup.roomDim = [3;4;3];
    : K- r$ g0 E  @) \% e" ]# q' m
    srcHeight = 1;
    ' R( l: {% J2 T# T4 W9 w# u0 CarrayHeight = 1;
    + E4 Y( `( I9 W, V# E
    0 Y2 O. t- |2 K0 `9 F- HarrayCenter = [setup.roomDim(1:2)/2;1];
    ; d" d. U* J# k' w7 t" T
    # ]/ k4 D& C) y! s. g- KarrayToSrcDistInt = [1,1];! {- g) r9 U- A$ Z+ ^& G/ T5 n
    " h: |6 G1 _7 Q; _3 `
    setup.srcPoint = [1.5;1;1];% d3 B  X9 u! F$ w2 }

    , _( v) _  V$ A; u) s  osetup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);, Z) V+ H8 ^3 w# K7 q

    ! A. J7 w+ |2 J' G- i! K2 r; R+ B2 a4 t
    [cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');
    9 f, e6 O. j& X; L( ^  A/ h+ z9 \* {5 T! |  t% |/ `- Y' _; ]
    %---------------------------------------------------initial end----------------------------------------, e( G9 V2 u! O0 Z5 ]/ [2 Q5 S

      ?- r. V: T$ F) b% k- \/ d
    $ r3 p$ d" |) G# o, E0 ^
    1 [( ~( T, E3 I! Z4 R: v%-------------------------------algorithm processing--------------------------------------------------
    2 W1 g0 }, n# h) F, P( S8 j: g; q7 V. E$ {- `
    if setup.reverbTime == 0,; B5 [! }1 g, Y& w: ?
        setup.reverbTime = 0.2;1 X) q1 u( n4 u; ^, T% l
        reflectionOrder = 0;: `" m# M9 B1 |( l5 E
    else/ g+ @% O' @+ t* ^( q. C; C
        reflectionOrder = -1;% @) e, l( y9 Q& f
    end4 q: a; z  Q7 J  A  K; T* ~; J
    + G1 Q& r; n2 D8 A! Y, x" d
    rirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',...
    " h/ w5 g3 D+ j/ m7 D* t* e    setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);* F- w3 d- \" t- I/ f

    ! X  k  d1 x* p) q, {+ S4 ~& }for iSens = 1:setup.nSensors,
    9 Q5 {1 ^6 c6 l8 u1 e: z$ `8 g# |0 C/ ]    tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);
    4 C! S( G. D  J& i7 N2 |& k, Qend8 i. v/ J3 Z6 d+ x. ?: Y
    mcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;
    # ~8 S) j' m' G$ P* X$ P$ jsetup.nSamples = length(mcSignals.clean);3 o  @" i/ t$ w/ c4 O

    ( Q4 q) {1 D9 d0 n5 R& NmcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);) c9 J3 j, q! e
    + K+ \& W; m% `. n* @) u
    %-------produce the microphone recieved clean signals---------------------------------------------9 m+ }( u! ]4 p. a/ A
    1 ?! I! D+ `0 c, U% X$ L& L0 S
    mic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold
    0 H1 ^7 t% ?* h* |' F4 ~mic_clean2=10*mcSignals.clean(:,2);
    % I0 e  K, ^, H  pmic_clean3=10*mcSignals.clean(:,3);
    ! y6 J- j, [# `mic_clean4=10*mcSignals.clean(:,4);$ m  R: B% x  }
    audiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);
    * {9 t- b  z$ s( ^: R: xaudiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);0 l9 V3 w+ ^* b, ]. w, \2 l! N
    audiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);
    ' {! F& r# U% p' baudiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);
    0 Q7 d+ V" s1 _* F  j; P- c7 [6 G: H, l/ r5 \
    %----------------------------------end--------------------------------------------------
    1 W' o( W1 u5 F+ z- J- Q' z1 L' e# ?  h6 }
    addpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);
    " ~5 X) I0 {& v# {, A9 M5 I
    # \6 G4 A  E6 C  qcleanSignalPowerMeas = var(mcSignals.clean);
    5 y3 ]! S! S1 Q/ m6 ]0 N. ?; x7 Q8 f/ }
    ; b, x9 {. `; b& I( I1 @5 S5 |& h) w, R
    mcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...
    4 r+ W4 _0 @# h7 b2 r0 E' S$ b    setup.speedOfSound,setup.noiseField);1 E. S3 R+ S1 l
    diffNoisePowerMeas = var(mcSignals.diffNoise);
    " \! E( H* W' ~2 s/ @5 l, wdiffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);
      a) C$ l! Q: T* AmcSignals.diffNoise = mcSignals.diffNoise*...' E2 _- i' ]7 X$ o
        diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));/ g6 Q- m+ |- P( \  D- p

    - q0 C* z- Z2 m' ^. RmcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);  n  m8 M  y$ C# ?
    sensNoisePowerMeas = var(mcSignals.sensNoise);
    ) D9 _( U3 Q) n, x9 ^1 F8 A7 asensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);( w$ K! f6 \3 O  d
    mcSignals.sensNoise = mcSignals.sensNoise*...' S3 B8 Y' Y0 D7 M" U; o: k/ E
        diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));7 o( ~. e* S' b" |- |3 {. v3 S0 \
    " D9 X; L. b/ g
    mcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;. `& H3 Z; ?# W& G1 I" ?% ^
    mcSignals.observed = mcSignals.clean + mcSignals.noise;
    " r4 J# t  r/ I, K5 X* c; k+ n# @6 `- v' t" i3 G6 Q
    %------------------------------processing end-----------------------------------------------------------
    $ N. O$ @5 {$ C2 \0 |0 m. `. P% K) T) u
    * O' U4 W  c. J, E' o& B2 V6 K* B1 w

    - L3 l/ M3 l; J& o5 l
    % O7 k6 c1 }# k- |; K- {%----------------produce the noisy speech of MIc in the specific ervironment sets------------------------2 U3 d) F  d9 H

    * g1 C! T, I& Y7 Knoisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold
    & {, D1 G/ _+ w0 W- enoisy_mix2=10*mcSignals.observed(:,2);
    9 ]6 b( ?  k8 C# {7 J1 Ynoisy_mix3=10*mcSignals.observed(:,3);
    1 p0 n- M) _0 gnoisy_mix4=10*mcSignals.observed(:,4);
    3 c9 g: x9 K9 H( e9 Tl1=size(noisy_mix1);& K' v; R4 t7 ^
    l2=size(noisy_mix2);  Q3 |2 E# @9 s. a. }; ^, u7 j) K
    l3=size(noisy_mix3);
    ' N4 c/ [2 Z  y+ L4 W- ]l4=size(noisy_mix4);9 J2 R6 P$ s0 W
    audiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);4 w/ s7 E" `( d* b$ V1 O( \
    audiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);
    0 _+ Q, P8 [6 U; daudiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);
    4 s' s% d$ L" I. ]0 Naudiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);
    5 j  q: E: c  h: Q' G- s
    ( j" w& B5 e; g. S' u
    , w3 C, r2 A2 q" C, _8 k% ~; ]( ?%-----------------------------end-------------------------------------------------------------------------
    ) |$ l; I) I3 ]: o8 F5 T1 q, v这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。
    $ W' ^- J7 U/ Q( m5 h直接把它们替换成你想要处理的音频文件即可。2 u/ u. i: b6 p! ^* s% Y& u  |) I

    " N2 v( o- y+ R  除此之外,还有一些基本实验环境参数设置,包括:麦克风的形状为线性麦克风阵列(该代码只能对线性阵列进行仿真建模,并且还是均匀线性阵列,这个不需要设置);麦克风的类型(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)。! ~2 g/ r8 m3 z  {3 P

    5 q* k- V, |( L. C# c; x* i/ G3 e7 S  ?% {+ p. d6 `

    9 B9 l" J# W* x$ q1 |图1 麦克风类型图9 r2 T) l9 B' i  W6 q" j" i
      y) }/ e. F! d/ @! I2 T% L
    图二 房间的坐标系
    * C9 s0 x6 t1 u# O  u3 y5 a% |9 `
    5 l8 ~5 k. M' R% M  以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。
    ! e$ t7 C4 P' l- w. f& B' O, D; P6 u! \————————————————
    # S6 o1 f$ I* p9 Y; e& E' [: g版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。' K) \. Z; w6 x$ k
    原文链接:https://blog.csdn.net/zhanglu_wind/article/details/79674998
    5 A" y+ t, `4 f  l: l' ?/ E
    3 M7 ^' q4 i; H; ]: h) f; k% A( y6 @/ G/ x4 W* 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-4-21 10:10 , Processed in 0.427002 second(s), 51 queries .

    回顶部