QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3306|回复: 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. 引言
    1 P7 h( S1 G& Z- B) F: o$ ~, x& K  之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。1 |- L1 _# V  m0 C# ^6 P

    9 R2 j$ @* P$ T" t$ ^5 Q/ k  然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。
    5 }1 w: W( P; _3 h
    ( B$ h% H  J$ u2. 代码介绍$ t' v% ]3 A$ v+ b7 l
      原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:0 Y0 m- ^, W( u' j
    function [mcSignals,setup] = multichannelSignalGenerator(setup)7 O9 G  y) J+ C8 x0 K, r  P$ H& Q8 P9 W
    * V5 U" {, @" Z  T+ U
    % E+ n7 S3 U* a; a8 f
    %-----------------------------------------------------------------------
    0 n: J+ l2 M- P) @2 ?1 G%  Producing the multi_noisy_signals for Mic array Beamforming.# G- b) _" B  {7 p* W: g2 C3 ~( h3 B
    % + i- m/ m% B7 R3 ~' b4 J' U. G6 G0 w
    %  Usage:  multichannelSignalGenerator(setup)
    / H# G; X2 n. x8 m+ S& y! e%         4 j1 x* q, X3 A  v  H
    %        setup.nRirLength : The length of Room Impulse Response Filter
    - T* \* q8 Y* v$ u9 |- E%        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default1 M7 U' H- J) n& p9 s1 q1 a! V
    %        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order.
      r6 p( D* C. r& F%        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.
    " ^" B9 }7 L/ H; t5 ~( j) y%           $ R" F* M5 Q, ]" ~
    %        setup.nSensors : The numbers of the Mic
    ( G- N0 @( A( n8 I%        setup.sensorDistance : The distance between the adjacent Mics (m)  z+ _& x  W* p- s
    %        setup.reverbTime : The reverberation time of room: t4 l8 l/ b4 c7 _: A8 U' @
    %        setup.speedOfSound : sound velocity (m/s)
    2 S' h" ~+ W" y8 \$ G# R: @%1 H9 d8 b' `3 P! @- U# s" |& N
    %        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'
    - c* j! H) m. s  W# r+ Q5 L%        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.9 C8 X- a8 p. r
    %        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.
    8 h+ w  T' e0 u, _%; c: m% b9 L9 H+ p; h
    %        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).             a5 z  l4 `& |0 ^2 G
    %        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m).
    8 O# `; d8 v' T6 K" P) t: Y8 e%        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m).
    8 o& |6 Y' }1 t% P%
    , X* f* G4 O4 M) `& e* k( b+ Y%        srcHeight : The height of target audio source
    " D( k% p' |* }! Z%        arrayHeight : The height of mic array
    9 `& B- k" ^( ?5 r  K%
    ! s$ A3 @  m! L' R4 I* W$ M% o5 R%        arrayCenter : The Center Postion of mic array 2 _) B2 ?, T  Z& C4 V
    %
    ' v9 z! W& m) L( |%        arrayToSrcDistInt :The distance between the array and audio source on the xy axis2 a  T5 ?) ?& W+ e0 U: B
    %
    9 V5 g; b& @: z+ c! \- M%                        ) [/ b3 Z- q% x# r: Z4 k
    %
    7 m% j: g2 L+ V% a. W%8 C& P3 C/ V4 }4 j' m
    %         ( C$ R& S: L1 x; |. H
    %
    / B3 T2 m0 M  j- K- g8 _, h& e1 {%  How To Use : JUST RUN& i& |8 j3 P  ?6 B: k6 N- N) ?" w
    %
    # J+ e' q9 `8 C! j- E; a8 W! i%  
    6 ?0 c1 W6 k- R0 h5 t6 X%   
    ; j4 P. v. @7 k% Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),
    / B0 S9 K2 P" N%            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.24. F: }1 ~1 R0 |# `
    %
    & Q" ~8 g1 }# Q" ?2 a: Z4 u% Copyright (C) 1989, 1991 Free Software Foundation, Inc.  i6 P& j) k3 R" G; ^
    %-------------------------------------------------------------------------' t: Z0 g4 F  J1 m
    & C+ N4 k; z) F* `# \

    / |6 B( M+ G4 i
    ; v4 z* C0 i" t' O* J: ?addpath([cd,'\..\rirGen\']);) k) f% Q8 g4 z
    % D. i) E: u' K% v( o# |
    %-----------------------------------------------initial parameters-----------------------------------
    / }! r5 t5 ]# ^) f) l- ^
    8 s; a6 i# r5 K& Vsetup.nRirLength = 2048;' b$ |7 P5 u. U2 F! W/ H2 _! `
    setup.hpFilterFlag = 1;
    3 M+ T; E9 e; Z. K( Y4 Z3 n/ hsetup.reflectionOrder = -1;+ `# o8 C0 `! T2 _9 x& T4 O" C" e; s
    setup.micType = 'omnidirectional';
    & i. [# h+ ^, D4 R: s% x6 Qsetup.nSensors = 4;) w5 l$ ^) }& B. [
    setup.sensorDistance = 0.05;2 a: M, H" A6 v$ Z
    setup.reverbTime = 0.1;
    0 |, I" }0 m9 f2 d. qsetup.speedOfSound = 340;$ i  M1 N: F& ^0 A

    " B7 y6 T$ b' Z$ F! |* Asetup.noiseField = 'spherical';
    2 k7 i4 g4 ^, e  a# rsetup.sdnr = 20;9 ]7 @$ g# A9 J6 B
    setup.ssnr = 25;
    0 o! \  q! Z; h& _& m+ J4 h
    $ p4 t# S9 Q1 V: M) B# O+ Bsetup.roomDim = [3;4;3];% b. \% u9 a" N/ N# r9 Y
    7 p2 g% c5 m1 E+ o: n
    srcHeight = 1;# H* K. L4 _1 R
    arrayHeight = 1;3 c- r/ F$ H% H8 Z3 K/ Z7 [
    9 ^7 p* j6 y  X8 Y: E
    arrayCenter = [setup.roomDim(1:2)/2;1];
    ' Y7 S0 H3 @- t9 D3 U1 P: P5 B/ O
    $ ~( U! z3 c+ ]  Q6 c& XarrayToSrcDistInt = [1,1];
    ( z8 q4 `: y# Y# V; A6 R. M+ ~& ?' J5 K; e3 d& e
    setup.srcPoint = [1.5;1;1];
    & P- O3 A0 Q6 {  `1 @
    * W: Z6 k' [. }% I) _setup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);
    ( i# }# r" L/ y$ m
    3 w' O, L4 ]0 s9 N8 W0 l- e. B8 Y
    [cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');
    9 D6 l* N  `+ C9 m" C6 ~  ~4 g: d' ?& @$ C4 R# c
    %---------------------------------------------------initial end----------------------------------------3 V& w/ g* R) }. W
    : Q6 w5 l) Q, C$ i
    1 _2 ~7 y' b4 L1 T5 z- D$ n

    , k. W/ L* H5 X* l2 s%-------------------------------algorithm processing--------------------------------------------------& l, d+ {5 ^- L  b; J2 G# ?

    * a1 ~/ ^4 [4 o2 K/ w9 D# x( P; Uif setup.reverbTime == 0,0 x" Z" O/ y5 Y* u0 S  e
        setup.reverbTime = 0.2;
    1 }; Z* M# m" h) c    reflectionOrder = 0;
    9 m/ d! V2 `. Zelse
    # }& Q, z9 g5 B+ e' l! u5 Q    reflectionOrder = -1;
    7 g4 s* b" _6 P5 _% i, v1 `end8 W. D9 F8 h# Z3 k  ^2 l4 b+ f

    3 T7 ~0 V% H3 WrirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',...
    ) p% F; J+ C$ E2 @. X0 o    setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);- k9 r% i* P* G# J# R9 E

    & a$ [6 \. \$ u$ {for iSens = 1:setup.nSensors,! ^. c4 C$ Y# |( s3 f9 |. R1 H
        tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);% |: J' J7 D2 K/ R0 D5 i5 w
    end
    + d0 ]" W/ s8 {mcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;; @1 H; L! ?5 p2 O# U# q9 X
    setup.nSamples = length(mcSignals.clean);
    6 P9 t  }- ~  |" O3 g7 f& l/ ^
    9 D/ S& s# o* K6 QmcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);
    ' _5 ^; C" h+ p) D5 T; {2 S7 i) E9 V) c; X
    %-------produce the microphone recieved clean signals---------------------------------------------
    . M. D; }' C5 ^6 |1 M5 R' B9 k  F% ^) H/ }( t  B
    mic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold
    9 ?- D0 v9 A; K# z! D6 Jmic_clean2=10*mcSignals.clean(:,2);
    5 M$ Q$ I5 h8 x+ W! q0 \; [" cmic_clean3=10*mcSignals.clean(:,3);9 |1 ^: A* {5 t" E# u/ d
    mic_clean4=10*mcSignals.clean(:,4);7 q7 z' a+ h$ {5 b7 e. }
    audiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);
    " Z9 m  u. s& j% |( D* N$ paudiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);/ f$ X" x) m4 H1 ^( e( G
    audiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);/ H8 U5 m, q' u- F0 v
    audiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);& ~! C  q! p6 A) ]+ ^
    6 f: p8 _- D% h
    %----------------------------------end--------------------------------------------------
    4 ]. U% M' b+ U9 u
    1 m9 `5 E& v9 U# ^+ haddpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);
    $ x" a" Q, ~. c! b% O+ N, y; Y6 N" w$ R  I
    cleanSignalPowerMeas = var(mcSignals.clean);
    * I" ~2 S# ]9 Z+ \4 i  O5 B: \- [0 a; ]( f

    3 n, o% W& [  HmcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...# D* g& n3 ^  \) y4 n
        setup.speedOfSound,setup.noiseField);' G0 O. L/ h" d8 M8 k
    diffNoisePowerMeas = var(mcSignals.diffNoise);$ U" v: B, j4 ]) r8 R
    diffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);
    5 x# F! T3 W/ OmcSignals.diffNoise = mcSignals.diffNoise*...
    $ Y8 ]. k# k9 T$ ~2 T! b/ X    diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));
    % f5 s9 A5 E& n# x4 c4 [2 i/ E2 i9 q+ c
    mcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);
    , l0 `3 F% ?% m. ?. N' T9 PsensNoisePowerMeas = var(mcSignals.sensNoise);
    ! ~8 S% O1 u: A: P# q+ ~! i$ ^sensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);3 i5 e! B2 `/ i
    mcSignals.sensNoise = mcSignals.sensNoise*...  R3 a/ J% v! J1 ~
        diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));- p7 s: }' b4 v  g0 \. J

    ) x8 ^: d6 o0 E2 [$ hmcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;
    + ?- ?4 m" X) }3 X) _# J. N( l3 PmcSignals.observed = mcSignals.clean + mcSignals.noise;
    % O. r, f4 X9 _$ K3 O/ l' s2 X  T; c, }( U1 A( a: ^
    %------------------------------processing end-----------------------------------------------------------+ F+ U% m" @( e* G
    3 S# l1 B3 J1 r4 j" z' @' g/ Z

    ' g8 J3 x6 W; P" e/ F7 o( j1 C% J3 m  ?

    4 {0 S  T4 r$ {; Q4 Q  c%----------------produce the noisy speech of MIc in the specific ervironment sets------------------------
    , U0 `  `/ l/ V& ^7 T/ ~( O! X* `: |# V* w9 W6 ?! x
    noisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold
    $ P% d* Q% h5 |% K5 Qnoisy_mix2=10*mcSignals.observed(:,2);% d# T7 g0 C. [; a+ j, v
    noisy_mix3=10*mcSignals.observed(:,3);
    1 g# a" A( G5 Y2 Y3 v  V. o4 V% \noisy_mix4=10*mcSignals.observed(:,4);
    0 X4 b; w$ q; P2 Tl1=size(noisy_mix1);
    0 Y' {1 B4 L4 V9 j% L+ jl2=size(noisy_mix2);; J0 ~  N5 E5 W. }- z* D
    l3=size(noisy_mix3);/ k: F' k) ^$ T1 l( ^% T2 y
    l4=size(noisy_mix4);# A6 K8 t! z- D; K! J
    audiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);
    8 G0 R$ K$ J- u6 Z& Q$ p+ A: L) ~$ V$ waudiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);$ K7 b9 O, ]: c# v7 F- B
    audiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);
    7 o) @- T% s$ ~1 e& xaudiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);
    - M( g' p3 _0 d- x, u8 v2 [' J( G. r# _2 A8 i  r. z
    % n. F  i3 {* W5 L( ]% W
    %-----------------------------end-------------------------------------------------------------------------$ U: b$ A- X7 g& L- x
    这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。0 R9 N  [9 j1 b6 I2 T' b& t
    直接把它们替换成你想要处理的音频文件即可。& L1 z" d; P6 M2 F4 w. B

    + M& a8 A$ l3 m  除此之外,还有一些基本实验环境参数设置,包括:麦克风的形状为线性麦克风阵列(该代码只能对线性阵列进行仿真建模,并且还是均匀线性阵列,这个不需要设置);麦克风的类型(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)。
    $ O, f' S2 D+ y, `% b% N
    2 t3 b/ c( j1 K9 Q/ @+ w7 I% b* s( ]8 Y' F% @/ _$ h1 x4 C: H  L7 O6 t

    + J) C$ Q; i+ \9 S6 k6 E图1 麦克风类型图
    $ ]( t7 d( m9 i
    - x& m0 {) h' F( Q7 M, T$ u图二 房间的坐标系8 ]% d1 p; _* k/ ?
    3 q. q9 N7 E, ^2 r. B/ @! h) I
      以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。
    3 V, O! Q" c$ R1 s4 `————————————————
    0 b( ?  d% O0 z4 S, f版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    # o3 D8 d& S5 D6 x0 m原文链接:https://blog.csdn.net/zhanglu_wind/article/details/79674998
    ! @1 U$ s" d4 g2 E
    5 U7 @3 R6 a6 J# V3 T  H, o9 y* \9 ?0 d8 K& ^- \! z; C* @0 e4 L6 g
    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 13:06 , Processed in 0.554282 second(s), 51 queries .

    回顶部