QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3302|回复: 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. 引言* o' G2 z$ R! m4 y
      之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。3 N0 Y- `* d) ]& ]0 ?
    5 R' h! G( A5 V  q7 H
      然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。- c. |& ^" Q' Z$ u
    # `; N! r2 h7 Q
    2. 代码介绍
    $ h6 _; l6 e* N: ]" n& s+ `. S  原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:* l0 m( P$ `* y9 `. @
    function [mcSignals,setup] = multichannelSignalGenerator(setup)
    $ v% ]  ^% b- O# V* K5 I0 W( x5 c3 H+ `- ~9 H

    2 q; Y( l; N- k; i: l%-----------------------------------------------------------------------( X4 B) q& Q3 L: `- b2 N
    %  Producing the multi_noisy_signals for Mic array Beamforming.( s! q* w- A0 y8 ^7 J% o6 [
    % / t/ K8 V+ v5 `3 V0 m& }
    %  Usage:  multichannelSignalGenerator(setup)! A1 _/ z/ N. V3 j$ @+ P
    %         1 b7 [/ f* ~( u8 w& v7 d$ J
    %        setup.nRirLength : The length of Room Impulse Response Filter
    ! t5 Y  w" T/ `: @" S$ C%        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default
      {! t" k* G: T* Z/ C" T! I%        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order.+ ~; t* |: r6 C: G
    %        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.& ~; T6 n  i  c' r
    %           / N0 R$ l. q, f- O& g' G
    %        setup.nSensors : The numbers of the Mic( L  Y* W% O7 q; x6 l  b
    %        setup.sensorDistance : The distance between the adjacent Mics (m)7 T( A" u( q" }0 r/ P; u+ a/ P
    %        setup.reverbTime : The reverberation time of room
    : f7 `: ^0 [' ]9 ~3 B8 U%        setup.speedOfSound : sound velocity (m/s)4 C# {* d+ N8 W  p" |# B
    %' I$ q5 o5 g- M  l4 k
    %        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'
    : b0 n! \: e2 w" p! B$ |%        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.) x8 B" ]8 [4 ?/ y6 L
    %        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.
    6 G4 f0 V2 W; I- T+ K%
    & a5 J/ @# m! B%        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).           
    9 M# m* q4 Y; L2 Y4 k%        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m). 9 ^  w& a' }1 |
    %        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m).
    : `( O/ E: A3 w3 Y. n8 t- Z4 i9 d%* e& c* I- A- ~0 L3 Q- O5 f+ @
    %        srcHeight : The height of target audio source' y4 P$ U0 {: J' u. T# O' A+ P! ~
    %        arrayHeight : The height of mic array: X. U' o1 c* H% Y
    %6 m, u1 [. S- k/ h  R$ }6 g
    %        arrayCenter : The Center Postion of mic array
    5 f4 B. Y; G3 @; @( U8 l%" s  ~; l7 S8 A# \6 U
    %        arrayToSrcDistInt :The distance between the array and audio source on the xy axis
    " j; s# t$ v" m: e. V& k% |%
    1 N" v2 C" j0 b! x( y%                       
    : e: I0 ~" c( ^8 `/ O& ~0 W1 E%
    + z8 w3 \2 \0 Q. V%9 K  B; z. U) c9 C, Y7 b  C! B
    %         6 G% Y& D: ^7 Z
    %0 O% z, j1 `" A7 D# G
    %  How To Use : JUST RUN
    ' ^) e2 H, k  p%
    1 S5 D! V: O5 [& F0 S%  7 X7 N2 W7 \  M! g
    %   
    / F- l' A7 y. v: Z% Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),
    6 O/ M/ O# n7 g( k6 F/ x, ~' B%            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.24) h3 t9 z9 g) T2 ~
    %0 w  F9 r% \" t# S* n3 e7 q
    % Copyright (C) 1989, 1991 Free Software Foundation, Inc.' M! J" f5 z: P! {2 Y
    %-------------------------------------------------------------------------
    8 d5 Y1 y: F; Q4 E% l$ p5 a3 j5 I/ r  w& ~9 u0 S

    0 n' B6 j4 n) C& j" ^5 U
    . l& ^" F+ }$ Z% f$ O6 Saddpath([cd,'\..\rirGen\']);
    # }2 E6 ?8 Q: Q, S" Y5 y- c/ u) J8 }/ c+ Q0 N6 J
    %-----------------------------------------------initial parameters-----------------------------------! g' I/ F$ g/ J2 }5 S% M5 [
    * W! r7 |$ n+ Z# V' h
    setup.nRirLength = 2048;) }) [$ f+ R; w7 n" R/ q5 d* ^
    setup.hpFilterFlag = 1;$ a* A: w3 P- Z, {: I
    setup.reflectionOrder = -1;
    * O1 x4 E: U" h  H- o5 hsetup.micType = 'omnidirectional';
    * o4 }3 }. l7 \  Nsetup.nSensors = 4;& a3 g' s, h( L4 Y0 O/ [# [
    setup.sensorDistance = 0.05;
    6 W$ @4 [/ ^7 `setup.reverbTime = 0.1;! w1 J$ B7 L$ g. n) Q2 Z6 o
    setup.speedOfSound = 340;
    2 D% e9 C) u5 \: s- H0 e8 \, @% z+ q
    setup.noiseField = 'spherical';3 q9 O7 N3 m8 m8 s% H7 E' N
    setup.sdnr = 20;+ g. O/ a% l& v& n' b- c
    setup.ssnr = 25;- W" s' A3 I; Q3 e" j4 c% E
    4 m8 ]  b: T: i% K6 D
    setup.roomDim = [3;4;3];5 j1 j! A5 |: J6 [0 A) D+ [* u( `

    9 T6 g/ b" m' D7 J7 EsrcHeight = 1;
    2 Q8 v4 H0 H* O1 u8 carrayHeight = 1;
    ! ]$ z/ ?  `5 E. ]: V" y- b7 P: x
    # [/ Y. X4 C1 Y" Q* marrayCenter = [setup.roomDim(1:2)/2;1];$ ^! a  N. f7 A% ^( M6 m

    # k! \' ]' k6 p' X8 j4 e( }4 UarrayToSrcDistInt = [1,1];' M, i4 k3 R, M: v! B6 j

    + p& k7 H) I1 \* y& \/ Y' h# gsetup.srcPoint = [1.5;1;1];1 Y! V  E9 X% i% `* }
      w# x# R" Q' ?- p3 L3 x7 h  w
    setup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);* m0 m. V( @$ n: F

    4 Z2 S/ x1 q) S5 i1 B* V# E; @% f
    % T* {7 ~3 ~& n, W2 z! e[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');- l0 a/ Q! z6 q, V0 Q, o8 W& i5 ?

    + U7 n5 ^: V3 `5 F4 J) K" B0 }2 D%---------------------------------------------------initial end----------------------------------------6 {8 d/ @5 p4 f# L! Y
    3 ]) o1 Q% `3 C* x# o" I/ ^

    6 a- ~) P+ g# [1 W" ~3 }; `! ?9 ?& C$ F
    %-------------------------------algorithm processing--------------------------------------------------
    . Z: R" F. e- f* Z0 I2 u' }
    * k" i* O: J5 `- \: Bif setup.reverbTime == 0,% Q1 ?/ \# {  x' |, e
        setup.reverbTime = 0.2;8 l  ]( k% |% r
        reflectionOrder = 0;+ V4 ^$ B0 T" Y5 j5 G# F+ v" }
    else- i6 K  E3 l2 l( R& u3 U
        reflectionOrder = -1;
    7 I9 b& U6 M  [8 ?1 bend5 V. |9 j3 a5 q# K( X2 L: o6 F; M
    # p- w. L' y6 W) f6 k0 m/ O* T
    rirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',...# R. O& V/ P( z2 f$ L- F
        setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);
    . h0 Y- Z' o7 H- e  B' c9 }# k* I( N1 L4 y# W
    for iSens = 1:setup.nSensors,
    4 i9 i- u# ], f& B4 Q3 ]3 X$ C6 w3 I    tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);
      i( b$ s0 y, D( g  v9 F: `4 t/ Jend
    , `7 T  y' K3 k" s( o9 \$ emcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;9 E' y2 A' o6 |& q) ~  S
    setup.nSamples = length(mcSignals.clean);% l$ n' L, v8 Q- f7 D9 Q

    # x6 z5 d: _0 _& ImcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);8 q7 i2 J% q4 h$ Q- \( w' h
    , c! V" |. h( O
    %-------produce the microphone recieved clean signals---------------------------------------------
    * T: V! w/ O- v. i  Q
    ( U8 w0 t( _! h( tmic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold
    ; q' h# e2 o& L7 g& \mic_clean2=10*mcSignals.clean(:,2);
    3 v) L* B2 V0 z- @8 }mic_clean3=10*mcSignals.clean(:,3);
    ' {' |' M7 \4 lmic_clean4=10*mcSignals.clean(:,4);
    - u" e7 t' ?  x( D% Naudiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);+ P9 v1 u9 ]# h; E
    audiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);
    ! O8 Y5 B$ F7 r2 p5 L& Kaudiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);* P) Z# q9 Y! N# M% T8 e$ F
    audiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);
    ; e& U. ?  P" j1 Z
    , \& r) d! }$ \* m%----------------------------------end--------------------------------------------------2 {( P! J- [) T2 o& u6 Y

    ( M8 e1 |" P. u3 A3 x5 i; e% {addpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);% p# ~! y: k* K0 B7 B& X- X

    5 x+ t( [: M% `+ u0 _1 CcleanSignalPowerMeas = var(mcSignals.clean);
    $ J) y. i; n. n3 w9 T* N
    ; h! [; F6 }1 p% H2 `0 c3 |/ T: d% g
    mcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...+ H; L. T% Y9 I2 I, ^
        setup.speedOfSound,setup.noiseField);
    ! S# A2 S& M5 QdiffNoisePowerMeas = var(mcSignals.diffNoise);
    9 \. y) w2 I3 [, x: F# N  GdiffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);
    & y4 d2 m2 I& \$ I) ~mcSignals.diffNoise = mcSignals.diffNoise*...  H5 n3 ]$ ?; ^
        diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));! }$ J4 L0 I. z) I& L
    $ m* ?4 ]. N( h0 S5 o& H( I7 _
    mcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);& `* n2 T* O: \
    sensNoisePowerMeas = var(mcSignals.sensNoise);
    ) A# y0 L$ t) n. p; e9 K1 osensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);- K/ w/ C6 {1 W! k. S
    mcSignals.sensNoise = mcSignals.sensNoise*...
    5 s0 h9 G& A5 Z8 O3 ]    diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));
    " ]% K+ l$ I; z' x+ s& o9 b+ c
    / m4 @* z- Y" F$ FmcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;
    4 E: U6 N7 S' N+ L" L2 b5 f$ R; bmcSignals.observed = mcSignals.clean + mcSignals.noise;; U" d- w: x4 c% w/ f

    9 ^& Y  \( B. w/ M%------------------------------processing end-----------------------------------------------------------
    : {/ X; L) a" z1 I0 b
    , ?# c* Y. o& W' a4 G
    # V+ m0 b+ t) a) _$ ]2 ^& Y5 E7 Q) N9 Q$ N5 L5 B1 B/ {3 ^

    " ?/ T  g+ |0 z" ?! N%----------------produce the noisy speech of MIc in the specific ervironment sets------------------------/ Y( [4 C) N' z* X# g* B

    $ q' O( D2 C2 h0 O0 xnoisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold
    % P$ J) l$ Y2 wnoisy_mix2=10*mcSignals.observed(:,2);
    % `' {& L: E( g8 V5 D: Y! Enoisy_mix3=10*mcSignals.observed(:,3);  U4 u% `9 ^- W! w& ?6 h
    noisy_mix4=10*mcSignals.observed(:,4);
      }7 M' ^2 ?/ x7 E7 }l1=size(noisy_mix1);
    $ A5 g2 d' |, dl2=size(noisy_mix2);
    7 V0 t3 u! L- I! o1 H5 s# H8 }l3=size(noisy_mix3);. _5 ?5 @* x+ ^6 |7 w9 `. S( x$ t- A
    l4=size(noisy_mix4);: V3 R) N; J; A; `0 R3 h. g/ e
    audiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);
    ; u0 G8 s; V: R6 I, p$ o! Uaudiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);
    0 Y+ R. m! }8 C- r8 F+ W# Yaudiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);
    3 ^6 |  j- q# ?audiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);  G  O; ~5 W9 F2 J- B3 L

    / Z* N8 ]/ t: W  K/ S, _9 ?4 u" I8 M! M$ @. u
    %-----------------------------end-------------------------------------------------------------------------
    ; e  T/ }& x' K3 F2 J- B这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。; X* s: C$ F& _6 J7 a* W2 u- N: Z
    直接把它们替换成你想要处理的音频文件即可。. T6 d; `' ?$ E/ n) u  H/ |) E
    1 e6 v" \& n# q9 J, Z1 M: q2 y
      除此之外,还有一些基本实验环境参数设置,包括:麦克风的形状为线性麦克风阵列(该代码只能对线性阵列进行仿真建模,并且还是均匀线性阵列,这个不需要设置);麦克风的类型(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# `$ O- u) P! S

    ! ]3 l8 t. ?7 e) r( d& Q8 I7 P) U
    ) y6 ?; w" c) A  s" E8 E$ ]+ b# z) |+ B# h7 O# b( R
    图1 麦克风类型图0 |  |5 R4 _, {! }$ V- r

    5 t2 C0 a2 v+ a图二 房间的坐标系" ?2 x0 f* t- @/ A. x, P7 \

    * V* b" |4 G6 T5 G  以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。
    0 @! d; S. L+ ]* B————————————————- f6 }6 L3 `. |, z: i4 q5 J
    版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。, @; K3 E( E9 J8 A$ K- U/ x) k
    原文链接:https://blog.csdn.net/zhanglu_wind/article/details/79674998
    # c. {5 M+ j. R/ _" u
    8 c) Z7 z2 U6 w. O
    1 l' y$ z* N9 u. \/ M: L% K0 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-4-20 05:38 , Processed in 0.584896 second(s), 50 queries .

    回顶部