QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3304|回复: 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. 引言
    / c0 q% b9 r2 ?9 [8 Q; Z  之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。7 x" k, U8 q! e: {
    " z/ o4 Q, B7 l8 D4 M
      然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。& o! |) W5 Y: C

    ! g$ J/ {2 `7 m; p2. 代码介绍$ n: T0 Q, `, b, T3 n: _5 F' K6 b6 u
      原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:. {6 {7 H$ x! Q. x/ `
    function [mcSignals,setup] = multichannelSignalGenerator(setup)
    9 S+ P: ~+ i3 P) A
    6 `5 R" i+ X8 _4 X* I; e
    / _8 t( g& ?! A$ v%-----------------------------------------------------------------------! a- V9 F9 o1 [  ^" ~
    %  Producing the multi_noisy_signals for Mic array Beamforming.
      n% J, l" s2 d3 e4 s%
    - ?8 P3 o+ O1 J- v. S8 D%  Usage:  multichannelSignalGenerator(setup)
    ' v' x8 k$ ~9 ]6 C7 u7 \  I%         + f$ l4 C' R, l  G# o* |! L4 K7 u9 q
    %        setup.nRirLength : The length of Room Impulse Response Filter8 n+ t0 l6 k0 V5 s
    %        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default
      o% q6 Z" k" ?2 @%        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order.
    ! U, [2 |% c0 k& o%        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.
    ! K3 _4 Q' v, I%           8 w# o$ i. |5 T, g/ r) c6 V" |
    %        setup.nSensors : The numbers of the Mic
    9 b; p# ^! I" @) h3 t%        setup.sensorDistance : The distance between the adjacent Mics (m)* w+ H3 V" x- X; y) Z% K: I3 d6 o
    %        setup.reverbTime : The reverberation time of room
    ! R$ Y8 t. @2 r, P  s/ z%        setup.speedOfSound : sound velocity (m/s)' g# ?0 y3 T% v/ a) A
    %
    $ g0 I# W8 E* ^1 X9 b%        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'
    ' E" Q& Z. C& m%        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.
    - Z  ~( K, @: ^! b%        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.
    . H9 ?0 _8 S4 L) G2 I$ @%
    7 ~+ t+ U, `' G- e. Y( t%        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).           
    ) q; Y8 z6 [9 [3 ]  F& s8 R: f) `%        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m).
    9 V2 b9 |' a1 T1 l%        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m). * P& I+ U/ T" ?$ t) f. f
    %* v6 v# r$ j1 B. ?& F
    %        srcHeight : The height of target audio source
    # X; R/ a* x; f9 ~0 Q, v4 [- ~%        arrayHeight : The height of mic array  ^' M- c/ h( l: N. [  v/ {
    %! O- |) F; a! }. G, k4 j! M5 T& ?
    %        arrayCenter : The Center Postion of mic array
    # E8 `8 h3 o( p, U# k: N%3 Z: r9 z1 |, }# p, E4 g6 H3 C( i
    %        arrayToSrcDistInt :The distance between the array and audio source on the xy axis" ]* l0 g# P: a4 A2 E' [
    %4 Z# ]# r) s( f
    %                        ; {2 ~4 K  e& k0 s. L$ J; }$ [5 u
    %
    2 m. r5 D/ `4 X) Q%% {$ q( s& L+ I4 Y
    %         
    6 H' ?2 T( i, t%( E2 Y' o2 W0 H9 J$ F$ i: d
    %  How To Use : JUST RUN
    & x3 T& l7 c1 ^9 s  s( d+ H8 |%3 d' z* ~2 u; u. [7 w4 Q* F& w
    %  * e  O* W$ D  |
    %   7 t5 B' E0 x9 R, y; \" p3 D
    % Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),
    1 q( L  i/ \* Y%            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.24
    3 E1 t8 H: s9 Z0 K3 s% e# c%; M& P6 x# c- \8 n& ^' N' S
    % Copyright (C) 1989, 1991 Free Software Foundation, Inc.9 _  u1 L. x0 F2 y' {/ r) R8 H
    %-------------------------------------------------------------------------6 t, X$ R% H: M/ h2 F
    ' j2 h7 \+ r( M9 c/ z

    0 j3 E) N* H0 n* H5 K4 [" g6 y+ T0 m& y6 N( d) K- T
    addpath([cd,'\..\rirGen\']);
    ' Z' H0 R# T2 a" d. z9 q$ \% V  b& b( ^& r3 ^/ _# c
    %-----------------------------------------------initial parameters-----------------------------------
    ) Q3 ?: q* Z* K* r5 e: j5 y7 a
    6 j7 B/ J& O. p2 }7 Ysetup.nRirLength = 2048;
    ; ^+ _% i; f  esetup.hpFilterFlag = 1;
    9 S+ x: Y4 w( x$ ?* G! usetup.reflectionOrder = -1;
    1 T( Y, i, g6 |4 p  c+ `setup.micType = 'omnidirectional';: c. r% {! O  O! B
    setup.nSensors = 4;* V' Y6 ~# J9 ?  Q# S5 Z
    setup.sensorDistance = 0.05;" D  n+ M) x1 X( X4 h
    setup.reverbTime = 0.1;
    9 @8 r* Q: l3 dsetup.speedOfSound = 340;/ F5 a* _: N  t' H

    1 [6 `7 Y& \) _, msetup.noiseField = 'spherical';
    $ R3 [. |4 \, M4 E$ Z( f% d! ~setup.sdnr = 20;# Q9 f3 ]# m+ o; O) f$ E2 J# `
    setup.ssnr = 25;( i6 O2 _7 F, X& G
    & x: {- {. O5 ^
    setup.roomDim = [3;4;3];
    1 C+ B) P; c) C1 p& M3 R" W( a0 e$ s% x' f9 n1 }# e3 b
    srcHeight = 1;
    1 t: n; A0 k4 {/ ^7 e" o5 CarrayHeight = 1;6 \. w1 \$ w- e
    6 {$ W' `" w$ ~# x! G! T& U; X  w
    arrayCenter = [setup.roomDim(1:2)/2;1];
      y! S. s/ }9 I5 W* H- V- y( @" k9 e; Q, t. E4 C% I5 D+ X5 r
    arrayToSrcDistInt = [1,1];
    ; d) o, x; k* x* V* a  ^& Y
    ( g* ?! K: e2 l. P& j4 {setup.srcPoint = [1.5;1;1];
    , p7 |4 b" |5 E  z# A4 A
    5 t' v  A, o$ ?7 ksetup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);/ M2 T0 ]) G* v# E* T/ ^7 \6 }8 K
    , E0 F! X' Z$ l
    4 b% s" W6 u! l. {7 h! y8 N& z/ [
    [cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');
    6 g# D! F5 {% ^. a( t* f
    * ]5 h  n' d) k* u8 S  t# d%---------------------------------------------------initial end----------------------------------------
    & f( d( ~1 s9 {+ \* N7 r
    * q" D0 [6 m% s+ v+ i, ~' |  l; ^3 [5 C+ D# ^- D& x
    8 v" ?  n4 l, C# |$ V
    %-------------------------------algorithm processing--------------------------------------------------6 P$ I1 @" i2 s5 z: }; s
    * _1 B) K6 e  p* K: n3 R  n" c! u
    if setup.reverbTime == 0,. L- V6 D% T4 u0 D- E/ G" |
        setup.reverbTime = 0.2;1 d/ @# f" M4 T7 X6 E, j0 j- x4 [
        reflectionOrder = 0;
    ( J( j! f5 I: {1 v+ [else
    . T- U6 W2 x8 o  A; C# @    reflectionOrder = -1;$ L3 }" w+ L+ N
    end3 @3 M' _; C3 W7 m$ E+ F
    % S  B; C: K# Z; X' a, C0 O
    rirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',...
    6 i% S* @: V0 Z% C6 q' p% S    setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);, ^3 @5 e7 w0 w4 B/ x
    5 a) g. }: X1 G" r/ x3 u7 j. c5 ?5 N+ p
    for iSens = 1:setup.nSensors,
    / x8 p7 ]" J& C    tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);1 B, V% `8 X) P0 J% m4 e8 n, V6 ?$ \
    end- ?3 W2 P% [# H6 K2 y/ q
    mcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;7 h( ^- b$ j) ]7 x
    setup.nSamples = length(mcSignals.clean);
    - q$ l3 U; n" E$ Q) {2 P8 Z* i) K( S+ m8 |
    mcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);9 W0 K8 M* \' z% W4 l3 J3 @

    1 j# z# Z) ~/ p& Z%-------produce the microphone recieved clean signals---------------------------------------------
    / r6 _/ u2 H: Q& y/ B! K8 z: s7 j& k" L
    mic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold
    . ^! o+ Z0 ^. Y  jmic_clean2=10*mcSignals.clean(:,2);# y' g$ g3 o8 v% x
    mic_clean3=10*mcSignals.clean(:,3);
    2 o) J% f, R2 g' I4 h! u, vmic_clean4=10*mcSignals.clean(:,4);
    9 d' A& S2 F2 m( J. J+ l7 xaudiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);
    9 b1 e/ T% o0 N/ b( eaudiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);; w7 i- O+ D% I4 J: A
    audiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);* [. Y& m# P* I8 L9 }
    audiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);  @4 u! n- [3 D  _7 f' d4 \; a
    ) h, D) U" V- T! V; s2 t9 ?/ g
    %----------------------------------end--------------------------------------------------, v9 G9 F- M: `3 q) F

    5 z: Z" ~$ c. [0 i7 ]8 j) x) Yaddpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);
    " E% H+ S$ n$ b0 v( f9 C0 R( \* R; L. S2 g) h
    cleanSignalPowerMeas = var(mcSignals.clean);; B* k* _2 }  h5 ^4 A* Y8 s  n* O
    ( X3 F9 v" n5 M. i! B

    9 ~+ J$ u4 m, H# K' A. ]' u& K8 smcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...
    0 T" R6 J4 I& L    setup.speedOfSound,setup.noiseField);: T# z$ n8 _! n" ^4 a8 d
    diffNoisePowerMeas = var(mcSignals.diffNoise);
    # T8 ~3 n5 X) J3 n* a- u2 c9 B- gdiffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);
    % p- @6 c, l/ jmcSignals.diffNoise = mcSignals.diffNoise*...
    ) h" A# F1 e2 ]1 x+ o    diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));: m- g8 t1 D4 Z6 Y. C2 s# i5 q5 `

    5 G+ w1 {" i5 _! E4 hmcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);: q9 q( o& `& c
    sensNoisePowerMeas = var(mcSignals.sensNoise);5 A  @# Q* \+ M. \0 c1 |3 O4 T
    sensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);& @, @4 U3 G! N
    mcSignals.sensNoise = mcSignals.sensNoise*...
    : _; a7 l: E- G; s: J$ K/ F    diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));
      ~: B6 e5 `0 }5 `6 S, v$ a' `# I
    ! \. g0 ?9 O& m, N# \1 M! o3 qmcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;  ~- x: c# b$ m) Y* T7 z5 V+ `
    mcSignals.observed = mcSignals.clean + mcSignals.noise;
    - ?& \. Y) R# j' n3 Q) ~# m5 d: b
    %------------------------------processing end-----------------------------------------------------------' t' J/ j/ k( O. S" l- G

    5 d0 k+ C' w: \  Y1 T. f1 x
    0 H+ k7 N. n8 l* ?; J5 U
    % `8 l4 ?# a6 W% A' _; u5 q. t
    0 ]: Q1 [3 H7 X%----------------produce the noisy speech of MIc in the specific ervironment sets------------------------# j3 V& G9 q: _& D
    + u4 l" Q* `1 M, T1 c* L. Q4 u
    noisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold7 q1 N; u& R1 S- m& f
    noisy_mix2=10*mcSignals.observed(:,2);" m5 O( G7 d& o- ^/ E- T
    noisy_mix3=10*mcSignals.observed(:,3);6 t9 R& q* \7 N- {" y
    noisy_mix4=10*mcSignals.observed(:,4);) j" Q: c9 y1 y# e
    l1=size(noisy_mix1);
    ( c6 W4 [& C, Wl2=size(noisy_mix2);1 B6 {$ ^; B$ H
    l3=size(noisy_mix3);5 L7 m" b/ d( m; X2 b3 `  |
    l4=size(noisy_mix4);
    0 o1 ~' o% G: p% Iaudiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);
    2 r( i: K4 F1 s; T: Z1 oaudiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);
    / |% s. |, |: X, T+ m4 ~audiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);
    * }! l" {: \6 T: i6 `( h1 _audiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);) C; d# k' M" c' o% o

    7 F6 }( i* L; T2 D" s/ B: Y) c% k0 @
    2 r5 k. r6 H+ C% r# w9 E# o9 X%-----------------------------end-------------------------------------------------------------------------
      ?9 D) {7 K! ^$ i6 N这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。
    , h. q! B- k7 a, O直接把它们替换成你想要处理的音频文件即可。
    ' W- l5 o9 l6 G1 @5 E3 m4 p
    # |) V8 v1 s+ b0 q7 w# d  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 `6 |; \% [0 `! q: ]9 }
    5 c# }2 }& [- J) V. n8 C. J( e/ f- k+ h1 l- F0 u% O

    & O% u: a8 i- U6 O) Z. Q! g图1 麦克风类型图" M& P# K; H3 n9 k9 J
    9 k! k9 t' ?# ?+ d$ H/ H$ r
    图二 房间的坐标系- T( C% F4 F* X5 @
    + l; h: w! f4 b5 t+ T! |0 g
      以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。5 R$ w1 p% G: T, M
    ————————————————+ p7 a; k9 Q0 L. l+ ^- i; f
    版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。& v9 O8 M0 L4 l
    原文链接:https://blog.csdn.net/zhanglu_wind/article/details/79674998
      [: b4 V& b% g% w3 g2 n  n2 F5 s# X9 u$ _9 e% Y

    5 q2 [: q) D2 n7 K2 r
    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 09:21 , Processed in 0.457893 second(s), 50 queries .

    回顶部