space-workshop/U02_2_Freq_Shift.en.ipynb
2025-09-19 23:21:37 +02:00

113 lines
4.1 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"id": "e67c2a43",
"metadata": {},
"source": [
"# Frequency Shift"
]
},
{
"cell_type": "markdown",
"id": "6482d25c",
"metadata": {},
"source": [
"```{figure} img/reference/raw_waterfall.webp\n",
"---\n",
"name: fig:raw_waterfall.en\n",
"---\n",
"Waterfall diagram. We can see both copies of the spectrum at $\\pm2.4\\text{kHz}$.\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "cbe50415",
"metadata": {},
"source": [
"As a first step, we want to shift the copy of the spectrum at 2.4 kHz to zero.\n",
"\n",
"In the frequency domain, we can represent this shift as a convolution with a singular peak at -2.4kHz.\n",
"How can we create such a peak?\n",
"\n",
"We remember:\n",
"$\\sin(2\\pi f t)$ and $\\cos(2\\pi f t)$ have peaks at $\\pm f$.\n",
"\n",
"To be precise:\n",
"```{math}\n",
"\\begin{align*}\n",
"\\sin(2\\pi f_0 t) \\,&\\circ\\!\\!-\\!\\!\\bullet\\, \\left\\{\\begin{array}{rcl}\n",
" \\frac{1}{2}i && f = -f_0 \\\\\n",
" -\\frac{1}{2}i &:& f = f_0 \\\\\n",
" 0 &:& \\text{otherwise} \\\\\n",
"\\end{array}\\right. \\\\\n",
"\\cos(2\\pi f_0 t) \\,&\\circ\\!\\!-\\!\\!\\bullet\\, \\left\\{\\begin{array}{rcl}\n",
" \\frac{1}{2} && f \\in \\{-f_0, f_0\\} \\\\\n",
" 0 &:& \\text{otherwise} \\\\\n",
"\\end{array}\\right. \\\\\n",
"\\end{align*}\n",
"```\n",
"\n",
"That is two peaks each\n",
"We can however combine sine and cosine so that one of them cancels out:\n",
"If we multiply the sine term with $i$, we get:\n",
"```{math}\n",
"i \\cdot \\sin(2\\pi f_0 t) \\,&\\circ\\!\\!-\\!\\!\\bullet\\, \\left\\{\\begin{array}{rcl}\n",
" i \\cdot \\frac{1}{2}i = -\\frac{1}{2} && f = -f_0 \\\\\n",
" i \\cdot -\\frac{1}{2}i = \\frac{1}{2} &:& f = f_0 \\\\\n",
" 0 &:& \\text{otherwise} \\\\\n",
"\\end{array}\\right.\n",
"```\n",
"And if we now add the cosine term:\n",
"```{math}\n",
"\\cos(2\\pi f_0 t) + i\\sin(2\\pi f_0 t) \\,&\\circ\\!\\!-\\!\\!\\bullet\\, \\left\\{\\begin{array}{rcl}\n",
" \\frac{1}{2} -\\frac{1}{2} = 0 && f = -f_0 \\\\\n",
" \\frac{1}{2} + \\frac{1}{2} = 1 &:& f = f_0 \\\\\n",
" 0 &:& \\text{otherwise} \\\\\n",
"\\end{array}\\right.\n",
"```\n",
"This yields exactly one peak at $f_0$.\n",
"\n",
"```{note}\n",
"The expression $\\cos(x) + i\\sin(x)$ may be familliar from [Euler's formula](https://en.wikipedia.org/wiki/Euler's_formula).\n",
"```\n",
"\n",
"To perform the frequency shift, we can simply multiply in the time domain (= each sample) with this function.\n",
"We do this as follows:\n",
"- For every sample $s$, we calculate the current time $t$.\n",
" Since the sampling rate $f_S$ equals $16640\\text{Hz}$ we know that the duration in between two samples is exactly $1/16640\\text{s}$.\n",
"- We then calculate $\\cos(2\\pi \\cdot -2400 \\cdot t) + i \\cdot \\sin(2\\pi \\cdot -2400 \\cdot t)$ and obtain a complex result $a + bi$.\n",
"- We multiply $s$ with this, resulting in $a \\cdot s + (b \\cdot s)i$, which we save as our new (complex) sample.\n",
"\n",
"```{note}\n",
"For this project, it is sufficient to represent complex numbers as pairs of two real numbers.\n",
"But in some programming languages, there are explicit types for complex numbers, e.g., [std::complex](https://en.cppreference.com/w/cpp/numeric/complex) in C++.\n",
"In Python, you can simply use `a + b * 1j`.\n",
"```"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"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.11.13"
}
},
"nbformat": 4,
"nbformat_minor": 5
}