\n",
+ "\n",
+ "### Prof. Dr. -Ing. Gerald Schuller Jupyter Notebook: Renato Profeta\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "vG10ULcILvAC",
+ "outputId": "0f10d576-41bf-4c3b-905c-db900475a33a",
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ }
+ },
+ "source": [
+ "# Configurations for Colab\n",
+ "import sys\n",
+ "path='./'\n",
+ "if 'google.colab' in sys.modules:\n",
+ " %matplotlib inline\n",
+ " !git clone https://github.com/GuitarsAI/ADSP_Tutorials.git\n",
+ " path=\"ADSP_Tutorials/\""
+ ],
+ "execution_count": 1,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "text": [
+ "Cloning into 'ADSP_Tutorials'...\n",
+ "remote: Enumerating objects: 202, done.\u001b[K\n",
+ "remote: Counting objects: 100% (202/202), done.\u001b[K\n",
+ "remote: Compressing objects: 100% (173/173), done.\u001b[K\n",
+ "remote: Total 275 (delta 92), reused 110 (delta 29), pack-reused 73\n",
+ "Receiving objects: 100% (275/275), 84.78 MiB | 30.85 MiB/s, done.\n",
+ "Resolving deltas: 100% (116/116), done.\n"
+ ],
+ "name": "stdout"
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "A4F0_lC9LCTV"
+ },
+ "source": [
+ "# Noble Identities, Filters"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "hide_input": true,
+ "id": "RxPDv8M4LCTV",
+ "outputId": "5f2228c7-17aa-4b46-a9af-1cd5d22e6580",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 336
+ }
+ },
+ "source": [
+ "%%html\n",
+ ""
+ ],
+ "execution_count": 2,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": []
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "QqFSQ49fLCTX"
+ },
+ "source": [
+ "## Filter Design"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "JV_Fcei-LCTX"
+ },
+ "source": [
+ "How do we design filters, such that they have desired properties?\n",
+ " \n",
+ "First we should know how the **ideal or desired filter** should look like. In general, we specify the frequency responses with magnitude and phase,\n",
+ "\n",
+ "$$\\large\n",
+ "H(\\Omega)=e^{j \\phi(\\Omega)} \\cdot A(\\Omega)$$\n",
+ "\n",
+ "where $\\phi(\\Omega)$ is our phase (in dependence of our normalized frequency $\\Omega$), and $A(\\Omega)$ is our magnitude. If we want to design our filter, we need to specify both, phase and magnitude.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "hide_input": true,
+ "id": "s6F6FvGbLCTX",
+ "outputId": "2542d80f-f385-4422-b6a9-25e99a108dfc",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 336
+ }
+ },
+ "source": [
+ "%%html\n",
+ ""
+ ],
+ "execution_count": 3,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": []
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "T4DqeBjwLCTX"
+ },
+ "source": [
+ "### Linear Phase and Signal Delay"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "vvt3aRo6LCTX"
+ },
+ "source": [
+ "The phase angle of our system is connected to the delay of our system. Imagine, we have a pure delay of d samples, resulting in a transfer function in the z-transform domain as $H(z)=z^{-d}$, then we get the frequency response in the Discrete Time Fourier Transform (DTFT) domain by replacing $z$ by $e^{j\\Omega}$ as $H(e^{j\\Omega})=e^{-j\\Omega \\cdot d}$. Hence our phase response is \n",
+ "\n",
+ "$$\\large\n",
+ "\\phi(\\Omega)=angle(e^{-j\\Omega \\cdot d})=-\\Omega \\cdot d$$\n",
+ " \n",
+ "The other way around, we can **obtain the delay** in samples by **dividing** the **phase angle** by the **normalized frequency**,\n",
+ " \n",
+ "$$\\large\n",
+ "d=\\frac{-angle(H(e^{j\\Omega}))} {\\Omega}$$\n",
+ "\n",
+ "Observe: In **Python**, the function np.angle() returns the angle of a complex number, in radians (between 0 and 2pi), suitable for our normalized frequencies.\n",
+ "\n",
+ "If the phase angle is a linear function in $\\Omega$, with a slope of -d, we call it a **“linear phase”**. Observe that (only) in this case we have the **same delay** d for all frequencies! We can now also see that the (negative) slope of the phase curve corresponds to the delay d. \n",
+ "\n",
+ "This linear phase is important for instance for image processing. Edges contain many different frequencies, and if we had different group delays for different frequencies, edges would “disolve” and appear unsharp.\n",
+ "\n",
+ "If the phase and delay is not important, often a linear phase is still chosen as default for filter design."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "P2EDglmGLCTX"
+ },
+ "source": [
+ "### General Phase and Signal Delay"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "hide_input": true,
+ "id": "W7VpSwdaLCTX",
+ "outputId": "91f2630e-a8d7-4cf7-9338-f81e552fbe5e",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 336
+ }
+ },
+ "source": [
+ "%%html\n",
+ ""
+ ],
+ "execution_count": 4,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": []
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "OL964PTjLCTY"
+ },
+ "source": [
+ "In general, we call the negative derivative with respect to $\\Omega$ the “**group delay**”, which may be dependent on the frequency $\\Omega$. If we call the group delay $d_g(\\Omega)$, then it is defined as\n",
+ "\n",
+ "$$\\large\n",
+ "d_g(\\Omega)= - \\frac{\\partial \\phi(\\Omega)}{\\partial \\Omega}\n",
+ "$$\n",
+ "\n",
+ "which is an important definition.\n",
+ "\n",
+ "This means that the phase tells you how much delay each frequency group has through the system. When we design a system, this is what we need to keep in mind."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "5tLY1PujLCTY"
+ },
+ "source": [
+ "### Magnitude Design"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "hide_input": true,
+ "id": "phEj_r0cLCTY",
+ "outputId": "6b7d79e6-b3b3-4688-ef76-ec07bfb3ee36",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 336
+ }
+ },
+ "source": [
+ "%%html\n",
+ ""
+ ],
+ "execution_count": 5,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": []
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "aldd-KtcLCTY"
+ },
+ "source": [
+ "Now we also need to think about the desired **magnitude** $A(\\Omega)$ of our filter. Often, one or multiple **pass bands** are desirable, where the signal is passed and hence has close to 0 dB attenuation, together with one or multiple **stop bands**, at which frequencies the signal is “**stopped**”, meaning it has strong attenuation. To do that we need to decide where the band edges are, in normalized frequencies.\n",
+ "\n",
+ "The filter coefficients of an FIR filter are its impulse response. We can obtain the ideal impulse response of a desired filter design in the frequency domain $H(e^{j\\Omega})$ by applying the inverse DTFT to it:\n",
+ "\n",
+ "$$\\large\n",
+ "h(n)= \\frac{1} {2 \\pi} \\cdot \\int_{\\Omega=-\\pi} ^ \\pi H(e^{j\\Omega}) e^{j \\Omega n} d \\Omega\n",
+ "$$\n",
+ "\n",
+ "But this “ideal filter” in general is infinitely long, into the past and future, and hence not realizable. We need to approximate our desired frequency response by minimizing some error function, which we need to define or choose, according to our applications requirements.\n",
+ "\n",
+ "Since we have no ideal filters, first we need to give the system **transition bands** between the pass bands and the stop bands, to give the filter space to come from one state (passing a signal) to another state (stopping a signal). This means, there need to be gaps between the pass bands and the stop bands."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "QqwD76crLCTY"
+ },
+ "source": [
+ "### Example"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "hide_input": true,
+ "id": "NC9GIp-sLCTY",
+ "outputId": "afd2d218-e989-4b5f-adb4-c34cc205f414",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 336
+ }
+ },
+ "source": [
+ "%%html\n",
+ ""
+ ],
+ "execution_count": 6,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": []
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "Aa38dfZHLCTY"
+ },
+ "source": [
+ "We would like to have a **half band low pass** filter. We would like to have a pass band from frequency 0 up to frequency $\\dfrac{\\pi}{2}$, a half band filter. If we want to use it for sampling rate conversion with a downsampling factor of 2, we actually need to make sure that the stop band starts at $\\dfrac{\\pi}{2}$.\n",
+ "\n",
+ "We also need to create a transition band, for instance going from $\\dfrac{\\pi}{2} -0.1$ to $\\dfrac{\\pi}{2}$. This transition band is where we don't care about that value of our frequency response, and it is something that we can use to fine-tune the resulting filter. For instance if we see we don't get enough attenuation, we can increase the bandwidth of our transition band.\n",
+ "\n",
+ "Here our **passband** is given as between 0 and $\\dfrac{\\pi}{2} -0.1$.\n",
+ "\n",
+ "This is now still not an ideal because of the infinite stopband attenuation. That is why we need to define an error measure or an **error function**, which measures how close we come to the ideal, how “good” the filter is, and which we can use to obtain a design which minimizes this error function.\n",
+ "\n",
+ "Often used error functions are the **mean squared error**, the **mean absolute error**, the **weighted mean squared error**, or the **minimax error** function (which seeks to minimize the maximum deviation to the ideal).\n",
+ "\n",
+ "The **weighted mean squared error** uses weights to give errors in different frequency regions different importance. For instance, the error in the stop-band is often more important than in the pass-band, to obtain a high attenuation in the stop-band. An error of 0.1 in the pass-band might not be so bad, but an error of 0.1 in the stop-band leads to only -20 dB attenuation, which is not very much. (we optimize in the linear domain and not in the dB domain). So in this case, we might assign a weight of 1 to the pass bands, and a weight of 1000 to the stop bands, to obtain higher stop band attenuations.\n",
+ "\n",
+ "The optimization usually results in the same or similar **weighted error** for all frequencies. For instance we get: errorstopband*1000=errorpassband*1, and hence errorstopband=errorpassband/1000.\n",
+ "\n",
+ "For **FIR linear phase filters**, Python has the specialized optimization in the function “remez” which implements the so-called Parks-McLellan algorithm, using the Chebyshev algorithm (see also the Book: Oppenheim, Schafer: “Discrete-Time Signal Processing”, Prentice Hall) . \n",
+ "\n",
+ "This is now also an example of the **minimax error function**. The algorithm minimizes the maximum error in the pass band and the stop band (weighted in comparison between the two), which leads to a so-called equi-ripple behaviour (all ripples have the same height in the same band, e.g. stop band or pass band) of the filter in the frequency domain. \n",
+ "It is called in the form:\n",
+ "\n",
+ "`hmin=scipy.signal.remez(N,F,A,W);`\n",
+ "\n",
+ "where N is the length of the filter, F is the vector containing the band edges (now normalized to the Nyquist frequency as 0.5, hence between 0 and 0.5) of the pass band and stop band (the gap between them is the transition band).\n",
+ "\n",
+ "A is the desired amplitude vector for the specified bands, and W is the weight vector for the bands."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "XCa1XkctLCTY"
+ },
+ "source": [
+ "### Python Example"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "hide_input": true,
+ "id": "xViNikHzLCTY",
+ "outputId": "e7aa1a9a-67d6-4adf-b73a-b3188c0a7b7f",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 336
+ }
+ },
+ "source": [
+ "%%html\n",
+ ""
+ ],
+ "execution_count": 7,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": []
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "H60CMBu3LCTY",
+ "outputId": "210f6ce8-4032-42f6-93bf-e6e7154301ad",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 279
+ }
+ },
+ "source": [
+ "if 'google.colab' in sys.modules:\n",
+ " %matplotlib inline\n",
+ "else:\n",
+ " %matplotlib notebook\n",
+ " \n",
+ "import matplotlib.pyplot as plt\n",
+ "import scipy.signal as sp\n",
+ "N=8;\n",
+ "F = [0.0, 0.5/2 - 0.05, 0.5/2, 0.5]\n",
+ "A = [1.0, 0.0]\n",
+ "W = [1, 100]\n",
+ "\n",
+ "hmin = sp.remez(N, F, A, weight=W)\n",
+ "\n",
+ "plt.figure()\n",
+ "plt.plot(hmin)\n",
+ "plt.xlabel('Sample')\n",
+ "plt.ylabel('Value');"
+ ],
+ "execution_count": 8,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": [],
+ "needs_background": "light"
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "Tq51wZ4yLCTZ"
+ },
+ "source": [
+ " Now we obtain a nice impulse response or set of coefficients hmin and its frequencies response is:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "CRMOrHS-LCTZ"
+ },
+ "source": [
+ "from scipy.signal import freqz\n",
+ "import numpy as np\n",
+ "from matplotlib.ticker import FuncFormatter, MultipleLocator"
+ ],
+ "execution_count": 9,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "5yowWrb8LCTZ"
+ },
+ "source": [
+ "w, h = freqz(hmin)"
+ ],
+ "execution_count": 10,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "18W1nxUMLCTZ",
+ "outputId": "38fedde6-ca5b-44c7-ef24-63f3359b1084",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 297
+ }
+ },
+ "source": [
+ "fig = plt.figure()\n",
+ "plt.title('Digital filter frequency response')\n",
+ "plt.subplot(2,1,1)\n",
+ "plt.plot(w, 20 * np.log10(abs(h)), 'b')\n",
+ "plt.ylabel('Amplitude (dB)')\n",
+ "plt.xlabel('Normalized Frequency')\n",
+ "plt.grid()\n",
+ "ax = plt.gca()\n",
+ "ax.xaxis.set_major_formatter(FuncFormatter(\n",
+ " lambda val,pos: '{:.0g}$\\pi$'.format(val/np.pi) if val !=0 else '0'\n",
+ "))\n",
+ "ax.xaxis.set_major_locator(MultipleLocator(base=0.5))\n",
+ "plt.subplot(2,1,2)\n",
+ "angles = np.unwrap(np.angle(h))\n",
+ "plt.plot(w, angles, 'g')\n",
+ "plt.ylabel('Angle (radians)')\n",
+ "plt.xlabel('Normalized Frequency')\n",
+ "ax = plt.gca()\n",
+ "ax.xaxis.set_major_formatter(FuncFormatter(\n",
+ " lambda val,pos: '{:.0g}$\\pi$'.format(val/np.pi) if val !=0 else '0'\n",
+ "))\n",
+ "ax.xaxis.set_major_locator(MultipleLocator(base=0.5))\n",
+ "plt.grid()\n",
+ "plt.tight_layout();"
+ ],
+ "execution_count": 11,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": [],
+ "needs_background": "light"
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "_qBePBPgLCTZ"
+ },
+ "source": [
+ "Here we see that we obtain about -40 dB of stop band attenuation, which roughly corresponds to our weight of 100 for the stop band."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "j-lHQ9ubLCTZ"
+ },
+ "source": [
+ "### Example with Sound"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "hide_input": true,
+ "id": "kL3KFzgALCTZ",
+ "outputId": "0d9fae30-9d76-4109-e0d1-7a2808a04564",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 336
+ }
+ },
+ "source": [
+ "%%html\n",
+ ""
+ ],
+ "execution_count": 12,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": []
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "Y8vJKHlJLCTZ"
+ },
+ "source": [
+ "We have **8000 Hz sampling rate**, and want to build a **band pass** filter. Our low stop band is between 0 and 0.05, our pass band between 0.1 and 0.2, and high stop band between 0.3 and 0.5 (again with 0.5 as Nyquist frequency and 1 as sampling frequency). Hence, our pass band will be between 0.1 * 8000=**800Hz** and 0.2 * 8000=**1600 Hz**. \n",
+ "Hence our vector bands is\n",
+ "\n",
+ "``` F=[0.0, 0.05, 0.1, 0.2, 0.3, 0.5]```\n",
+ "\n",
+ "The vector desired contains the desired magnitude A per band. Hence here for our bandpass filter it is:\n",
+ "\n",
+ "```A=[0.0, 1.0, 0.0]```\n",
+ "\n",
+ "We choose our weights:\n",
+ "\n",
+ "```weight=[100.0, 1.0, 100.0]```\n",
+ "\n",
+ "and our numtaps =N= 32.\n",
+ "\n",
+ "Hence our design function in Python is:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "-Q23p5WCLCTa",
+ "outputId": "98c49770-ae04-4795-89ec-a40026a649a0",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 295
+ }
+ },
+ "source": [
+ "import numpy as np\n",
+ "import scipy.signal\n",
+ "import matplotlib.pyplot as plt\n",
+ "N=32\n",
+ "bpass=scipy.signal.remez(N, [0.0, 0.05, 0.1, 0.2, 0.3, 0.5] , [0.0, 1.0, 0.0], weight=[100.0, 1.0, 100.0])\n",
+ "\n",
+ "plt.figure()\n",
+ "[freq, response] = scipy.signal.freqz(bpass)\n",
+ "plt.plot(freq, 20*np.log10(np.abs(response)+1e-6))\n",
+ "plt.xlabel('Normalized Frequency (pi is Nyquist Frequency)')\n",
+ "plt.ylabel(\"Magnitude of Frequency Response in dB\")\n",
+ "plt.title(\"Magnitude of Frequency Response for our Bandbass Filter\")\n",
+ "plt.grid()\n",
+ "plt.show();"
+ ],
+ "execution_count": 13,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": [],
+ "needs_background": "light"
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "bXT91HY_LCTa"
+ },
+ "source": [
+ "**Observe:** The equi-ripple behaviour inside each band is clearly visible, and we see our pass band a little left of the center. The side lobe to its right is from the transition band there.\n",
+ "Next we plot its **impulse response**,"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "J8xyD9gWLCTa",
+ "outputId": "51da27ae-0515-4387-ccdc-9226a27401f2",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 281
+ }
+ },
+ "source": [
+ "plt.figure()\n",
+ "plt.plot(bpass) \n",
+ "plt.title('Impulse Response of our Bandpass Filter')\n",
+ "plt.grid()\n",
+ "plt.show()"
+ ],
+ "execution_count": 14,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": [],
+ "needs_background": "light"
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "HaLeKF4kLCTa"
+ },
+ "source": [
+ "**Observe:** The impulse response is symmetric around the center, because it is a linear phase filter, and it still has similarity with a sinc function."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "hide_input": true,
+ "id": "J4QHXl1dLCTa",
+ "outputId": "dc16b5d8-5878-4e13-cbc7-6b1c9669bfcd",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 336
+ }
+ },
+ "source": [
+ "%%html\n",
+ ""
+ ],
+ "execution_count": 15,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": []
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "ut9INxpfLCTa"
+ },
+ "source": [
+ "\"\"\"\n",
+ "PyAudio Example: Filter the audio signal between input and output (i.e., record a\n",
+ "few samples, filter them, and play them back immediately).\n",
+ "Gerald Schuller, November 2014\n",
+ "\n",
+ "\n",
+ "Updated and Ported to Jupyter Notebooks by: Renato Profeta, November 2019\n",
+ "Using PyAudio Callback Mode, Matplolib\n",
+ "\"\"\"\n",
+ "\n",
+ "import time\n",
+ "import numpy as np\n",
+ "from pyaudio import PyAudio, paFloat32, paContinue, paInt16, paComplete\n",
+ "from ipywidgets import ToggleButton, Checkbox\n",
+ "import threading\n",
+ "import scipy.signal\n",
+ "\n",
+ "filter_on=False\n",
+ "\n",
+ "button_stop= ToggleButton(description='Stop')\n",
+ "box_filter = Checkbox(False, description='Filter ON / OFF')\n",
+ "\n",
+ "def on_button_stop(change):\n",
+ " if change['new']==True:\n",
+ " stream.stop_stream()\n",
+ " stream.close()\n",
+ " pa.terminate()\n",
+ " button_stop.disabled=True\n",
+ " print('PyAudio terminated...')\n",
+ "button_stop.observe(on_button_stop, 'value')\n",
+ "display(button_stop)\n",
+ "\n",
+ "def box_filter_changed(box_filter):\n",
+ " global filter_on\n",
+ " if box_filter['new']: \n",
+ " filter_on=True\n",
+ " else:\n",
+ " filter_on=False \n",
+ "box_filter.observe(box_filter_changed, names='value')\n",
+ "display(box_filter)\n",
+ "\n",
+ "N=32\n",
+ "bpass=scipy.signal.remez(N, [0.0, 0.05, 0.1, 0.2, 0.3, 0.5] , [0.0, 1.0, 0.0], weight=[100.0, 1.0, 100.0])\n",
+ "z=np.zeros(N-1)\n",
+ "\n",
+ "\n",
+ "\n",
+ "def callback(in_data, frame_count, time_info, flag):\n",
+ " global filter_on, z, bpass\n",
+ " audio_data = np.frombuffer(in_data, dtype=np.float32)\n",
+ " audio_data_s = audio_data\n",
+ " if filter_on:\n",
+ " [filtered,z]=scipy.signal.lfilter(bpass, [1], audio_data_s, zi=z)\n",
+ " audio_data_s=filtered.astype(np.float32)\n",
+ " if button_stop.value==True:\n",
+ " return (audio_data_s, paComplete)\n",
+ " return (audio_data_s, paContinue)\n",
+ "\n",
+ "pa = PyAudio()\n",
+ "\n",
+ "stream = pa.open(format = paFloat32,\n",
+ " channels = 1,\n",
+ " rate = 8000,\n",
+ " output = True,\n",
+ " input = True,\n",
+ " frames_per_buffer = 1024,\n",
+ " stream_callback = callback)\n",
+ "\n",
+ "\n",
+ "def keep_alive(button_stop):\n",
+ " while stream.is_active():\n",
+ " if button_stop.value==True:\n",
+ " break\n",
+ " time.sleep(0.1)\n",
+ "\n",
+ "# Create a Thread for run_spectrogram function\n",
+ "thread = threading.Thread(target=keep_alive, args=(button_stop,))\n",
+ "stream.start_stream()\n",
+ "thread.start()"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "RRqAVSvxLCTb"
+ },
+ "source": [
+ "**Observe:** Speech sounds like through a very cheap telephone, since only a small band is left of it (telephone bandwidth is about 0.3 to 3.4 kHz)."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "8ibMqi6qLCTb"
+ },
+ "source": [
+ "## Filtering and Sampling"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "hide_input": true,
+ "id": "qGkZ28_OLCTb",
+ "outputId": "4bfa55b7-a7ed-4cfa-f84c-fd2efaaaf750",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 336
+ }
+ },
+ "source": [
+ "%%html\n",
+ ""
+ ],
+ "execution_count": 16,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": []
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "DPRWEZcBLCTb"
+ },
+ "source": [
+ "
\n",
+ " \n",
+ "The symbol $\\downarrow N$ means: Downsampling by a factor of N by keeping only every N'th sample.\n",
+ "\n",
+ "The symbol $\\uparrow N$ means: upsamling the sequence by inserting N-1 zeros after each sample.\n",
+ "\n",
+ "**Example:** The filter impulse response shall be $h=[1,2,3]$, hence its z-transform is\n",
+ "\n",
+ "$$\\large\n",
+ "H(z)=1+z^{-1} \\cdot 2 + z^{-2} \\cdot 3\n",
+ "$$\n",
+ "\n",
+ "For N=2 the upsampled version is\n",
+ "\n",
+ "$H(z^2)= 1 + z^{-2} \\cdot 2 + z^{-4} \\cdot 3$, which corresponds to the upsampled, (“sparse” because of the zeros in it), impulse response\n",
+ "$hu=[1,0,2,0,3]$.\n",
+ "\n",
+ "The Noble Identities tell us, in which cases we can **exchange down or up-sampling with filtering**. This can be done in the case of sparse impulse responses, as can be seen above.\n",
+ "\n",
+ "Observe $H(z^N)$ that is the upsampled version of $H(z)$. Remember that the upsampled impulse response has N-1 zeros inserted after each sample of the original impulse response.\n",
+ "\n",
+ "**Observe:** This upsampled filter $H(z^N)$ is in most applications a useless filter, because we not only have 1 passband, but also get N-1 aliased versions for a total of N passbands! But in most applications we want to have only 1 passband. We will make it useful later.\n",
+ "\n",
+ "**Example:** Take a simple filter, in Matlab or Octave or Python notation: B=[1,1]; (a running average filter), an input signal x=[1,2,3,4,...] , in Python:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "LdFuEXJhLCTb",
+ "outputId": "c3205510-a61a-47b6-e011-923240a7cd62",
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ }
+ },
+ "source": [
+ "x =np.arange(1,10, dtype='float') #lfilter needs float\n",
+ "N=2\n",
+ "x"
+ ],
+ "execution_count": 18,
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": [
+ "array([1., 2., 3., 4., 5., 6., 7., 8., 9.])"
+ ]
+ },
+ "metadata": {
+ "tags": []
+ },
+ "execution_count": 18
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "ZQtFTUUvLCTb"
+ },
+ "source": [
+ "Now we would like to implement the **first block diagram** of the Noble Identities, the down-sampling (the pair on the first line, with outputs y1 and y2). \n",
+ "\n",
+ "$\\rightarrow$ First, for **y1, first down sampling, then filtering**, the down-sampling by a factor of N=2:\n",
+ "\n",
+ "```xd = x[::N]```\n",
+ "\n",
+ "This yields:\n",
+ "`xd=1,3,5,7,9`\n",
+ "\n",
+ "Then apply the filter ```B=[1,1]```,\n",
+ "\n",
+ "```y1 = scipy.signal.lfilter(B, 1, xd)```\n",
+ "\n",
+ "This yields the sum of each pair in xd:\n",
+ "\n",
+ "```y1= 1,4,8,12,16```\n",
+ "\n",
+ " \n",
+ "$\\rightarrow$ Now **first filtering, then down sampling**, to implement the corresponding right-hand side block diagram of the noble identity. Our filter is now up-sampled by N=2:\n",
+ "\n",
+ "``` Bu = np.zeros(3)```\n",
+ "\n",
+ "``` Bu[::N] = B```\n",
+ "\n",
+ "This yields\n",
+ "\n",
+ "```Bu= 1,0,1```\n",
+ "\n",
+ "Now filter the signal before down-sampling:\n",
+ "\n",
+ "\n",
+ "```yu = scipy.signal.lfilter(Bu, 1, x)```\n",
+ "\n",
+ "This yields\n",
+ "\n",
+ "```yu= 1, 2, 4, 6, 8, 10, 12, 14, 16, 18```\n",
+ "\n",
+ "Now down-sample it:\n",
+ "\n",
+ "```y2 = yu[::N]```\n",
+ "\n",
+ "This yields\n",
+ "\n",
+ "```y2= 1,4,8,12,16```\n",
+ "\n",
+ "Here we can now see that they are indeed identical, y1=y2!\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "a70SGLX-LCTb",
+ "outputId": "c519d77c-1248-4eda-a1ce-1d10516311f3",
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ }
+ },
+ "source": [
+ "xd = x[::N]\n",
+ "print(\"downsampled x = \",xd)\n",
+ "B=[1,1]\n",
+ "y1 = scipy.signal.lfilter(B, 1, xd)\n",
+ "print(\"y1 = \",y1)\n",
+ "Bu = np.zeros(3)\n",
+ "Bu[::N] = B\n",
+ "print(\"Bu = \",Bu)\n",
+ "\n",
+ "yu = scipy.signal.lfilter(Bu, 1, x)\n",
+ "y2 = yu[::N]\n",
+ "print(\"y2 = \",y2)"
+ ],
+ "execution_count": 19,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "text": [
+ "downsampled x = [1. 3. 5. 7. 9.]\n",
+ "y1 = [ 1. 4. 8. 12. 16.]\n",
+ "Bu = [1. 0. 1.]\n",
+ "y2 = [ 1. 4. 8. 12. 16.]\n"
+ ],
+ "name": "stdout"
+ }
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "hide_input": true,
+ "id": "6fLdjygFLCTb",
+ "outputId": "b1b18d18-eef8-45ec-c281-90cb4ffbb105",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 336
+ }
+ },
+ "source": [
+ "%%html\n",
+ ""
+ ],
+ "execution_count": 20,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": []
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "u1hlRBmsLCTb"
+ },
+ "source": [
+ "These Noble identities can be used to create efficient systems for sampling rate conversions. In this way we can have filters, which always **run** on the **lower sampling rate**, which makes the implementation easier (Remember: so far we always did the filtering at the higher sampling rate).\n",
+ "\n",
+ "It is always possible to **rewrite a filter as a sum of up-sampled versions** of its phase shifted and down-sampled impulse response, as can be seen in the following decomposition of a filter $H(z)$. In this way we can make out of our previously **useless** filter **useful** filters, by combining several of our upsampled versions into a new useful filter $H(z)$(e.g. coming out of remez):\n",
+ " \n",
+ " $$\\large\n",
+ " H(z)= H_0(z^N)+ H_1(z^N)\\cdot z^{-1} + ...+H_{N-1}(z^N) \\cdot z^{-(N-1)}$$\n",
+ "\n",
+ "Here $H_0(z^N)$,contains the coefficients of our original filter $H(z)$ at positions at $mN$, at phase 0, \n",
+ "$H_1(z^N)$contains the coefficients at positions $mN+1$, at phase 1, and in general $H_i(z^N))$ contains the coefficients at positions mN+i, at phase i. This means :\n",
+ "\n",
+ "$H_i(z)$ **is the z-transform** of $h(mN+i)$\n",
+ "\n",
+ "(where $h(n)$ is the impulse response of our original filter).\n",
+ "\n",
+ "Since it can be seen as many different “phases” of our impulse response, the components $H_i(z)$ are also called “**polyphase components**” or “**polyphase elements**”."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "0WjZuVjYLCTc"
+ },
+ "source": [
+ "This is illustrated in the following pictures. First is a simple time sequence,\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ " \n",
+ "\n",
+ "This sequence, for a sampling factor of N=3, can then be decomposed in the following 3 **up-sampled polyphase components** (meaning containing the zeros in it):\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ " \n",
+ "\n",
+ "The upper plot is $H_0(z^N)$, the middle plot is $z^{-1}\\cdot H_1(z^N)$, and the lower plot is $z^{-2}\\cdot H_2(z^N)$.\n",
+ "\n",
+ "The same can be done for our signal $x(n)$. Our **polyphase component** $H_i(z)$ is the z-transform of $x(mN+i)$.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "hide_input": true,
+ "id": "pHgzlv7qLCTc",
+ "outputId": "8270ef4b-c6e9-429d-8a48-25b502c5ecc6",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 336
+ }
+ },
+ "source": [
+ "%%html\n",
+ ""
+ ],
+ "execution_count": 21,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": []
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "KRq4nmyyLCTc"
+ },
+ "source": [
+ "**Example:**\n",
+ "\n",
+ "The impulse response or our filter is\n",
+ "$$h=[1,2,3,4,...]$$\n",
+ "then its z-Transform is\n",
+ "\n",
+ "$$H(z)=1+2z^{-1}+3z^{-2}+4z^{-3}+...$$\n",
+ "Assume N=2. Then we obtain its (up-sampled) polyphase components as\n",
+ "\n",
+ "$$H_0(z^2)=1+3z^{-2}+5z^{-4}+...$$\n",
+ "$$H_1(z^2)=2+4z^{-2}+6z^{-4}+...$$\n",
+ "\n",
+ "Hence we can combine the total filter from its polyphase components,\n",
+ "\n",
+ "$$H(z)=H_0(z^2)+z^{-1} H_1(z^2)$$\n",
+ "\n",
+ "The general case is illustrated in the following block diagram, which consists of a delay chain on the left to implement the different delays $z^{-i}$, and the polyphase components $H_i(z^N)$ of the filter:\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "\n",
+ "(Figure 1)\n",
+ "\n",
+ "This could be a system for down-sampling rate conversion, where we first low-pass filter the signal x to avoid aliasing, and then down-sample it.\n",
+ "\n",
+ "In this way we can decompose our filter in N polyphase components, where i is the “phase” index.\n",
+ "\n",
+ "Now we can simplify this system by using the **Noble Identities**.\n",
+ "\n",
+ "Because in this sum we have transfer functions of the form $H_i(z^N)$, we can use the Noble identities to simplify our sampling rate conversion, to shift the down-samplers before the sum and before the filters (but not before the delay chain on the left side), with replacing the polyphase filters arguments $z^N $ with $z$:\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ " \n",
+ "\n",
+ "Looking at the delay chain and the following down-samplers, we see that this corresponds to “**blocking**” the signal x into consecutive blocks of size N. This can also seen as a **serial to parallel** conversion for each N samples. Hence we now have a block-wise processing with our filter, and the filtering is now completely done at the lower sampling rate, which reduces speed requirements for the hardware. We obtained a parallel processing at the lower sampling rate.\n",
+ "\n",
+ "Since we have N polyphase components in parallel, we can also represent them as **polyphase vectors**, and obtain a vector multiplication for the filtering at the lower sampling rate,\n",
+ "\n",
+ "$$\\large\n",
+ "\\sum_{i=0} ^{N-1} X_i(z) \\cdot H_i(z)=Y(z)\n",
+ "$$\n",
+ "\n",
+ "$$\\large\n",
+ "[X_0(z),..., X_{N-1}] \\cdot [H_0(z), ... , H_{N-1}(z)]^T=Y(z) \n",
+ "$$\n",
+ "\n",
+ "**Observe:** If we have more than 1 filter, we can collect their polyphase vectors into “**polyphase matrices**”.\n",
+ "\n",
+ "**Observe:** This is mathematically a very convenient description, because it includes **sampling** as part of this simple **vector multiplication**!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "hide_input": true,
+ "id": "_UBAt9M6LCTc",
+ "outputId": "5bf2eb19-91a0-4ddb-d76d-1b73fe58aa99",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 336
+ }
+ },
+ "source": [
+ "%%html\n",
+ ""
+ ],
+ "execution_count": 22,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": []
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "MbFv9mjwLCTc"
+ },
+ "source": [
+ "**Python Example Down-sample:** \n",
+ "Down-sample an audio signal. First read in the audio signal into the variable x:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "hide_input": true,
+ "id": "LTlz7pUaLCTc",
+ "outputId": "81173e21-f2d8-4ceb-a4bc-dc6ba9bff5d6",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 336
+ }
+ },
+ "source": [
+ "%%html\n",
+ ""
+ ],
+ "execution_count": 23,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": []
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "Se9fKzOGLCTc"
+ },
+ "source": [
+ "# Impoirts\n",
+ "import librosa"
+ ],
+ "execution_count": 24,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "y_MXIj8PLCTc",
+ "outputId": "83eb282e-8d34-4346-d18e-fd953e7810d8",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 75
+ }
+ },
+ "source": [
+ "x, sr = librosa.load(path+'audio/the-dead-daisies_long-way-to-go.mp3')\n",
+ "\n",
+ "import IPython.display as ipd\n",
+ "display(ipd.Audio(x[10*sr:20*sr], rate=sr))"
+ ],
+ "execution_count": 25,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/html": [
+ "\n",
+ " \n",
+ " "
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": []
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "p6jYRpmELCTd"
+ },
+ "source": [
+ "Take a low pass FIR filter with impulse response \n",
+ "h=[0.5, 1, 1.1, 0.6] and a down-sampling factor N=2. Hence we get the z-transform of the impulse response as $H(z)=0.5+1 \\cdot z^{-1} +1.1 \\cdot z^{-2}+0.6 \\cdot z^{-3}$ and its polyphase components as\n",
+ "\n",
+ "$$H_0(z)=0.5 + 1.1 \\cdot z^{-1}$$ \n",
+ ", $$H_1(z)=1+0.6 z^{-1}$$\n",
+ "\n",
+ "#The polyphase components in in the time domain (in Python) are hence:\n",
+ "\n",
+ "```h0 = h[0::2]```\n",
+ "\n",
+ "```h1 = h[1::2]```\n",
+ "\n",
+ "\n",
+ "Produce the 2 phases of a down-sampled input signal x:\n",
+ "\n",
+ "```x0 = x[0::2]```\n",
+ "\n",
+ "```x1 = x[1::2]```\n",
+ "\n",
+ "We look at our diagram above for N=2, where we see: $Y(z)=X_0(z) \\cdot H_0(z) + X_1(z) \\cdot H_1(z)$, and remember that a multiplication in the z-domain is a convolution or filtering in the time domain. Then the filtered and down-sampled output y is\n",
+ "\n",
+ "```y=scipy.signal.lfilter(h0,1,x0)+scipy.signal.lfilter(h1,1,x1)```"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "iUrJU-fpLCTd"
+ },
+ "source": [
+ "h=[0.5, 1, 1.1, 0.6]\n",
+ "h0 = h[0::2]\n",
+ "h1 = h[1::2]\n",
+ "x0 = x[0::2]\n",
+ "x1 = x[1::2]\n",
+ "\n",
+ "import scipy.signal\n",
+ "y=scipy.signal.lfilter(h0,1,x0)+scipy.signal.lfilter(h1,1,x1)\n"
+ ],
+ "execution_count": 26,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "0tM8La1JLCTd"
+ },
+ "source": [
+ "Observe that each of these 2 filters now works on a down-sampled signal, but the result is identical to first filtering and then down-sampling. \n",
+ "\n",
+ "Now listen to the resulting down-sampled signal:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "p_n8S7IZLCTd",
+ "outputId": "9ba155de-3fa8-4f86-e662-01dbdd6c4e85",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 75
+ }
+ },
+ "source": [
+ "display(ipd.Audio(y[10*(sr//2):20*(sr//2)], rate=sr//2))"
+ ],
+ "execution_count": 27,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/html": [
+ "\n",
+ " \n",
+ " "
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": []
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "f1IDIx2MLCTd"
+ },
+ "source": [
+ "Correspondingly, **up-samplers** can also be obtained with filters operating on the **lower sampling rate**.\n",
+ "\n",
+ "Since $H_i(z^N)$ and $z^{-i}$are linear time-invariant systems, we can exchange their ordering,\n",
+ "\n",
+ "$$\\large\n",
+ "H_i(z^N) \\cdot z^{-i}=z^{-i}\\cdot H_i(z^N)\n",
+ "$$\n",
+ "\n",
+ "Hence we can redraw the polyphase decomposition for an up-sampler followed by a (e.g. low pass) filter (at the high sampling rate) as follows (compare to Figure 1, with the delay elements shifted to the output). Hence we have for upsampling followed by low pass filtering the following picture,\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ " \n",
+ "\n",
+ "Using the Noble Identities, we can now shift the up-sampler to the right, behind the polyphase filters (with changing their arguments from $z^N$ to $z$) and before the delay chain, polyphase components $Y_i(z)$\n",
+ "\n",
+ "
\n",
+ " \n",
+ "
\n",
+ "(Picture 2)\n",
+ " \n",
+ "\n",
+ "\n",
+ "Again, this leads to a parallel processing, with N filters working in **parallel** at the **lower sampling rate**. The structure on the right with the up-sampler and the delay chain can be seen as a **de-blocking** operation. Each time the up-sampler let a complete block through, it is given to the delay chain. In the next time-steps the up-samplers stop letting through, and the block is shifted through the delay chain as a sequence of samples. This can also be seen as a **parallel to serial conversion**.\n",
+ "\n",
+ "With the polyphase elements $Y_i(z)$ the processing at the lower sampling rate can also be written in terms of **polyphase vectors**\n",
+ "\n",
+ "$$\\large\n",
+ "Y(z) \\cdot [H_0(z),..., H_{N-1}(z)]=[Y_0(z),...,Y_{N-1}(z)]\n",
+ "$$\n",
+ "\n",
+ "**Observe:** If we have more than 1 filter, we can collect their polyphase vectors into **polyphase matrices**."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "-3ba_ZmrLCTd"
+ },
+ "source": [
+ "**Python Example Up-Sample**\n",
+ "\n",
+ "Up-sample the signal y by a factor of N=2 and low-pass filter it with the filter h = np.array([0.5, 1, 1.1, 0.6]) as in the previous example. \n",
+ "\n",
+ "Again we obtain the filters polyphase components as h0 = h[0::2],\n",
+ "h1 = h[1::2]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "hide_input": true,
+ "id": "tI16DhGPLCTd",
+ "outputId": "3a1c109a-a822-4fc4-8be5-14a37f6ab4ff",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 336
+ }
+ },
+ "source": [
+ "%%html\n",
+ ""
+ ],
+ "execution_count": 28,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": []
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "KSV-XpraLCTe"
+ },
+ "source": [
+ "h = np.array([0.5, 1, 1.1, 0.6])\n",
+ "h0 = h[0::2]\n",
+ "h1 = h[1::2]"
+ ],
+ "execution_count": 29,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "QLaLPNXzLCTe"
+ },
+ "source": [
+ "Next we need to upsample and do the phase delay (see the block diagram Picture 2), for our de-blocking:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "8kGMYcYPLCTe"
+ },
+ "source": [
+ "y0 = scipy.signal.lfilter(h0,1,y)\n",
+ "y1 = scipy.signal.lfilter(h1,1,y)\n",
+ "L = max([len(y0), len(y1)]) \n",
+ "yu = np.zeros(2*L)\n",
+ "#upsampling with phase 0:\n",
+ "yu[0::2] = y0\n",
+ "#upsampling with phase 1:\n",
+ "yu[1::2] = y1"
+ ],
+ "execution_count": 30,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "OKgS_IxaLCTe"
+ },
+ "source": [
+ "Where now the signal yu is the same as if we had first up-sampled and then filtered the signal!\n",
+ "Now listen to the up-sampled signal:"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "kiAsgCpgLCTe",
+ "outputId": "d33fe073-d739-47d5-db73-30730dbff5f2",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 75
+ }
+ },
+ "source": [
+ "display(ipd.Audio(yu[10*sr:20*sr], rate=sr))"
+ ],
+ "execution_count": 31,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "text/html": [
+ "\n",
+ " \n",
+ " "
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {
+ "tags": []
+ }
+ }
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "XBhycq63LCTf"
+ },
+ "source": [
+ "\n"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "ZdzsZTWNN55O"
+ },
+ "source": [
+ ""
+ ],
+ "execution_count": null,
+ "outputs": []
+ }
+ ]
+}
\ No newline at end of file