|
| 1 | +""" |
| 2 | + Compute the plane wave decomposition for an incident broadband plane wave |
| 3 | + on an open circular array using a modal beamformer of finite order. |
| 4 | +""" |
| 5 | + |
| 6 | +import numpy as np |
| 7 | +import matplotlib.pyplot as plt |
| 8 | +import micarray |
| 9 | + |
| 10 | +Nsf = 50 # order of the incident sound field |
| 11 | +N = 30 # order of modal beamformer/microphone array |
| 12 | +pw_angle = 1 * np.pi # incidence angle of plane wave |
| 13 | +pol_pwd = np.linspace(0, 2*np.pi, 180, endpoint=False) # angles for plane wave decomposition |
| 14 | +k = np.linspace(0.1, 20, 100) # wavenumber vector |
| 15 | +r = 1 # radius of array |
| 16 | +M = 61 # number of microphones |
| 17 | + |
| 18 | +# get uniform grid (microphone positions) of number M |
| 19 | +pol, weights = micarray.modal.angular.grid_equal_polar_angle(M) |
| 20 | + |
| 21 | +# get circular harmonics matrix for sensors |
| 22 | +bn = micarray.modal.radial.circular_pw(Nsf, k, r, setup='rigid') |
| 23 | +D = micarray.modal.radial.circ_diagonal_mode_mat(bn) |
| 24 | +Psi_p = micarray.modal.angular.cht_matrix(Nsf, pol, weights) |
| 25 | +Psi_pw = micarray.modal.angular.cht_matrix(Nsf, pw_angle) |
| 26 | +p = np.matmul(np.matmul(np.conj(Psi_pw.T), D), Psi_p) |
| 27 | +p = np.squeeze(p) |
| 28 | + |
| 29 | +# get circular harmonics matrix for a source ensemble of azimuthal plane wave |
| 30 | +Psi_p = micarray.modal.angular.cht_matrix(N, pol) |
| 31 | +Psi_q = micarray.modal.angular.cht_matrix(N, pol_pwd) |
| 32 | +# get radial filters |
| 33 | +Bn = micarray.modal.radial.circular_pw(N, k, r, setup='rigid') |
| 34 | +Dn, _ = micarray.modal.radial.regularize(1/Bn, 100, 'softclip') |
| 35 | +D = micarray.modal.radial.circ_diagonal_mode_mat(Dn) |
| 36 | +# compute plane wave decomposition |
| 37 | +A_pwd = np.matmul(np.matmul(np.conj(Psi_q.T), D), Psi_p) |
| 38 | +q_pwd = np.squeeze(np.matmul(A_pwd, np.expand_dims(p, 2))) |
| 39 | +q_pwd_t = np.fft.fftshift(np.fft.irfft(q_pwd, axis=0), axes=0) |
| 40 | + |
| 41 | +# visualize plane wave decomposition (aka beampattern) |
| 42 | +plt.figure() |
| 43 | +plt.pcolormesh(k, pol_pwd/np.pi, micarray.util.db(q_pwd.T), vmin=-40) |
| 44 | +plt.colorbar() |
| 45 | +plt.xlabel(r'$kr$') |
| 46 | +plt.ylabel(r'$\phi / \pi$') |
| 47 | +plt.title('Plane wave docomposition by modal beamformer (frequency domain)') |
| 48 | +plt.savefig('modal_open_beamformer_pwd_fd.png') |
| 49 | + |
| 50 | +plt.figure() |
| 51 | +plt.pcolormesh(range(2*len(k)-2), pol_pwd/np.pi, micarray.util.db(q_pwd_t.T), vmin=-40) |
| 52 | +plt.colorbar() |
| 53 | +plt.ylabel(r'$\phi / \pi$') |
| 54 | +plt.title('Plane wave docomposition by modal beamformer (time domain)') |
| 55 | +plt.savefig('modal_open_beamformer_pwd_td.png') |
0 commit comments