QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 3342|回复: 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 U- i. q( R3 Q8 H2 O: r. `5 k  之前,我在语音增强一文中,提到了有关麦克风阵列语音增强的介绍,当然,麦克风阵列能做的东西远远不只是在语音降噪上的应用,它还可以用来做声源定位、声源估计、波束形成、回声抑制等。个人认为,麦克风阵列在声源定位和波束形成(多指抑制干扰语音方面)的优势是单通道麦克风算法无法比拟的。因为,利用多麦克风以后,就会将空间信息考虑到算法中,这样就特别适合解决一些与空间相关性很强的语音处理问题。2 h. m7 a3 O8 Q3 u* X
    $ V/ \$ a. {0 ]) N
      然而,在做一些麦克风阵列相关的算法研究的时候,最先遇到的问题就是:实验环境的搭建。很多做麦克风阵列的爱好者并没有实际的硬件实验环境,这也就成了很多人进行麦克风阵列入门的难题。这里,我要分享的是爱丁堡大学语音实验室开源的基于MATLAB的麦克风阵列实验仿真环境。利用该仿真环境,我们就可以随意的设置房间的大小,混响程度,声源方向以及噪声等基本参数,然后得到我们想要的音频文件去测试你自己相应的麦克风阵列算法。5 R6 u8 v6 l# `! c
    5 ~. [) A' v& D/ z- E
    2. 代码介绍
    3 d3 N, z7 H" x$ E6 \  J" l  原始的代码被我加以修改,也是为了更好的运行,如果有兴趣的话,大家还可以参考爱丁堡大学最初的源码,并且我也上传到我的CSDN码云上了,链接是:https://gitee.com/wind_hit/Microphone-Array-Simulation-Environment。 这套MATLAB代码的主函数是multichannelSignalGenerator(),具体如下:
    # A) F4 T. }" @  pfunction [mcSignals,setup] = multichannelSignalGenerator(setup)/ F1 D8 N) |8 m- i6 G- k. v9 v

      B2 f7 d5 ~# A/ e. v2 R& E0 c5 @6 k
    %-----------------------------------------------------------------------$ x4 [# a" M0 k% q; S2 T- n
    %  Producing the multi_noisy_signals for Mic array Beamforming.; E$ W  @0 s) s- i/ B
    %
    ) H7 N$ ~! H! f* o  @%  Usage:  multichannelSignalGenerator(setup)
    ! q: U2 j' `1 h6 h# p/ l  S+ I%         
    : H' u2 Y: Y/ I+ G; `8 _%        setup.nRirLength : The length of Room Impulse Response Filter+ I' M* A0 g; g  _3 I
    %        setup.hpFilterFlag  : use 'false' to disable high-pass filter, the high-%pass filter is enabled by default1 N' o9 d. l+ f9 {
    %        setup.reflectionOrder : reflection order, default is -1, i.e. maximum order.
    - O' a6 z5 ^- }. d3 u& h%        setup.micType : [omnidirectional, subcardioid, cardioid, hypercardioid, bidirectional], default is omnidirectional.
    9 R! Z6 h7 r+ s3 _( v8 V- d%           
    9 G! R& e; [3 H( J( G0 ^%        setup.nSensors : The numbers of the Mic1 r6 l1 b- E: q5 s& r0 V$ o
    %        setup.sensorDistance : The distance between the adjacent Mics (m)
    " @8 e( ?1 u* X/ R%        setup.reverbTime : The reverberation time of room
    . X2 p9 V5 A6 N2 s) I5 ?%        setup.speedOfSound : sound velocity (m/s)
    0 O" s0 b* Z- I6 ]%
    0 P3 E  a! j; L$ e%        setup.noiseField : Two kinds of Typical noise field, 'spherical' and 'cylindrical'
    0 U" h( o; d* k2 p%        setup.sdnr : The target mixing snr for diffuse noise and clean siganl.: T% h, F! Q, o; a1 A" X
    %        setup.ssnr : The approxiated mixing snr for sensor noise and clean siganl.
    - B( j0 S, ]8 _) x$ S% k%
    . b: A9 j6 }% C' R%        setup.roomDim : 1 x 3 array specifying the (x,y,z) coordinates of the room (m).           
    : R" j* @; A1 n4 r%        setup.micPoints : 3 x M array, the rows specifying the (x,y,z) coordinates of the mic postions (m).
    6 L0 A+ b; B3 H9 W%        setup.srcPoint  : 3 x M array, the rows specifying the (x,y,z) coordinates of the  audio source postion (m).
    0 o! U: |+ X* l4 i%: ~" O- r6 `2 J* _8 N
    %        srcHeight : The height of target audio source; K" R, ]0 C5 @( v5 {1 M6 R7 k
    %        arrayHeight : The height of mic array
    8 M; w" q% t+ B7 o4 P) }%1 \; e& m  q7 i: N; k
    %        arrayCenter : The Center Postion of mic array
    $ R+ o6 e2 ]- a5 e%9 q3 o7 t* U! h
    %        arrayToSrcDistInt :The distance between the array and audio source on the xy axis7 Y- a, J2 r, b6 E! t
    %
    - e9 ?: Q( V3 H! o%                        - \0 a: ]# R+ J: h  H  |( X2 W$ c7 B2 C; O
    %7 C4 R, r) Y4 j: U/ F* m
    %0 u9 A" ?6 U- p- Q
    %         $ R9 {( E+ F4 L% V( U8 a& [: O
    %
    8 F. M7 D" k% B%  How To Use : JUST RUN, |: @- }% K4 X# s9 s
    %
    8 c" m3 F0 u2 @%  
    9 C" I8 \, |' G7 n2 [; F%   
    - I+ j& W; f) V6 g; w: t% Code From: Audio analysis Lab of Aalborg University (Website: https://audio.create.aau.dk/),6 C8 P4 o2 O1 v5 c' S' ?
    %            slightly modified by Wind at Harbin Institute  of Technology, Shenzhen, in 2018.3.24
    2 m$ w+ w2 u" Z1 D4 m) a%  O6 g' p5 n2 x* a6 f
    % Copyright (C) 1989, 1991 Free Software Foundation, Inc.
    # Q; Q# W7 T( d1 z4 V%-------------------------------------------------------------------------: W" e3 N( |; y/ n$ a
    $ R; w6 u' K  ~( a& w* a
    2 e  l5 J- T# W. T
    7 n! M; B' N8 Z% n6 g! A
    addpath([cd,'\..\rirGen\']);
    ) J5 C3 B2 h$ M4 Q4 E& z  g2 F6 S$ z, N5 _) Y# x
    %-----------------------------------------------initial parameters-----------------------------------9 ]; H+ b% V) |8 D5 s
    ) B+ V# F# E" M, I+ G$ ]
    setup.nRirLength = 2048;
    4 ^' L7 ?$ f9 J" T( }setup.hpFilterFlag = 1;
    / M, N' d$ a; ?' H+ Tsetup.reflectionOrder = -1;& v9 r5 @" X. e1 d* G
    setup.micType = 'omnidirectional';& b! g1 S0 F( s- o# `6 l
    setup.nSensors = 4;
    8 i& J) z1 `  b/ M/ }3 S  }/ o" Jsetup.sensorDistance = 0.05;
    ' N) M4 @8 B; I, o0 n6 lsetup.reverbTime = 0.1;
    - _' V2 `7 q! W3 z4 @) usetup.speedOfSound = 340;' V) m1 _) L8 u, a
    : \: m3 J* D5 V. I' d
    setup.noiseField = 'spherical';
    ! [' g# U: \  Z% H+ c0 L: @setup.sdnr = 20;  m5 _/ t6 g# v8 w+ f7 N9 ?' J
    setup.ssnr = 25;
    + |1 N: i) i$ y/ ~1 [
    ; w2 `' `/ E2 T$ Rsetup.roomDim = [3;4;3];! Y/ L1 m- q- W2 i
    0 u0 P* f4 Q/ J- j8 G& s
    srcHeight = 1;4 n: l( C" p7 M+ u4 P- k
    arrayHeight = 1;
    5 `5 t4 s+ b0 t; D; d7 N5 O( ], m) X1 y& {! w" U
    arrayCenter = [setup.roomDim(1:2)/2;1];
    , X9 }5 I! E, H! B
    , c% ~/ b+ l$ C2 m. d4 u& o4 z7 varrayToSrcDistInt = [1,1];9 H; w, e9 I8 \) R% Y0 K7 s" K+ S

    ; D0 B4 N" }+ K; Isetup.srcPoint = [1.5;1;1];
    ' [. r. N( p# Z; e0 U0 T- f+ {6 g  r& U. z
    setup.micPoints = generateUlaCoords(arrayCenter,setup.nSensors,setup.sensorDistance,0,arrayHeight);
    9 m% \0 {! X9 u- T( z
    5 F$ D9 s; }0 Q/ V- f  s4 r# r. s' P, A9 Y  H( H' t1 B$ t
    [cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav');
    1 d% O! O  ~; R; f7 k& b, }- L. `" b; l# \0 D4 e% U
    %---------------------------------------------------initial end----------------------------------------
    & e; e; B& _. H4 E+ d0 p  l2 m! {: O. ?; X5 A0 g" l5 [

    2 X7 L  |2 A, q1 ~3 z7 I" l7 |$ t& R" Y/ W% ^
    %-------------------------------algorithm processing--------------------------------------------------8 v- f# g- C  ]3 b

    2 _* B, ~: M" B, ^: j$ Y& z8 Tif setup.reverbTime == 0,
    7 j# ]7 z. j" R+ v    setup.reverbTime = 0.2;
    ( [( h3 ~6 U4 O  Q" O9 d    reflectionOrder = 0;4 i' p; Z8 r3 f9 Y2 j
    else
    $ |' w! I* b/ J+ u% z    reflectionOrder = -1;( E8 A. Y; A. e1 ]9 d' o
    end9 ?2 e$ `% n/ `9 ?
    8 m" d5 x1 D) M# M" [; z
    rirMatrix = rir_generator(setup.speedOfSound,setup.sampFreq,setup.micPoints',setup.srcPoint',setup.roomDim',...
    7 z; j4 p. Y0 C7 d% H% t    setup.reverbTime,setup.nRirLength,setup.micType,setup.reflectionOrder,[],[],setup.hpFilterFlag);3 l* x/ O5 B/ L' v. b; \. C
    % D- k8 l7 O. p) J0 A1 |* D
    for iSens = 1:setup.nSensors,
    - g2 j3 H/ v6 F' ^* _/ j* d! m) o    tmpCleanSignal(:,iSens) = fftfilt(rirMatrix(iSens,',cleanSignal);2 L5 g# P* V% [
    end
    1 i1 U# p5 r6 c2 {: T$ JmcSignals.clean = tmpCleanSignal(setup.nRirLength:end,;
    / n& @1 E1 V, S! Xsetup.nSamples = length(mcSignals.clean);- [4 j# l3 N' {7 n3 C  }

    ! \) S) r$ U; A0 A- T9 |mcSignals.clean = mcSignals.clean - ones(setup.nSamples,1)*mean(mcSignals.clean);
    ' Z3 b" f/ C1 e3 @6 g: U3 {+ c% S' R  S  R4 ~
    %-------produce the microphone recieved clean signals---------------------------------------------
    , i' d9 W7 c9 H  @- t; s4 O" H" I3 f4 @' u: N2 l
    mic_clean1=10*mcSignals.clean(:,1); %Because of the attenuation of the recievd signals,Amplify the signals recieved by Mics with tenfold, [4 d$ z* E5 A- ^" `
    mic_clean2=10*mcSignals.clean(:,2);
    4 v; H9 L% |, r/ D9 a# ymic_clean3=10*mcSignals.clean(:,3);" b+ A) ~+ T: Z' K6 n: o
    mic_clean4=10*mcSignals.clean(:,4);
    7 j3 Z+ f. v$ O: d+ _audiowrite('mic_clean1.wav' ,mic_clean1,setup.sampFreq);7 ^0 {, F/ P) r  g! M4 f
    audiowrite('mic_clean2.wav' ,mic_clean2,setup.sampFreq);5 q) b# G" E0 C4 w' w* |. g" Q
    audiowrite('mic_clean3.wav' ,mic_clean3,setup.sampFreq);
    & o+ ]' s  h2 O" z2 [audiowrite('mic_clean4.wav' ,mic_clean4,setup.sampFreq);1 p2 W# t- O6 G0 ?( @$ d7 _

    9 o, G5 ?6 l  Z5 G) x7 z%----------------------------------end--------------------------------------------------6 n9 k8 U& {* ]% r: [5 X

    4 I+ K" I9 O7 `- ~0 M! Q3 Taddpath([cd,'\..\nonstationaryMultichanNoiseGenerator\']);
    1 w9 u+ R2 }1 J9 Y3 y6 L  v+ H- Q$ h2 E7 D5 s, x5 V) d+ ~# l
    cleanSignalPowerMeas = var(mcSignals.clean);* o0 V7 g( g9 x& l% c

    - y' s* D: k0 z
    0 E8 ]4 `5 e: |; i4 N! l! N  omcSignals.diffNoise = generateMultichanBabbleNoise(setup.nSamples,setup.nSensors,setup.sensorDistance,...
    . V& s( d2 N$ k/ R- a" k    setup.speedOfSound,setup.noiseField);
    / H# I4 P) M, Z0 ]4 X3 K  AdiffNoisePowerMeas = var(mcSignals.diffNoise);
    % }4 w8 H" e( W5 q' ]- BdiffNoisePowerTrue = cleanSignalPowerMeas/10^(setup.sdnr/10);
    ) {  S( L0 N# DmcSignals.diffNoise = mcSignals.diffNoise*...$ J! L* |" E! ~! z+ x
        diag(sqrt(diffNoisePowerTrue)./sqrt(diffNoisePowerMeas));( q$ ?' A$ O( L3 b4 m# \& t( f$ ^$ O
    5 m. j( Q( [7 c/ g. m1 L. D
    mcSignals.sensNoise = randn(setup.nSamples,setup.nSensors);3 p' }7 L; z5 `3 m5 Z& H
    sensNoisePowerMeas = var(mcSignals.sensNoise);
    2 b6 V2 F8 W; V# Z# |5 r6 X, jsensNoisePowerTrue = cleanSignalPowerMeas/10^(setup.ssnr/10);
    , q+ O( x3 f1 m) \mcSignals.sensNoise = mcSignals.sensNoise*...
    ' d' x+ S* G* S5 h& r# [& ~    diag(sqrt(sensNoisePowerTrue)./sqrt(sensNoisePowerMeas));3 M1 A+ w+ S6 A" C% X! c. p7 `: |

    9 ?! D: @  F4 ?8 mmcSignals.noise = mcSignals.diffNoise + mcSignals.sensNoise;; a- l9 X/ r/ J0 g! h
    mcSignals.observed = mcSignals.clean + mcSignals.noise;& X* v# V* W2 y6 i1 V

    . k, E: }4 i4 l! j: Z%------------------------------processing end-----------------------------------------------------------. E% N8 l; _1 N/ N/ W# u

    , l& U$ u) G; g0 Z* U
    " X' `6 a2 d- q. _6 s4 A6 B! F9 {- p) {% L1 }5 @1 R$ L# Y7 s! n; K+ v2 K
    & H# P' a7 \. F3 K$ w! B( A- `8 r
    %----------------produce the noisy speech of MIc in the specific ervironment sets------------------------& r2 h$ e. w" ?$ U; T% {1 y0 e+ p

    # q- n+ I) _5 i+ P! F. [% Xnoisy_mix1=10*mcSignals.observed(:,1); %Amplify the signals recieved by Mics with tenfold& i- q* Q8 Z! q1 w, c2 v
    noisy_mix2=10*mcSignals.observed(:,2);1 O& L0 |3 R1 D7 }5 P, U: d
    noisy_mix3=10*mcSignals.observed(:,3);' {, v2 ~; x( t- a- L# e
    noisy_mix4=10*mcSignals.observed(:,4);
    3 b* ~5 e$ D7 _: x+ el1=size(noisy_mix1);) @7 @) {$ s6 w  s- c
    l2=size(noisy_mix2);
    / l+ R* r4 ]5 F3 `2 q* }$ ol3=size(noisy_mix3);
    : q# M% s$ {0 X; Jl4=size(noisy_mix4);( a2 f- h% u; M- Z7 d* c
    audiowrite('diffused_babble_noise1_20dB.wav' ,noisy_mix1,setup.sampFreq);: d( i' A/ E: G
    audiowrite('diffused_babble_noise2_20dB.wav' ,noisy_mix2,setup.sampFreq);8 D7 K" h+ Q0 |
    audiowrite('diffused_babble_noise3_20dB.wav' ,noisy_mix3,setup.sampFreq);; Q  C; c* D. {  Z7 |' j
    audiowrite('diffused_babble_noise4_20dB.wav' ,noisy_mix4,setup.sampFreq);
    2 _' s# v- {7 T; m0 _9 S% H: V; Q. `2 b$ q, w( X8 F: A
    * p9 B+ x2 `3 ?, P! }
    %-----------------------------end-------------------------------------------------------------------------
    ' }% J8 U6 G& W2 [这个是主函数,直接运行尽可以得到想要的音频文件,但是你需要先给出你的纯净音频文件和噪声音频,分别对应着:multichannelSignalGenerator()函数中的语句:[cleanSignal,setup.sampFreq] = audioread('..\data\twoMaleTwoFemale20Seconds.wav'),和generateMultichanBabbleNoise()函数中的语句:[singleChannelData,samplingFreq] = audioread('babble_8kHz.wav') 。5 N* c) a& c( B4 T+ j5 _9 p
    直接把它们替换成你想要处理的音频文件即可。
    2 ~8 V2 S) q+ A; f3 D
    ! F' \7 j3 p9 z; l  除此之外,还有一些基本实验环境参数设置,包括:麦克风的形状为线性麦克风阵列(该代码只能对线性阵列进行仿真建模,并且还是均匀线性阵列,这个不需要设置);麦克风的类型(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)。4 M" n* x4 }0 B/ b8 y4 e& N

    3 o* k, _6 l" j7 o! ?, p
    + y7 u$ W2 U* |5 N3 m. D1 _1 }% r5 ~- H( x  P
    图1 麦克风类型图: W2 ^; e4 ~. [- V; D" `: d2 Z* W
    1 j9 X7 Q# O  {4 I% ?: |
    图二 房间的坐标系
    - U8 j9 ~7 y( ]9 r6 V  ]! A# a
    " F' G+ A1 `* [6 O; y6 {  以上便是整个仿真实验环境的参数配置,虽然只能对均匀线性的麦克风阵列进行实验测试,但是这对满足我们进行线阵阵列算法的测试是有很大的帮助。说到底,这种麦克风阵列环境的音频数据产生方法还是基于数学模型的仿真,并不可能取代实际的硬件实验环境测试,所以要想在工程上实现麦克风阵列的一些算法,仍然避免不了在实际的环境中进行测试。最后,希望分享的这套代码对大家进行麦克风阵列算法的入门提供帮助。
    ' L, h3 Y5 x* j" Y# H$ g$ c. A1 m————————————————
    # g5 i3 N8 |- a9 F版权声明:本文为CSDN博主「Mr_Researcher」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    : R/ I+ @2 s# H1 s% L  f$ v原文链接:https://blog.csdn.net/zhanglu_wind/article/details/79674998
    " a: K4 S9 P2 I* e( M6 t/ w/ `1 L3 v1 h& W
    2 B* o6 l5 O  m# `1 f4 ^& L9 j/ @
    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-6-12 09:26 , Processed in 0.475502 second(s), 51 queries .

    回顶部