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.")
Пример #3
0
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.")
Пример #4
0
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.")
Пример #5
0
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]: