QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3392|回复: 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. 引言  k' v8 v2 ~6 O, T4 ?+ h+ `# S
      之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。
    ; h6 i1 D- |: D/ G! ^. B; j8 I6 z3 N3 w
      然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。
    6 U4 R) w& W, ~+ K8 C( C8 c6 r! ^( O/ Y5 q: }6 E% g
    2. 代码介绍
    # t9 k' C" b9 u! r# R2 p7 S  原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:( R3 r* w2 U$ e0 L
    function [mcSignals,setup] = multichannelSignalGenerator(setup)  O: k) F5 f! B7 t
      B; m; K& ]% X  Q* z$ g

    ) f0 N4 o. F) V& I%-----------------------------------------------------------------------
    * n" l; u( x, Z: c4 D%  Producing the multi_noisy_signals for Mic array Beamforming.
    1 h9 r$ V- V* e4 e: C( Q6 q! O. z%
    " q& T, t  q/ D+ m0 v%  Usage:  multichannelSignalGenerator(setup)- |+ z3 N8 |7 |; W( W6 |& ~
    %         6 M2 Z" d0 I. V8 F
    %        setup.nRirLength : The length of Room Impulse Response Filter) U/ g8 C# C. [8 k) d- l
    %        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default
    " N- L- R  J- _1 J& p%        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order.* [: g$ ]( t% v! Q0 R9 N
    %        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.4 @4 A3 s- T8 B2 h6 r* B" [
    %           
    + G5 B; F( H) Z- c1 [%        setup.nSensors : The numbers of the Mic/ u9 l1 `+ g9 c' X# k
    %        setup.sensorDistance : The distance between the adjacent Mics (m); k: m- S: R+ u
    %        setup.reverbTime : The reverberation time of room
    % z5 \' S( `1 C+ v' K, a% G%        setup.speedOfSound : sound velocity (m/s)4 h/ S" G5 Q4 K0 i& ~
    %& u, Y4 R! @6 G5 S
    %        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'
    8 p/ ]% |8 Q' u, ^%        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.
    ! G9 T! l: ^# ~1 Y! x  p9 r0 ~%        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.) I1 H( U$ _5 o( E
    %! d+ c* i% N' l0 X: z6 b: V
    %        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).           5 _2 n+ H- \& j- O$ Y/ W
    %        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m). + O1 o* ^, H- \0 ?8 ^* P
    %        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m). 4 Y1 A  y/ Q3 o" r' {
    %
    ' |8 [' \% I' b%        srcHeight : The height of target audio source
    * ]& S3 b5 e' P" K: \, ]%        arrayHeight : The height of mic array
    & K& s- J1 G: |' E; }2 @. |4 b( [) O%
    : C/ G$ r+ v, u%        arrayCenter : The Center Postion of mic array
    . M7 x3 b7 v: o' {3 F# m%5 w" k, L" [) k% W6 [' A
    %        arrayToSrcDistInt :The distance between the array and audio source on the xy axis
    + f. p: b7 i0 |# f$ I5 j%
      Y2 Y  P* n& d8 ~%                       
    ) D6 k3 o( T9 E- o1 \. R, {%
    8 m: @3 g' E. J4 ]4 y  _! ~; _%$ n- ~8 n$ A5 x
    %         
    ) |, @$ T) D$ |+ o% H1 i) W%/ Z& e8 S. O$ w7 S
    %  How To Use : JUST RUN3 z' ^, W( L* K1 x' Q
    %2 J. Y2 E7 |; M. L# f
    %  
    + N0 p2 G! _; W% v1 z; G%     }% `* T+ `% K4 I
    % Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),+ Q9 @( |& y' y- I# e
    %            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.24! Q+ i0 s4 J; m8 R. o
    %1 ?3 a5 k: i9 Q; ~
    % Copyright (C) 1989, 1991 Free Software Foundation, Inc.
    9 t& m+ F9 z2 z. ~8 s9 s0 q%-------------------------------------------------------------------------
    4 q, C" x+ T& S  i3 i2 o/ E4 F8 I3 d) C( g# c. \( k: Y

    / Z. T  M# d0 X& A3 A
    % K. [' D' j2 F% g# J8 ^addpath([cd,'\..\rirGen\']);/ O. n$ D2 I( y! s

    9 N$ g/ P1 I7 ~$ a  a1 S' o6 ^%-----------------------------------------------initial parameters-----------------------------------
    " V; G& v* U) [% C& q' `
    7 X3 \. p( A- W) x7 |setup.nRirLength = 2048;
    4 Q* Q' B! ]' E! R, ssetup.hpFilterFlag = 1;
    3 b/ U0 @( K9 ]6 Xsetup.reflectionOrder = -1;
    - g. X/ n+ Y# ~setup.micType = 'omnidirectional';
    % B; [& t; t* B& c. Lsetup.nSensors = 4;
    ( q- |( x6 ]0 ^# jsetup.sensorDistance = 0.05;
    8 {: S; l/ u" rsetup.reverbTime = 0.1;8 C( O: F' w0 b( ?4 O
    setup.speedOfSound = 340;% C- ]( n; M6 c; D& ^. `

    7 D6 n* c! ]1 H4 `9 j# wsetup.noiseField = 'spherical';
    ) A% [1 y# K& l) P! L* j+ o  Ysetup.sdnr = 20;
    5 ]; ?' Q" f: C, d* J" ~setup.ssnr = 25;
    , N1 r1 I, D2 S5 _9 [. ^- m
    % D) b, ?/ Z7 ~) o; H% e9 S# f- Tsetup.roomDim = [3;4;3];
    % v* s8 [1 o) l) Y- H0 |& u/ C
    0 \) M$ _: R1 R2 P! j- m  DsrcHeight = 1;: u2 s: o7 K# m8 \( ~2 }
    arrayHeight = 1;3 L' m; ]5 u/ G1 `( `$ b' v6 `! @

    $ |0 I5 D+ \. V0 s% g+ P* AarrayCenter = [setup.roomDim(1:2)/2;1];
    # q4 Y  [  e9 g7 O# o( H" {5 U) e& m6 E
    arrayToSrcDistInt = [1,1];4 ~9 W$ f* M4 t. C( b
    . Q( s- l  ]* b$ F0 A
    setup.srcPoint = [1.5;1;1];9 {) V9 L9 v/ [( m/ F0 ]# H3 j
    ) J7 i1 D# F* `5 A3 A2 y- D
    setup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);* a$ H3 @1 q6 F# c7 n4 X. f0 R/ G

    6 v" Y. H; H# u; S7 _( D+ M. ~% l
    3 `& _1 _, f4 `* n, A[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');
    ; P7 \) u+ c( R) a0 V8 {3 }7 J* y0 J/ D5 P* E; n
    %---------------------------------------------------initial end----------------------------------------! J8 h6 K6 [! x% _

    % O1 f  V* X* @! ^( f! T9 O/ S2 R0 m1 c/ O; T- F: z; M
    0 Z! O/ _% u$ ]; q( c
    %-------------------------------algorithm processing--------------------------------------------------
    - M: s2 L1 `! H. r' M8 u
    : s0 E* h$ P1 s; Aif setup.reverbTime == 0,
    % ~& k9 l4 w7 Z0 d! A    setup.reverbTime = 0.2;2 e: |6 ]( ^( j1 c
        reflectionOrder = 0;
    $ y( ?% I8 w- A! G1 Kelse
    : D0 t! c4 M' v* p    reflectionOrder = -1;
    , F( g7 C7 G/ z7 ~( s& S' Jend$ f2 B. k8 J4 E
    ) S. I) Q4 m' ?1 T5 y2 A4 F3 I
    rirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',..." o$ _8 U$ W$ c1 }4 ]' k
        setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);
    7 ^1 |4 @8 I, F/ G( ?! C
    3 @+ i0 \% z' u* B9 X) Gfor iSens = 1:setup.nSensors,$ j. ?' T( i# o
        tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);
    ! z+ D( |3 F( bend
    # `" W; k2 K- U5 dmcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;) g, l8 e* [7 B: _* B% a
    setup.nSamples = length(mcSignals.clean);
    . I2 p' f/ r0 Q- K- |# a4 _  [4 O. P
    mcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);
    * ]  X3 P( r* w7 B
    & c( ~) a8 @' E) b1 I& T* Q0 _# R%-------produce the microphone recieved clean signals---------------------------------------------
      y6 V( r! }; e. O
    : ^% L) ~8 g' g( omic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold7 D# e1 T5 D$ ~, X2 {
    mic_clean2=10*mcSignals.clean(:,2);* c" P9 L  |2 q; z8 B) S
    mic_clean3=10*mcSignals.clean(:,3);
    1 `7 k* V0 r2 p" ^( qmic_clean4=10*mcSignals.clean(:,4);1 d4 f( [# h1 q' K# S& R
    audiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);. y! R7 N. O9 j7 b
    audiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);
    ' z7 [  b2 j, x4 }! Oaudiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);# p* D7 `1 z, l7 I
    audiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);" k, z1 [# ~: w* }1 q0 N8 X

    " g6 B2 p- I* r' t, ]! U%----------------------------------end--------------------------------------------------
    6 d  ~( k  t  N  c9 d1 b$ U9 n2 j7 b, G
    addpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);
    , {6 @& e- ~; n" ~  J% K% S3 Y7 s9 t9 x8 P' D6 f
    cleanSignalPowerMeas = var(mcSignals.clean);
      D+ }( |2 G6 A4 V. j! r, ]" _
    8 E6 g0 W& {$ E( L' G- h. d$ R
    mcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...
    3 [8 y% _1 X6 q5 j    setup.speedOfSound,setup.noiseField);
    & R1 w8 c9 Q2 J4 ldiffNoisePowerMeas = var(mcSignals.diffNoise);
    + E9 t/ m9 Q+ W3 ?0 @$ hdiffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);
    6 ^1 N# L  c0 V5 n2 bmcSignals.diffNoise = mcSignals.diffNoise*...
    & l$ ?  v3 u6 D1 I) \) G, |    diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));
    + S- m/ J& l. @$ i7 `- L
    3 [7 Q" z/ u1 o2 T- T* amcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);
    : x" l/ S# c5 isensNoisePowerMeas = var(mcSignals.sensNoise);
    + H( N; a  B) o# m& [$ `sensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);! l9 Q8 |, ]' C6 b3 A4 p8 C
    mcSignals.sensNoise = mcSignals.sensNoise*...
    ! M0 g. J( ~& K9 c3 C; z8 J    diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));
    * a9 T5 @" ~$ U
    ' V7 s  t9 E/ D7 w8 g( q7 BmcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;
    + n5 _, E7 J; b* I; o- JmcSignals.observed = mcSignals.clean + mcSignals.noise;$ l0 r: r7 h% {7 @9 {. W
    0 F1 U2 h7 Y2 F' l
    %------------------------------processing end-----------------------------------------------------------8 e- t. E% L; @3 O
    " [0 C, p  b; W1 y9 f$ @
    " {3 J+ F& z' S! x+ R- K9 p

    0 S" {5 m& ~. Z" S" c9 Q. T. d
    3 ]; z' t. M3 H, m% q; C* Y%----------------produce the noisy speech of MIc in the specific ervironment sets------------------------! H% Q1 m1 x8 t& w7 a2 O% e) z

    4 ~9 T0 z* s: Gnoisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold
    * _/ z2 C! D, \: Tnoisy_mix2=10*mcSignals.observed(:,2);* F1 I  n3 Z" l( `- j. O4 ?
    noisy_mix3=10*mcSignals.observed(:,3);1 ^& ^, F- y" I3 G* I( n1 h. a( t( X% n
    noisy_mix4=10*mcSignals.observed(:,4);
    % Y3 }1 y  q% e, l5 Y8 `2 Rl1=size(noisy_mix1);
    . v) Y% e$ ^" \- U, Y, b9 H. hl2=size(noisy_mix2);
    - q  T& T& r- R9 ]l3=size(noisy_mix3);6 ?/ r+ ]( x5 f& W7 T
    l4=size(noisy_mix4);
    5 q6 W/ d9 |2 ~/ N- }audiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);  h9 A% ]: x2 O0 [& G8 q6 e3 `; K
    audiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);& @8 t$ |0 z" r0 @4 W5 G8 _0 {
    audiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);4 V* j  _" L$ A' m& G* O
    audiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);4 H3 F3 k. G& {0 y
    $ u1 j' y- v1 f3 Q

    : \7 Q3 I) Q6 Y%-----------------------------end-------------------------------------------------------------------------
    - G) w; O( }7 C3 c2 X9 O这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。5 ~3 r' G# H4 E. p, R- W1 r
    直接把它们替换成你想要处理的音频文件即可。: c7 B! o/ |# Z7 C- x! [& V

    6 k4 B9 _. v4 A! i8 J0 ?6 Z& m# C& v  除此之外,还有一些基本实验环境参数设置,包括:麦克风的形状为线性麦克风阵列(该代码只能对线性阵列进行仿真建模,并且还是均匀线性阵列,这个不需要设置);麦克风的类型(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)。/ K* Z' H. H5 z

    7 ~4 y7 d! W, W3 I& e
    1 ^6 n/ N" ~+ g. A) C: m( J( j! _( `1 T  m2 ?' M" F
    图1 麦克风类型图8 \- o: D  }% l
    & W$ A1 d7 T7 G- A6 N/ y+ S
    图二 房间的坐标系
    * U& @9 ^& \$ w/ E! W% g9 C! m) \- E( [7 d% S0 c* k. F
      以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。
    7 y& x0 e% v# w) k————————————————
    # `1 }1 h) b, D* v, d版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
      ~+ M! x5 J- h0 V  _+ ^0 B/ C3 F原文链接:https://blog.csdn.net/zhanglu_wind/article/details/79674998) Z0 S3 [$ c' U7 F6 x2 M2 a2 ^

    ( K5 Q4 d. ?$ u# z; ?+ x6 B
    ; W9 K' `1 _) a* A4 W' O7 X
    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 11:28 , Processed in 0.391579 second(s), 52 queries .

    回顶部