|
47 | 47 | "metadata": {}, |
48 | 48 | "outputs": [], |
49 | 49 | "source": [ |
50 | | - "def sound_field(\n", |
51 | | - " d, xref, selection, secondary_source, array, grid):\n", |
| 50 | + "def sound_field(d, xref, selection, secondary_source, array, grid):\n", |
52 | 51 | "\n", |
53 | | - " p = sfs.fd.synthesize(\n", |
54 | | - " d, selection, array, secondary_source, grid=grid)\n", |
| 52 | + " p = sfs.fd.synthesize(d, selection, array, secondary_source, grid=grid)\n", |
55 | 53 | "\n", |
56 | 54 | " fig, [ax_amp, ax_lvl] = plt.subplots(2, 1, sharex=True)\n", |
57 | 55 | " fig.set_figheight(fig.get_figwidth() * 3/2)\n", |
58 | 56 | " sfs.plot2d.amplitude(p, grid, vmax=2, vmin=-2, ax=ax_amp)\n", |
59 | | - " sfs.plot2d.level(\n", |
60 | | - " p, grid, vmax=6, vmin=-6, ax=ax_lvl, cmap='seismic',\n", |
61 | | - " colorbar_kwargs={'label': 'dB'})\n", |
| 57 | + " sfs.plot2d.level(p, grid, vmax=6, vmin=-6, ax=ax_lvl,\n", |
| 58 | + " colorbar_kwargs={'label': 'dB'})\n", |
| 59 | + " sfs.plot2d.level_contour(p, grid, levels=[0], colors='w', ax=ax_lvl)\n", |
62 | 60 | " for ax in ax_amp, ax_lvl:\n", |
63 | | - " sfs.plot2d.loudspeakers(\n", |
64 | | - " array.x, array.n, selection, size=0.125, ax=ax)\n", |
65 | | - " ax.scatter(*xref[selection, :2].T, s=20, c='dimgray',\n", |
| 61 | + " sfs.plot2d.loudspeakers(array.x, array.n, selection, size=0.125, ax=ax)\n", |
| 62 | + " ax_lvl.scatter(*xref[selection, :2].T, marker='o', s=20, c='lightsalmon',\n", |
66 | 63 | " zorder=3)\n", |
67 | | - " ax.grid(True)\n", |
68 | 64 | " plt.tight_layout()\n", |
69 | | - " return p\n" |
| 65 | + " return p" |
70 | 66 | ] |
71 | 67 | }, |
72 | 68 | { |
|
75 | 71 | "metadata": {}, |
76 | 72 | "outputs": [], |
77 | 73 | "source": [ |
78 | | - "xs = sfs.util.asarray_of_rows((-4, 0, 0))\n", |
| 74 | + "xs = sfs.util.asarray_of_rows(xs)\n", |
79 | 75 | "f = sfs.default.c / wavelength # Hz\n", |
80 | 76 | "omega = 2 * np.pi * f # rad/s\n", |
81 | 77 | "normalize_gain = 4 * np.pi * np.linalg.norm(xs)" |
|
106 | 102 | "\n", |
107 | 103 | "d, selection, secondary_source = sfs.fd.wfs.point_25d(\n", |
108 | 104 | " omega, array.x, array.n, xs, xref=xref)\n", |
109 | | - "p_line = sound_field(\n", |
110 | | - " d * normalize_gain, xref, selection,\n", |
111 | | - " secondary_source, array, grid)" |
| 105 | + "p_line = sound_field(d * normalize_gain, xref, selection, secondary_source,\n", |
| 106 | + " array, grid)" |
| 107 | + ] |
| 108 | + }, |
| 109 | + { |
| 110 | + "cell_type": "markdown", |
| 111 | + "metadata": {}, |
| 112 | + "source": [ |
| 113 | + "The level plot includes a white 0 dB isobar curve, which nicely demonstrates the intended amplitude correct synthesis. Note that this isobar is not perfectly aligned along the intended reference contour (gray points) due to diffraction artifacts, which cannot really be compensated." |
112 | 114 | ] |
113 | 115 | }, |
114 | 116 | { |
|
136 | 138 | "\n", |
137 | 139 | "d, selection, secondary_source = sfs.fd.wfs.point_25d(\n", |
138 | 140 | " omega, array.x, array.n, xs, xref=xref)\n", |
139 | | - "p_circ = sound_field(\n", |
140 | | - " d * normalize_gain, xref, selection,\n", |
141 | | - " secondary_source, array, grid)" |
| 141 | + "p_circ = sound_field(d * normalize_gain, xref, selection, secondary_source,\n", |
| 142 | + " array, grid)" |
| 143 | + ] |
| 144 | + }, |
| 145 | + { |
| 146 | + "cell_type": "markdown", |
| 147 | + "metadata": {}, |
| 148 | + "source": [ |
| 149 | + "The (complex-valued) difference between the two sound fields tells us about the difference of both approaches in terms of amplitude." |
142 | 150 | ] |
143 | 151 | }, |
144 | 152 | { |
|
147 | 155 | "metadata": {}, |
148 | 156 | "outputs": [], |
149 | 157 | "source": [ |
150 | | - "# (complex-valued) ratio between the two soundfields tells\n", |
151 | | - "# us about the difference of both approaches in terms of dB\n", |
152 | | - "sfs.plot2d.level(\n", |
153 | | - " p_line / p_circ, grid, vmax=1, vmin=-1, cmap='seismic',\n", |
154 | | - " colorbar_kwargs={'label': 'dB'})\n", |
| 158 | + "sfs.plot2d.amplitude(p_line - p_circ, grid, vmax=1e-1, vmin=-1e-1)\n", |
155 | 159 | "sfs.plot2d.loudspeakers(array.x, array.n, selection, size=0.125)\n", |
156 | | - "plt.grid(True)\n", |
157 | 160 | "plt.tight_layout()" |
158 | 161 | ] |
159 | 162 | }, |
| 163 | + { |
| 164 | + "cell_type": "markdown", |
| 165 | + "metadata": {}, |
| 166 | + "source": [ |
| 167 | + "The (complex-valued) ratio between the two sound fields tells us about the difference of both approaches in terms of dB. Note that again a white 0 dB isobar curve is added as contour plot." |
| 168 | + ] |
| 169 | + }, |
160 | 170 | { |
161 | 171 | "cell_type": "code", |
162 | 172 | "execution_count": null, |
163 | 173 | "metadata": {}, |
164 | 174 | "outputs": [], |
165 | 175 | "source": [ |
166 | | - "# (complex-valued) difference between the two soundfields tells\n", |
167 | | - "# us about the difference of both approaches in terms of magnitude\n", |
168 | | - "sfs.plot2d.amplitude(\n", |
169 | | - " p_line - p_circ, grid, vmax=1e-1, vmin=-1e-1)\n", |
| 176 | + "sfs.plot2d.level(p_line / p_circ, grid, vmax=1, vmin=-1,\n", |
| 177 | + " colorbar_kwargs={'label': 'dB'})\n", |
| 178 | + "sfs.plot2d.level_contour(p_line / p_circ, grid, levels=[0], colors='w')\n", |
170 | 179 | "sfs.plot2d.loudspeakers(array.x, array.n, selection, size=0.125)\n", |
171 | | - "plt.grid(True)\n", |
172 | 180 | "plt.tight_layout()" |
173 | 181 | ] |
| 182 | + }, |
| 183 | + { |
| 184 | + "cell_type": "markdown", |
| 185 | + "metadata": {}, |
| 186 | + "source": [ |
| 187 | + "### Reference point" |
| 188 | + ] |
| 189 | + }, |
| 190 | + { |
| 191 | + "cell_type": "markdown", |
| 192 | + "metadata": {}, |
| 193 | + "source": [ |
| 194 | + "The default handling in\n", |
| 195 | + "`point_25d(omega, x0, n0, xs, xref=[0, 0, 0], c=None, omalias=None)`\n", |
| 196 | + "uses just a reference point, and more specifically the origin, from which the reference contour is determined.\n", |
| 197 | + "This handling is chosen due to convenience and practical relevance using circular loudspeaker arrays.\n", |
| 198 | + "The example below shows the resulting reference contour for the default case.\n", |
| 199 | + "In the example it looks similar to the line referencing contour, but is in general not the same!" |
| 200 | + ] |
| 201 | + }, |
| 202 | + { |
| 203 | + "cell_type": "code", |
| 204 | + "execution_count": null, |
| 205 | + "metadata": {}, |
| 206 | + "outputs": [], |
| 207 | + "source": [ |
| 208 | + "xref = [0, 0, 0]\n", |
| 209 | + "d, selection, secondary_source = sfs.fd.wfs.point_25d(\n", |
| 210 | + " omega, array.x, array.n, xs, xref=xref)\n", |
| 211 | + "p_circ = sound_field(d * normalize_gain, np.array([xref]*array.x.shape[0]),\n", |
| 212 | + " selection, secondary_source, array, grid)" |
| 213 | + ] |
| 214 | + }, |
| 215 | + { |
| 216 | + "cell_type": "markdown", |
| 217 | + "metadata": {}, |
| 218 | + "source": [ |
| 219 | + "The reference point handling might (and indeed mostly will) fail for other reference point locations, as can be seen below.\n", |
| 220 | + "The 0 dB isobar curve does not meet the intended xref point.\n", |
| 221 | + "Hence, be very careful with this referencing in non-default scenarios." |
| 222 | + ] |
| 223 | + }, |
| 224 | + { |
| 225 | + "cell_type": "code", |
| 226 | + "execution_count": null, |
| 227 | + "metadata": {}, |
| 228 | + "outputs": [], |
| 229 | + "source": [ |
| 230 | + "xref = [-0.5, 0, 0]\n", |
| 231 | + "d, selection, secondary_source = sfs.fd.wfs.point_25d(\n", |
| 232 | + " omega, array.x, array.n, xs, xref=xref)\n", |
| 233 | + "p_circ = sound_field(d * normalize_gain, np.array([xref]*array.x.shape[0]),\n", |
| 234 | + " selection, secondary_source, array, grid)" |
| 235 | + ] |
| 236 | + }, |
| 237 | + { |
| 238 | + "cell_type": "markdown", |
| 239 | + "metadata": {}, |
| 240 | + "source": [ |
| 241 | + "A plane wave like sound field, by setting `xs = -1000, 0, 0`, for all above examples reveals some more implications of the different referencing schemes." |
| 242 | + ] |
174 | 243 | } |
175 | 244 | ], |
176 | 245 | "metadata": { |
|
0 commit comments