\n",
"\n",
"### Prof. Dr. -Ing. Gerald Schuller Jupyter Notebook: Renato Profeta\n",
"\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 386
},
"id": "446yVDjVhbGO",
"outputId": "6c1c61fe-dbbd-4cfc-edb1-b6cd4c6449f2"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Not inside Google Colab: No module named 'google'. Using standard configurations.\n"
]
}
],
"source": [
"# For Google Colab Only\n",
"try:\n",
" import google.colab\n",
" !pip uninstall plotly -y\n",
" !pip install plotly==3.10.0\n",
" \n",
"except Exception as e:\n",
" print(\"Not inside Google Colab: %s. Using standard configurations.\" % (e))"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"id": "dtfFyDDvh8Kt"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Not inside Google Colab: No module named 'google'. Using standard configurations.\n"
]
}
],
"source": [
"# For Google Colab Only\n",
"inColab=False\n",
"try:\n",
" import google.colab\n",
" import plotly.io as pio\n",
" pio.renderers.default = 'colab'\n",
" def enable_plotly_in_cell():\n",
" import IPython\n",
" from plotly.offline import init_notebook_mode\n",
" display(IPython.core.display.HTML(''''''))\n",
" init_notebook_mode(connected=False)\n",
" inColab=True\n",
" \n",
"except Exception as e:\n",
" print(\"Not inside Google Colab: %s. Using standard configurations.\" % (e))"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "2vktcivXhbGS"
},
"source": [
"# Quantization"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 336
},
"hide_input": true,
"id": "Nz_MoewZhbGT",
"outputId": "eb907d3d-485e-4120-d9a2-4e4a558eaf42"
},
"outputs": [
{
"data": {
"text/html": [
"\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%html\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "8e1H4L0GhbGY"
},
"source": [
"**Quantization** is the process of mapping a continuous range of values into a finite range of discrete values. "
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 336
},
"hide_input": true,
"id": "PfBuncD1hbGY",
"outputId": "e73cf04c-f657-417c-d08b-d23c1c8d0622"
},
"outputs": [
{
"data": {
"text/html": [
"\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%html\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "B035bN44hbGb"
},
"source": [
"#### Python Example\n",
"Assume our A/D converter has an input range of -1V to 1V, 4 bit accuracy (meaning we have a total of $2^4$ codewords or indices), and the A/D converter has **0.2 V** at its **input**."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"id": "S-TYfu41hbGc",
"outputId": "2ffc2c50-3723-4f5e-c58b-5d9dfd76fa2e"
},
"outputs": [
{
"data": {
"text/plain": [
"0.125"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Stepsize\n",
"range_max=1 # Maximum input range\n",
"range_min=-1 # Minumum input range\n",
"N=4 # Number of bits\n",
"\n",
"stepsize=(range_max-range_min)/(2**N)\n",
"stepsize"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "i4uOTRoBhbGe"
},
"source": [
"Next we get **quantization index** which is then encoded as a **codeword:**"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"id": "GS9FRL-PhbGf",
"outputId": "10c3775b-67b0-47e8-a8b3-bb22d0dbeb74"
},
"outputs": [
{
"data": {
"text/plain": [
"2"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"input_voltage=0.2\n",
"index = round(input_voltage/stepsize)\n",
"index"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "nWhAugrUhbGh"
},
"source": [
"**Observe:** If the quantization **stepsize is constant**, independent of the signal, we call it a “**uniform quantizer**”. \n",
"The index then is **coded** using the 4 bits and sent to a decoder, for instance using the 4 bit binary **codeword** “0010”. The first bit usually is the sign bit. The **decoder reconstructs** the voltage by first decoding the codeword to an index, and for instance by **multiplying the index** with the **stepsize:**"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
},
"id": "3EEW32-shbGi",
"outputId": "e20bd5e3-3566-47f3-fdba-1796da1c0bcd"
},
"outputs": [
{
"data": {
"text/plain": [
"0.25"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"reconstr=stepsize*index\n",
"reconstr"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "8EjJrDY0hbGn"
},
"source": [
"This is also called the **(de-)quantized signal**, and its difference to the original value or signal is called the **quantization error**. In our example the quantization error is **Quantized Value – Original Value** = 0.25V-0.2V=**0.05 V**\n",
" \n",
"**Observe:** There is always a range of voltages which is mapped to the same codeword. We call this range $\\Delta$, or **stepsize**. These steps represent the quantization in the A/D conversion process, and they lead to quantization errors. \n",
"The output after quantization is a linear **“Pulse Code Modulation” (PCM)** signal. It is linear in the sense that the code values are proportional to the input signal values. \n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "heUOF4sihbGo"
},
"source": [
"## Quantization Error"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 336
},
"hide_input": true,
"id": "LNTTCC_UhbGo",
"outputId": "f3c3bdc1-ba52-4061-c315-426c998d7f05"
},
"outputs": [
{
"data": {
"text/html": [
"\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%html\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "1Ifit4BlhbGr"
},
"source": [
"Let's now call our quantization error “**e**”. Then the **quantization error power** is the **expectation** value of the squared quantization error **e**: \n",
"\n",
"$$ \\large\n",
"E(e^2)=\\int_{-\\Delta /2}^{\\Delta /2}e^2.p(e)de$$\n",
"\n",
"where **$p(e)$** is the probability of error value **e**. Here we compute the power of each possible error value **e** by squaring it, and multiply it with its probability to obtain the **average power**.\n",
"
\n",
"This number will give us some impression of the signal quality after quantization, if we set it in **relation to the signal energy**. Then we get a **Signal to Noise Ratio** (SNR) for our quantizer and A/D converter. \n",
"Assume the quantization error **e** is uniformly distributed (all possible values of the quantization error e appear with equal probability), which is usually the case if the signal is much larger than the quantization step size $\\Delta$ (large signal condition). Since the integral over the probabilities of all possible values of **e** must be 1, and the possible values of e are between $-\\Delta /2$ and $\\Delta /2$, \n",
"\n",
"$$ \\large\n",
"1=\\int_{-\\Delta /2}^{\\Delta /2}p(e)de=p(e) \\cdot \\int_{-\\Delta /2}^{\\Delta /2}de=p(e) \\cdot \\Delta$$\n",
"\n",
"\n",
"we have\n",
"\n",
"$$ \\large p(e)=1/\\Delta$$\n",
"which yields\n",
"\n",
"$$ \\large E(e^2)=\\frac{1} {\\Delta} \\cdot \\int_ {-\\Delta/2} ^ {\\Delta/2} e^2 de\n",
"= \\frac{1} {\\Delta} \\left(\\frac{(\\Delta/2)^3} {3} - \\frac{(-\\Delta/2)^3} {3} \\right) = \\frac{\\Delta^2}{12}$$\n",
"\n",
"Hence the **quantization error power for a uniform quantizer** with stepsize $\\Delta$ and with a large signal is:\n",
"\n",
"$$ \\large E(e^2)=\\frac{\\Delta^2}{12} $$"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "6fQ0_wWEhbGr"
},
"source": [
"## Mid-Rise and Mid-Tread Quantization"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 336
},
"hide_input": true,
"id": "1DJC0mVqhbGs",
"outputId": "09c6b283-c25d-4a46-db15-9873a5c6ec36"
},
"outputs": [
{
"data": {
"text/html": [
"\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%%html\n",
""
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Wd1-WK4ThbGw"
},
"source": [
"Depending on if the quantizer has the input voltage 0 at the center of a quantization interval or on the boundary of that interval, we call the quantizer a mid-tread or a mid rise quantiser, as illustrated in the following picture:\n",
"\n",
"
\n",
" \n",
"(From:http://eeweb.poly.edu/~yao/EE3414/quantization.pdf)\n",
"\n",
"\n",
"Here, $Q_i(f)$ is the index after quantization (which is then encoded and sent to the receiver), and Q(f) is the de-quantization, which produces the quantized reconstructed value at the receiver.