{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Time-frequency transforms : constraints on the transform length\n", "The examples below illustrate how to use the `param_constraint` option to fit the transform length constraints, i.e. the signal length must be a multiple of the hop size and of the number of frequency bins." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%pylab inline\n", "import numpy as np\n", "from madarrays import Waveform\n", "from pyteuf import Stft" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Case 1 : parameters fitting the constraints" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let us define a signal composed of a pure sine" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "signal_params = {'sig_len': 32, 'fs': 1}\n", "f0 = signal_params['fs'] / 8\n", "x = Waveform(np.sin(2 * np.pi * f0 * np.arange(signal_params['sig_len'])),\n", " fs = signal_params['fs'])\n", "x.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We use three similar `Stft` that only differ in the `param_constraint` option." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "stft_params = {'hop': 8, 'n_bins': 16, 'win_name': 'hann', 'win_len': 16, 'zero_pad_full_sig': False}\n", "stft_fix = Stft(param_constraint='fix', **stft_params)\n", "print(stft_fix)\n", "stft_pad = Stft(param_constraint='pad', **stft_params)\n", "print(stft_pad)\n", "stft_pow2 = Stft(param_constraint='pow2', **stft_params)\n", "print(stft_pow2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since the constraint is satisfied, `stft_fix` and `stft_pad` transforms give the same results" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "_ = stft_fix.apply(x).plot_spectrogram(dynrange=100.)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "_ = stft_pad.apply(x).plot_spectrogram(dynrange=100.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since the hop size and the number of bins are powers of 2, the results by `stft_pow2` is also the same." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "_ = stft_pow2.apply(x).plot_spectrogram(dynrange=100.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Case 2: parameters not fitting the constraints" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Again, the signal is composed of a pure sine, but its size is different." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "signal_params = {'sig_len': 50, 'fs': 1}\n", "f0 = signal_params['fs'] / 8\n", "x = Waveform(np.sin(2 * np.pi * f0 * np.arange(signal_params['sig_len'])),\n", " fs = signal_params['fs'])\n", "x.plot()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We use three similar `Stft` that only differ in the `param_constraint` option and choose a hop size and a number of bins that are not divisor of the signal length." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "stft_params = {'hop': 9, 'n_bins': 17, 'win_name': 'hann', 'win_len': 16,\n", " 'zero_pad_full_sig':False}\n", "stft_fix = Stft(param_constraint='fix', **stft_params)\n", "print(stft_fix)\n", "stft_pad = Stft(param_constraint='pad', **stft_params)\n", "print(stft_pad)\n", "stft_pow2 = Stft(param_constraint='pow2', **stft_params)\n", "print(stft_pow2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For `param_constraint='fix'`, an error is raised since the signal length is not a multiple of the hop length." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "try:\n", " X_fix = stft_fix.apply(x)\n", "except BaseException as e:\n", " print('Error raised:', e)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "One option is to use `param_constraint='pad'`: the signal is zero-padded so that the transform-length constraint is satisfied. As shown here, this may results in a adding a lot of zeros at the end of the signal." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "X_pad = stft_pad.apply(x)\n", "print(X_pad)\n", "_ = X_pad.plot_spectrogram(dynrange=100.)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Another option is to use `param_constraint='pow2'`: the hop size and the number of frequency bins are adjusted to a power of two and the signal is zero-padded so that the transform-length constraint is satisfied. Compared to the previous case, the transform parameters are slightly adjusted to limit the padding length needed to satisfy the constraint." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "X_pow2 = stft_pow2.apply(x)\n", "print(X_pow2)\n", "_ = X_pow2.plot_spectrogram(dynrange=100.)" ] }, { "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": 1 }