Skip to content

Commit 24d294b

Browse files
committed
simplify referencing code, add reference, add difference plot, small text mods
1 parent 9d31786 commit 24d294b

File tree

3 files changed

+45
-38
lines changed

3 files changed

+45
-38
lines changed

doc/examples/wfs-referencing.ipynb

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
"source": [
77
"# WFS Referencing Schemes\n",
88
"\n",
9-
"Illustrates the usage of the SFS toolbox for the simulation of different sound fields using 2.5D WFS and referencing schemes for contours that exhibit amplitude correct synthesis, cf. Ch. 4.1.3 in Gergely Firtha's doctoral thesis [A Generalized Wave Field Synthesis Framework with Application for Moving Virtual Sources](https://last.hit.bme.hu/download/firtha/PhD_thesis/firtha_phd_thesis.pdf) of 2019.\n",
10-
"\n"
9+
"Illustrates the usage of the SFS toolbox for the simulation of different 2.5D WFS referencing schemes for contours within the listening area that exhibit amplitude correct synthesis, cf. Ch. 4.1.3 in [[Fir19]](https://last.hit.bme.hu/download/firtha/PhD_thesis/firtha_phd_thesis.pdf) and [[FFSS17]](doi:10.1109/TASLP.2017.2689245)"
1110
]
1211
},
1312
{
@@ -31,7 +30,7 @@
3130
"array = sfs.array.circular(N=64, R=R)\n",
3231
"grid = sfs.util.xyz_grid([-2, 2], [-2, 2], 0, spacing=0.02)\n",
3332
"\n",
34-
"xs = -4, 0, 0 # point source on negative x-axis\n",
33+
"xs = sfs.util.asarray_of_rows((-4, 0, 0)) # point source on negative x-axis\n",
3534
"normalize_gain = 4 * np.pi * np.linalg.norm(xs)\n",
3635
"wavelength = 1 / 4 # m\n",
3736
"f = sfs.default.c / wavelength # Hz\n",
@@ -63,9 +62,10 @@
6362
" tapering_window,\n",
6463
" size=0.125, ax=axs[i])\n",
6564
" axs[i].plot(xref[:, 0][selection],\n",
66-
" xref[:, 1][selection], 'C5o', ms=4)\n",
65+
" xref[:, 1][selection], 'o', color='dimgray', ms=4)\n",
6766
" axs[i].grid(True)\n",
68-
" plt.tight_layout()"
67+
" plt.tight_layout()\n",
68+
" return p\n"
6969
]
7070
},
7171
{
@@ -74,7 +74,7 @@
7474
"source": [
7575
"### Line as reference contour\n",
7676
"\n",
77-
"The reference contour is calculated according to https://github.com/spatialaudio/wfs_chapter_hda/blob/master/python/wfs25d_circSSD.py#L91 for a virtual point source on x-axis."
77+
"The reference contour is calculated according to [Fir19, eq. (52)] for a virtual point source on x-axis."
7878
]
7979
},
8080
{
@@ -85,28 +85,16 @@
8585
"source": [
8686
"# reference contour is a straight line\n",
8787
"xref_line = 0\n",
88-
"# calc reference contour xref(x0):\n",
89-
"x0_tmp = array.x.T[np.newaxis, :]\n",
90-
"xs_tmp = np.array(xs)[np.newaxis, :, np.newaxis]\n",
91-
"x0xs = x0_tmp - xs_tmp\n",
92-
"x0xs_length = np.linalg.norm(x0xs, axis=1)\n",
93-
"x0xs_unit = x0xs / x0xs_length\n",
94-
"n0_ = array.n.T[np.newaxis, :]\n",
95-
"xref = np.zeros_like(x0_tmp)\n",
96-
"# code assumes that virtual point source is on x-axis:\n",
97-
"for i in range(array.x.shape[0]):\n",
98-
" cosbeta = np.dot(-n0_[0, :, i], [-1, 0, 0]) # use outward SSD normal\n",
99-
" tmp = x0xs_unit[0, :, i]\n",
100-
" tmp *= -x0xs_length[0, i]\n",
101-
" tmp *= xref_line + R * cosbeta\n",
102-
" tmp /= xs_tmp[0, 0, 0] + R * cosbeta\n",
103-
" xref[0, :, i] = x0_tmp[0, :, i] + tmp\n",
104-
"xref = np.squeeze(xref).T\n",
88+
"# calc reference contour xref(x0), cf. [Fir19, eq. (24), (31), (52)]\n",
89+
"# this code assumes virtual point source on negative x-axis\n",
90+
"cosbeta = (array.n @ [1, 0, 0]).reshape(-1, 1)\n",
91+
"xref = array.x + (xs - array.x) * \\\n",
92+
" (xref_line + R * cosbeta) / (xs[0, 0] + R * cosbeta)\n",
10593
"\n",
10694
"d, selection, secondary_source = sfs.fd.wfs.point_25d(\n",
10795
" omega, array.x, array.n, xs, xref=xref)\n",
108-
"sound_field(d * normalize_gain, xref, selection,\n",
109-
" secondary_source, array, grid, tapering=False)"
96+
"p_line = sound_field(d * normalize_gain, xref, selection,\n",
97+
" secondary_source, array, grid, tapering=False)"
11098
]
11199
},
112100
{
@@ -115,7 +103,7 @@
115103
"source": [
116104
"### Circle as reference contour\n",
117105
"\n",
118-
"This reference contour is a circle with origin xs and a radius, such that the origin is on this circle. This contour is straightforward with some obvious vector calculus."
106+
"This reference contour is a circle with origin xs and a radius, such that the origin is on this circle. This contour is obtained with straightforward vector calculus."
119107
]
120108
},
121109
{
@@ -126,19 +114,31 @@
126114
"source": [
127115
"# reference contour is a circle with origin xs\n",
128116
"xref_dist = np.linalg.norm(xs)\n",
129-
"# calc reference contour xref(x0):\n",
130-
"x0_tmp = array.x.T[np.newaxis, :]\n",
131-
"xs_tmp = np.array(xs)[np.newaxis, :, np.newaxis]\n",
132-
"x0xs = x0_tmp - xs_tmp\n",
133-
"x0xs_length = np.linalg.norm(x0xs, axis=1)\n",
134-
"x0xs_unit = x0xs / x0xs_length\n",
135-
"xref = x0_tmp + (xref_dist - x0xs_length) * x0xs_unit\n",
136-
"xref = np.squeeze(xref).T\n",
117+
"# calc reference contour xref(x0), cf. [Fir19, eq. (24), (31)]\n",
118+
"x0xs = array.x - xs\n",
119+
"x0xs_length = np.linalg.norm(x0xs, axis=1, keepdims=True)\n",
120+
"x0xs_unit = x0xs / x0xs_length # unit vec\n",
121+
"xref = xs + xref_dist * x0xs_unit\n",
137122
"\n",
138123
"d, selection, secondary_source = sfs.fd.wfs.point_25d(\n",
139124
" omega, array.x, array.n, xs, xref=xref)\n",
140-
"sound_field(d * normalize_gain, xref, selection,\n",
141-
" secondary_source, array, grid, tapering=False)"
125+
"p_circ = sound_field(d * normalize_gain, xref, selection,\n",
126+
" secondary_source, array, grid, tapering=False)"
127+
]
128+
},
129+
{
130+
"cell_type": "code",
131+
"execution_count": null,
132+
"metadata": {},
133+
"outputs": [],
134+
"source": [
135+
"# (complex-valued) ratio between the two soundfields tells\n",
136+
"# us about the difference of both approaches\n",
137+
"sfs.plot2d.level(p_line / p_circ, grid, vmax=1, vmin=-1,\n",
138+
" cmap='seismic', colorbar_kwargs={'label': 'dB'})\n",
139+
"sfs.plot2d.loudspeakers(array.x, array.n, size=0.125)\n",
140+
"plt.grid(True)\n",
141+
"plt.tight_layout()"
142142
]
143143
}
144144
],

