|
| 1 | +import numpy as np |
| 2 | +from scipy.fftpack import idct, dct |
| 3 | + |
| 4 | +class ARDSimulator: |
| 5 | + |
| 6 | + C = 343 # Speed of sound [m/s] |
| 7 | + |
| 8 | + def __init__(self, room_size, max_simulation_frequency, spatial_samples_per_wave_length=4): |
| 9 | + ''' |
| 10 | + Instantiates an ARD simulation session. |
| 11 | +
|
| 12 | + Parameters |
| 13 | + ---------- |
| 14 | + room_size : ndarray |
| 15 | + Size of the room in meters. |
| 16 | + max_simulation_frequency : float |
| 17 | + Uppermost frequency of simulation. Can be dialed in lower to enhance performance. |
| 18 | + spatial_samples_per_wave_length : int |
| 19 | + Number of spatial samples per wave length. Usually 2 to 4. Lower values decrease |
| 20 | + resolution but enhances performance. |
| 21 | + ''' |
| 22 | + assert(len(room_size) >= 1, "Room dimensions should be bigger than 1D.") |
| 23 | + assert(len(room_size) <= 3, "Room dimensions should be lower than 3D.") |
| 24 | + |
| 25 | + self.room_size = room_size |
| 26 | + self.max_simulation_frequency = max_simulation_frequency |
| 27 | + self.H = self.calculate_voxelization_step( |
| 28 | + spatial_samples_per_wave_length) |
| 29 | + self.pressure_field = None |
| 30 | + |
| 31 | + def preprocessing(self): |
| 32 | + ''' |
| 33 | + Preprocessing stage. Refers to Step 1 in the paper. |
| 34 | +
|
| 35 | + Parameters |
| 36 | + ---------- |
| 37 | +
|
| 38 | + Returns |
| 39 | + ------- |
| 40 | + ''' |
| 41 | + # Step 1 a). Preparing pressure field. Equates to function p(x) on the paper. |
| 42 | + self.pressure_field = np.zeros( |
| 43 | + shape=[len(self.room_size), np.max(self.room_size) / self.H]) |
| 44 | + |
| 45 | + # Step 1 b). Rectangular decomposition. Skipped as of now. TODO: Implement rectangular decomposition |
| 46 | + |
| 47 | + # Step 1 c). Precomputation for the DCTs to be performed. Skipped partitions as of now. TODO: Implement partitions |
| 48 | + |
| 49 | + def simulation(self): |
| 50 | + ''' |
| 51 | + Simulation stage. Refers to Step 2 in the paper. |
| 52 | +
|
| 53 | + Parameters |
| 54 | + ---------- |
| 55 | +
|
| 56 | + Returns |
| 57 | + ------- |
| 58 | + ''' |
| 59 | + pass |
| 60 | + |
| 61 | + @classmethod |
| 62 | + def pressure_field_calculation(): |
| 63 | + pass |
| 64 | + |
| 65 | + def calculate_voxelization_step(self, spatial_samples_per_wave_length): |
| 66 | + ''' |
| 67 | + Calculate voxelization step for the segmentation of the room (voxelizing the scene). |
| 68 | + The cell size is fixed by the chosen wave length and the number of spatial samples per |
| 69 | + wave length. |
| 70 | + Calculation: ℎ <= 𝑐 / (2 * 𝑓_max) |
| 71 | +
|
| 72 | + Parameters |
| 73 | + ---------- |
| 74 | + spatial_samples_per_wave_length : int |
| 75 | + Number of spatial samples per wave length. Usually 2 to 4. |
| 76 | +
|
| 77 | + Returns |
| 78 | + ------- |
| 79 | + float |
| 80 | + ℎ, the voxelization step. In numerics and papers, it's usually referred to ℎ. |
| 81 | + ''' |
| 82 | + return self.C / (spatial_samples_per_wave_length * self.max_simulation_frequency) |
0 commit comments