Nahuel Passano
update
50f2907
raw
history blame
4.54 kB
import numpy as np
import tmatrix
from utils import layer_wise_dot_product, struve, bessel
from config import AcousticalConstantsConfig
def simulate_loudspeaker(
thiele_small_params: dict,
angular_freq_array: np.ndarray,
acoustical_constants: AcousticalConstantsConfig,
):
n_bins = len(angular_freq_array)
Re_tmatrix = tmatrix.resistance_series(thiele_small_params["Re"], n_bins)
Z_Le_tmatrix = tmatrix.inductance_series(
thiele_small_params["Le"], angular_freq_array
)
Bl_tmatrix = tmatrix.gyrator(thiele_small_params["Bl"], n_bins)
Z_Mm_tmatrix = tmatrix.inductance_series(
thiele_small_params["Mm"], angular_freq_array
)
Z_Cm_tmatrix = tmatrix.capacitance_series(
thiele_small_params["Cm"], angular_freq_array
)
Rm_tmatrix = tmatrix.resistance_series(thiele_small_params["Rm"], n_bins)
electro_mechanical_tmatrix = layer_wise_dot_product(
Re_tmatrix,
Z_Le_tmatrix,
Bl_tmatrix,
Z_Mm_tmatrix,
Z_Cm_tmatrix,
Rm_tmatrix,
)
t_11 = electro_mechanical_tmatrix[0, 0]
t_12 = electro_mechanical_tmatrix[0, 1]
t_21 = electro_mechanical_tmatrix[1, 0]
t_22 = electro_mechanical_tmatrix[1, 1]
# Electrical response
electrical_impedance_shorted_output = t_12 / t_22
# Mechanical response
electrical_input_voltage = np.ones(n_bins)
electrical_input_current = (
electrical_input_voltage / electrical_impedance_shorted_output
)
electro_mechanical_tmatrix_det = np.abs(t_11 * t_22 - t_12 * t_21)
electro_mechanical_tmatrix_inv = np.array(
[
[
t_22 / electro_mechanical_tmatrix_det,
-t_12 / electro_mechanical_tmatrix_det,
],
[
-t_21 / electro_mechanical_tmatrix_det,
t_11 / electro_mechanical_tmatrix_det,
],
]
)
mechanical_force, mechanical_velocity = layer_wise_dot_product(
electro_mechanical_tmatrix_inv,
np.array(
[
[electrical_input_voltage, electrical_input_voltage],
[electrical_input_current, electrical_input_current],
]
),
)[:, 0]
# Acoustical response
air_impedance = acoustical_constants.air_density * acoustical_constants.sound_speed
wave_number_array = angular_freq_array / acoustical_constants.sound_speed
effective_radiation_radius = thiele_small_params["effective_diameter"] / 2
ka_array = wave_number_array * effective_radiation_radius
Sd_value = np.pi * effective_radiation_radius**2
Sd_tmatrix = tmatrix.transformer(Sd_value, n_bins)
### Mechanical impedance of radiation
ZM_rad_real_array = Sd_value * air_impedance * (1 - bessel(2 * ka_array) / ka_array)
ZM_rad_imag_array = (
Sd_value * air_impedance * (1j * (struve(2 * ka_array) / ka_array))
)
ZM_rad_array = ZM_rad_real_array + ZM_rad_imag_array
ZM_rad_tmatrix = np.array(
[[np.ones(n_bins), ZM_rad_array], [np.zeros(n_bins), np.ones(n_bins)]]
)
# Specific acoustic impedance
ZA_rad = (
1j
* angular_freq_array
* acoustical_constants.air_density
* acoustical_constants.directivity_factor
) / (
4
* np.pi
* acoustical_constants.measurement_distance
* np.exp(1j * wave_number_array * acoustical_constants.measurement_distance)
)
Z_delay = 1j * np.exp(
-1j * wave_number_array * acoustical_constants.measurement_distance
) # Phase rotation due air propagation time
electro_mechanical_acoustic_tmatrix = layer_wise_dot_product(
electro_mechanical_tmatrix, ZM_rad_tmatrix, Sd_tmatrix
)
electrical_input_voltage = 2.83
t_11 = electro_mechanical_acoustic_tmatrix[0, 0]
t_12 = electro_mechanical_acoustic_tmatrix[0, 1]
t_21 = electro_mechanical_acoustic_tmatrix[1, 0]
t_22 = electro_mechanical_acoustic_tmatrix[1, 1]
voltage_pressure_transfer_function = (ZA_rad) / (t_11 * ZA_rad + t_12)
acoustical_pressure = (
electrical_input_voltage
* (voltage_pressure_transfer_function / Z_delay)
/ acoustical_constants.reference_pressure
)
loudspeaker_responses = {
"electrical_impedance": electrical_impedance_shorted_output,
"mechanical_force": mechanical_force,
"mechanical_velocity": mechanical_velocity,
"acoustical_pressure": acoustical_pressure,
}
return loudspeaker_responses