doc/references.bib

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,10 @@ @phdthesis{Schultz2016
9696
year = {2016},
9797
doi = {10.18453/rosdok_id00001765}
9898
}
99+
@phdthesis{Firtha2019,
100+
author = {Firtha, G.},
101+
title = {{A Generalized Wave Field Synthesis Framework with Application
102+
for Moving Virtual Sources}},
103+
school = {Budapest University of Technology and Economics},
104+
year = {2019}
105+
}

sfs/fd/wfs.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ def point_25d(omega, x0, n0, xs, xref=[0, 0, 0], c=None, omalias=None):
205205
206206
is implemented.
207207
The theoretical link of `point_25d()` and `point_25d_legacy()` was
208-
introduced as *unified WFS framework* in :cite:`Firtha2017`.
208+
introduced as *unified WFS framework* in :cite:`Firtha2017`, :cite:`Firtha2019`.
209209
210210
Examples
211211
--------
@@ -292,7 +292,7 @@ def point_25d_legacy(omega, x0, n0, xs, xref=[0, 0, 0], c=None, omalias=None):
292292
\e{-\i\wc |\x_0-\x_\text{s}|}
293293
294294
The theoretical link of `point_25d()` and `point_25d_legacy()` was
295-
introduced as *unified WFS framework* in :cite:`Firtha2017`.
295+
introduced as *unified WFS framework* in :cite:`Firtha2017`, :cite:`Firtha2019`.
296296
Also cf. Eq. (2.145)-(2.147) :cite:`Schultz2016`.
297297
298298
Examples

0 commit comments

Comments
 (0)