pi = np.pi N = 9 # Order Nrf = N # Radial filter order Nviz = N # Visualization order krViz = 30 # Select kr bin for vizualisation r = 0.5 # Array radius ac = 2 # Array configuration, 2: Rigid sphere array FS = 48000 # Sampling Frequency NFFT = 128 # FFT-Bins AZ = pi / 3 # Azimuth angle EL = pi / 3 # Elevation angle # Generate an ideal plane wave Pnm, kr = gen.idealWave(N, r, ac, FS, NFFT, AZ, EL) # Generate radial filters for the rigid sphere array dn, _ = gen.radFilter(Nrf, kr, ac) # Generate visualization data vizMTX = plot.makeMTX(Pnm, dn, krIndex=krViz, Nviz=Nviz) # Visualize layout = {'title': 'Ideal unity plane wave', 'height': 800, 'width': 800} plot.plot3D(vizMTX, style='shape', layout=layout) print("3D visualization opened in browser window, exiting.")
# SFA example 4: Level/Space Resolution import sys sys.path.insert(0, '../') from sound_field_analysis import io, gen, process, plot matFile = 'data/SOFiA_A2_struct.mat' Nsft = 5 # Spatial Fourier Transform Order Nrf = Nsft # Radial Filter Order amp_maxdB = 10 # Maximum modal amplification [dB] ac = 2 # Array configuration: Rigid sphere Nmtx = Nsft # Plot Order krIndex = 128 # kr-bin (frequency) to plot # Read in .mat struct timeData = io.readMiroStruct(matFile) # Transform time domain data to frequency domain and generate kr-vector fftData, kr, f, _ = process.FFT(timeData) # Spatial Fourier transform Pnm = process.spatFT(Nsft, fftData, timeData.quadratureGrid) # Radial filters dn, _ = gen.radFilter(Nrf, kr, ac, amp_maxdB=amp_maxdB) # Plot vizMTX = plot.makeMTX(Pnm, dn, Nviz=Nmtx, krIndex=krIndex) fig = plot.plot3D(vizMTX, style='shape', colorize=False) print("3D visualization opened in browser window, exiting.")
fftData, kr = gen.sampledWave(r=r, gridData=quadrature_grid, ac=ac, FS=FS, NFFT=NFFT, AZ=AZ, EL=EL) # Spatial Fourier Transform Pnm = process.spatFT(Nsft, fftData, quadrature_grid) # Make radial filters dn, _ = gen.radFilter(Nrf, kr, ac) # Generate data to visualize mtxDataLOW = plot.makeMTX(Pnm, dn, krIDX[0], Nviz=Nviz) mtxDataMID = plot.makeMTX(Pnm, dn, krIDX[1], Nviz=Nviz) mtxDataHIGH = plot.makeMTX(Pnm, dn, krIDX[2], Nviz=Nviz) mtxDataVHIGH = plot.makeMTX(Pnm, dn, krIDX[3], Nviz=Nviz) vizMtx = [ np.abs(mtxDataLOW), np.abs(mtxDataMID), np.abs(mtxDataHIGH), np.abs(mtxDataVHIGH) ] plot.plot3Dgrid(2, 2, vizMtx, style='shape', normalize=True) print("3D visualization opened in browser window, exiting.")
FFToversize = 2 startSample = [50, 760, 1460, 2170] # Examplary values (Enable area plot) K = len(startSample) blockSize = 256 # Read in .mat struct timeData = io.readMiroStruct(matFile) vizMtx = np.empty((K, 181, 360)) for k in range(0, K): # Transform time domain data to frequency domain and generate kr-vector fftData, kr, f, _ = process.FFT(timeData, FFToversize=FFToversize, firstSample=startSample[k], lastSample=startSample[k] + blockSize) # Spatial Fourier transform Pnm = process.spatFT(Nsft, fftData, timeData.quadratureGrid) # Radial filters dn, _ = gen.radFilter(Nrf, kr, ac, amp_maxdB=amp_maxdB) # Generate data to visualize mtxData = plot.makeMTX(Pnm, dn, krIndex, Nviz=Nviz) vizMtx[k] = np.abs(mtxData) plot.plot3Dgrid(2, 2, vizMtx, style='shape', normalize=True) print("3D visualization opened in browser window, exiting.")
spatial_coefficients = process.spatFT(fftData, array_data.grid, order_max=order) radial_filter = gen.radial_filter_fullspec( order, NFFT=NFFT, fs=array_data.signal.fs, array_configuration=array_data.configuration) # ## Plot # To visualized the recorded data, the spherical fourier coefficients and the radial filters are passed to plot.makeMTX() along with a specific kr bin. The function returns the sound pressure at a resolution of 1 degree, which then can be visualized using plot.plot3D(). Several styles ('shape', 'sphere', 'flat') exist. # # To plot a specific frequency, we use utils.nearest_to_value_IDX() find the index closest to the desired frequency. # In[ ]: vizMTX1 = plot.makeMTX(spatial_coefficients, radial_filter, kr_IDX=utils.nearest_to_value_IDX(f, 100)) vizMTX2 = plot.makeMTX(spatial_coefficients, radial_filter, kr_IDX=utils.nearest_to_value_IDX(f, 1000)) vizMTX3 = plot.makeMTX(spatial_coefficients, radial_filter, kr_IDX=utils.nearest_to_value_IDX(f, 5000)) vizMTX4 = plot.makeMTX(spatial_coefficients, radial_filter, kr_IDX=utils.nearest_to_value_IDX(f, 10000)) plot.plot3Dgrid(2, 2, [vizMTX1, vizMTX2, vizMTX3, vizMTX4], 'shape')
# In[3]: ideal_array_data = gen.ideal_wave(order, fs, azimuth, colatitude, array_configuration, NFFT=NFFT) simulated_array_data = gen.sampled_wave(order, fs, NFFT, array_configuration, quadrature_grid, azimuth, colatitude) radial_filter = gen.radial_filter_fullspec(order, NFFT, fs, array_configuration) # ## Visualization # # To visualize the plane waves, the spherical fourier coefficients and the generated radial filters are passed to plot.makeMTX() along with a kr bin. The function returns the sound pressure at a resolution of 1 degree, which then can be visualized using plot.plot3D(). Several styles ('shape', 'sphere', 'flat') are available. # In[4]: kr_IDX = 64 vizMTX_ideal = plot.makeMTX(ideal_array_data, radial_filter, kr_IDX) vizMTX_simulated = plot.makeMTX(simulated_array_data, radial_filter, kr_IDX) # In[5]: fig = plot.plot3Dgrid(rows=1, cols=2, viz_data=[vizMTX_ideal, vizMTX_simulated], style='shape') # ## Extracting impulse responses # In order to extract the impulse response, a plane wave decomposition (PWD) is performed using `process.plane_wave_decomp()`. The output in the frequency domain can then simply be transformed to the time domain using `process.iFFT()`. We can calculate several looking directions at once by supplying a vector of azimuth / colatitude pairs. # # # For the ideal plane wave, the impulse response will be almost dirac impulse-like in the direction of the plane wave (azimuth = 0°, colatitude = 90°) and almost zero at a 90° angle (like azimuth = 90°, colatitude = 90°). The spatial resampling exhibit strong aliasing above a certain cutoff frequency (see spectrum), which results in temporal smearing in the time domain. # In[6]: