{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Mirror Image Sources and the Sound Field in a Rectangular Room"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import sfs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "L = 2, 2.7, 3  # room dimensions\n",
    "x0 = 1.2, 1.7, 1.5  # source position\n",
    "max_order = 2  # maximum order of image sources\n",
    "coeffs = .8, .8, .6, .6, .7, .7  # wall reflection coefficients"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2D Mirror Image Sources"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "xs, wall_count = sfs.util.image_sources_for_box(x0[0:2], L[0:2], max_order)\n",
    "source_strength = np.prod(coeffs[0:4]**wall_count, axis=1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from matplotlib.patches import Rectangle"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig, ax = plt.subplots()\n",
    "ax.scatter(*xs.T, source_strength * 20)\n",
    "ax.add_patch(Rectangle((0, 0), L[0], L[1], fill=False))\n",
    "ax.set_xlabel('x / m')\n",
    "ax.set_ylabel('y / m')\n",
    "ax.axis('equal');"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Monochromatic Sound Field"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "omega = 2 * np.pi * 1000  # angular frequency"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "grid = sfs.util.xyz_grid([0, L[0]], [0, L[1]], 1.5, spacing=0.02)\n",
    "P = sfs.fd.source.point_image_sources(omega, x0, grid, L,\n",
    "                                      max_order=max_order, coeffs=coeffs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sfs.plot2d.amplitude(P, grid, xnorm=[L[0]/2, L[1]/2, L[2]/2]);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Spatio-temporal Impulse Response"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fs = 44100  # sample rate\n",
    "signal = [1, 0, 0], fs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "grid = sfs.util.xyz_grid([0, L[0]], [0, L[1]], 1.5, spacing=0.005)\n",
    "p = sfs.td.source.point_image_sources(x0, signal, 0.004, grid, L, max_order,\n",
    "                                      coeffs=coeffs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "sfs.plot2d.level(p, grid)\n",
    "sfs.plot2d.virtualsource(x0)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.2+"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
