.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "api/gallery/communications/digitization/plot_02_delta_modulation.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code or to run this example in your browser via JupyterLite. .. rst-class:: sphx-glr-example-title .. _sphx_glr_api_gallery_communications_digitization_plot_02_delta_modulation.py: Delta modulation (1946-1952) ============================ PCM needs an accurate multilevel coder. Delta modulation needs one comparator. The encoder keeps a staircase copy of the signal and sends a single bit per sample: 1 to step up by :math:`\Delta`, 0 to step down (:func:`~engineeringkit.communications.delta_modulate`). The decoder rebuilds the staircase (:func:`~engineeringkit.communications.delta_demodulate`) and smooths it. The idea appears in a 1946 French patent by Maurice Deloraine and colleagues at ITT's Paris laboratory; Frank de Jager of Philips gave the first full published analysis in 1952. The step size is a compromise: small steps fall behind fast signals (*slope overload*, beyond :math:`\Delta f_s`, :func:`~engineeringkit.communications.delta_slope_limit`), large steps leave *granular noise* where the signal is flat. .. GENERATED FROM PYTHON SOURCE LINES 19-24 .. code-block:: Python import matplotlib.pyplot as plt import numpy as np from engineeringkit.communications import delta_demodulate, delta_modulate, delta_slope_limit .. GENERATED FROM PYTHON SOURCE LINES 25-27 Tracking, overload and granular noise ------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 27-44 .. code-block:: Python fs, f, A = 32e3, 400.0, 1.0 t = np.arange(400) / fs x = A * np.sin(2 * np.pi * f * t) needed = 2 * np.pi * f * A fig, axes = plt.subplots(1, 3, figsize=(14, 3.8)) for ax, step, name in zip(axes[:2], (0.03, 0.1), ("slope overload", "tracking")): staircase = delta_demodulate(delta_modulate(x, step), step) ax.plot(t * 1e3, x, label="signal") ax.step(t * 1e3, staircase, where="post", label="staircase") limit = float(delta_slope_limit(step, fs)) ax.set(xlabel="time [ms]", title=f"{name}: step {step}, limit {limit:.0f}/s vs {needed:.0f}/s") ax.legend() error = np.max(np.abs(staircase[:-1] - x[1:])) print(f"step {step}: slope limit {limit:.0f} per s, worst error {error:.3f}") assert (limit < needed) == (error > 3 * step) .. image-sg:: /api/gallery/communications/digitization/images/sphx_glr_plot_02_delta_modulation_001.png :alt: slope overload: step 0.03, limit 960/s vs 2513/s, tracking: step 0.1, limit 3200/s vs 2513/s :srcset: /api/gallery/communications/digitization/images/sphx_glr_plot_02_delta_modulation_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none step 0.03: slope limit 960 per s, worst error 0.954 step 0.1: slope limit 3200 per s, worst error 0.178 .. GENERATED FROM PYTHON SOURCE LINES 45-47 The best step balances the two errors ------------------------------------- .. GENERATED FROM PYTHON SOURCE LINES 47-65 .. code-block:: Python steps = np.logspace(-2.5, -0.5, 41) noise = [] for step in steps: staircase = delta_demodulate(delta_modulate(x, step), step) noise.append(np.mean((staircase[:-1] - x[1:]) ** 2)) noise = np.array(noise) best = steps[np.argmin(noise)] axes[2].loglog(steps, noise) axes[2].axvline(needed / fs, color="k", ls=":", label=r"$\Delta = 2\pi f A / f_s$") axes[2].axvline(best, color="C3", label="minimum") axes[2].set(xlabel=r"step $\Delta$", ylabel="mean-square error", title="Overload (left) vs granular noise (right)") axes[2].legend() fig.tight_layout() print(f"overload boundary {needed / fs:.3f}, best step {best:.3f}") assert needed / fs < best < 3 * needed / fs plt.show() .. rst-class:: sphx-glr-script-out .. code-block:: none overload boundary 0.079, best step 0.079 .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.180 seconds) .. _sphx_glr_download_api_gallery_communications_digitization_plot_02_delta_modulation.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: lite-badge .. image:: images/jupyterlite_badge_logo.svg :target: ../../../../lite/lab/index.html?path=api/gallery/communications/digitization/plot_02_delta_modulation.ipynb :alt: Launch JupyterLite :width: 150 px .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_02_delta_modulation.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_02_delta_modulation.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_02_delta_modulation.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_