QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3345|回复: 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. 引言( s- E7 g+ E" w) A# P: ~
      之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。* k: i/ a4 m3 e( L; g

    " F0 g, v% T3 p; {2 N, n9 l5 d. _  然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。; g: {8 @5 s# p( K9 S5 G
    * U0 p  l* B0 q1 S: q
    2. 代码介绍
    6 K" }/ u. Z! |' [$ N# X8 x  原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:
    ( i4 g- ^8 R5 U( n% e) r2 efunction [mcSignals,setup] = multichannelSignalGenerator(setup)$ c" X: o% Z- w: X! s. r, Z

    . f4 n! k+ A$ S* |) A$ v
    1 i2 B" P8 }; h%-----------------------------------------------------------------------" \+ ~  t/ [# I1 A
    %  Producing the multi_noisy_signals for Mic array Beamforming.! w5 E4 V& G4 K* p& u
    %
    8 R0 C; l3 W; C%  Usage:  multichannelSignalGenerator(setup)
    3 J* N3 Q2 D# s1 Z; s%         / F8 X2 `7 X4 W1 q; y4 r
    %        setup.nRirLength : The length of Room Impulse Response Filter9 {' J4 n. P; R8 g  l& b$ Q- n
    %        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default& M4 e$ _/ D7 Q
    %        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order.
    3 C$ T! k9 P5 V, m9 Z2 ?7 N%        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.* d: j0 y5 a* P6 S. Y
    %           
    8 K. E  B2 G+ J6 R8 M7 U3 H%        setup.nSensors : The numbers of the Mic
    * v) o  h% y$ c% E0 M0 z%        setup.sensorDistance : The distance between the adjacent Mics (m)
    , w( i: Z% ^7 H9 ]$ V%        setup.reverbTime : The reverberation time of room& O1 A8 D+ `/ A" A. s
    %        setup.speedOfSound : sound velocity (m/s)$ V0 @  |7 m1 w1 c" U& ?7 E
    %9 E( J/ q; d# F4 u
    %        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'8 z+ u- \& O' J# n
    %        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.
    * Y5 G$ n% L7 }: q% T4 t% l%        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.9 g8 h6 a7 T, L
    %3 N7 l6 A8 j6 T
    %        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).           - ]+ e; K& I- p+ I2 ]8 m
    %        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m). / m6 ?( n& L9 w2 g$ E- i) |
    %        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m).
    + Y% T, Z1 Y' o' I2 i/ c  d5 l%
    , [2 b8 ~- q/ d& T7 x%        srcHeight : The height of target audio source2 B! N  ~2 u' z1 G& P" A& N8 J
    %        arrayHeight : The height of mic array3 W& R2 X% c0 q7 Q
    %7 ]+ D3 h& }- h/ `, R4 ?0 z
    %        arrayCenter : The Center Postion of mic array
    ! x! p* ~' p. c) a9 P0 `%
    5 @6 p3 E* `% v1 r  ], a! W4 x%        arrayToSrcDistInt :The distance between the array and audio source on the xy axis
    ' o# j0 B! k4 P' r# i4 ]' w%2 A4 U9 E) z5 o  _8 k4 ?
    %                          t8 P) W" _! M) y
    %; v, W- _9 V1 b- p- o
    %
    2 w9 G6 e) u$ m%         
    + s" y+ ?) Y: I4 G- v( e* }. n5 }%
      T5 Y( h) B( \%  How To Use : JUST RUN
    9 w/ B7 i4 }$ p* q4 H! J( C%
    * e6 F0 x' X8 K8 r$ N, H+ Y%  
    $ b$ Z9 K" y- J+ x8 [%   
      U; K# D" B: a" m% Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),
    9 U/ ]( J1 W# Z" |! @+ w1 n%            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.24& u; x' C9 A) u7 v, P
    %0 E, s5 @' M; \8 V
    % Copyright (C) 1989, 1991 Free Software Foundation, Inc.
    5 h: ^/ n6 P( `* X%-------------------------------------------------------------------------
    & v9 f. L/ O0 T- j5 U/ F2 F# X
    8 `5 \* \% o4 Q( ]) G2 p4 I2 n( y$ A, Z
    ; m$ H6 m! m% y9 j+ W
    addpath([cd,'\..\rirGen\']);$ p! S) g' x6 p$ f" a% }  r' N5 |

    1 S+ c1 s! [6 R%-----------------------------------------------initial parameters-----------------------------------
    ) l2 ^- E7 C$ s' w1 f
    ' u7 I$ ~" w' @# {setup.nRirLength = 2048;9 U% J4 N& W! U# M
    setup.hpFilterFlag = 1;
    # m1 A* {/ O3 `5 s) {$ @% bsetup.reflectionOrder = -1;
    1 E  o% w7 s; C# c1 Y# K, `setup.micType = 'omnidirectional';
    9 l$ x  W: \1 [; p% V1 vsetup.nSensors = 4;
    4 R* a9 s! C7 d1 @$ ^setup.sensorDistance = 0.05;# _: a& X2 d3 q- X3 q9 x( K
    setup.reverbTime = 0.1;
    , Q( B9 Q( G" T" Y8 hsetup.speedOfSound = 340;2 H- s& L; ~# }: v" g

    # }+ ?+ o- P% f  msetup.noiseField = 'spherical';$ {4 c# j+ O8 H$ f3 I
    setup.sdnr = 20;
    5 J5 ^1 r: f- ~8 q$ P% hsetup.ssnr = 25;9 |: Z( j' ]% I8 x! [- K

    3 P2 ^  I4 s2 a0 ?% Gsetup.roomDim = [3;4;3];
    8 j7 D' l  T0 P6 ^( `, n! v' q7 L2 I* H7 y1 n# q2 n
    srcHeight = 1;- [/ Y! J, x" G$ ~; [( |. ^
    arrayHeight = 1;
    # Z; b4 \  s  F6 i6 i4 r& G7 |6 X
    arrayCenter = [setup.roomDim(1:2)/2;1];
    ) F& t8 H9 H, J- }0 ?) b! m( T
    9 t: P+ ]. c; G8 h/ H9 R# KarrayToSrcDistInt = [1,1];
    ! f3 V. D. D% {1 X& ?6 f4 _% _% U" B6 T4 u3 G
    setup.srcPoint = [1.5;1;1];' B# |. O0 H6 W' H: G

    ' e7 O+ [2 @0 bsetup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);
    # z; S  e4 n( }' J" N
    ) Z" p8 ~+ L* o+ G+ K# g/ j4 Q
    + j) M3 Y) S$ n7 ]6 i# [  i[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');3 s2 z$ z4 C+ h

    $ j& \" _( j% U7 o$ j%---------------------------------------------------initial end----------------------------------------8 |/ C6 U3 c% V% N  Q
    / u) n  }" h. ^5 W
    % G9 g3 Q8 B2 U# |
    1 H, q* h: x5 z" Z
    %-------------------------------algorithm processing--------------------------------------------------
    , y* z! {7 {& Q  F# A3 T6 I- C2 w6 Z2 H, K% O
    if setup.reverbTime == 0,
    . |9 i" _7 X4 Z    setup.reverbTime = 0.2;
    * N/ V# R7 W+ k5 x- Q3 \    reflectionOrder = 0;
    ! f% O+ \, N1 d" L9 t8 R1 I3 Telse
    # V: |1 Y9 w4 W+ b: E: l2 B0 K3 u  e    reflectionOrder = -1;( z; W4 I$ A" ~4 L6 q& B0 P
    end0 X* w; F$ o& t' j# b
    7 z, P; i, Z: h  v0 ?4 ?0 z
    rirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',...
    5 H; s9 ?; _+ y3 d+ l1 A& t/ {    setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);
    1 q, k$ o6 y- L$ U1 `! F4 N! n. I, Y, l$ {% U' s
    for iSens = 1:setup.nSensors,
      q: y" B3 c  T  ?: r    tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);
    7 O  t, |8 i7 A3 c) gend+ j+ ^, [. A6 S0 g% B
    mcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;7 X5 b9 T! }4 p9 T
    setup.nSamples = length(mcSignals.clean);
    0 x* @4 ]( h1 K* F9 R5 ^
    6 A( s2 k+ p0 e* v0 VmcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);* s! _( s: C  b/ U$ v% G

    8 w  Y$ j- I0 N4 d5 X7 B, u%-------produce the microphone recieved clean signals---------------------------------------------; ]- p. @- p3 m' Y4 k$ c

    * J: [* w# S$ [6 m, c& I. {7 Fmic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold
    " ]# ^/ b% L4 g- \9 ^: Zmic_clean2=10*mcSignals.clean(:,2);+ T$ Y5 W7 {4 d
    mic_clean3=10*mcSignals.clean(:,3);3 ?0 m: h& F- W* k: J1 h* o" J
    mic_clean4=10*mcSignals.clean(:,4);
      A4 E+ z; G. O% d7 h& }* w, Z2 ^1 Iaudiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);- [; q" s3 \9 G5 O5 t
    audiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);
    1 q* b  ~& V0 p9 laudiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);
    : A% O9 f$ N1 s% waudiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);' m# S0 ^' |* ^; T9 E
    6 v* E/ [& X" R: d& |4 U' m) p
    %----------------------------------end--------------------------------------------------3 @3 C  g  x5 A2 }  `- b9 O
    & O; m4 D. c4 K/ {, Q: M+ e: b
    addpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);) R, G2 J' u! a

    ( B0 w2 ~3 |3 K$ Y0 U0 n3 R& bcleanSignalPowerMeas = var(mcSignals.clean);" n3 `- ^% I1 n- O
    . M2 `- Q* l! t! U
    $ v6 a+ B! _1 l  H( E
    mcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...
    5 g( `* M* A) F! [1 n    setup.speedOfSound,setup.noiseField);
    & h9 ?# f6 m% D8 a8 I6 NdiffNoisePowerMeas = var(mcSignals.diffNoise);" x9 L; y% `, A' Z2 W
    diffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);& Y' l8 z$ k3 d/ O2 c7 B
    mcSignals.diffNoise = mcSignals.diffNoise*...* a- Z/ b" i+ N- d5 i5 H$ d0 J
        diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));
    ) P3 w9 P2 Q# O: _
    + ?+ m! l4 U; `/ B1 omcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);
    - F# e* Q2 E9 JsensNoisePowerMeas = var(mcSignals.sensNoise);
    * y3 o1 K* O5 U( ]: IsensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);8 W9 R( b2 C8 h& g) c
    mcSignals.sensNoise = mcSignals.sensNoise*...
    0 @+ D$ _9 S* ~% g6 H" Z; J5 e& D    diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));
    0 N, F) m+ S+ S6 j% U
    - Y9 V& p3 h0 ^! EmcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;
    - V# ?& X2 j6 e; Q! |4 {mcSignals.observed = mcSignals.clean + mcSignals.noise;8 ?4 e" @6 a  `, A
    7 H) v4 R, G# U3 |4 V9 R% ^' D
    %------------------------------processing end-----------------------------------------------------------' x9 N% L! ?7 v- B% b7 V

    " \' h0 B* v1 ^: r: e
    7 ?  ?  v) O- ~1 z" X! [
    6 D4 ]! _6 f( ]; B; h
    ; G" s3 }5 z0 \' I. }% Y%----------------produce the noisy speech of MIc in the specific ervironment sets------------------------0 J( \' R2 v1 V, _  D
    # C% `3 l4 p& U
    noisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold
    & ^- I6 H7 Q+ W* j% n: Rnoisy_mix2=10*mcSignals.observed(:,2);
    % x2 F: A5 @$ R9 D: M5 O( D7 lnoisy_mix3=10*mcSignals.observed(:,3);
    ) Y  C! W5 X* M, b, q, K1 Ynoisy_mix4=10*mcSignals.observed(:,4);. q4 w# V8 U  J5 ]% r1 Z7 ?
    l1=size(noisy_mix1);
    + w3 T! X/ i% W- T5 G5 `l2=size(noisy_mix2);9 P9 S2 F7 e" N4 @* N; M
    l3=size(noisy_mix3);5 z6 l, p  x5 i  g% B- B* p
    l4=size(noisy_mix4);* M8 c; S) b3 O* `0 |0 b
    audiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);0 `4 ^6 K: F" g/ n( i
    audiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);
    5 D( A# x; B5 E- v6 `+ Z8 [) qaudiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);
    ) J1 v. i8 j* f$ o* G1 Kaudiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);( v5 f1 B6 n8 P' U

    4 y1 M& Y  A7 u$ Q9 ]# P% I2 U  c  K
    %-----------------------------end-------------------------------------------------------------------------0 c! L& h" t- f/ H, C
    这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。# B3 c5 M; U" T$ D2 s# ~
    直接把它们替换成你想要处理的音频文件即可。
    . |0 ~- c, m( _& o9 G1 P) w! H. z) Z
    4 T2 i7 c$ z% l/ K2 _' v1 D0 |  除此之外,还有一些基本实验环境参数设置,包括:麦克风的形状为线性麦克风阵列(该代码只能对线性阵列进行仿真建模,并且还是均匀线性阵列,这个不需要设置);麦克风的类型(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)。" G" N6 O2 P  G6 Z6 W( x$ L; \

    8 Z0 v" H$ l" f( A& l& c& B# r- n" h5 M6 O( r
    6 d: X1 r( `& W! a7 ~4 n
    图1 麦克风类型图1 g9 w( R( \  J% P$ \% T0 |
    % W! N/ X4 B- b# |4 T% M: S
    图二 房间的坐标系
    # f. ^6 [7 i! ]- v5 h$ B
    + d$ h5 {+ z2 {) D  以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。4 w* v% Z6 s% ?
    ————————————————& o8 {1 G4 G: G, O7 c( r  L1 x
    版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    ( }5 F+ s  N4 i& G6 P2 T- A% {原文链接:https://blog.csdn.net/zhanglu_wind/article/details/796749981 T8 X& @( s7 ^  o7 N* ~

    9 [; u/ T$ `6 w& [3 I9 [9 a
    ) @3 J5 a# j1 P' y  q2 `0 Y
    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-15 13:07 , Processed in 0.437133 second(s), 51 queries .

    回顶部