Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions dft/dft_complex_exponential.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"- lecture: https://github.com/spatialaudio/digital-signal-processing-lecture\n",
"- tutorial: https://github.com/spatialaudio/digital-signal-processing-exercises\n",
"\n",
"Feel free to contact lecturer jacob.thoenes@uni-rostock.de"
"Feel free to contact the lecturer jacob.thoenes@uni-rostock.de"
]
},
{
Expand All @@ -28,8 +28,8 @@
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"from numpy.fft import fft, ifft\n",
"\n",
"# from scipy.fft import fft, ifft\n",
Expand Down Expand Up @@ -100,9 +100,7 @@
"# print(np.allclose(x, x_tmp))\n",
"\n",
"# calc DFT -> DTFT interpolation\n",
"N_dtft = (\n",
" 2**10\n",
") # number of frequencies along unit circle at which DTFT values are calc\n",
"N_dtft = 2**10 # number of frequencies along unit circle at which DTFT values are calc\n",
"Om_dtft = np.arange(N_dtft) * 2 * np.pi / N_dtft # set up frequency vector\n",
"X_dtft = dft2dtft(X, Om_dtft) # perform interp"
]
Expand Down Expand Up @@ -193,7 +191,7 @@
"- the signal $x[k]$ is zero for $k<0$ and $k>N-1$, thus **non-periodic**\n",
"- the signal is discrete\n",
"- the DTFT spectrum is periodic in $2\\pi$\n",
"- the DTFT spectrum is continous"
"- the DTFT spectrum is continuous"
]
},
{
Expand Down Expand Up @@ -304,7 +302,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
"version": "3.12.2"
}
},
"nbformat": 4,
Expand Down
58 changes: 29 additions & 29 deletions dft/dft_intro.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"- lecture: https://github.com/spatialaudio/digital-signal-processing-lecture\n",
"- tutorial: https://github.com/spatialaudio/digital-signal-processing-exercises\n",
"\n",
"Feel free to contact lecturer jacob.thoenes@uni-rostock.de"
"Feel free to contact the lecturer jacob.thoenes@uni-rostock.de"
]
},
{
Expand All @@ -28,10 +28,10 @@
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"from numpy.linalg import inv\n",
"import numpy as np\n",
"from numpy.fft import fft, ifft\n",
"from numpy.linalg import inv\n",
"\n",
"# from scipy.fft import fft, ifft"
]
Expand All @@ -52,7 +52,7 @@
"Let us first define a **complex-valued signal** $x[k]$ of a certain block length $N$ ranging from $0\\leq k\\leq N-1$.\n",
"\n",
"The variable `tmpmu` defines the frequency of the signal. We will see later how this is connected to the DFT.\n",
"For now on, leave it with `tmpmu=1`. This results in exactly one period of cosine and sine building the complex signal. If `tmpmu=2` we get exactly two periods of cos/sin. We'll get get an idea of `tmpmu`..."
"From now on, leave it with `tmpmu=1`. This results in exactly one period of cosine and sine building the complex signal. If `tmpmu=2`, we get exactly two periods of cos/sin. We'll get an idea of `tmpmu`..."
]
},
{
Expand Down Expand Up @@ -87,7 +87,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"We will now perform an DFT of $x[k]$ since we are interested in the frequency spectrum of it.\n",
"We will now perform a DFT of $x[k]$ since we are interested in the frequency spectrum of it.\n",
"\n",
"## DFT Definition\n",
"\n",
Expand All @@ -97,7 +97,7 @@
"\\text{IDFT}: x[k]=\\frac{1}{N}&\\sum_{\\mu=0}^{N-1}X[\\mu]\\cdot\\mathrm{e}^{+\\mathrm{j}\\frac{2\\pi}{N}k\\mu}\n",
"\\end{align}\n",
"\n",
"Note the sign reversal in the exp()-function and the $1/N$ normalization in the IDFT. This convention is used by the majority of DSP text books and also in Python's `numpy.fft.fft()`, `numpy.fft.ifft()` and Matlab's `fft()`, `ifft()` routines."
"Note the sign reversal in the exp()-function and the $1/N$ normalization in the IDFT. This convention is used by the majority of DSP textbooks and also in Python's `numpy.fft.fft()`, `numpy.fft.ifft()` and Matlab's `fft()`, `ifft()` routines."
]
},
{
Expand All @@ -106,11 +106,11 @@
"source": [
"## DFT and IDFT with For-Loops\n",
"\n",
"We are now going to implement the DFT and IDFT with for-loop handling. While this might be helpful to validate algorithms in its initial development phase, this should be avoided for practical used code in the field: for-loops are typically slow and very often more complicated to read than appropriate set up matrices and vectors. Especially for very large $N$ the computation time is very long.\n",
"We are now going to implement the DFT and IDFT with a for-loop handling. While this might be helpful to validate algorithms in their initial development phase, this should be avoided for practical use code in the field: for-loops are typically slow and very often more complicated to read than an appropriate setup of matrices and vectors. Especially for very large $N$, the computation time is very long.\n",
"\n",
"Anyway, the for-loop concept is: the DFT can be implemented with an outer for loop iterating over $\\mu$ and an inner for loop summing over all $k$ for a specific $\\mu$.\n",
"\n",
"We use variable with _ subscript here, in order to save nice variable names for the matrix based calculation."
"We use a variable with _ subscript here, in order to save nice variable names for the matrix based calculation."
]
},
{
Expand Down Expand Up @@ -160,9 +160,9 @@
"source": [
"## DFT and IDFT with Matrix Multiplication\n",
"\n",
"Now we do a little better: We should think of the DFT/IDFT in terms of a matrix operation setting up a set of linear equations.\n",
"Now we do a little better: We should think of the DFT/IDFT in terms of a matrix operation, setting up a set of linear equations.\n",
"\n",
"For that we define a column vector containing the samples of the discrete-time signal $x[k]$\n",
"For that, we define a column vector containing the samples of the discrete-time signal $x[k]$\n",
"\\begin{equation}\n",
"\\mathbf{x}_k = (x[k=0], x[k=1], x[k=2], \\dots , x[k=N-1])^\\mathrm{T}\n",
"\\end{equation}\n",
Expand Down Expand Up @@ -214,7 +214,7 @@
"\\end{equation}\n",
"containing all possible products $k\\,\\mu$ in a suitable arrangement.\n",
"\n",
"For the simple case $N=4$ these matrices are\n",
"For the simple case $N=4$, these matrices are\n",
"\\begin{align}\n",
"\\mathbf{K} = \\begin{bmatrix}\n",
"0 & 0 & 0 & 0\\\\\n",
Expand Down Expand Up @@ -296,7 +296,7 @@
"source": [
"## Fourier Matrix Properties\n",
"\n",
"The DFT and IDFT basically solve two sets of linear equations, that are linked as forward and inverse problem.\n",
"The DFT and IDFT basically solve two sets of linear equations, which are linked as a forward and inverse problem.\n",
"\n",
"This is revealed with the important property of the Fourier matrix\n",
"\n",
Expand All @@ -323,16 +323,16 @@
"(\\frac{\\mathbf{W}}{\\sqrt{N}})^\\mathrm{H} \\, (\\frac{\\mathbf{W}}{\\sqrt{N}}) = \\mathbf{I} =\n",
"(\\frac{\\mathbf{W}}{\\sqrt{N}})^{-1} \\, (\\frac{\\mathbf{W}}{\\sqrt{N}})\n",
"\\end{equation}\n",
"holds, i.e. the complex-conjugate, transpose is equal to the inverse\n",
"holds, i.e., the complex-conjugate transpose is equal to the inverse\n",
"$(\\frac{\\mathbf{W}}{\\sqrt{N}})^\\mathrm{H} = (\\frac{\\mathbf{W}}{\\sqrt{N}})^{-1}$\n",
"and due to the matrix symmetry also\n",
"and due to the matrix symmetry, also\n",
"$(\\frac{\\mathbf{W}}{\\sqrt{N}})^* =\n",
"(\\frac{\\mathbf{W}}{\\sqrt{N}})^{-1}$\n",
"is valid.\n",
"\n",
"This tells that the matrix $\\frac{\\mathbf{W}}{\\sqrt{N}}$ is **orthonormal**, i.e. the matrix spans a orthonormal vector basis (the best what we can get in linear algebra world to work with) of $N$ normalized DFT eigensignals.\n",
"This tells that the matrix $\\frac{\\mathbf{W}}{\\sqrt{N}}$ is **orthonormal**, i.e., the matrix spans an orthonormal vector basis (the best we can get in the linear algebra world to work with) of $N$ normalized DFT eigensignals.\n",
"\n",
"So, DFT and IDFT is transforming vectors into other vectors using the vector basis of the Fourier matrix.\n"
"So, DFT and IDFT are transforming vectors into other vectors using the vector basis of the Fourier matrix.\n"
]
},
{
Expand All @@ -348,7 +348,7 @@
"since we have intentionally set up the matrix this way.\n",
"\n",
"The plot below shows the eigensignal for $\\mu=1$, which fits again one signal period in the block length $N$.\n",
"For $\\mu=2$ we obtain two periods in one block.\n",
"For $\\mu=2$, we obtain two periods in one block.\n",
"\n",
"The eigensignals for $0\\leq \\mu \\leq N-1$ therefore exhibit a certain digital frequency, the so called DFT eigenfrequencies.\n",
"\n",
Expand Down Expand Up @@ -383,11 +383,11 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"The nice thing about the chosen eigenfrequencies, is that the eigensignals are **orthogonal**.\n",
"The nice thing about the chosen eigenfrequencies is that the eigensignals are **orthogonal**.\n",
"\n",
"This choice of the vector basis is on purpose and one of the most important ones in linear algebra and signal processing.\n",
"\n",
"We might for example check orthogonality with the **complex** inner product of some matrix columns."
"We might, for example, check orthogonality with the **complex** inner product of some matrix columns."
]
},
{
Expand Down Expand Up @@ -419,13 +419,13 @@
"\n",
"Let us synthesize a discrete-time signal by using the IDFT in matrix notation for $N=8$.\n",
"\n",
"The signal should contain a DC value, the first and second eigenfrequency with different amplitudes, such as\n",
"The signal should contain a DC value, the first and second eigenfrequencies with different amplitudes, such as\n",
"\n",
"\\begin{equation}\n",
"\\mathbf{x}_\\mu = [8, 2, 4, 0, 0, 0, 0, 0]^\\text{T}\n",
"\\end{equation}\n",
"\n",
"using large `X_test` in code."
"using a large `X_test` in code."
]
},
{
Expand Down Expand Up @@ -480,7 +480,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"We don't need summing the other columns, since their DFT coefficients in `X_test` are zero.\n",
"We don't need to sum up the other columns, since their DFT coefficients in `X_test` are zero.\n",
"\n",
"Finally, normalizing yields the IDFT."
]
Expand All @@ -502,7 +502,7 @@
"source": [
"## Initial Example: DFT Spectrum Analysis for N=8\n",
"\n",
"Now, let us calculate the DFT of the signal `x_test`. As result, we'd expect the DFT vector\n",
"Now, let us calculate the DFT of the signal `x_test`. As a result, we'd expect the DFT vector\n",
"\n",
"\\begin{equation}\n",
"\\mathbf{x}_\\mu = [8, 2, 4, 0, 0, 0, 0, 0]^\\text{T}\n",
Expand Down Expand Up @@ -552,17 +552,17 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"The analysis stage for the discrete-time signal domain, i.e. the DFT\n",
"The analysis stage for the discrete-time signal domain, i.e., the DFT\n",
"can be reinvented by some intuition:\n",
"How 'much' of the reference signal $\\mathbf{w}_{\\text{column i}}$\n",
"(any column in $\\mathbf{W}$)\n",
"is contained in the discrete-time signal $\\mathbf{x}_k$ that is to be analysed.\n",
"\n",
"In signal processing / statistic terms we look for the amount of correlation\n",
"In signal processing/statistics terms, we look for the amount of correlation\n",
"of the signals\n",
"$\\mathbf{w}_{\\text{column i}}$ and $\\mathbf{x}_k$.\n",
"\n",
"In linear algebra terms we are interested in the projection of $\\mathbf{x}_k$ onto\n",
"In linear algebra terms, we are interested in the projection of $\\mathbf{x}_k$ onto\n",
"$\\mathbf{w}_{\\text{column i}}$, because the resulting length of this vector\n",
"reveals the amount of correlation, which is precisely one DFT coefficient $X[\\cdot]$.\n",
"\n",
Expand Down Expand Up @@ -597,7 +597,7 @@
"X[\\mu=N-1] =& \\mathbf{w}_{\\text{column N}}^\\text{H} \\cdot \\mathbf{x}_k.\n",
"\\end{align}\n",
"\n",
"Naturally, all operations can be merged to one single\n",
"Naturally, all operations can be merged into one single\n",
"matrix multiplication using the conjugate transpose of $\\mathbf{W}$.\n",
"\n",
"\\begin{equation}\n",
Expand Down Expand Up @@ -635,7 +635,7 @@
"source": [
"Next, let us plot the magnitude of the spectrum over $\\mu$.\n",
"\n",
"- We should play around with the variable `tmpmu` when defining the input signal at the very beginning of the notebook. For example we can check what happens for `tmpmu = 1`, `tmpmu = 2` and run the whole notebook to visualize the actual magnitude spectra.\n",
"- We should play around with the variable `tmpmu` when defining the input signal at the very beginning of the notebook. For example, we can check what happens for `tmpmu = 1`, `tmpmu = 2`, and run the whole notebook to visualize the actual magnitude spectra.\n",
"\n",
"We should recognize the link of the 'energy' at $\\mu$ in the magnitude spectrum with the chosen `tmpmu`.\n",
"\n",
Expand Down Expand Up @@ -685,7 +685,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
"version": "3.12.2"
}
},
"nbformat": 4,
Expand Down
22 changes: 11 additions & 11 deletions dft/dft_to_dtft_interpolation.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"- lecture: https://github.com/spatialaudio/digital-signal-processing-lecture\n",
"- tutorial: https://github.com/spatialaudio/digital-signal-processing-exercises\n",
"\n",
"Feel free to contact lecturer jacob.thoenes@uni-rostock.de\n"
"Feel free to contact the lecturer jacob.thoenes@uni-rostock.de"
]
},
{
Expand Down Expand Up @@ -61,7 +61,7 @@
"(-1)^{m(N-1)}&\\text{for }\\Omega=2\\pi m\\end{cases},\\,\\,m\\in\\mathbb{Z},\n",
"\\end{align}\n",
"\n",
"which is also known as aliased sinc and Dirichlet function.\n",
"which is also known as the aliased sinc and the Dirichlet function.\n",
"\n",
"Below, we give an example graph for $\\text{psinc}_N(\\Omega)$.\n",
"Note that the orange dots indicate the DFT eigenfrequencies."
Expand Down Expand Up @@ -132,13 +132,13 @@
"\\end{align}\n",
"for $0\\leq k \\leq N-1$.\n",
"\n",
"Furthermore, assume that $x[k]$ results from continuous-time signal $x(t)$ using sampling frequency of $f_s=10$ Hz.\n",
"Furthermore, assume that $x[k]$ results from a continuous-time signal $x(t)$ using a sampling frequency of $f_s=10$ Hz.\n",
"\n",
"1. Plot the discrete-time signals that correspond to the DFT and the DTFT spectrum.\n",
"\n",
"2. Calculate the DFT spectrum $X[\\mu]$ of $x[k]$ and visualise the real and imaginary part as well as the magnitude and the phase of $X[\\mu]$ over $0\\leq\\mu\\leq N-1$.\n",
"2. Calculate the DFT spectrum $X[\\mu]$ of $x[k]$ and visualise the real and imaginary parts as well as the magnitude and the phase of $X[\\mu]$ over $0\\leq\\mu\\leq N-1$.\n",
"\n",
"3. Implement the above mentioned interpolation towards the DTFT and visualise the resulting magnitude spectra $|X[\\mu]|$, $|X(\\Omega)|$ over frequency axes $\\mu$, $\\Omega$ as well as the physical frequency $f$."
"3. Implement the above mentioned interpolation towards the DTFT and visualise the resulting magnitude spectra $|X[\\mu]|$, $|X(\\Omega)|$ over frequency axes $\\mu$, $\\Omega$, as well as the physical frequency $f$."
]
},
{
Expand Down Expand Up @@ -331,19 +331,19 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"We observe that 7 of 8 DFT coeefficients are precisely zero, and only $|X[\\mu=4]|=8$. This is intentional and is expected for the chosen signal that oscillates with exactly a DFT eigenfrequency, here half of the sampling frequency.\n",
"We observe that 7 of 8 DFT coefficients are precisely zero, and only $|X[\\mu=4]|=8$. This is intentional and is expected for the chosen signal that oscillates with exactly a DFT eigenfrequency, here, half of the sampling frequency.\n",
"\n",
"The code above allows for two more playgrounds:\n",
"\n",
"- We might change $\\Omega=1\\cdot\\frac{2\\pi}{N}$, $\\Omega=2\\cdot\\frac{2\\pi}{N}$, $\\Omega=3\\cdot\\frac{2\\pi}{N}$\n",
"and observe how the spectrum moves around the frequency axis, however the shape is preserved.\n",
"and observe how the spectrum moves around the frequency axis, however, the shape is preserved.\n",
"The main lobe precisely corresponds to the chosen $\\mu$.\n",
"\n",
"- We might change $\\Omega=1.5\\cdot\\frac{2\\pi}{N}$, $\\Omega=2.5\\cdot\\frac{2\\pi}{N}$, $\\Omega=3.5\\cdot\\frac{2\\pi}{N}$\n",
"and observe that - since these frequencies are **no** DFT eigenfrequencies - now all DFT coefficients exhibit energy. This suggests frequencies in the signal which are actually not there, but originate from cutting the signal to the chosen block size $N$. The effect is known as **leakage effect**.\n",
"and observe that - since these frequencies are **no** DFT eigenfrequencies - now all DFT coefficients exhibit energy. This suggests frequencies in the signal that are actually not there, but originate from cutting the signal to the chosen block size $N$. The effect is known as the **leakage effect**.\n",
"\n",
"- In task 2 we might optionally apply a window to the signal. The plots for task 3 then reveal how the leakage effect is reduced but the main lobe gets broader.\n",
"Since we have chosen a mono-frequent, complex oscillation as input signal to the DFT / DTFT, the actual window spectrum can be directly seen in the plots."
"- In task 2, we might optionally apply a window to the signal. The plots for task 3 then reveal how the leakage effect is reduced, but the main lobe gets broader.\n",
"Since we have chosen a mono-frequent, complex oscillation as an input signal to the DFT / DTFT, the actual window spectrum can be directly seen in the plots."
]
},
{
Expand Down Expand Up @@ -372,7 +372,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.12"
"version": "3.12.2"
}
},
"nbformat": 4,
Expand Down
Loading
Loading