QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3391|回复: 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. 引言
    ! b& ]4 T& K* F& ~2 b: I  之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。) ~3 z7 P4 |" C1 `9 h  Q2 n
    - F7 x3 |! U' Z; Q$ C5 a1 l
      然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。
    . w$ U4 i( ]/ e* F/ f7 j. |; ~+ W/ \4 ?. s* f& }: Q& |
    2. 代码介绍
    & u5 |8 h6 K3 |6 w* u/ H8 s  原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:- E( J' e9 y, X1 H2 ?0 ^+ Y
    function [mcSignals,setup] = multichannelSignalGenerator(setup)" S9 ?2 O5 X- C/ L6 e; M
    2 _- k' P$ M; `* O! R4 A

    + W; i3 l  K! a7 M  D%-----------------------------------------------------------------------2 B) j. N  r. @/ l
    %  Producing the multi_noisy_signals for Mic array Beamforming.. G7 D1 t, h9 h# f  o& j4 z" Y4 l
    %
    + P8 S& E4 |3 r%  Usage:  multichannelSignalGenerator(setup)! q, r! t* j. G1 q( v' _
    %         
    5 A+ l- |2 l; `%        setup.nRirLength : The length of Room Impulse Response Filter
    2 M% m( F0 f  l6 [%        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default
    . h8 ^  Z5 s7 S$ i%        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order.
    ! v! j: a# Z) q  A$ F%        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.
    7 T$ B# M1 w" O4 r+ ~. ^% L%           6 }$ c8 x% x) M7 Z* d; u
    %        setup.nSensors : The numbers of the Mic
    6 h+ k) _" Y) K! v& Z: r%        setup.sensorDistance : The distance between the adjacent Mics (m)8 P* r: M- p( j% A  q9 r+ ~3 e2 i3 \  l
    %        setup.reverbTime : The reverberation time of room2 x& c3 c6 H7 J% W; S& ?$ J2 N
    %        setup.speedOfSound : sound velocity (m/s)  m% l0 `' r! h* s( r
    %  s- Q0 W& P6 @, L
    %        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'
    / }. [' P3 e8 f& B, p%        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.: K* c1 @6 k3 k# V; K% N
    %        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.
    0 w( C/ `- f# L7 G! h5 a6 F%
    - P* W: T9 `3 @  M%        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).           $ a$ Q% j" m4 ?7 S) P5 D, E
    %        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m).
    : {6 b; t  u6 B$ J1 D8 a4 |+ h8 V%        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m).
    , Q8 G! k5 a7 {& o5 J0 Q3 j%
    0 z7 U% V' p$ t# F$ i# |/ s%        srcHeight : The height of target audio source
    + b' S9 \! S  C: m# v; N%        arrayHeight : The height of mic array# C; t% N' _, F( K* J% X
    %3 k  h# W% p  C2 U' k- J
    %        arrayCenter : The Center Postion of mic array 6 A3 Y  \* A. |2 t
    %5 d1 H' B2 M3 D
    %        arrayToSrcDistInt :The distance between the array and audio source on the xy axis
    2 O- q/ E' J; R: d% t: U0 L%. b, Y* m$ y; U7 B' `7 q3 Z
    %                        8 Z, Z& {$ o8 U" o$ r1 a1 U/ A8 A
    %: y$ ?0 ?8 M' e; P' f  G
    %8 v; D4 g( d7 {; p) J4 [
    %         
    & N' h/ L! |" F5 s4 f; d# x4 J. j%
    - _: F/ z/ C" w%  How To Use : JUST RUN
    * [+ `8 ?0 c+ O0 o/ v: t! c8 n%
    ; g9 m4 C. g- ?& a6 D% H%  3 T' k9 G+ w: }* ^% ~! }
    %   
    ' ~6 i0 O2 D8 B- ]$ Z% Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),
    % H1 M2 |! Q" O8 G: R; ]0 w%            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.24
    6 S" Z4 B, A: V4 \; k: }6 G2 [%
    4 ~' h! j# R$ m$ h% Copyright (C) 1989, 1991 Free Software Foundation, Inc., N, y1 @9 ~/ ^! t
    %-------------------------------------------------------------------------
    5 V: i! p: }/ p% E
    ; D- H: D) ^! \7 K# j9 h$ a/ f' X/ v0 k+ U9 f% w

    $ L  K+ m$ ?# t4 |6 saddpath([cd,'\..\rirGen\']);
    " ?1 L; O; J+ y. `- u7 B0 Y6 |) D3 c* @3 L! J0 Q  x/ G$ {, A
    %-----------------------------------------------initial parameters-----------------------------------
    + |5 b, J8 |: C, |# m) F0 o# V$ _, A3 S2 h- |* ]9 a6 a* F
    setup.nRirLength = 2048;
    $ i4 e7 ]- E, u0 x6 t) S3 _setup.hpFilterFlag = 1;* ~5 V$ x) m+ \; T
    setup.reflectionOrder = -1;
    ; k4 n& c( R7 }& C  J1 ~& N5 Msetup.micType = 'omnidirectional';8 X$ a1 E6 d3 J: v4 k; t
    setup.nSensors = 4;
    8 Y) C+ {0 K( C0 f+ n& |setup.sensorDistance = 0.05;) V) ]2 D# W* s7 u3 D6 ^4 c
    setup.reverbTime = 0.1;
    9 D8 N- K5 |) O1 Isetup.speedOfSound = 340;* ^1 s( Z8 J5 E  Z* q/ o
    9 Z- q, T3 U" W* j% V8 _! }
    setup.noiseField = 'spherical';1 T! I, `* d* Y3 G% R
    setup.sdnr = 20;
    6 H- g0 x  q. I2 P* bsetup.ssnr = 25;- ?. m( z% m" L; N' b

    9 f9 V: q; H5 b/ }( R* jsetup.roomDim = [3;4;3];
    : n; W9 i8 f3 f4 W  f0 S/ r7 N$ K3 A* }; r9 Y& @
    srcHeight = 1;
    * G7 Z( F2 E9 a5 j7 R4 karrayHeight = 1;
    + h$ [* G' e4 _$ ]
    + X$ }1 Z7 q7 c6 c4 sarrayCenter = [setup.roomDim(1:2)/2;1];
    6 c3 P: t7 j7 g4 M& m9 ]2 {  S3 C3 }' q6 W6 Y
    arrayToSrcDistInt = [1,1];
    , n# S+ i$ @; d. n5 N9 P! ~6 ^/ B! ~
    setup.srcPoint = [1.5;1;1];# n5 {7 ~* Y7 G; @

    ( g9 C' l7 _$ s1 r1 X' S# `setup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);  M5 S4 p# u; U3 B

    4 B' ]! @) F& I' R2 d6 l' U7 Y- Q9 z, T9 a" f
    [cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');
    7 @. M3 l3 r6 W6 s3 S3 _6 H9 o6 E+ r3 B8 f
    %---------------------------------------------------initial end----------------------------------------# W, C2 V' Y) B% G

    # R4 l- Y5 o' U" q( f% a2 p; ~6 |! c" x! U/ h

    4 |& {6 ?' s: ^  Q%-------------------------------algorithm processing--------------------------------------------------, l( i3 \* z8 N% ]# ]

    2 t# d! y: r" A$ Q9 a+ Z# f: F- g# d9 uif setup.reverbTime == 0,8 }  \6 X* S/ D  _* N0 v" E
        setup.reverbTime = 0.2;
    ; u% O9 B3 B7 v* ]( G1 v    reflectionOrder = 0;# p" |& y! |7 `8 Z8 Y4 p8 z
    else& D7 p5 E# [* U1 [) h4 h& x
        reflectionOrder = -1;/ K9 D2 ]1 |& C
    end
    / N" ~' Z/ X- A& S% x+ N* O. L4 o6 F) A" K
    rirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',...
    " _0 G) _1 A' D! S: x9 c# G# x    setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);
    ) Y& z$ z5 E; F* H0 d* c5 }# `
    7 E; S! e' l$ ?! k8 ufor iSens = 1:setup.nSensors,; n  r" E* s- i5 V; r5 F
        tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);, V3 K6 Q2 i; y1 ]0 p- C1 r
    end
    ) c, O6 d0 X7 @5 P$ N* S5 MmcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;8 @% s. s: _4 u2 K, I4 v; {! ~
    setup.nSamples = length(mcSignals.clean);/ O, Z! u8 `0 S* o( H5 h) I
    # ~" V- Q3 n& n/ [  O
    mcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);
    % Y& z: Z4 N- t! |' D- H5 p6 A) c4 c/ v
    %-------produce the microphone recieved clean signals---------------------------------------------3 ?! Y# e1 e+ M/ G9 O

    & V+ O" b! q' {9 ?& P7 Gmic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold- M0 W  g% f& e0 P0 V9 v
    mic_clean2=10*mcSignals.clean(:,2);$ Z! x9 {$ F' m
    mic_clean3=10*mcSignals.clean(:,3);0 M- d/ G& P! I
    mic_clean4=10*mcSignals.clean(:,4);. M4 e  F2 O/ }* N
    audiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);1 T8 ^) r- a& ?; ^, S
    audiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);; x) }1 ~6 P  E3 d; N# d) N
    audiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);
    6 M; @6 W8 N5 Z8 |% Waudiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);+ O% f/ F% k) o- y) y2 ]+ ?
    ! \% I' {( V0 t5 Q' ]5 q
    %----------------------------------end--------------------------------------------------5 Z% N. `0 d5 e
    & `9 G7 N! U) G+ }
    addpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);8 B$ O: ^: k, K. e( S
    5 H' D9 t/ p, c
    cleanSignalPowerMeas = var(mcSignals.clean);, c4 ]- L2 M+ N$ ?9 P' F+ i/ ?

    - J' O, c8 `! t, Y1 D# c8 y3 A$ E. P, Q* O9 P9 o+ z
    mcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,.... X( G  x9 [& V! q( w5 t6 a. G
        setup.speedOfSound,setup.noiseField);
    9 i$ h. D% }1 N( h- f" odiffNoisePowerMeas = var(mcSignals.diffNoise);
    ' a0 ^6 o3 h& c3 L, ydiffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);" i, y* q7 k& k" J/ @" g
    mcSignals.diffNoise = mcSignals.diffNoise*...* b6 V/ Z9 }$ L
        diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));& ?. E  p( y% I' q6 G
    + z% k- y/ g' Z7 t7 S
    mcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);! W4 T' R8 P0 f) [
    sensNoisePowerMeas = var(mcSignals.sensNoise);
    * y: h' W) u8 y" YsensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);+ @7 H4 v) q- m/ f7 l) e( O- o, o
    mcSignals.sensNoise = mcSignals.sensNoise*...
    7 i; t8 n* t& S, M- y* ^1 t: i, H    diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));1 S. x$ a6 S# T7 |, k# ^1 b7 Y

    5 |1 I: u2 i6 |/ j: J# DmcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;! t2 ~" Q/ q- f2 L( F' n8 Q" G+ k
    mcSignals.observed = mcSignals.clean + mcSignals.noise;# E: _* M( y" I4 j

    ( Y' m; {0 c( b$ r) x, h%------------------------------processing end-----------------------------------------------------------3 c8 t6 B+ b! S. b/ N# b
    ( Q0 y* @( ]! E; x4 ?' P7 U% a+ e

    6 N3 |+ Q0 V. X( D' u
    8 p0 s- L" o4 g: R/ V; S+ c$ L. }3 q6 Z4 v
    %----------------produce the noisy speech of MIc in the specific ervironment sets------------------------  v- s) n; }; L/ {" n6 i# d
    % K+ Y! a5 O3 l8 x6 L
    noisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold
    9 l, k# D7 d( E5 {4 r) U" Tnoisy_mix2=10*mcSignals.observed(:,2);
    7 Z6 x9 ]( K0 F: Q0 mnoisy_mix3=10*mcSignals.observed(:,3);+ B6 b+ x* @- h
    noisy_mix4=10*mcSignals.observed(:,4);
      s& O' W" ~" m7 ^7 Rl1=size(noisy_mix1);
    5 h& G. w  Z  Gl2=size(noisy_mix2);
    ( G' h4 ?9 h2 Cl3=size(noisy_mix3);
    & ?+ G4 T: }1 B2 l0 X0 cl4=size(noisy_mix4);
    ' R$ ^& J9 z  ?! [audiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);
    $ p# M9 {( V, c7 n+ q' H$ oaudiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);
    ' l/ ~1 K! _+ l9 J: J  j* qaudiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);
    ( t4 E4 o6 [# f- ?. ^. ^. Saudiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);
    ) [' q! P+ K4 d  ~: ]
    5 j: T: |+ \$ ?9 Q; O4 t5 O& ?6 Y+ b% k' I) V# y& ^
    %-----------------------------end-------------------------------------------------------------------------; R: }$ H* e) \7 {( n  ]
    这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。
    & C  u) B7 v  B# u- B直接把它们替换成你想要处理的音频文件即可。7 l, z6 H4 D) B2 @0 {- y

    ' D5 ]& R, ~' o3 F( ~* A9 a  除此之外,还有一些基本实验环境参数设置,包括:麦克风的形状为线性麦克风阵列(该代码只能对线性阵列进行仿真建模,并且还是均匀线性阵列,这个不需要设置);麦克风的类型(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)。
    " E: _/ f% Q9 Q- V" `# `6 U: x( b7 }' w

    1 d2 y0 d/ l2 f% |- `4 D8 Y3 S& F! I7 D, k: W
    图1 麦克风类型图( Q* k0 J+ N9 f
    $ Q2 a2 S$ O# x: z# d  A0 x+ h
    图二 房间的坐标系
    1 C$ `( B& P9 m- E, M4 p
    ( V8 d& j+ l% c1 c7 R# p  以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。
    : L/ N1 X" o! p9 h————————————————
    & i. ?+ p/ ]) B5 y) g版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。  r1 G2 [( \3 ?6 ?; W6 Z8 y
    原文链接:https://blog.csdn.net/zhanglu_wind/article/details/79674998) J3 e# N2 |' w, F* D- C

    1 P- i8 B( O7 d6 ~8 J8 G8 p
    $ p5 L. w0 A- G. y6 i7 ~# i
    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 08:04 , Processed in 0.363116 second(s), 51 queries .

    回顶部