{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%pylab inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Time-Frequency analysis with missing data\n", "\n", "## `Stft` objects\n", "\n", "Short-time Fourier transforms (STFT) of signals can be handled using `Stft` objects. This is a wrapper for the `ltfatpy` package. \n", "\n", "### Transform and inverse transform\n", "`Stft` takes as input the parameters of the STFT, namely the hop size `hop`, the number of bins `n_bins`, the window type `win_name` and length `win_len`, as well as two other parameters, `param_constraint` (see tutorial on the constraints on the transform length) and `zero_pad_full_sig` (see tutorial on boundary effects).\n", " \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from pyteuf import Stft\n", "from madarrays import Waveform" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "stft = Stft(hop=16, n_bins=512, win_name='sine', win_len=256,\n", " param_constraint='pad', zero_pad_full_sig=False)\n", "print(stft)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The inverse transform may obtained from the direct transform by" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "istft = stft.get_istft()\n", "print(istft)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Example on a synthetic real signal" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Create a signal composed of two sines" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "nu1 = 1/33\n", "nu2 = 3/16\n", "duration = 0.5\n", "fs = 8000\n", "t = np.arange(0, int(duration*fs)) / fs\n", "x = np.cos(2*np.pi*t*nu1*fs) + 0.5*np.cos(2*np.pi*t*nu2*fs)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Compute STFT and display the spectrogram" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "X = stft.apply(x, fs=fs)\n", "print(X)\n", "_ = X.plot_spectrogram(dynrange=100.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that the negative frequencies are not displayed since the STFT of a real signal is symetric hermitian, and that boundary effects appear at the beginning and the end of the time axis.\n", "\n", "Reconstruction is obtained by:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "y = istft.apply(X)\n", "print('Reconstruction: {}'.format(y))\n", "print('Reconstruction error: {:.3f} dB'.format(10 * np.log10(np.mean(np.abs(x - y)**2))))" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "### Example on a synthetic complex signal" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Create a waveform composed of two sines" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "nu1 = 1/33\n", "nu2 = 3/16\n", "duration = 0.5\n", "fs = 8000\n", "t = np.arange(0, int(duration*fs)) / fs\n", "x = Waveform(np.exp(1j*2*np.pi*t*nu1*fs) + 0.5*np.exp(1j*2*np.pi*t*nu2*fs) , fs=fs)\n", "\n", "print(x)\n", "np.real(x).show_player()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "X = stft.apply(x)\n", "print(X)\n", "_ = X.plot_spectrogram(dynrange=100.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that all the frequencies are shown since the signal is complex.\n", "\n", "Reconstruction is obtained by:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "y = istft.apply(X)\n", "print('Reconstruction: {}'.format(y))\n", "print('Reconstruction error: {:.3f} dB'.format(10 * np.log10(np.mean(np.abs(x - y)**2))))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Example on a real sound" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Load test sound" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from ltfatpy import gspi\n", "x, fs = gspi()\n", "x = Waveform(x, fs=fs)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that one may also use static method `Waveform.from_wavfile(filename)` in order to load a `Waveform` object from an audio file." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Apply STFT and display properties of Stft data" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "X = stft.apply(x)\n", "print(X)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Get a related Istft object, apply istft, display properties of reconstruction" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "y = istft.apply(X)\n", "print('Reconstruction: {}'.format(y))\n", "print('Reconstruction error: {:.3f} dB'.format(10 * np.log10(np.mean(np.abs(x - y)**2))))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that `x-y` computes the difference between two `Waveform` object and returns a new `Waveform`, that may be displayed or processed, as below. Many operators can be applied in the same way to `Waveform` objects." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plt.figure(figsize=(12,2))\n", "x.plot(y_axis_label=None)\n", "\n", "plt.figure(figsize=(12,4))\n", "X.plot_spectrogram(dynrange=100.)\n", "\n", "plt.figure(figsize=(12,2))\n", "(x-y).plot(y_axis_label=None)\n", "plt.title('Error signal')" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "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.6.2" } }, "nbformat": 4, "nbformat_minor": 2 }