├── .binder ├── apt.txt └── requirements.txt ├── .github └── workflows │ ├── lint_nb.yml │ ├── notebook_ci.yml │ └── run_nb.yml ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── ci ├── README.md └── requirements.txt ├── conf.py ├── data ├── amplifier_noise.npz ├── gold_sequences.npz ├── linear_sweep.wav ├── speech.wav ├── speech_8k.wav ├── vocal_o.wav └── vocal_o_8k.wav ├── filter_design ├── RLC_lowpass.png ├── audiofilter.ipynb ├── audiofilter.py ├── biblio.bib ├── bilinear_transform.ipynb ├── comparison_non_recursive.ipynb ├── frequency_sampling_method.ipynb ├── ipython_kernel_config.py ├── sz_mapping.png └── window_method.ipynb ├── images ├── README ├── filter_design.tex ├── introduction.tex ├── mk_filter_design.sh ├── mk_introduction.sh ├── mk_nonrecursive_filters.sh ├── mk_quantization.sh ├── mk_random_signals.sh ├── mk_recursive_filters.sh ├── mk_spectral_analysis.sh ├── mk_systems.sh ├── mk_wiener_filter.sh ├── non_recursive_filters.tex ├── prefix.tex ├── quantization.tex ├── random_signals.tex ├── recursive_filters.tex ├── spectral_analysis.tex ├── ss2-figures.sty ├── systems.tex └── wiener_filter.tex ├── index.ipynb ├── index.rst ├── introduction ├── DSP.png ├── analog_discrete_digital.png └── introduction.ipynb ├── ipython_kernel_config.py ├── nonrecursive_filters ├── LTI_system_td.png ├── fast_convolution.ipynb ├── introduction.ipynb ├── overlap_add.png ├── overlap_save.png ├── quantization_effects.ipynb ├── roundoff_model.png └── segmented_convolution.ipynb ├── quantization ├── analog_discrete_digital.png ├── ideal_ADC.png ├── introduction.ipynb ├── ipython_kernel_config.py ├── linear_uniform_characteristic.ipynb ├── linear_uniform_quantization_error.ipynb ├── mid_rise_characteristic.png ├── mid_tread_characteristic.png ├── model_quantization.png ├── noise_shaping.ipynb ├── noise_shaping.png ├── nonlinear_quantization_speech_signal.ipynb ├── oversampling.ipynb ├── oversampling.png ├── oversampling_anti_aliasing.png ├── requantization_speech_signal.ipynb ├── speech_2bit.wav ├── speech_2bit_error.wav ├── speech_4bit.wav ├── speech_4bit_error.wav ├── speech_6bit.wav ├── speech_6bit_error.wav ├── speech_8bit.wav ├── speech_8bit_error.wav ├── speech_8k_8bit.wav ├── speech_8k_8bit_error.wav ├── speech_Alaw_8k_8bit.wav └── speech_Alaw_8k_8bit_error.wav ├── random_signals ├── communication_channel.png ├── correlation_functions.ipynb ├── cosine.wav ├── cosine_noise.wav ├── distributions.ipynb ├── ensemble_averages.ipynb ├── important_distributions.ipynb ├── independent.ipynb ├── introduction.ipynb ├── ipython_kernel_config.py ├── measurement_channel.png ├── noise.wav ├── power_spectral_densities.ipynb ├── speech_noise.wav ├── stationary_ergodic.ipynb ├── superposition.ipynb ├── uniform_white_noise.wav └── white_noise.ipynb ├── random_signals_LTI_systems ├── LTI_system_td.png ├── Wiener_observed_signal.wav ├── Wiener_output.wav ├── acoustic_impulse_response_measurement.ipynb ├── artificial_vocal.wav ├── correlation_functions.ipynb ├── introduction.ipynb ├── ipython_kernel_config.py ├── linear_mean.ipynb ├── linear_prediction.ipynb ├── model_wiener_filter.png ├── power_spectral_densities.ipynb ├── uniform_pink_noise.wav ├── uniform_white_noise.wav └── wiener_filter.ipynb ├── recursive_filters ├── cascaded_structures.ipynb ├── coupled_form.png ├── direct_form_i.png ├── direct_form_ii.png ├── direct_form_ii_t.png ├── direct_forms.ipynb ├── introduction.ipynb ├── ipython_kernel_config.py ├── quantization_of_coefficients.ipynb └── quantization_of_variables.ipynb ├── reference_cards ├── RC_discrete_signals_and_systems.pdf └── RC_random_signals_and_LTI_systems.pdf ├── requirements.txt ├── spectral_analysis_deterministic_signals ├── Fourier_transforms.png ├── ipython_kernel_config.py ├── leakage_effect.ipynb ├── stft.ipynb ├── summary.ipynb ├── window_functions.ipynb └── zero_padding.ipynb └── spectral_estimation_random_signals ├── analysis_model.png ├── introduction.ipynb ├── ipython_kernel_config.py ├── parametric_methods.ipynb ├── periodogram.ipynb ├── synthesis_model.png └── welch_method.ipynb /.binder/apt.txt: -------------------------------------------------------------------------------- 1 | libsndfile1 2 | sndfile-programs 3 | -------------------------------------------------------------------------------- /.binder/requirements.txt: -------------------------------------------------------------------------------- 1 | ../requirements.txt -------------------------------------------------------------------------------- /.github/workflows/lint_nb.yml: -------------------------------------------------------------------------------- 1 | name: Linting Notebooks 2 | 3 | on: 4 | push: 5 | branches: 6 | - master # Change this to the repository's main branch 7 | pull_request: 8 | branches: 9 | - master 10 | jobs: 11 | lint: 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - name: Checkout code 16 | uses: actions/checkout@v4 17 | 18 | - name: Set up Python 19 | uses: actions/setup-python@v4 20 | with: 21 | python-version: "3.12" # Change this to your desired Python version 22 | 23 | - name: Install dependencies 24 | run: | 25 | pip install black==23.1.0 nbformat black[jupyter] 26 | continue-on-error: false 27 | 28 | - name: Find notebooks 29 | id: find-notebooks 30 | run: | 31 | find . -name "*.ipynb" > notebooks.txt 32 | continue-on-error: true 33 | 34 | - name: Lint notebooks 35 | run: | 36 | cat notebooks.txt | xargs -I {} black --line-length 88 --check {} 37 | continue-on-error: true 38 | 39 | - name: Check lint results 40 | run: | 41 | if grep -q "would reformat" notebooks.txt; then 42 | echo "Linting issues found. Run 'black' to auto-format the notebooks." 43 | exit 1 44 | else 45 | echo "All notebooks are properly formatted." 46 | fi 47 | -------------------------------------------------------------------------------- /.github/workflows/notebook_ci.yml: -------------------------------------------------------------------------------- 1 | # executes all cells (e.g. numerical examples) in all notebooks 2 | # by using sphinx with the nbsphinx extension 3 | 4 | name: Sphinx build 5 | 6 | on: 7 | push: 8 | pull_request: 9 | 10 | schedule: 11 | - cron: '30 1 1,15 * *' 12 | 13 | jobs: 14 | linux_py3_12: 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v3 19 | - uses: actions/setup-python@v3 20 | with: 21 | python-version: 3.12 22 | - run: sudo apt-get install libsndfile1 pandoc 23 | - run: pip install -r requirements.txt 24 | - run: pip install -r ci/requirements.txt 25 | - run: python -m sphinx . _build/ -b html 26 | -------------------------------------------------------------------------------- /.github/workflows/run_nb.yml: -------------------------------------------------------------------------------- 1 | name: Run Notebooks 2 | 3 | on: 4 | push: 5 | branches: 6 | - master # Change this to the repository's main branch 7 | pull_request: 8 | branches: 9 | - master 10 | schedule: 11 | - cron: "0 0 * * 0" # Run every Sunday at midnight UTC (4 week interval) 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | strategy: 17 | matrix: 18 | python-version: ["3.10", "3.11", "3.12"] 19 | 20 | steps: 21 | - name: Checkout code 22 | uses: actions/checkout@v4 23 | 24 | - name: Setup node 25 | uses: actions/setup-node@v4 26 | 27 | - name: Set up Python ${{ matrix.python-version }} 28 | uses: actions/setup-python@v5 29 | with: 30 | python-version: ${{ matrix.python-version }} 31 | 32 | # Testing matrix by printing the current Python version: 33 | - name: Display Python version 34 | run: python -c "import sys; print(sys.version)" 35 | 36 | - name: Install dependencies 37 | run: pip install jupyter nbconvert 38 | - run: pip install -r requirements.txt 39 | - run: pip install -r ci/requirements.txt 40 | 41 | - name: Install PortAudio library 42 | run: sudo apt-get install libportaudio2 43 | - run: sudo apt-get install libasound-dev 44 | 45 | - name: Find notebooks 46 | id: find-notebooks 47 | run: | 48 | find . -name "*.ipynb" -not -name "acoustic_impulse_response_measurement.ipynb" > notebooks.txt 49 | cat notebooks.txt 50 | shell: bash 51 | 52 | - name: Execute notebooks 53 | run: | 54 | cat notebooks.txt | while read -r notebook; do 55 | jupyter nbconvert --to notebook --execute --inplace "$notebook" 56 | done 57 | continue-on-error: false 58 | shell: bash 59 | 60 | - name: Check for errors 61 | run: | 62 | if grep "raise Exception(" *.ipynb; then 63 | echo "Error found in notebook(s)." 64 | exit 1 65 | else 66 | echo "No errors found in notebooks." 67 | fi 68 | shell: bash 69 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *checkpoint.ipynb 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | dist: xenial 3 | python: 4 | - "3.7" 5 | addons: 6 | apt: 7 | packages: 8 | - pandoc 9 | - ffmpeg 10 | - libportaudio2 11 | install: 12 | - pip install -r requirements.txt 13 | - pip install -r ci/requirements.txt 14 | script: 15 | - python -m sphinx . _build/ -b html 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Attribution 4.0 International 2 | 3 | ======================================================================= 4 | 5 | Creative Commons Corporation ("Creative Commons") is not a law firm and 6 | does not provide legal services or legal advice. Distribution of 7 | Creative Commons public licenses does not create a lawyer-client or 8 | other relationship. Creative Commons makes its licenses and related 9 | information available on an "as-is" basis. Creative Commons gives no 10 | warranties regarding its licenses, any material licensed under their 11 | terms and conditions, or any related information. Creative Commons 12 | disclaims all liability for damages resulting from their use to the 13 | fullest extent possible. 14 | 15 | Using Creative Commons Public Licenses 16 | 17 | Creative Commons public licenses provide a standard set of terms and 18 | conditions that creators and other rights holders may use to share 19 | original works of authorship and other material subject to copyright 20 | and certain other rights specified in the public license below. The 21 | following considerations are for informational purposes only, are not 22 | exhaustive, and do not form part of our licenses. 23 | 24 | Considerations for licensors: Our public licenses are 25 | intended for use by those authorized to give the public 26 | permission to use material in ways otherwise restricted by 27 | copyright and certain other rights. Our licenses are 28 | irrevocable. Licensors should read and understand the terms 29 | and conditions of the license they choose before applying it. 30 | Licensors should also secure all rights necessary before 31 | applying our licenses so that the public can reuse the 32 | material as expected. Licensors should clearly mark any 33 | material not subject to the license. This includes other CC- 34 | licensed material, or material used under an exception or 35 | limitation to copyright. More considerations for licensors: 36 | wiki.creativecommons.org/Considerations_for_licensors 37 | 38 | Considerations for the public: By using one of our public 39 | licenses, a licensor grants the public permission to use the 40 | licensed material under specified terms and conditions. If 41 | the licensor's permission is not necessary for any reason--for 42 | example, because of any applicable exception or limitation to 43 | copyright--then that use is not regulated by the license. Our 44 | licenses grant only permissions under copyright and certain 45 | other rights that a licensor has authority to grant. Use of 46 | the licensed material may still be restricted for other 47 | reasons, including because others have copyright or other 48 | rights in the material. A licensor may make special requests, 49 | such as asking that all changes be marked or described. 50 | Although not required by our licenses, you are encouraged to 51 | respect those requests where reasonable. More_considerations 52 | for the public: 53 | wiki.creativecommons.org/Considerations_for_licensees 54 | 55 | ======================================================================= 56 | 57 | Creative Commons Attribution 4.0 International Public License 58 | 59 | By exercising the Licensed Rights (defined below), You accept and agree 60 | to be bound by the terms and conditions of this Creative Commons 61 | Attribution 4.0 International Public License ("Public License"). To the 62 | extent this Public License may be interpreted as a contract, You are 63 | granted the Licensed Rights in consideration of Your acceptance of 64 | these terms and conditions, and the Licensor grants You such rights in 65 | consideration of benefits the Licensor receives from making the 66 | Licensed Material available under these terms and conditions. 67 | 68 | 69 | Section 1 -- Definitions. 70 | 71 | a. Adapted Material means material subject to Copyright and Similar 72 | Rights that is derived from or based upon the Licensed Material 73 | and in which the Licensed Material is translated, altered, 74 | arranged, transformed, or otherwise modified in a manner requiring 75 | permission under the Copyright and Similar Rights held by the 76 | Licensor. For purposes of this Public License, where the Licensed 77 | Material is a musical work, performance, or sound recording, 78 | Adapted Material is always produced where the Licensed Material is 79 | synched in timed relation with a moving image. 80 | 81 | b. Adapter's License means the license You apply to Your Copyright 82 | and Similar Rights in Your contributions to Adapted Material in 83 | accordance with the terms and conditions of this Public License. 84 | 85 | c. Copyright and Similar Rights means copyright and/or similar rights 86 | closely related to copyright including, without limitation, 87 | performance, broadcast, sound recording, and Sui Generis Database 88 | Rights, without regard to how the rights are labeled or 89 | categorized. For purposes of this Public License, the rights 90 | specified in Section 2(b)(1)-(2) are not Copyright and Similar 91 | Rights. 92 | 93 | d. Effective Technological Measures means those measures that, in the 94 | absence of proper authority, may not be circumvented under laws 95 | fulfilling obligations under Article 11 of the WIPO Copyright 96 | Treaty adopted on December 20, 1996, and/or similar international 97 | agreements. 98 | 99 | e. Exceptions and Limitations means fair use, fair dealing, and/or 100 | any other exception or limitation to Copyright and Similar Rights 101 | that applies to Your use of the Licensed Material. 102 | 103 | f. Licensed Material means the artistic or literary work, database, 104 | or other material to which the Licensor applied this Public 105 | License. 106 | 107 | g. Licensed Rights means the rights granted to You subject to the 108 | terms and conditions of this Public License, which are limited to 109 | all Copyright and Similar Rights that apply to Your use of the 110 | Licensed Material and that the Licensor has authority to license. 111 | 112 | h. Licensor means the individual(s) or entity(ies) granting rights 113 | under this Public License. 114 | 115 | i. Share means to provide material to the public by any means or 116 | process that requires permission under the Licensed Rights, such 117 | as reproduction, public display, public performance, distribution, 118 | dissemination, communication, or importation, and to make material 119 | available to the public including in ways that members of the 120 | public may access the material from a place and at a time 121 | individually chosen by them. 122 | 123 | j. Sui Generis Database Rights means rights other than copyright 124 | resulting from Directive 96/9/EC of the European Parliament and of 125 | the Council of 11 March 1996 on the legal protection of databases, 126 | as amended and/or succeeded, as well as other essentially 127 | equivalent rights anywhere in the world. 128 | 129 | k. You means the individual or entity exercising the Licensed Rights 130 | under this Public License. Your has a corresponding meaning. 131 | 132 | 133 | Section 2 -- Scope. 134 | 135 | a. License grant. 136 | 137 | 1. Subject to the terms and conditions of this Public License, 138 | the Licensor hereby grants You a worldwide, royalty-free, 139 | non-sublicensable, non-exclusive, irrevocable license to 140 | exercise the Licensed Rights in the Licensed Material to: 141 | 142 | a. reproduce and Share the Licensed Material, in whole or 143 | in part; and 144 | 145 | b. produce, reproduce, and Share Adapted Material. 146 | 147 | 2. Exceptions and Limitations. For the avoidance of doubt, where 148 | Exceptions and Limitations apply to Your use, this Public 149 | License does not apply, and You do not need to comply with 150 | its terms and conditions. 151 | 152 | 3. Term. The term of this Public License is specified in Section 153 | 6(a). 154 | 155 | 4. Media and formats; technical modifications allowed. The 156 | Licensor authorizes You to exercise the Licensed Rights in 157 | all media and formats whether now known or hereafter created, 158 | and to make technical modifications necessary to do so. The 159 | Licensor waives and/or agrees not to assert any right or 160 | authority to forbid You from making technical modifications 161 | necessary to exercise the Licensed Rights, including 162 | technical modifications necessary to circumvent Effective 163 | Technological Measures. For purposes of this Public License, 164 | simply making modifications authorized by this Section 2(a) 165 | (4) never produces Adapted Material. 166 | 167 | 5. Downstream recipients. 168 | 169 | a. Offer from the Licensor -- Licensed Material. Every 170 | recipient of the Licensed Material automatically 171 | receives an offer from the Licensor to exercise the 172 | Licensed Rights under the terms and conditions of this 173 | Public License. 174 | 175 | b. No downstream restrictions. You may not offer or impose 176 | any additional or different terms or conditions on, or 177 | apply any Effective Technological Measures to, the 178 | Licensed Material if doing so restricts exercise of the 179 | Licensed Rights by any recipient of the Licensed 180 | Material. 181 | 182 | 6. No endorsement. Nothing in this Public License constitutes or 183 | may be construed as permission to assert or imply that You 184 | are, or that Your use of the Licensed Material is, connected 185 | with, or sponsored, endorsed, or granted official status by, 186 | the Licensor or others designated to receive attribution as 187 | provided in Section 3(a)(1)(A)(i). 188 | 189 | b. Other rights. 190 | 191 | 1. Moral rights, such as the right of integrity, are not 192 | licensed under this Public License, nor are publicity, 193 | privacy, and/or other similar personality rights; however, to 194 | the extent possible, the Licensor waives and/or agrees not to 195 | assert any such rights held by the Licensor to the limited 196 | extent necessary to allow You to exercise the Licensed 197 | Rights, but not otherwise. 198 | 199 | 2. Patent and trademark rights are not licensed under this 200 | Public License. 201 | 202 | 3. To the extent possible, the Licensor waives any right to 203 | collect royalties from You for the exercise of the Licensed 204 | Rights, whether directly or through a collecting society 205 | under any voluntary or waivable statutory or compulsory 206 | licensing scheme. In all other cases the Licensor expressly 207 | reserves any right to collect such royalties. 208 | 209 | 210 | Section 3 -- License Conditions. 211 | 212 | Your exercise of the Licensed Rights is expressly made subject to the 213 | following conditions. 214 | 215 | a. Attribution. 216 | 217 | 1. If You Share the Licensed Material (including in modified 218 | form), You must: 219 | 220 | a. retain the following if it is supplied by the Licensor 221 | with the Licensed Material: 222 | 223 | i. identification of the creator(s) of the Licensed 224 | Material and any others designated to receive 225 | attribution, in any reasonable manner requested by 226 | the Licensor (including by pseudonym if 227 | designated); 228 | 229 | ii. a copyright notice; 230 | 231 | iii. a notice that refers to this Public License; 232 | 233 | iv. a notice that refers to the disclaimer of 234 | warranties; 235 | 236 | v. a URI or hyperlink to the Licensed Material to the 237 | extent reasonably practicable; 238 | 239 | b. indicate if You modified the Licensed Material and 240 | retain an indication of any previous modifications; and 241 | 242 | c. indicate the Licensed Material is licensed under this 243 | Public License, and include the text of, or the URI or 244 | hyperlink to, this Public License. 245 | 246 | 2. You may satisfy the conditions in Section 3(a)(1) in any 247 | reasonable manner based on the medium, means, and context in 248 | which You Share the Licensed Material. For example, it may be 249 | reasonable to satisfy the conditions by providing a URI or 250 | hyperlink to a resource that includes the required 251 | information. 252 | 253 | 3. If requested by the Licensor, You must remove any of the 254 | information required by Section 3(a)(1)(A) to the extent 255 | reasonably practicable. 256 | 257 | 4. If You Share Adapted Material You produce, the Adapter's 258 | License You apply must not prevent recipients of the Adapted 259 | Material from complying with this Public License. 260 | 261 | 262 | Section 4 -- Sui Generis Database Rights. 263 | 264 | Where the Licensed Rights include Sui Generis Database Rights that 265 | apply to Your use of the Licensed Material: 266 | 267 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right 268 | to extract, reuse, reproduce, and Share all or a substantial 269 | portion of the contents of the database; 270 | 271 | b. if You include all or a substantial portion of the database 272 | contents in a database in which You have Sui Generis Database 273 | Rights, then the database in which You have Sui Generis Database 274 | Rights (but not its individual contents) is Adapted Material; and 275 | 276 | c. You must comply with the conditions in Section 3(a) if You Share 277 | all or a substantial portion of the contents of the database. 278 | 279 | For the avoidance of doubt, this Section 4 supplements and does not 280 | replace Your obligations under this Public License where the Licensed 281 | Rights include other Copyright and Similar Rights. 282 | 283 | 284 | Section 5 -- Disclaimer of Warranties and Limitation of Liability. 285 | 286 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE 287 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS 288 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF 289 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, 290 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, 291 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR 292 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, 293 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT 294 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT 295 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. 296 | 297 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE 298 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, 299 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, 300 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, 301 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR 302 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN 303 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR 304 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR 305 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. 306 | 307 | c. The disclaimer of warranties and limitation of liability provided 308 | above shall be interpreted in a manner that, to the extent 309 | possible, most closely approximates an absolute disclaimer and 310 | waiver of all liability. 311 | 312 | 313 | Section 6 -- Term and Termination. 314 | 315 | a. This Public License applies for the term of the Copyright and 316 | Similar Rights licensed here. However, if You fail to comply with 317 | this Public License, then Your rights under this Public License 318 | terminate automatically. 319 | 320 | b. Where Your right to use the Licensed Material has terminated under 321 | Section 6(a), it reinstates: 322 | 323 | 1. automatically as of the date the violation is cured, provided 324 | it is cured within 30 days of Your discovery of the 325 | violation; or 326 | 327 | 2. upon express reinstatement by the Licensor. 328 | 329 | For the avoidance of doubt, this Section 6(b) does not affect any 330 | right the Licensor may have to seek remedies for Your violations 331 | of this Public License. 332 | 333 | c. For the avoidance of doubt, the Licensor may also offer the 334 | Licensed Material under separate terms or conditions or stop 335 | distributing the Licensed Material at any time; however, doing so 336 | will not terminate this Public License. 337 | 338 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public 339 | License. 340 | 341 | 342 | Section 7 -- Other Terms and Conditions. 343 | 344 | a. The Licensor shall not be bound by any additional or different 345 | terms or conditions communicated by You unless expressly agreed. 346 | 347 | b. Any arrangements, understandings, or agreements regarding the 348 | Licensed Material not stated herein are separate from and 349 | independent of the terms and conditions of this Public License. 350 | 351 | 352 | Section 8 -- Interpretation. 353 | 354 | a. For the avoidance of doubt, this Public License does not, and 355 | shall not be interpreted to, reduce, limit, restrict, or impose 356 | conditions on any use of the Licensed Material that could lawfully 357 | be made without permission under this Public License. 358 | 359 | b. To the extent possible, if any provision of this Public License is 360 | deemed unenforceable, it shall be automatically reformed to the 361 | minimum extent necessary to make it enforceable. If the provision 362 | cannot be reformed, it shall be severed from this Public License 363 | without affecting the enforceability of the remaining terms and 364 | conditions. 365 | 366 | c. No term or condition of this Public License will be waived and no 367 | failure to comply consented to unless expressly agreed to by the 368 | Licensor. 369 | 370 | d. Nothing in this Public License constitutes or may be interpreted 371 | as a limitation upon, or waiver of, any privileges and immunities 372 | that apply to the Licensor or You, including from the legal 373 | processes of any jurisdiction or authority. 374 | 375 | 376 | ======================================================================= 377 | 378 | Creative Commons is not a party to its public 379 | licenses. Notwithstanding, Creative Commons may elect to apply one of 380 | its public licenses to material it publishes and in those instances 381 | will be considered the “Licensor.” The text of the Creative Commons 382 | public licenses is dedicated to the public domain under the CC0 Public 383 | Domain Dedication. Except for the limited purpose of indicating that 384 | material is shared under a Creative Commons public license or as 385 | otherwise permitted by the Creative Commons policies published at 386 | creativecommons.org/policies, Creative Commons does not authorize the 387 | use of the trademark "Creative Commons" or any other trademark or logo 388 | of Creative Commons without its prior written consent including, 389 | without limitation, in connection with any unauthorized modifications 390 | to any of its public licenses or any other arrangements, 391 | understandings, or agreements concerning use of licensed material. For 392 | the avoidance of doubt, this paragraph does not form part of the 393 | public licenses. 394 | 395 | Creative Commons may be contacted at creativecommons.org. 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | The MIT License (MIT) 409 | 410 | Copyright (c) 2015-16 Sascha Spors 411 | 412 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 413 | 414 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 415 | 416 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 417 | 418 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Digital Signal Processing - Theory and Computational Examples 2 | 3 | [![Linting](https://github.com/spatialaudio/digital-signal-processing-lecture/actions/workflows/lint_nb.yml/badge.svg?branch=master)](https://github.com/spatialaudio/digital-signal-processing-lecture/actions/workflows/lint_nb.yml) 4 | [![Run Notebooks](https://github.com/spatialaudio/digital-signal-processing-lecture/actions/workflows/run_nb.yml/badge.svg?branch=master)](https://github.com/spatialaudio/digital-signal-processing-lecture/actions/workflows/run_nb.yml) 5 | [![Sphinx Built](https://github.com/spatialaudio/digital-signal-processing-lecture/actions/workflows/notebook_ci.yml/badge.svg?branch=master)](https://github.com/spatialaudio/digital-signal-processing-lecture/actions/workflows/notebook_ci.yml) 6 | 7 | This repository collects didactically edited [Jupyter](https://jupyter.org/) notebooks that introduce basic concepts of [Digital Signal Processing](https://en.wikipedia.org/wiki/Digital_signal_processing). Please take a look at the [static version](http://nbviewer.ipython.org/github/spatialaudio/digital-signal-processing-lecture/blob/master/index.ipynb) 8 | at first glance. The materials provide an introduction to the foundations of spectral analysis, random signals, quantization, and filtering. A series of computational examples and exercises written in [IPython 3](http://ipython.org/) accompany the theory. 9 | 10 | ![Digital signal processing chain](https://github.com/spatialaudio/digital-signal-processing-lecture/blob/master/introduction/DSP.png) 11 | 12 | The notebooks constitute the lecture notes to the master's course [Digital Signal Processing](http://www.int.uni-rostock.de/Digitale-Signalverarbeitung.48.0.html) given by [Sascha Spors](http://www.int.uni-rostock.de/Staff-Info.23+B6JmNIYXNoPWUxOTliMTNjY2U2MDcyZjJiZTI0YTc4MmFkYTE5NjQzJnR4X2pwc3RhZmZfcGkxJTVCYmFja0lkJTVEPTMmdHhfanBzdGFmZl9waTElNUJzaG93VWlkJTVEPTExMQ__.0.html) at the University of Rostock, Germany. The contents are provided as [Open Educational Resource](https://de.wikipedia.org/wiki/Open_Educational_Resources), so feel free to fork, share, teach and learn. 13 | You can give the project a [Star](https://github.com/spatialaudio//digital-signal-processing-lecture/stargazers) if you like it. 14 | 15 | 16 | ## Getting Started 17 | 18 | The Jupyter notebooks are accessible in various ways 19 | 20 | * Online as [static web pages](http://nbviewer.ipython.org/github/spatialaudio/digital-signal-processing-lecture/blob/master/index.ipynb) 21 | * Online for [interactive usage](https://mybinder.org/v2/gh/spatialaudio/digital-signal-processing-lecture/master?filepath=index.ipynb) with [binder](https://mybinder.org/) 22 | * Local for interactive usage on your computer 23 | 24 | Other online services (e.g. [Google Colaboratory](https://colab.research.google.com), 25 | [Microsoft Azure](https://azure.microsoft.com/), ...) also provide environments for the 26 | interactive execution of Jupyter notebooks. 27 | Local execution on your computer requires a local Jupyter/IPython installation. 28 | The [Anaconda distribution](https://www.continuum.io/downloads) is considered a convenient starting point. 29 | Then, you would have to [clone/download the notebooks from Github](http://github.com/spatialaudio/digital-signal-processing-lecture). 30 | Use a [Git](http://git-scm.org/) client to clone the notebooks and start 31 | your local Jupyter server. For manual installation under OS X/Linux please 32 | refer to your packet manager. 33 | 34 | ## Concept and Contents 35 | 36 | An understanding of the underlying mechanisms and the limitations of basic digital signal processing methods is essential for designing more complex algorithms, such as the recent contributions on indirect [detection of supermassive 37 | black holes](https://en.wikipedia.org/wiki/Messier_87) 38 | heavily relying on system identification and image processing. 39 | 40 | The present notebooks cover fundamental aspects of digital signal processing. 41 | A focus is laid on a detailed mathematical treatise. 42 | Discussing the mathematical background is essential to understand the underlying principles more broadly. 43 | The materials contain computational examples and exercises to 44 | interpret the theoretical findings and foster understanding. 45 | The examples are designed to be explored interactively. 46 | Furthermore, an outlook on practical applications is given whenever possible. 47 | 48 | The material covers the following topics 49 | 50 | * spectral analysis of deterministic signals 51 | * random signals and linear-time invariant systems 52 | * spectral estimation for random signals 53 | * realization of non-recursive and recursive filters 54 | * design of digital filters 55 | 56 | 57 | ## Usage and Contributing 58 | 59 | The contents are provided as [Open Educational Resource](https://de.wikipedia.org/wiki/Open_Educational_Resources). 60 | The text is licensed under [Creative Commons Attribution 4.0](https://creativecommons.org/licenses/by/4.0/) 61 | , and the code of the IPython examples is under the [MIT license](https://opensource.org/licenses/MIT). 62 | Feel free to use the entire collection, parts, or even single notebooks for your purposes. 63 | I am curious on the usage of the provided resources, so feel free to drop a 64 | line or report to [Sascha.Spors@uni-rostock.de](mailto:Sascha.Spors@uni-rostock.de). 65 | 66 | Our long-term vision is to lay the grounds for a **community-driven concise and 67 | reliable resource** covering all relevant aspects of digital signal processing revised 68 | by research and engineering professionals. 69 | We aim to link the strengths of good old-fashioned textbooks 70 | and the interactive playground of computational environments. 71 | Open Educational Resources, combined with open source tools (Jupyter, Python) and well-established tools for data literacy (git), provides the unique possibility for collaborative and well-maintained resources. 72 | Jupyter is chosen due to its seamless text, math, and code integration. The contents are represented future proof, as a simple markdown layout allowing for conversion into many other formats (html, PDF, ...). The git version management system features tracking of the changes and authorship. 73 | 74 | You are invited to contribute on different levels. 75 | The lowest level is to provide feedback in terms of a 76 | [Star](https://github.com/spatialaudio/digital-signal-processing-lecture/stargazers) 77 | if you like the content. 78 | Please consider reporting errors or suggestions for improvements as 79 | [issues](https://github.com/spatialaudio/digital-signal-processing-lecture/issues). 80 | We are always looking forward to new examples and exercises, and reformulated existing and novel sub-sections or sections. 81 | Authorship of each considerable contribution is clearly stated. 82 | One way of introducing reformulated and new material is to handle them as 83 | a tracked [pull request](https://github.com/spatialaudio/digital-signal-processing-lecture/pulls). 84 | 85 | 86 | ## Build Status 87 | 88 | The notebooks' computational examples are automatically built and checked for errors by continuous integration using github actions. 89 | 90 | [![Linting](https://github.com/spatialaudio/digital-signal-processing-lecture/actions/workflows/lint_nb.yml/badge.svg?branch=master)](https://github.com/spatialaudio/digital-signal-processing-lecture/actions/workflows/lint_nb.yml) 91 | [![Run Notebooks](https://github.com/spatialaudio/digital-signal-processing-lecture/actions/workflows/run_nb.yml/badge.svg?branch=master)](https://github.com/spatialaudio/digital-signal-processing-lecture/actions/workflows/run_nb.yml) 92 | [![Sphinx Built](https://github.com/spatialaudio/digital-signal-processing-lecture/actions/workflows/notebook_ci.yml/badge.svg?branch=master)](https://github.com/spatialaudio/digital-signal-processing-lecture/actions/workflows/notebook_ci.yml) 93 | -------------------------------------------------------------------------------- /ci/README.md: -------------------------------------------------------------------------------- 1 | # Continuous Integration 2 | 3 | This directory holds configuration files for continuous integration checks of the Jupiter notebooks and the numerical examples contained. All notebooks are executed using the sphinx documentation system with the nbsphinx extension. -------------------------------------------------------------------------------- /ci/requirements.txt: -------------------------------------------------------------------------------- 1 | Sphinx>=1.3.6 2 | Sphinx-RTD-Theme 3 | nbsphinx 4 | ipykernel 5 | sphinx_bootstrap_theme 6 | -------------------------------------------------------------------------------- /conf.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Digital Signal Processing documentation build configuration file, created by 5 | # sphinx-quickstart on Sat Dec 26 19:02:47 2015. 6 | # 7 | # This file is execfile()d with the current directory set to its 8 | # containing dir. 9 | # 10 | # Note that not all possible configuration values are present in this 11 | # autogenerated file. 12 | # 13 | # All configuration values have a default; values that are commented out 14 | # serve to show the default. 15 | 16 | import sys 17 | import os 18 | 19 | import sphinx_bootstrap_theme 20 | 21 | # If extensions (or modules to document with autodoc) are in another directory, 22 | # add these directories to sys.path here. If the directory is relative to the 23 | # documentation root, use os.path.abspath to make it absolute, like shown here. 24 | # sys.path.insert(0, os.path.abspath('.')) 25 | 26 | # -- General configuration ------------------------------------------------ 27 | 28 | # If your documentation needs a minimal Sphinx version, state it here. 29 | # needs_sphinx = '1.0' 30 | 31 | # Add any Sphinx extension module names here, as strings. They can be 32 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 33 | # ones. 34 | extensions = [ 35 | "nbsphinx", 36 | "sphinx.ext.mathjax", 37 | ] 38 | 39 | # Add any paths that contain templates here, relative to this directory. 40 | templates_path = ["_templates"] 41 | 42 | # The suffix(es) of source filenames. 43 | # You can specify multiple suffix as a list of string: 44 | source_suffix = [".rst"] 45 | 46 | # The encoding of source files. 47 | # source_encoding = 'utf-8-sig' 48 | 49 | # The master toctree document. 50 | master_doc = "index" 51 | 52 | # General information about the project. 53 | project = "Digital Signal Processing" 54 | copyright = "Sascha Spors, University of Rostock" 55 | author = "Sascha Spors" 56 | 57 | # The version info for the project you're documenting, acts as replacement for 58 | # |version| and |release|, also used in various other places throughout the 59 | # built documents. 60 | # 61 | # The short X.Y version. 62 | version = "0.9" 63 | # The full version, including alpha/beta/rc tags. 64 | release = "Wintersemester 2022/23" 65 | 66 | # The language for content autogenerated by Sphinx. Refer to documentation 67 | # for a list of supported languages. 68 | # 69 | # This is also used if you do content translation via gettext catalogs. 70 | # Usually you set "language" from the command line for these cases. 71 | language = "en" 72 | 73 | # There are two options for replacing |today|: either, you set today to some 74 | # non-false value, then it is used: 75 | # today = '' 76 | # Else, today_fmt is used as the format for a strftime call. 77 | # today_fmt = '%B %d, %Y' 78 | 79 | # List of patterns, relative to source directory, that match files and 80 | # directories to ignore when looking for source files. 81 | exclude_patterns = [ 82 | "_build", 83 | "**.ipynb_checkpoints", 84 | "demos", 85 | "data", 86 | "export", 87 | "**/_*.ipynb", 88 | ] 89 | 90 | # The reST default role (used for this markup: `text`) to use for all 91 | # documents. 92 | # default_role = None 93 | 94 | # If true, '()' will be appended to :func: etc. cross-reference text. 95 | # add_function_parentheses = True 96 | 97 | # If true, the current module name will be prepended to all description 98 | # unit titles (such as .. function::). 99 | # add_module_names = True 100 | 101 | # If true, sectionauthor and moduleauthor directives will be shown in the 102 | # output. They are ignored by default. 103 | # show_authors = False 104 | 105 | # The name of the Pygments (syntax highlighting) style to use. 106 | pygments_style = "sphinx" 107 | 108 | # A list of ignored prefixes for module index sorting. 109 | # modindex_common_prefix = [] 110 | 111 | # If true, keep warnings as "system message" paragraphs in the built documents. 112 | # keep_warnings = False 113 | 114 | # If true, `todo` and `todoList` produce output, else they produce nothing. 115 | todo_include_todos = False 116 | 117 | 118 | # -- Options for HTML output ---------------------------------------------- 119 | 120 | # The theme to use for HTML and HTML Help pages. See the documentation for 121 | # a list of builtin themes. 122 | html_theme = "bootstrap" 123 | 124 | # Theme options are theme-specific and customize the look and feel of a theme 125 | # further. For a list of options available for each theme, see the 126 | # documentation. 127 | html_theme_options = { 128 | "navbar_title": "DSP", 129 | "navbar_site_name": "Chapters", 130 | "navbar_pagenav_name": "This Page", 131 | "navbar_fixed_top": "false", 132 | "source_link_position": "none", 133 | "bootswatch_theme": "cosmo", 134 | #'bootswatch_theme': 'lumen', 135 | #'bootswatch_theme': 'sandstone', 136 | #'bootswatch_theme': 'spacelab', 137 | } 138 | 139 | # Add any paths that contain custom themes here, relative to this directory. 140 | html_theme_path = sphinx_bootstrap_theme.get_html_theme_path() 141 | 142 | # The name for this set of Sphinx documents. If None, it defaults to 143 | # " v documentation". 144 | # html_title = None 145 | 146 | # A shorter title for the navigation bar. Default is the same as html_title. 147 | # html_short_title = None 148 | 149 | # The name of an image file (relative to this directory) to place at the top 150 | # of the sidebar. 151 | # html_logo = None 152 | 153 | # The name of an image file (within the static path) to use as favicon of the 154 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 155 | # pixels large. 156 | # html_favicon = None 157 | 158 | # Add any paths that contain custom static files (such as style sheets) here, 159 | # relative to this directory. They are copied after the builtin static files, 160 | # so a file named "default.css" will overwrite the builtin "default.css". 161 | # html_static_path = ['_static'] 162 | 163 | # Add any extra paths that contain custom files (such as robots.txt or 164 | # .htaccess) here, relative to this directory. These files are copied 165 | # directly to the root of the documentation. 166 | # html_extra_path = [] 167 | 168 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 169 | # using the given strftime format. 170 | # html_last_updated_fmt = '%b %d, %Y' 171 | 172 | # If true, SmartyPants will be used to convert quotes and dashes to 173 | # typographically correct entities. 174 | # html_use_smartypants = True 175 | 176 | # Custom sidebar templates, maps document names to template names. 177 | # html_sidebars = {} 178 | 179 | # Additional templates that should be rendered to pages, maps page names to 180 | # template names. 181 | # html_additional_pages = {} 182 | 183 | # If false, no module index is generated. 184 | # html_domain_indices = True 185 | 186 | # If false, no index is generated. 187 | # html_use_index = True 188 | 189 | # If true, the index is split into individual pages for each letter. 190 | # html_split_index = False 191 | 192 | # If true, links to the reST sources are added to the pages. 193 | # html_show_sourcelink = True 194 | 195 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 196 | # html_show_sphinx = True 197 | 198 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 199 | # html_show_copyright = True 200 | 201 | # If true, an OpenSearch description file will be output, and all pages will 202 | # contain a tag referring to it. The value of this option must be the 203 | # base URL from which the finished HTML is served. 204 | # html_use_opensearch = '' 205 | 206 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 207 | # html_file_suffix = None 208 | 209 | # Language to be used for generating the HTML full-text search index. 210 | # Sphinx supports the following languages: 211 | # 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja' 212 | # 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr' 213 | # html_search_language = 'en' 214 | 215 | # A dictionary with options for the search language support, empty by default. 216 | # Now only 'ja' uses this config value 217 | # html_search_options = {'type': 'default'} 218 | 219 | # The name of a javascript file (relative to the configuration directory) that 220 | # implements a search results scorer. If empty, the default will be used. 221 | # html_search_scorer = 'scorer.js' 222 | 223 | # Output file base name for HTML help builder. 224 | htmlhelp_basename = "Digital_Signal_Processing_doc" 225 | 226 | # -- Options for LaTeX output --------------------------------------------- 227 | nbsphinx_execute_arguments = ['--InlineBackend.figure_formats={"svg", "pdf"}'] 228 | nbsphinx_execute = "always" 229 | nbsphinx_timeout = 300 230 | nbsphinx_allow_errors = False 231 | 232 | 233 | latex_elements = { 234 | # The paper size ('letterpaper' or 'a4paper'). 235 | "papersize": "a4paper", 236 | # The font size ('10pt', '11pt' or '12pt'). 237 | #'pointsize': '10pt', 238 | # Additional stuff for the LaTeX preamble. 239 | "preamble": r""" 240 | \usepackage{amssymb} 241 | \setcounter{tocdepth}{2} 242 | """, 243 | # Latex figure (float) alignment 244 | #'figure_align': 'htbp', 245 | } 246 | 247 | # Grouping the document tree into LaTeX files. List of tuples 248 | # (source start file, target name, title, 249 | # author, documentclass [howto, manual, or own class]). 250 | latex_documents = [ 251 | (master_doc, "Digital_Signal_Processing.tex", project, author, "manual"), 252 | ] 253 | 254 | # The name of an image file (relative to this directory) to place at the top of 255 | # the title page. 256 | # latex_logo = None 257 | 258 | # For "manual" documents, if this is true, then toplevel headings are parts, 259 | # not chapters. 260 | # latex_use_parts = False 261 | 262 | # If true, show page references after internal links. 263 | # latex_show_pagerefs = False 264 | 265 | # If true, show URL addresses after external links. 266 | # latex_show_urls = False 267 | 268 | # Documents to append as an appendix to all manuals. 269 | # latex_appendices = [] 270 | 271 | # If false, no module index is generated. 272 | # latex_domain_indices = True 273 | 274 | 275 | # -- Options for manual page output --------------------------------------- 276 | 277 | # One entry per manual page. List of tuples 278 | # (source start file, name, description, authors, manual section). 279 | man_pages = [ 280 | (master_doc, "digitalsignalprocessing", "Digital Signal Processing", [author], 1) 281 | ] 282 | 283 | # If true, show URL addresses after external links. 284 | # man_show_urls = False 285 | 286 | 287 | # -- Options for Texinfo output ------------------------------------------- 288 | 289 | # Grouping the document tree into Texinfo files. List of tuples 290 | # (source start file, target name, title, author, 291 | # dir menu entry, description, category) 292 | texinfo_documents = [ 293 | ( 294 | master_doc, 295 | "Digital_Signal_Processing", 296 | "Digital Signal Processing", 297 | author, 298 | "Digital_Signal_Processing", 299 | "Lecture notes featuring computational examples", 300 | "Miscellaneous", 301 | ), 302 | ] 303 | 304 | # Documents to append as an appendix to all manuals. 305 | # texinfo_appendices = [] 306 | 307 | # If false, no module index is generated. 308 | # texinfo_domain_indices = True 309 | 310 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 311 | # texinfo_show_urls = 'footnote' 312 | 313 | # If true, do not generate a @detailmenu in the "Top" node's menu. 314 | # texinfo_no_detailmenu = False 315 | -------------------------------------------------------------------------------- /data/amplifier_noise.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/data/amplifier_noise.npz -------------------------------------------------------------------------------- /data/gold_sequences.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/data/gold_sequences.npz -------------------------------------------------------------------------------- /data/linear_sweep.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/data/linear_sweep.wav -------------------------------------------------------------------------------- /data/speech.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/data/speech.wav -------------------------------------------------------------------------------- /data/speech_8k.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/data/speech_8k.wav -------------------------------------------------------------------------------- /data/vocal_o.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/data/vocal_o.wav -------------------------------------------------------------------------------- /data/vocal_o_8k.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/data/vocal_o_8k.wav -------------------------------------------------------------------------------- /filter_design/RLC_lowpass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/filter_design/RLC_lowpass.png -------------------------------------------------------------------------------- /filter_design/audiofilter.py: -------------------------------------------------------------------------------- 1 | """Routines to create filter coefficients and plot filters. 2 | 3 | for 1st / 2nd order audio biquads 4 | 5 | this code is included in the open educational resource 6 | "Sascha Spors, Digital Signal Processing - Lecture notes featuring 7 | computational examples" 8 | 9 | hosted at 10 | URL = ('https://github.com/spatialaudio/' 11 | 'digital-signal-processing-lecture/tree/master/' 12 | 'filter_design') 13 | 14 | and is licensed under The MIT License (MIT): 15 | Copyright (c) 2020 Sascha Spors, Frank Schultz 16 | Permission is hereby granted, free of charge, to any person obtaining a copy of 17 | this software and associated documentation files (the "Software"), to deal in 18 | the Software without restriction, including without limitation the rights to 19 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 20 | of the Software, and to permit persons to whom the Software is furnished to do 21 | so, subject to the following conditions: 22 | The above copyright notice and this permission notice shall be included in all 23 | copies or substantial portions of the Software. 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | SOFTWARE. 31 | 32 | """ 33 | import matplotlib.pyplot as plt 34 | from matplotlib.patches import Circle 35 | import numpy as np 36 | from scipy import signal 37 | 38 | 39 | def bilinear_biquad(B, A, fs): 40 | """Get the bilinear transform of a 2nd-order Laplace transform. 41 | 42 | bilinear transform H(s)->H(z) with s=2*fs*(z-1)/(z+1) 43 | 44 | input: 45 | B[0] = B0 B[1] = B1 B[2] = B2 46 | A[0] = A0 A[1] = A1 A[2] = A2 47 | fs...sampling frequency in Hz 48 | Y(s) B0*s^2+B1*s+B2 B[0]*s^2+B[1]*s+B[2] 49 | H(s) = ---- = -------------- = -------------------- 50 | X(s) A0*s^2+A1*s+A2 A[0]*s^2+A[1]*s+A[2] 51 | output: 52 | b[0] = b0 b[1] = b1 b[2] = b2 53 | a[0] = 1 a[1] = a1 a[2] = a2 54 | Y(z) b2*z^-2+b1*z^-1+b0 b[2]*z^-2+b[1]*z^-1+b[0] 55 | H(z) = ---- = ------------------ = ------------------------ 56 | X(z) a2*z^-2+a1*z^-1+ 1 a[2]*z^-2+a[1]*z^-1+a[0] 57 | """ 58 | A0, A1, A2 = A 59 | B0, B1, B2 = B 60 | fs2 = fs**2 61 | 62 | a0 = A2 + 2 * A1 * fs + 4 * A0 * fs2 63 | b0 = B2 + 2 * B1 * fs + 4 * B0 * fs2 64 | 65 | b1 = 2 * B2 - 8 * B0 * fs2 66 | a1 = 2 * A2 - 8 * A0 * fs2 67 | 68 | b2 = B2 - 2 * B1 * fs + 4 * B0 * fs2 69 | a2 = A2 - 2 * A1 * fs + 4 * A0 * fs2 70 | 71 | b = np.array([b0, b1, b2]) / a0 72 | a = np.array([a0, a1, a2]) / a0 73 | 74 | return b, a 75 | 76 | 77 | def bw_from_q(q): 78 | """Convert bandpass quality to bandwidth in octaves.""" 79 | return 2 / np.log(2) * np.arcsinh(1 / (2 * q)) 80 | 81 | 82 | def q_from_bw(bw): 83 | """Convert bandwidth in octaves to bandpass quality.""" 84 | return 1 / (2 * np.sinh(np.log(2) / 2 * bw)) 85 | 86 | 87 | def f_prewarping(f, fs): 88 | """Do the frequency prewarping. 89 | 90 | input: 91 | f...analog frequency in Hz to be prewarped 92 | fs...sampling frequency in Hz 93 | output: 94 | prewarped angular frequency in rad/s 95 | """ 96 | return 2 * fs * np.tan(np.pi * f / fs) 97 | 98 | 99 | def q_prewarping(q, fm, fs, q_warp_method="cos"): 100 | """Do the quality prewarping. 101 | 102 | input: 103 | q...bandpass quality to be prewarped 104 | fm...analog mid-frequency in Hz 105 | fs...sampling frequency in Hz 106 | q_warp_method: 107 | "sin"...Robert Bristow-Johnson (1994): "The equivalence of various methods 108 | of computing biquad coefficients for audio parametric equalizers."In: 109 | Proc. of 97th AES Convention, San Fransisco. eq. (14) 110 | "cos"...Rainer Thaden (1997): "Entwicklung und Erprobung einer digitalen 111 | parametrischen Filterbank." Diplomarbeit, RWTH Aachen 112 | "tan"...Clark, R.J.; Ifeachor, E.C.; Rogers, G.M.; et al. (2000): 113 | "Techniques for Generating Digital Equalizer Coefficients". 114 | In: J. Aud. Eng. Soc. 48(4):281-298. 115 | output: 116 | prewarped quality 117 | """ 118 | if q_warp_method == "sin": 119 | bandwidth = bw_from_q(q) 120 | w0 = 2 * np.pi * fm / fs 121 | bandwidth = bandwidth * w0 / np.sin(w0) 122 | qpre = q_from_bw(bandwidth) 123 | elif q_warp_method == "cos": 124 | qpre = q * np.cos(np.pi * fm / fs) 125 | elif q_warp_method == "tan": 126 | qpre = q * (np.pi * fm / fs) / np.tan(np.pi * fm / fs) 127 | else: 128 | qpre = q 129 | return qpre 130 | 131 | 132 | def biquad_lp1st(fc, fs): 133 | """Calc coeff for lowpass 1st order. 134 | 135 | input: 136 | fc...cut frequency in Hz 137 | fs...sampling frequency in Hz 138 | output: 139 | B...numerator coefficients Laplace transfer function 140 | A...denominator coefficients Laplace transfer function 141 | b...numerator coefficients z-transfer function 142 | a...denominator coefficients z-transfer function 143 | """ 144 | wc = 2 * np.pi * fc 145 | B = np.array([0.0, 0, 1]) 146 | A = np.array([0, 1 / wc, 1]) 147 | 148 | wcpre = f_prewarping(fc, fs) 149 | Bp = 0.0, 0.0, 1.0 150 | Ap = 0.0, 1 / wcpre, 1.0 151 | b, a = bilinear_biquad(Bp, Ap, fs) 152 | 153 | return B, A, b, a 154 | 155 | 156 | def biquad_lp2nd(fc, fs, bi=1.0, ai=np.sqrt(2)): 157 | """Calc coeff for lowpass 2nd order. 158 | 159 | input: 160 | fc...cut frequency in Hz 161 | fs...sampling frequency in Hz 162 | bi, ai...filter characteristics coefficients, e.g. 163 | bi = 0.6180, ai = 1.3617 for Bessel 2nd order 164 | bi = 1, ai = 1.4142 for Butterworth 2nd order (default) 165 | output: 166 | B...numerator coefficients Laplace transfer function 167 | A...denominator coefficients Laplace transfer function 168 | b...numerator coefficients z-transfer function 169 | a...denominator coefficients z-transfer function 170 | """ 171 | wc = 2 * np.pi * fc 172 | B = np.array([0.0, 0, 1]) 173 | A = np.array([bi / wc**2, ai / wc, 1]) 174 | 175 | wcpre = f_prewarping(fc, fs) 176 | Bp = 0.0, 0.0, 1.0 177 | Ap = bi / wcpre**2, ai / wcpre, 1.0 178 | b, a = bilinear_biquad(Bp, Ap, fs) 179 | 180 | return B, A, b, a 181 | 182 | 183 | def biquad_hp1st(fc, fs): 184 | """Calc coeff for highpass 1st order. 185 | 186 | input: 187 | fc...cut frequency in Hz 188 | fs...sampling frequency in Hz 189 | output: 190 | B...numerator coefficients Laplace transfer function 191 | A...denominator coefficients Laplace transfer function 192 | b...numerator coefficients z-transfer function 193 | a...denominator coefficients z-transfer function 194 | """ 195 | wc = 2 * np.pi * fc 196 | B = np.array([0, 1 / wc, 0]) 197 | A = np.array([0, 1 / wc, 1]) 198 | 199 | wcpre = f_prewarping(fc, fs) 200 | Bp = 0.0, 1 / wcpre, 0.0 201 | Ap = 0.0, 1 / wcpre, 1.0 202 | b, a = bilinear_biquad(Bp, Ap, fs) 203 | 204 | return B, A, b, a 205 | 206 | 207 | def biquad_hp2nd(fc, fs, bi=1.0, ai=np.sqrt(2)): 208 | """Calc coeff for highpass 2nd order. 209 | 210 | input: 211 | fc...cut frequency in Hz 212 | fs...sampling frequency in Hz 213 | bi, ai...filter characteristics coefficients, e.g. 214 | bi = 0.6180, ai = 1.3617 for Bessel 2nd order 215 | bi = 1, ai = 1.4142 for Butterworth 2nd order (default) 216 | output: 217 | B...numerator coefficients Laplace transfer function 218 | A...denominator coefficients Laplace transfer function 219 | b...numerator coefficients z-transfer function 220 | a...denominator coefficients z-transfer function 221 | """ 222 | wc = 2 * np.pi * fc 223 | B = np.array([1 / wc**2, 0, 0]) 224 | A = np.array([1 / wc**2, ai / wc, bi]) 225 | 226 | wcpre = f_prewarping(fc, fs) 227 | Bp = 1 / wcpre**2, 0.0, 0.0 228 | Ap = 1 / wcpre**2, ai / wcpre, bi 229 | b, a = bilinear_biquad(Bp, Ap, fs) 230 | 231 | return B, A, b, a 232 | 233 | 234 | def biquad_bp2nd(fm, q, fs, q_warp_method="cos"): 235 | """Calc coeff for bandpass 2nd order. 236 | 237 | input: 238 | fm...mid frequency in Hz 239 | q...bandpass quality 240 | fs...sampling frequency in Hz 241 | q_warp_method..."sin", "cos", "tan" 242 | output: 243 | B...numerator coefficients Laplace transfer function 244 | A...denominator coefficients Laplace transfer function 245 | b...numerator coefficients z-transfer function 246 | a...denominator coefficients z-transfer function 247 | """ 248 | wm = 2 * np.pi * fm 249 | B = np.array([0, 1 / (q * wm), 0]) 250 | A = np.array([1 / wm**2, 1 / (q * wm), 1]) 251 | 252 | wmpre = f_prewarping(fm, fs) 253 | qpre = q_prewarping(q, fm, fs, q_warp_method) 254 | Bp = 0.0, 1 / (qpre * wmpre), 0.0 255 | Ap = 1 / wmpre**2, 1 / (qpre * wmpre), 1.0 256 | b, a = bilinear_biquad(Bp, Ap, fs) 257 | 258 | return B, A, b, a 259 | 260 | 261 | def biquad_bs2nd(fm, q, fs, q_warp_method="cos"): 262 | """Calc coeff for bandstop 2nd order. 263 | 264 | input: 265 | fm...mid frequency in Hz 266 | q...bandpass quality 267 | fs...sampling frequency in Hz 268 | q_warp_method..."sin", "cos", "tan" 269 | output: 270 | B...numerator coefficients Laplace transfer function 271 | A...denominator coefficients Laplace transfer function 272 | b...numerator coefficients z-transfer function 273 | a...denominator coefficients z-transfer function 274 | """ 275 | wm = 2 * np.pi * fm 276 | B = np.array([1 / wm**2, 0, 1]) 277 | A = np.array([1 / wm**2, 1 / (q * wm), 1]) 278 | 279 | wmpre = f_prewarping(fm, fs) 280 | qpre = q_prewarping(q, fm, fs, q_warp_method) 281 | Bp = 1 / wmpre**2, 0.0, 1.0 282 | Ap = 1 / wmpre**2, 1 / (qpre * wmpre), 1.0 283 | b, a = bilinear_biquad(Bp, Ap, fs) 284 | 285 | return B, A, b, a 286 | 287 | 288 | def biquad_ap1st(fc, fs, ai=1.0): 289 | """Calc coeff for allpass 1st order. 290 | 291 | input: 292 | fc...cut frequency in Hz 293 | fs...sampling frequency in Hz 294 | ai...filter characteristics coefficients, e.g. ai = 1 295 | output: 296 | B...numerator coefficients Laplace transfer function 297 | A...denominator coefficients Laplace transfer function 298 | b...numerator coefficients z-transfer function 299 | a...denominator coefficients z-transfer function 300 | """ 301 | wc = 2 * np.pi * fc 302 | B = np.array([0, -ai / wc, 1]) 303 | A = np.array([0, +ai / wc, 1]) 304 | 305 | wcpre = f_prewarping(fc, fs) 306 | Bp = 0.0, -ai / wcpre, 1.0 307 | Ap = 0.0, +ai / wcpre, 1.0 308 | b, a = bilinear_biquad(Bp, Ap, fs) 309 | 310 | return B, A, b, a 311 | 312 | 313 | def biquad_ap2nd(fc, fs, bi=1.0, ai=np.sqrt(2)): 314 | """Calc coeff for allpass 2nd order. 315 | 316 | input: 317 | fc...cut frequency in Hz 318 | fs...sampling frequency in Hz 319 | bi, ai...filter characteristics coefficients, e.g. 320 | bi = 1, ai = 1.4142 321 | output: 322 | B...numerator coefficients Laplace transfer function 323 | A...denominator coefficients Laplace transfer function 324 | b...numerator coefficients z-transfer function 325 | a...denominator coefficients z-transfer function 326 | """ 327 | wc = 2 * np.pi * fc 328 | B = np.array([bi / wc**2, -ai / wc, 1]) 329 | A = np.array([bi / wc**2, +ai / wc, 1]) 330 | 331 | wcpre = f_prewarping(fc, fs) 332 | Bp = bi / wcpre**2, -ai / wcpre, 1.0 333 | Ap = bi / wcpre**2, +ai / wcpre, 1.0 334 | b, a = bilinear_biquad(Bp, Ap, fs) 335 | 336 | return B, A, b, a 337 | 338 | 339 | def biquad_peq2nd(fm, G, q, fs, filter_type="III", q_warp_method="cos"): 340 | """Calc coeff for peak/dip equalizer (PEQ) 2nd order. 341 | 342 | input: 343 | fm...mid frequency in Hz 344 | G...gain or attenuation in dB 345 | q...quality 346 | fs...sampling frequency in Hz 347 | filter_type..."I", "II", "III" 348 | q_warp_method..."sin", "cos", "tan" 349 | output: 350 | B...numerator coefficients Laplace transfer function 351 | A...denominator coefficients Laplace transfer function 352 | b...numerator coefficients z-transfer function 353 | a...denominator coefficients z-transfer function 354 | """ 355 | wm = 2 * np.pi * fm 356 | wmpre = f_prewarping(fm, fs) 357 | g = 10 ** (G / 20) 358 | qpre = q_prewarping(q, fm, fs, q_warp_method) 359 | if filter_type == "I": # aka constant-Q PEQ 360 | gamma = g 361 | delta = g 362 | elif filter_type == "II": # aka symmetrical PEQ 363 | gamma = 1 364 | delta = g 365 | elif filter_type == "III": # aka one-half pad loss PEQ or midpoint PEQ 366 | gamma = g**0.5 367 | delta = g**0.5 368 | else: 369 | raise ValueError( 370 | ("inappropriate filter_type, " "please use 'I', 'II' or 'III' only") 371 | ) 372 | if np.isclose(G, 0, rtol=1e-05, atol=1e-08, equal_nan=False): 373 | B = np.array([0.0, 0, 1]) # flat EQ 374 | A = B 375 | b = np.array([1.0, 0, 0]) 376 | a = b 377 | elif G > 0: 378 | B = np.array([1 / wm**2, delta / (q * wm), 1]) 379 | A = np.array([1 / wm**2, (delta / g) / (q * wm), 1]) 380 | 381 | Bp = 1 / wmpre**2, delta / (qpre * wmpre), 1.0 382 | Ap = 1 / wmpre**2, (delta / g) / (qpre * wmpre), 1.0 383 | b, a = bilinear_biquad(Bp, Ap, fs) 384 | else: 385 | B = np.array([1 / wm**2, gamma / (q * wm), 1]) 386 | A = np.array([1 / wm**2, (gamma / g) / (q * wm), 1]) 387 | 388 | Bp = 1 / wmpre**2, gamma / (qpre * wmpre), 1.0 389 | Ap = 1 / wmpre**2, (gamma / g) / (qpre * wmpre), 1.0 390 | b, a = bilinear_biquad(Bp, Ap, fs) 391 | return B, A, b, a 392 | 393 | 394 | def biquad_peq2nd_zoelzer(fm, G, q, fs): 395 | """Calc coeff for peak/dip equalizer (PEQ) 2nd order. 396 | 397 | according to 398 | U. Zoelzer (2011): "DAFX - Digital Audio Effects", 2nd, Wiley, Table 2.4 399 | 400 | input: 401 | fm...mid frequency in Hz 402 | G...gain or attenuation in dB 403 | q...quality 404 | fs...sampling frequency in Hz 405 | output: 406 | B...numerator coefficients Laplace transfer function 407 | A...denominator coefficients Laplace transfer function 408 | b...numerator coefficients z-transfer function 409 | a...denominator coefficients z-transfer function 410 | """ 411 | K = np.tan(np.pi * fm / fs) 412 | V0 = 10 ** (G / 20) 413 | if np.isclose(G, 0, rtol=1e-05, atol=1e-08, equal_nan=False): 414 | b = np.array([1.0, 0, 0]) # flat EQ 415 | a = b 416 | elif G > 0: 417 | tmp = 1 + K / q + K**2 418 | b = np.array( 419 | [ 420 | (1 + V0 / q * K + K**2) / tmp, 421 | 2 * (K**2 - 1) / tmp, 422 | (1 - V0 / q * K + K**2) / tmp, 423 | ] 424 | ) 425 | a = np.array([1, 2 * (K**2 - 1) / tmp, (1 - K / q + K**2) / tmp]) 426 | else: 427 | tmp = 1 + K / (V0 * q) + K**2 428 | b = np.array( 429 | [ 430 | (1 + K / q + K**2) / tmp, 431 | 2 * (K**2 - 1) / tmp, 432 | (1 - K / q + K**2) / tmp, 433 | ] 434 | ) 435 | a = np.array([1, 2 * (K**2 - 1) / tmp, (1 - K / (V0 * q) + K**2) / tmp]) 436 | return b, a 437 | 438 | 439 | def biquad_peq2nd_RBJ(fm, G, q, fs): 440 | """Calc coeff for peak/dip equalizer (PEQ) 2nd order. 441 | 442 | according to 443 | Robert Bristow-Johnson (1994): "The equivalence of various methods of 444 | computing biquad coefficients for audio parametric equalizers." 445 | In: Proc. of 97th AES Convention, San Fransisco, eq. (16) 446 | http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt 447 | 448 | input: 449 | fm...mid frequency in Hz 450 | G...gain or attenuation in dB 451 | q...quality 452 | fs...sampling frequency in Hz 453 | output: 454 | B...numerator coefficients Laplace transfer function 455 | A...denominator coefficients Laplace transfer function 456 | b...numerator coefficients z-transfer function 457 | a...denominator coefficients z-transfer function 458 | """ 459 | Ksqrt = 10 ** (G / 40) 460 | w0 = 2 * np.pi * fm / fs 461 | BW = bw_from_q(q) 462 | gamma = np.sinh(np.log(2) / 2 * (BW * w0) / np.sin(w0)) * np.sin(w0) 463 | tmp = 1 + gamma / Ksqrt 464 | if np.isclose(G, 0, rtol=1e-05, atol=1e-08, equal_nan=False): 465 | b = np.array([1.0, 0, 0]) # flat EQ 466 | a = b 467 | else: 468 | b = np.array( 469 | [ 470 | (1 + gamma * Ksqrt) / tmp, 471 | -2 * np.cos(w0) / tmp, 472 | (1 - gamma * Ksqrt) / tmp, 473 | ] 474 | ) 475 | a = np.array([1, -2 * np.cos(w0) / tmp, (1 - gamma / Ksqrt) / tmp]) 476 | return b, a 477 | 478 | 479 | def biquad_lshv1st(fc, G, fs, filter_type="III"): 480 | """Calc coeff for lowshelving 1st order. 481 | 482 | input: 483 | fc...cut frequency in Hz 484 | G...gain or attenuation in dB 485 | fs...sampling frequency in Hz 486 | filter_type..."I", "II", "III" 487 | output: 488 | B...numerator coefficients Laplace transfer function 489 | A...denominator coefficients Laplace transfer function 490 | b...numerator coefficients z-transfer function 491 | a...denominator coefficients z-transfer function 492 | """ 493 | wc = 2 * np.pi * fc 494 | wcpre = f_prewarping(fc, fs) 495 | g = 10 ** (G / 20) 496 | if filter_type == "I": 497 | alpha = 1 498 | elif filter_type == "II": 499 | alpha = g**0.5 500 | elif filter_type == "III": # one-half pad loss, midpoint 501 | alpha = g**0.25 502 | else: 503 | raise ValueError( 504 | ("inappropriate filter_type, " "please use 'I', 'II' or 'III' only") 505 | ) 506 | if np.isclose(G, 0, rtol=1e-05, atol=1e-08, equal_nan=False): 507 | B = np.array([0.0, 0, 1]) # flat EQ 508 | A = B 509 | b = np.array([1.0, 0, 0]) 510 | a = b 511 | elif G > 0: 512 | B = np.array([0, 1 / wc, g * alpha**-2]) 513 | A = np.array([0, 1 / wc, alpha**-2]) 514 | 515 | Bp = 0.0, 1 / wcpre, g * alpha**-2 516 | Ap = 0.0, 1 / wcpre, alpha**-2 517 | b, a = bilinear_biquad(Bp, Ap, fs) 518 | else: 519 | B = np.array([0, 1 / wc, alpha**2]) 520 | A = np.array([0, 1 / wc, g**-1 * alpha**2]) 521 | 522 | Bp = 0.0, 1 / wcpre, alpha**2 523 | Ap = 0.0, 1 / wcpre, g**-1 * alpha**2 524 | b, a = bilinear_biquad(Bp, Ap, fs) 525 | return B, A, b, a 526 | 527 | 528 | def biquad_lshv2nd(fc, G, fs, filter_type="III", qz=1 / np.sqrt(2), qp=1 / np.sqrt(2)): 529 | """Calc coeff for lowshelving 2nd order. 530 | 531 | input: 532 | fc...cut frequency in Hz 533 | G...gain or attenuation in dB 534 | fs...sampling frequency in Hz 535 | filter_type..."I", "II", "III" 536 | qz...zero Quality, e.g. qz = 1/np.sqrt(2) for Butterworth quality 537 | qp...pole quality, e.g. qp = 1/np.sqrt(2) for Butterworth quality 538 | output: 539 | B...numerator coefficients Laplace transfer function 540 | A...denominator coefficients Laplace transfer function 541 | b...numerator coefficients z-transfer function 542 | a...denominator coefficients z-transfer function 543 | """ 544 | g = 10 ** (G / 20) 545 | wc = 2 * np.pi * fc 546 | wcpre = f_prewarping(fc, fs) 547 | if filter_type == "I": 548 | alpha = 1 549 | elif filter_type == "II": 550 | alpha = g**0.5 551 | elif filter_type == "III": # one-half pad loss, midpoint 552 | alpha = g**0.25 553 | else: 554 | raise ValueError( 555 | ("inappropriate filter_type, " "please use 'I', 'II' or 'III' only") 556 | ) 557 | if np.isclose(G, 0, rtol=1e-05, atol=1e-08, equal_nan=False): 558 | B = np.array([0.0, 0, 1]) # flat EQ 559 | A = B 560 | b = np.array([1.0, 0, 0]) 561 | a = b 562 | elif G > 0: 563 | B = np.array([1 / wc**2, g**0.5 * alpha**-1 / (qz * wc), g * alpha**-2]) 564 | A = np.array([1 / wc**2, alpha**-1 / (qp * wc), alpha**-2]) 565 | 566 | Bp = [1 / wcpre**2, g**0.5 * alpha**-1 / (qz * wcpre), g * alpha**-2] 567 | Ap = [1 / wcpre**2, alpha**-1 / (qp * wcpre), alpha**-2] 568 | b, a = bilinear_biquad(Bp, Ap, fs) 569 | else: 570 | B = np.array([1 / wc**2, alpha / (qz * wc), alpha**2]) 571 | A = np.array([1 / wc**2, g**-0.5 * alpha / (qp * wc), g**-1 * alpha**2]) 572 | 573 | Bp = [1 / wcpre**2, alpha / (qz * wcpre), alpha**2] 574 | Ap = [1 / wcpre**2, g**-0.5 * alpha / (qp * wcpre), g**-1 * alpha**2] 575 | b, a = bilinear_biquad(Bp, Ap, fs) 576 | return B, A, b, a 577 | 578 | 579 | def biquad_lshv2nd_Zoelzer(fc, G, fs): 580 | """Calc coeff for highshelving 2nd order. 581 | 582 | according to 583 | U. Zoelzer (2011): "DAFX - Digital Audio Effects", 2nd, Wiley, Table 2.3 584 | 585 | input: 586 | fc...cut frequency in Hz 587 | G...gain or attenuation in dB 588 | fs...sampling frequency in Hz 589 | output: 590 | B...numerator coefficients Laplace transfer function 591 | A...denominator coefficients Laplace transfer function 592 | b...numerator coefficients z-transfer function 593 | a...denominator coefficients z-transfer function 594 | """ 595 | V0 = 10 ** (G / 20) 596 | K = np.tan(np.pi * fc / fs) 597 | if np.isclose(G, 0, rtol=1e-05, atol=1e-08, equal_nan=False): 598 | b = np.array([1.0, 0, 0]) # flat EQ 599 | a = b 600 | elif G > 0: 601 | tmp = 1 + np.sqrt(2) * K + K**2 602 | b = np.array( 603 | [ 604 | (1 + np.sqrt(2 * V0) * K + V0 * K**2) / tmp, 605 | 2 * (V0 * K**2 - 1) / tmp, 606 | (1 - np.sqrt(2 * V0) * K + (V0 * K**2)) / tmp, 607 | ] 608 | ) 609 | a = np.array([1, 2 * (K**2 - 1) / tmp, (1 - np.sqrt(2) * K + K**2) / tmp]) 610 | else: 611 | tmp = V0 + np.sqrt(2 * V0) * K + K**2 612 | b = np.array( 613 | [ 614 | V0 * (1 + np.sqrt(2) * K + K**2) / tmp, 615 | 2 * V0 * (K**2 - 1) / tmp, 616 | V0 * (1 - np.sqrt(2) * K + K**2) / tmp, 617 | ] 618 | ) 619 | a = np.array( 620 | [1, 2 * (K**2 - V0) / tmp, (V0 - np.sqrt(2 * V0) * K + K**2) / tmp] 621 | ) 622 | return b, a 623 | 624 | 625 | def biquad_lshv2nd_RBJ(fc, G, S, fs): 626 | """Calc coeff for lowshelving 2nd order. 627 | 628 | according to 629 | http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt 630 | 631 | input: 632 | fc...cut frequency in Hz 633 | G...gain or attenuation in dB 634 | S...normalized quality 635 | fs...sampling frequency in Hz 636 | output: 637 | B...numerator coefficients Laplace transfer function 638 | A...denominator coefficients Laplace transfer function 639 | b...numerator coefficients z-transfer function 640 | a...denominator coefficients z-transfer function 641 | """ 642 | A = 10 ** (G / 40) 643 | w0 = 2 * np.pi * fc / fs 644 | alpha = np.sin(w0) / 2 * np.sqrt((A + 1 / A) * (1 / S - 1) + 2) 645 | if np.isclose(G, 0, rtol=1e-05, atol=1e-08, equal_nan=False): 646 | b = np.array([1.0, 0, 0]) # flat EQ 647 | a = b 648 | else: 649 | a0 = (A + 1) + (A - 1) * np.cos(w0) + 2 * np.sqrt(A) * alpha 650 | b = np.array( 651 | [ 652 | A * ((A + 1) - (A - 1) * np.cos(w0) + 2 * np.sqrt(A) * alpha), 653 | 2 * A * ((A - 1) - (A + 1) * np.cos(w0)), 654 | A * ((A + 1) - (A - 1) * np.cos(w0) - 2 * np.sqrt(A) * alpha), 655 | ] 656 | ) 657 | a = np.array( 658 | [ 659 | a0, 660 | -2 * ((A - 1) + (A + 1) * np.cos(w0)), 661 | (A + 1) + (A - 1) * np.cos(w0) - 2 * np.sqrt(A) * alpha, 662 | ] 663 | ) 664 | a = a / a0 665 | b = b / a0 666 | return b, a 667 | 668 | 669 | def biquad_hshv1st(fc, G, fs, filter_type="III"): 670 | """Calc coeff for highshelving 1st order. 671 | 672 | input: 673 | fc...cut frequency in Hz 674 | G...gain or attenuation in dB 675 | fs...sampling frequency in Hz 676 | filter_type..."I", "II", "III" 677 | output: 678 | B...numerator coefficients Laplace transfer function 679 | A...denominator coefficients Laplace transfer function 680 | b...numerator coefficients z-transfer function 681 | a...denominator coefficients z-transfer function 682 | """ 683 | wc = 2 * np.pi * fc 684 | wcpre = f_prewarping(fc, fs) 685 | g = 10 ** (G / 20) 686 | if filter_type == "I": 687 | alpha = 1 688 | elif filter_type == "II": 689 | alpha = g**0.5 690 | elif filter_type == "III": # one-half pad loss, midpoint 691 | alpha = g**0.25 692 | else: 693 | raise ValueError( 694 | ("inappropriate filter_type, " "please use 'I', 'II' or 'III' only") 695 | ) 696 | if np.isclose(G, 0, rtol=1e-05, atol=1e-08, equal_nan=False): 697 | B = np.array([0.0, 0, 1]) # flat EQ 698 | A = B 699 | b = np.array([1.0, 0, 0]) 700 | a = b 701 | elif G > 0: 702 | B = np.array([0, g * alpha**-2 / wc, 1]) 703 | A = np.array([0, alpha**-2 / wc, 1]) 704 | 705 | Bp = 0.0, g * alpha**-2 / wcpre, 1.0 706 | Ap = 0.0, alpha**-2 / wcpre, 1.0 707 | b, a = bilinear_biquad(Bp, Ap, fs) 708 | else: 709 | B = np.array([0, alpha**2 / wc, 1]) 710 | A = np.array([0, g**-1 * alpha**2 / wc, 1]) 711 | 712 | Bp = 0.0, alpha**2 / wcpre, 1.0 713 | Ap = 0.0, g**-1 * alpha**2 / wcpre, 1.0 714 | b, a = bilinear_biquad(Bp, Ap, fs) 715 | return B, A, b, a 716 | 717 | 718 | def biquad_hshv2nd(fc, G, fs, filter_type="III", qz=1 / np.sqrt(2), qp=1 / np.sqrt(2)): 719 | """Calc coeff for highshelving 2nd order. 720 | 721 | input: 722 | fc...cut frequency in Hz 723 | G...gain or attenuation in dB 724 | fs...sampling frequency in Hz 725 | filter_type..."I", "II", "III" 726 | qz...zero Quality, e.g. qz = 1/np.sqrt(2) for Butterworth quality 727 | qp...pole quality, e.g. qp = 1/np.sqrt(2) for Butterworth quality 728 | output: 729 | B...numerator coefficients Laplace transfer function 730 | A...denominator coefficients Laplace transfer function 731 | b...numerator coefficients z-transfer function 732 | a...denominator coefficients z-transfer function 733 | """ 734 | wc = 2 * np.pi * fc 735 | wcpre = f_prewarping(fc, fs) 736 | g = 10 ** (G / 20) 737 | if filter_type == "I": 738 | alpha = 1 739 | elif filter_type == "II": 740 | alpha = g**0.5 741 | elif filter_type == "III": # one-half pad loss, midpoint 742 | alpha = g**0.25 743 | else: 744 | raise ValueError( 745 | ("inappropriate filter_type, " "please use 'I', 'II' or 'III' only") 746 | ) 747 | if np.isclose(G, 0, rtol=1e-05, atol=1e-08, equal_nan=False): 748 | B = np.array([0.0, 0, 1]) # flat EQ 749 | A = B 750 | b = np.array([1.0, 0, 0]) 751 | a = b 752 | elif G > 0: 753 | B = np.array([g * alpha**-2 / wc**2, g**0.5 * alpha**-1 / (qz * wc), 1]) 754 | A = np.array([alpha**-2 / wc**2, alpha**-1 / (qp * wc), 1]) 755 | 756 | Bp = g * alpha**-2 / wcpre**2, g**0.5 * alpha**-1 / (qz * wcpre), 1.0 757 | Ap = alpha**-2 / wcpre**2, alpha**-1 / (qp * wcpre), 1.0 758 | b, a = bilinear_biquad(Bp, Ap, fs) 759 | else: 760 | B = np.array([alpha**2 / wc**2, alpha / (qz * wc), 1]) 761 | A = np.array([g**-1 * alpha**2 / wc**2, g**-0.5 * alpha / (qp * wc), 1]) 762 | 763 | Bp = alpha**2 / wcpre**2, alpha / (qz * wcpre), 1.0 764 | Ap = g**-1 * alpha**2 / wcpre**2, g**-0.5 * alpha / (qp * wcpre), 1.0 765 | b, a = bilinear_biquad(Bp, Ap, fs) 766 | return B, A, b, a 767 | 768 | 769 | def biquad_hshv2nd_Zoelzer(fc, G, fs): 770 | """Calc coeff for highshelving 2nd order. 771 | 772 | according to 773 | U. Zoelzer (2011): "DAFX - Digital Audio Effects", 2nd, Wiley, Table 2.3 774 | 775 | input: 776 | fc...cut frequency in Hz 777 | G...gain or attenuation in dB 778 | fs...sampling frequency in Hz 779 | output: 780 | B...numerator coefficients Laplace transfer function 781 | A...denominator coefficients Laplace transfer function 782 | b...numerator coefficients z-transfer function 783 | a...denominator coefficients z-transfer function 784 | """ 785 | V0 = 10 ** (G / 20) 786 | K = np.tan(np.pi * fc / fs) 787 | if np.isclose(G, 0, rtol=1e-05, atol=1e-08, equal_nan=False): 788 | b = np.array([1.0, 0, 0]) # flat EQ 789 | a = b 790 | elif G > 0: 791 | tmp = 1 + np.sqrt(2) * K + K**2 792 | b = np.array( 793 | [ 794 | (V0 + np.sqrt(2 * V0) * K + K**2) / tmp, 795 | 2 * (K**2 - V0) / tmp, 796 | (V0 - np.sqrt(2 * V0) * K + K**2) / tmp, 797 | ] 798 | ) 799 | a = np.array([1, 2 * (K**2 - 1) / tmp, (1 - np.sqrt(2) * K + K**2) / tmp]) 800 | else: 801 | tmp = 1 + np.sqrt(2 * V0) * K + (V0 * K**2) 802 | b = np.array( 803 | [ 804 | V0 * (1 + np.sqrt(2) * K + K**2) / tmp, 805 | 2 * V0 * (K**2 - 1) / tmp, 806 | V0 * (1 - np.sqrt(2.0) * K + K**2) / tmp, 807 | ] 808 | ) 809 | a = np.array( 810 | [ 811 | 1, 812 | 2 * (V0 * K**2 - 1) / tmp, 813 | (1 - np.sqrt(2 * V0) * K + (V0 * K**2)) / tmp, 814 | ] 815 | ) 816 | return b, a 817 | 818 | 819 | def biquad_hshv2nd_RBJ(fc, G, S, fs): 820 | """Calc coeff for highshelving 2nd order. 821 | 822 | according to 823 | http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt 824 | 825 | input: 826 | fc...cut frequency in Hz 827 | G...gain or attenuation in dB 828 | S...normalized quality 829 | fs...sampling frequency in Hz 830 | output: 831 | B...numerator coefficients Laplace transfer function 832 | A...denominator coefficients Laplace transfer function 833 | b...numerator coefficients z-transfer function 834 | a...denominator coefficients z-transfer function 835 | """ 836 | A = 10 ** (G / 40) 837 | w0 = 2 * np.pi * fc / fs 838 | alpha = np.sin(w0) / 2 * np.sqrt((A + 1 / A) * (1 / S - 1) + 2) 839 | if np.isclose(G, 0, rtol=1e-05, atol=1e-08, equal_nan=False): 840 | b = np.array([1.0, 0, 0]) # flat EQ 841 | a = b 842 | else: 843 | a0 = (A + 1) - (A - 1) * np.cos(w0) + 2 * np.sqrt(A) * alpha 844 | b = np.array( 845 | [ 846 | A * ((A + 1) + (A - 1) * np.cos(w0) + 2 * np.sqrt(A) * alpha), 847 | -2 * A * ((A - 1) + (A + 1) * np.cos(w0)), 848 | A * ((A + 1) + (A - 1) * np.cos(w0) - 2 * np.sqrt(A) * alpha), 849 | ] 850 | ) 851 | a = np.array( 852 | [ 853 | a0, 854 | 2 * ((A - 1) - (A + 1) * np.cos(w0)), 855 | (A + 1) - (A - 1) * np.cos(w0) - 2 * np.sqrt(A) * alpha, 856 | ] 857 | ) 858 | b = b / a0 859 | a = a / a0 860 | return b, a 861 | 862 | 863 | def zplane_plot(ax, z, p, k): 864 | """Plot pole/zero/gain plot of discrete-time, linear-time-invariant system. 865 | 866 | Note that the for-loop handling might be not very efficient 867 | for very long FIRs 868 | 869 | z...array of zeros in z-plane 870 | p...array of poles in z-zplane 871 | k...gain factor 872 | 873 | taken from own work 874 | URL = ('https://github.com/spatialaudio/signals-and-systems-exercises/' 875 | 'blob/master/sig_sys_tools.py') 876 | 877 | currently we don't use the ax input parameter, we rather just plot 878 | in hope for getting an appropriate place for it from the calling function 879 | """ 880 | # draw unit circle 881 | Nf = 2**7 882 | Om = np.arange(Nf) * 2 * np.pi / Nf 883 | plt.plot(np.cos(Om), np.sin(Om), "C7") 884 | 885 | try: # TBD: check if this pole is compensated by a zero 886 | circle = Circle((0, 0), radius=np.max(np.abs(p)), color="C7", alpha=0.15) 887 | plt.gcf().gca().add_artist(circle) 888 | except ValueError: 889 | print("no pole at all, ROC is whole z-plane") 890 | 891 | zu, zc = np.unique(z, return_counts=True) # find and count unique zeros 892 | for zui, zci in zip(zu, zc): # plot them individually 893 | plt.plot( 894 | np.real(zui), np.imag(zui), ms=7, color="C0", marker="o", fillstyle="none" 895 | ) 896 | if zci > 1: # if multiple zeros exist then indicate the count 897 | plt.text(np.real(zui), np.imag(zui), zci) 898 | 899 | pu, pc = np.unique(p, return_counts=True) # find and count unique poles 900 | for pui, pci in zip(pu, pc): # plot them individually 901 | plt.plot(np.real(pui), np.imag(pui), ms=7, color="C3", marker="x") 902 | if pci > 1: # if multiple poles exist then indicate the count 903 | plt.text(np.real(pui), np.imag(pui), pci) 904 | 905 | plt.text(0, +1, "k=%f" % k) 906 | plt.text(0, -1, "ROC for causal: white") 907 | plt.axis("square") 908 | # plt.axis([-2, 2, -2, 2]) 909 | plt.xlabel(r"$\Re\{z\}$") 910 | plt.ylabel(r"$\Im\{z\}$") 911 | plt.grid(True) 912 | 913 | 914 | def bode_plot(B, A, b, a, fs, N, fig=None): 915 | """Realize a bode plot containing magnitude, phase and zplane. 916 | 917 | input: 918 | B...numerator coefficients Laplace transfer function 919 | A...denominator coefficients Laplace transfer function 920 | b...numerator coefficients z-transfer function 921 | a...denominator coefficients z-transfer function 922 | fs...sampling frequency in Hz 923 | output: 924 | bode plot as new figure 925 | """ 926 | if fig is None: 927 | fig = plt.figure() 928 | z, p, k = signal.tf2zpk(b, a) 929 | W, Hd = signal.freqz(b, a, N) 930 | s, Ha = signal.freqs(B, A, fs * W) 931 | if Hd[0] == 0: 932 | Hd[0] = 1e-15 # avoid zero at DC for plotting dB 933 | if Ha[0] == 0: 934 | Ha[0] = 1e-15 935 | f = fs * W / (2 * np.pi) 936 | 937 | gs = fig.add_gridspec(2, 2) 938 | # magnitude 939 | ax1 = fig.add_subplot(gs[0, 0]) 940 | ax1.plot( 941 | f, 942 | 20 * np.log10(np.abs(Ha)), 943 | "C0", 944 | label=r"$|H(\omega)|$ continuous-time", 945 | linewidth=3, 946 | ) 947 | ax1.plot( 948 | f, 949 | 20 * np.log10(np.abs(Hd)), 950 | "C1", 951 | label=(r"$|H(\Omega)|$ discrete-time, fs=%5.f Hz" % fs), 952 | linewidth=2, 953 | ) 954 | ax1.set_xscale("log") 955 | ax1.set_yscale("linear") 956 | ax1.set_xlabel(r"$f$ / Hz", color="xkcd:navy blue") 957 | ax1.set_ylabel(r"$A$ / dB", color="xkcd:navy blue") 958 | ax1.set_title("Bode plot: magnitude", color="xkcd:navy blue") 959 | ax1.set_xlim(20, 20000) 960 | ax1.set_xticks((20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000)) 961 | ax1.set_xticklabels( 962 | ["20", "50", "100", "200", "500", "1k", "2k", "5k", "10k", "20k"], 963 | color="xkcd:navy blue", 964 | ) 965 | ax1.set_ylim(-15, 15) 966 | ax1.set_yticks(np.arange(-15, 15 + 3, 3)) 967 | ax1.set_yticklabels( 968 | ["-15", "-12", "-9", "-6", "-3", "0", "3", "6", "9", "12", "15"], 969 | color="xkcd:navy blue", 970 | ) 971 | ax1.legend(loc="best") 972 | ax1.grid( 973 | True, 974 | which="both", 975 | axis="both", 976 | linestyle="-", 977 | linewidth=0.5, 978 | color=(0.8, 0.8, 0.8), 979 | ) 980 | 981 | # phase 982 | ax2 = fig.add_subplot(gs[1, 0]) 983 | ax2.plot( 984 | f, 985 | (np.angle(Ha) * 180 / np.pi), 986 | "C0", 987 | label=r"$\mathrm{angle}(H(" r"\omega))$ continuous-time", 988 | linewidth=3, 989 | ) 990 | ax2.plot( 991 | f, 992 | (np.angle(Hd) * 180 / np.pi), 993 | "C1", 994 | label=(r"$\mathrm{angle}(H(\Omega))$ discrete-time, " "fs=%5.f Hz" % fs), 995 | linewidth=2, 996 | ) 997 | ax2.set_xscale("log") 998 | ax2.set_yscale("linear") 999 | ax2.set_xlabel(r"$f$ / Hz", color="xkcd:navy blue") 1000 | ax2.set_ylabel(r"$\phi$ / deg", color="xkcd:navy blue") 1001 | ax2.set_title("Bode plot: phase", color="xkcd:navy blue") 1002 | ax2.set_xlim(20, 20000) 1003 | ax2.set_xticks((20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000)) 1004 | ax2.set_xticklabels( 1005 | ["20", "50", "100", "200", "500", "1k", "2k", "5k", "10k", "20k"], 1006 | color="xkcd:navy blue", 1007 | ) 1008 | ax2.set_ylim(-180, +180) 1009 | ax2.set_yticks(np.arange(-180, 180 + 45, 45)) 1010 | ax2.set_yticklabels( 1011 | ["-180", "-135", "-90", "-45", "0", "45", "90", "135", "180"], 1012 | color="xkcd:navy blue", 1013 | ) 1014 | ax2.legend(loc="best") 1015 | ax2.grid( 1016 | True, 1017 | which="both", 1018 | axis="both", 1019 | linestyle="-", 1020 | linewidth=0.5, 1021 | color=(0.8, 0.8, 0.8), 1022 | ) 1023 | 1024 | # zplane 1025 | ax3 = fig.add_subplot(gs[:, 1]) 1026 | zplane_plot(ax3, z, p, k) 1027 | 1028 | print("B =", B) 1029 | print("A =", A) 1030 | print("b =", b) 1031 | print("a =", a) 1032 | 1033 | 1034 | def magnitude_plot_overlay(x, y, title, legend, fig=None): 1035 | """Realize a bode plot containing magnitude for overlay.""" 1036 | if fig is None: 1037 | plt.figure() 1038 | sz = y.shape 1039 | lines = plt.semilogx(x, 20 * np.log10(np.abs(y))) 1040 | plt.legend(lines[: sz[1]], legend) 1041 | plt.autoscale("tight") 1042 | plt.title(title) 1043 | plt.xlabel(r"$f$ / Hz") 1044 | plt.ylabel(r"20 log10 |$H$| / dB") 1045 | plt.axis([1000, 24000, 0, 18]) 1046 | plt.yticks(np.arange(-18, 18 + 3, 3)) 1047 | plt.xticks( 1048 | (20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000), 1049 | ["20", "50", "100", "200", "500", "1k", "2k", "5k", "10k", "20k"], 1050 | ) 1051 | plt.xlim(20, x.max()) 1052 | plt.ylim(-18, 18) 1053 | plt.grid( 1054 | True, 1055 | which="both", 1056 | axis="both", 1057 | linestyle="-", 1058 | linewidth=0.5, 1059 | color=(0.8, 0.8, 0.8), 1060 | ) 1061 | plt.show() 1062 | -------------------------------------------------------------------------------- /filter_design/biblio.bib: -------------------------------------------------------------------------------- 1 | @article{ValimakiReiss2016, 2 | Author = {Vesa Välimäki AND Joshua D. Reiss}, 3 | Journal = {Appl. Sci.}, 4 | Number = {5}, 5 | Pages = {129}, 6 | Title = {All About Audio Equalization: Solutions and Frontiers}, 7 | Volume = {6}, 8 | Year = {1997}} 9 | 10 | @mastersthesis{Thaden1997, 11 | Author = {Rainer Thaden}, 12 | School = {RWTH Aachen}, 13 | Title = {Entwicklung und Erprobung einer digitalen parametrischen Filterbank}, 14 | Year = {1997}} 15 | 16 | @book{Zoelzer2011, 17 | Author = {Udo Zoelzer}, 18 | Edition = {2.}, 19 | Publisher = {Wiley}, 20 | Title = {DAFX - Digital Audio Effects}, 21 | Year = {2011}} 22 | 23 | @book{Moschytz1981, 24 | Author = {G. S. Moschytz AND P. Horn}, 25 | Publisher = {John Wiley \& Sons}, 26 | Title = {Active filter design handbook: For use with programmable pocket calculators and minicomputers}, 27 | Year = {1981}} 28 | 29 | @url{Redmon2013, 30 | Author = {Nigel Redmon}, 31 | Lastchecked = {2016-08-29}, 32 | Title = {Biquad calculator v2}, 33 | Urldate = {http://www.earlevel.com/main/2013/10/13/biquad-calculator-v2/}} 34 | 35 | @book{TietzeSchenk2008, 36 | Address = {Heidelberg}, 37 | Author = {Ulrich Tietze and Christoph Schenk and Eberhard Schenk}, 38 | Edition = {2. English = 12. German}, 39 | Publisher = {Springer}, 40 | Title = {Electronic Circuits---Handbook for Design and Application}, 41 | Year = {2008}} 42 | 43 | @book{Zoelzer2002, 44 | Address = {New York}, 45 | Author = {Udo Zoelzer}, 46 | Publisher = {Wiley}, 47 | Title = {DAFX - Digital Audio Effects}, 48 | Year = {2002}} 49 | 50 | @book{Zoelzer2005, 51 | Address = {Wiesbaden}, 52 | Author = {Udo Zoelzer}, 53 | Edition = {3.}, 54 | Publisher = {Teubner}, 55 | Title = {Digitale Audiosignalverarbeitung}, 56 | Year = {2005}} 57 | 58 | @incollection{Zoelzer2008, 59 | Address = {Berlin}, 60 | Author = {Udo Zoelzer}, 61 | Booktitle = {Handbuch der Audiotechnik}, 62 | Editor = {Stefan Weinzierl}, 63 | Publisher = {Springer}, 64 | Title = {Digitale Audiotechnik: Signalverarbeitung, Filter und Effekte}, 65 | Year = {2008}} 66 | 67 | @book{OppenheimSchaferBuck2004, 68 | Address = {München}, 69 | Author = {Alan V. Oppenheim and Ronald W. Schafer and John R. Buck}, 70 | Edition = {2.}, 71 | Publisher = {Pearson Studium}, 72 | Title = {Zeitdiskrete Signalverarbeitung}, 73 | Year = {2004}} 74 | 75 | @incollection{Kimball1938, 76 | Address = {New York}, 77 | Author = {H. Kimball}, 78 | Booktitle = {Motion Picture Sound Engineering}, 79 | Editor = {{Academy of Motion Picture Arts and Sciences}}, 80 | Publisher = {D. Van Nostrand}, 81 | Title = {Attenuation Equalizers}, 82 | Year = {1938}} 83 | 84 | @article{Orfanidis1997, 85 | Author = {Sophoncles J. Orfanidis}, 86 | Journal = {J. Aud. Eng. Soc.}, 87 | Number = {6}, 88 | Pages = {444-455}, 89 | Title = {Digital parametric equalizer design with prescribed Nyquist-frequency gain}, 90 | Volume = {45}, 91 | Year = {1997}} 92 | 93 | @inproceedings{Christensen2003, 94 | Author = {Knud Bank Christensen}, 95 | Booktitle = {Proc. of 115th AES Convention, New York}, 96 | Number = {5916}, 97 | Title = {A Generalization of the Biquadratic Parametric Equalizer}, 98 | Year = {2003}} 99 | 100 | @url{Bristow-Johnson, 101 | Author = {R. Bristow-Johnson}, 102 | Howpublished = {WWW}, 103 | Lastchecked = {12.08.2009}, 104 | Title = {{Cookbook formulae for audio EQ biquad filter coefficients}}, 105 | Url = {http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt}} 106 | 107 | @inproceedings{Schmidt2010, 108 | Author = {Thorsten Schmidt AND Joerg Bitzer}, 109 | Booktitle = {Proc. of 128th AES Convention, London}, 110 | Number = {7964}, 111 | Title = {Digital equalization filter: New solution to the frequency response near Nyquist and evaluation by listening tests}, 112 | Year = {2010}} 113 | 114 | @article{Alaoui2010, 115 | Author = {Mohamad Adnan Al-Alaoui}, 116 | Journal = {J. Aud. Eng. Soc.}, 117 | Number = {12}, 118 | Pages = {1064-1082}, 119 | Title = {Improving the Magnitude Responses of Digital Filters for Loudspeaker Equalization}, 120 | Volume = {58}, 121 | Year = {2010}} 122 | 123 | @inproceedings{Bristow-Johnson1994, 124 | Author = {Robert Bristow-Johnson}, 125 | Booktitle = {Proc. of 97th AES Convention, San Fransisco}, 126 | Number = {3906}, 127 | Title = {The equivalence of various methods of computing biquad coefficients for audio parametric equalizers}, 128 | Year = {1994}} 129 | 130 | @article{Alaoui2007, 131 | Author = {Mohamad Adnan Al-Alaoui}, 132 | Journal = {IEEE Transactions on Circuits and Systems I: Regular Papers}, 133 | Number = {2}, 134 | Pages = {338-350}, 135 | Title = {Novel Approach to Analog-to-Digital Transforms}, 136 | Volume = {54}, 137 | Year = {2007}} 138 | 139 | @inproceedings{Gunness2007, 140 | Author = {David W. Gunness AND Ojas S. Chauhan}, 141 | Booktitle = {Proc. of 32nd Intl AES Conference: DSP For Loudspeakers, Hilleroed, Denmark}, 142 | Title = {Optimizing the Magnitude Response of Matched Z-Transform Filters ("MZTi") for Loudspeaker Equalization}, 143 | Year = {2007}} 144 | 145 | @article{Clark2000, 146 | Author = {Rob J. Clark AND Emmanuel C. Ifeachor AND Glenn M. Rogers AND Peter W. J. Van Eetvelt}, 147 | Journal = {J. Aud. Eng. Soc.}, 148 | Number = {4}, 149 | Pages = {281-298}, 150 | Title = {Techniques for Generating Digital Equalizer Coefficients}, 151 | Volume = {48}, 152 | Year = {2000}} 153 | -------------------------------------------------------------------------------- /filter_design/ipython_kernel_config.py: -------------------------------------------------------------------------------- 1 | ../ipython_kernel_config.py -------------------------------------------------------------------------------- /filter_design/sz_mapping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/filter_design/sz_mapping.png -------------------------------------------------------------------------------- /images/README: -------------------------------------------------------------------------------- 1 | The illustrations in the notebooks are drawn in LaTeX using the TikZ/PGF package. The images are exported as PNG files using the standalone package and resized by convert from ImageMagick. The PNG parameter ‚density‘ is set for an appropriate size when exporting the notebooks as PDF using nbconvert. The OS X/Linux shell scripts recreate the images in the correct subdirectories. -------------------------------------------------------------------------------- /images/filter_design.tex: -------------------------------------------------------------------------------- 1 | \input{prefix} 2 | 3 | % ============================================================================= 4 | % ============================================================================= 5 | \begin{document} 6 | 7 | 8 | % Bilinear transform 9 | % ============================================================================= 10 | \begin{tikzpicture} 11 | 12 | \begin{scope} 13 | 14 | \draw[->] (-2,0)--(2.3,0) node[right]{$\sigma$}; 15 | \draw[->] (0,-2.2)--(0,2.2) node[left]{$j \omega$}; 16 | \filldraw[pattern=north west lines,draw=none] (-1.8,-1.5) rectangle (0,1.5); 17 | \filldraw[pattern=horizontal lines,draw=none] (0,-1.5) rectangle (1.8,1.5); 18 | 19 | \draw[blue,thick] (-1.8,1.5)--(1.8,1.5); 20 | \draw[blue,thick] (-1.8,-1.5)--(1.8,-1.5); 21 | \node[above right] at (0,1.5){$j \frac{\pi}{T}$}; 22 | \node[below right] at (0,-1.5){$- j \frac{\pi}{T}$}; 23 | \draw[red,thick] (0,-1.5)--(0,1.5); 24 | 25 | \filldraw[cyan] (0,1.5) circle(0.07); 26 | \filldraw[cyan] (0,-1.5) circle(0.07); 27 | \filldraw[black] (0,0) circle(0.07); 28 | 29 | 30 | \end{scope} 31 | 32 | \begin{scope}[xshift=6cm] 33 | 34 | 35 | \filldraw[pattern=horizontal lines,draw=none] (-1.8,-1.8) rectangle (1.8,1.8); 36 | \filldraw[nonzero rule,pattern=north west lines,draw=red,fill=white,thick] (0,0) circle(1.25); 37 | \filldraw[pattern=north west lines,draw=none] (0,0) circle(1.25); 38 | 39 | \draw[->] (-2,0)--(2.2,0) node[right]{$\text{Re}\{z\}$}; 40 | \draw[->] (0,-2.2)--(0,2.3) node[left]{$\text{Im}\{z\}$}; 41 | 42 | \filldraw[black] (1.25,0) circle(0.07); 43 | \filldraw[cyan] (-1.25,0) circle(0.07); 44 | 45 | \node[below right] at (1.25,0){$1$}; 46 | \node[above left] at (0,1.25){$1$}; 47 | 48 | \end{scope} 49 | 50 | \end{tikzpicture} 51 | 52 | % 2nd order lowpass 53 | % ============================================================================= 54 | \begin{circuitikz}[european] 55 | \draw (-0,0) to [R, l=R,o-] (2,0); 56 | \draw (2,0) to [L,l=L,-*,i=$i(t)$] (5,0); 57 | \draw (5,0) to [C,l=C,-*] (5,-2); 58 | \draw (5,0) to [short,-o] (7,0); 59 | \draw (0,-2) to [short,o-o] (7,-2); 60 | \draw[-latex] (0,-0.2)--(0,-1.8) node[midway,left]{$x(t)$}; 61 | \draw[-latex] (7,-0.2)--(7,-1.8) node[midway,right]{$y(t)$}; 62 | \end{circuitikz} 63 | 64 | 65 | \end{document} -------------------------------------------------------------------------------- /images/introduction.tex: -------------------------------------------------------------------------------- 1 | \input{prefix} 2 | 3 | % ============================================================================= 4 | % ============================================================================= 5 | \begin{document} 6 | 7 | 8 | % digital signal processing chain 9 | \begin{tikzpicture}[auto, node distance=4cm] 10 | \node [input, name=input] {}; 11 | \node [block, right of=input,xshift=-2cm] (ADC){ADC}; 12 | \node [block, right of=ADC,yshift=0cm] (DSP){DSP}; 13 | \node [block, right of=DSP,yshift=0cm] (DAC){DAC}; 14 | \node [output, right of=DAC,xshift=-2cm] (output) {}; 15 | 16 | \draw [-latex] (input) node[left]{$x(t)$} -- (ADC); 17 | \draw [-latex] (ADC) -- (DSP) node[midway, below]{$x_\text{D}[k]$}; 18 | \draw [-latex] (DSP) -- (DAC) node[midway, below]{$y_\text{D}[k]$};; 19 | \draw [-latex] (DAC) -- (output) node[right]{$y(t)$}; 20 | \end{tikzpicture} 21 | 22 | 23 | \end{document} 24 | -------------------------------------------------------------------------------- /images/mk_filter_design.sh: -------------------------------------------------------------------------------- 1 | latex -shell-escape filter_design.tex 2 | convert -units PixelsPerInch -density 144 -resize 600 filter_design-1.png ../filter_design/sz_mapping.png 3 | convert -units PixelsPerInch -density 144 -resize 600 filter_design-2.png ../filter_design/RLC_lowpass.png 4 | 5 | 6 | -------------------------------------------------------------------------------- /images/mk_introduction.sh: -------------------------------------------------------------------------------- 1 | latex -shell-escape introduction.tex 2 | convert -units PixelsPerInch -density 144 -resize 700 introduction-1.png ../introduction/DSP.png 3 | 4 | -------------------------------------------------------------------------------- /images/mk_nonrecursive_filters.sh: -------------------------------------------------------------------------------- 1 | latex -shell-escape non_recursive_filters.tex 2 | convert -units PixelsPerInch -density 144 -resize 600 non_recursive_filters-1.png ../nonrecursive_filters/overlap_add.png 3 | convert -units PixelsPerInch -density 144 -resize 600 non_recursive_filters-2.png ../nonrecursive_filters/overlap_save.png 4 | convert -units PixelsPerInch -density 144 -resize 400 non_recursive_filters-3.png ../nonrecursive_filters/roundoff_model.png 5 | -------------------------------------------------------------------------------- /images/mk_quantization.sh: -------------------------------------------------------------------------------- 1 | latex -shell-escape quantization.tex 2 | convert -units PixelsPerInch -density 144 -resize 300 quantization-1.png ../quantization/model_quantization.png 3 | convert -units PixelsPerInch -density 144 -resize 400 quantization-2.png ../quantization/mid_tread_characteristic.png 4 | convert -units PixelsPerInch -density 144 -resize 400 quantization-3.png ../quantization/mid_rise_characteristic.png 5 | convert -units PixelsPerInch -density 144 -resize 400 quantization-4.png ../quantization/noise_shaping.png 6 | convert -units PixelsPerInch -density 144 -resize 400 quantization-5.png ../quantization/ideal_ADC.png 7 | convert -units PixelsPerInch -density 144 -resize 600 quantization-6.png ../quantization/oversampling.png 8 | convert -units PixelsPerInch -density 144 -resize 800 quantization-7.png ../quantization/oversampling_anti_aliasing.png 9 | -------------------------------------------------------------------------------- /images/mk_random_signals.sh: -------------------------------------------------------------------------------- 1 | latex -shell-escape random_signals.tex 2 | convert -units PixelsPerInch -density 144 -resize 600 random_signals-1.png ../random_signals/measurement_channel.png 3 | convert -units PixelsPerInch -density 144 -resize 500 random_signals-2.png ../random_signals/communication_channel.png 4 | 5 | 6 | -------------------------------------------------------------------------------- /images/mk_recursive_filters.sh: -------------------------------------------------------------------------------- 1 | latex -shell-escape recursive_filters.tex 2 | convert -units PixelsPerInch -density 144 -resize 600 recursive_filters-1.png ../recursive_filters/direct_form_i.png 3 | convert -units PixelsPerInch -density 144 -resize 600 recursive_filters-2.png ../recursive_filters/direct_form_ii.png 4 | convert -units PixelsPerInch -density 144 -resize 600 recursive_filters-3.png ../recursive_filters/direct_form_ii_t.png 5 | convert -units PixelsPerInch -density 144 -resize 500 recursive_filters-4.png ../recursive_filters/coupled_form.png 6 | -------------------------------------------------------------------------------- /images/mk_spectral_analysis.sh: -------------------------------------------------------------------------------- 1 | latex -shell-escape spectral_analysis.tex 2 | convert -units PixelsPerInch -density 144 -resize 600 spectral_analysis-1.png ../spectral_analysis_deterministic_signals/Fourier_transforms.png 3 | 4 | -------------------------------------------------------------------------------- /images/mk_systems.sh: -------------------------------------------------------------------------------- 1 | latex -shell-escape systems.tex 2 | convert -units PixelsPerInch -density 144 -resize 400 systems-1.png systems-1.png 3 | convert -units PixelsPerInch -density 144 -resize 400 systems-2.png ../random_signals_LTI_systems/LTI_system_td.png 4 | convert -units PixelsPerInch -density 144 -resize 400 systems-2.png ../nonrecursive_filters/LTI_system_td.png 5 | convert -units PixelsPerInch -density 144 -resize 400 systems-3.png ../spectral_estimation_random_signals/synthesis_model.png 6 | convert -units PixelsPerInch -density 144 -resize 400 systems-4.png ../spectral_estimation_random_signals/analysis_model.png 7 | 8 | -------------------------------------------------------------------------------- /images/mk_wiener_filter.sh: -------------------------------------------------------------------------------- 1 | latex -shell-escape wiener_filter.tex 2 | convert -units PixelsPerInch -density 144 -resize 600 wiener_filter-1.png ../random_signals_LTI_systems/model_wiener_filter.png 3 | -------------------------------------------------------------------------------- /images/non_recursive_filters.tex: -------------------------------------------------------------------------------- 1 | \input{prefix} 2 | 3 | % ============================================================================= 4 | % ============================================================================= 5 | \begin{document} 6 | 7 | 8 | 9 | 10 | % overlap-add convolution 11 | \pgfdeclarelayer{background} 12 | \pgfsetlayers{background,main} 13 | 14 | \begin{tikzpicture}[auto, node distance=25mm] 15 | 16 | % input segments 17 | \node[block, minimum height=1em, minimum width=25mm] (x0){$x_0[k]$}; 18 | \node[block, right of=x0, minimum height=1em, minimum width=25mm] (x1){$x_1[k]$}; 19 | \node[block, right of=x1, minimum height=1em, minimum width=25mm] (x2){$x_2[k]$}; 20 | \node[block, right of=x2, minimum height=1em, minimum width=25mm] (x3){$x_3[k]$}; 21 | \node[right of=x3, xshift=-5mm] {$\dots$}; 22 | 23 | \node[block, right of=x0, minimum height=1em, minimum width=15mm, xshift=10cm] (h){$h_N[k]$}; 24 | \node[left of=h, xshift=15mm] {$*$}; 25 | 26 | % convolved segments 27 | \node[block, minimum height=1em, minimum width=40mm, anchor=west](y0) at ($(x0.west) - (0, 1.5)$) {$y_0[k] = x_0[k] * h_N[k]$}; 28 | \node[block, minimum height=1em, minimum width=40mm, anchor=west](y1) at ($(x1.west) - (0, 2.75)$) {$y_1[k] = x_1[k] * h_N[k]$}; 29 | \node[block, minimum height=1em, minimum width=40mm, anchor=west](y2) at ($(x2.west) - (0, 4)$) {$y_2[k] = x_2[k] * h_N[k]$}; 30 | \node[block, minimum height=1em, minimum width=40mm, anchor=west](y3) at ($(x3.west) - (0, 5.25)$) {$y_3[k] = x_3[k] * h_N[k]$}; 31 | % output 32 | \node[block, minimum height=1em, minimum width=100mm, anchor=west](y) at ($(x0.west) - (0, 7)$) {$y[k]$}; 33 | \node[right of=y, xshift=35mm] {$\dots$}; 34 | 35 | % segment borders 36 | \begin{pgfonlayer}{background} 37 | \draw[dashed] (x1.west) -- ($(x1.west) - (0, 7)$); 38 | \draw[dashed] (x2.west) -- ($(x2.west) - (0, 7)$); 39 | \draw[dashed] (x3.west) -- ($(x3.west) - (0, 7)$); 40 | \draw[dashed] (x3.east) -- ($(x3.east) - (0, 7)$); 41 | 42 | \draw[dashed] (y0.east) -- ($(y0.east) - (0, 1.25)$); 43 | \draw[dashed] (y1.east) -- ($(y1.east) - (0, 1.25)$); 44 | \draw[dashed] (y2.east) -- ($(y2.east) - (0, 1.25)$); 45 | \end{pgfonlayer} 46 | 47 | % sums 48 | \node at ($(y0.east) - (7mm, 6mm)$) {\bf $+$}; 49 | \node at ($(y1.east) - (7mm, 6mm)$) {\bf $+$}; 50 | \node at ($(y2.east) - (7mm, 6mm)$) {\bf $+$}; 51 | 52 | % sizes 53 | \draw ($(x0.north west) + (0,.1) $) -- ($(x0.north west) + (0,.4) $); 54 | \draw ($(x0.north east) + (0,.1) $) -- ($(x0.north east) + (0,.4) $); 55 | \draw[<->] ($(x0.north west) + (0,.3) $) -- ($(x0.north east) + (0,.3) $) node[midway]{$P$}; 56 | 57 | \draw ($(h.north west) + (0,.1) $) -- ($(h.north west) + (0,.4) $); 58 | \draw ($(h.north east) + (0,.1) $) -- ($(h.north east) + (0,.4) $); 59 | \draw[<->] ($(h.north west) + (0,.3) $) -- ($(h.north east) + (0,.3) $) node[midway]{$N$}; 60 | 61 | \draw ($(y0.north west) + (0,.1) $) -- ($(y0.north west) + (0,.4) $); 62 | \draw ($(y0.north east) + (0,.1) $) -- ($(y0.north east) + (0,.4) $); 63 | \draw[<->] ($(y0.north west) + (0,.3) $) -- ($(y0.north east) + (0,.3) $) node[midway]{$P + N - 1$}; 64 | 65 | \end{tikzpicture} 66 | 67 | 68 | 69 | % overlap-save convolution 70 | \pgfdeclarelayer{background} 71 | \pgfsetlayers{background,main} 72 | 73 | \begin{tikzpicture}[auto, node distance=25mm] 74 | 75 | % input 76 | \node[block, minimum height=1em, minimum width=100mm](x) {$x[k]$}; 77 | \node[block, minimum height=5mm, minimum width=15mm, anchor=east](x00) at (x.west) {$0 {\color{gray!20} [}$}; 78 | \node[right of=x, xshift=35mm] {$\dots$}; 79 | 80 | % input segments 81 | \node[block, minimum height=1em, minimum width=40mm, anchor=west](x0) at ($(x00.west) - (0, 1.5)$) {$x_0[k]$}; 82 | \node[block, minimum height=1em, minimum width=40mm, anchor=west, xshift=-15mm](x1) at ($(x0.east) - (0, 1.5)$) {$x_1[k]$}; 83 | \node[block, minimum height=1em, minimum width=40mm, anchor=west, xshift=-15mm](x2) at ($(x1.east) - (0, 1.5)$) {$x_2[k]$}; 84 | \node[block, minimum height=1em, minimum width=40mm, anchor=west, xshift=-15mm](x3) at ($(x2.east) - (0, 1.5)$) {$x_3[k]$}; 85 | 86 | % convolved segments 87 | \node[block, minimum height=1em, minimum width=40mm, anchor=west](yc0) at ($(x0.west) - (0, 0.6)$) {$\qquad \qquad x_0[k] \circledast h_N[k]$}; 88 | \node[block, minimum height=1em, minimum width=40mm, anchor=west](yc1) at ($(x1.west) - (0, 0.6)$) {$\qquad \qquad x_1[k] \circledast h_N[k]$}; 89 | \node[block, minimum height=1em, minimum width=40mm, anchor=west](yc2) at ($(x2.west) - (0, 0.6)$) {$\qquad \qquad x_2[k] \circledast h_N[k]$}; 90 | \node[block, minimum height=1em, minimum width=40mm, anchor=west](yc3) at ($(x3.west) - (0, 0.6)$) {$\qquad \qquad x_3[k] \circledast h_N[k]$}; 91 | 92 | \draw[draw=gray!100, opacity=0.5] (yc0.north west) -- ($(yc0.south west) + (1.5, 0)$); 93 | \draw[draw=gray!100, opacity=0.5] (yc0.south west) -- ($(yc0.north west) + (1.5, 0)$); 94 | \draw[draw=gray!100, opacity=0.5] ($(yc0.north west) + (1.5, 0)$) -- ($(yc0.south west) + (1.5, 0)$); 95 | 96 | \draw[draw=gray!100, opacity=0.5] (yc1.north west) -- ($(yc1.south west) + (1.5, 0)$); 97 | \draw[draw=gray!100, opacity=0.5] (yc1.south west) -- ($(yc1.north west) + (1.5, 0)$); 98 | \draw[draw=gray!100, opacity=0.5] ($(yc1.north west) + (1.5, 0)$) -- ($(yc1.south west) + (1.5, 0)$); 99 | 100 | \draw[draw=gray!100, opacity=0.5] (yc2.north west) -- ($(yc2.south west) + (1.5, 0)$); 101 | \draw[draw=gray!100, opacity=0.5] (yc2.south west) -- ($(yc2.north west) + (1.5, 0)$); 102 | \draw[draw=gray!100, opacity=0.5] ($(yc2.north west) + (1.5, 0)$) -- ($(yc2.south west) + (1.5, 0)$); 103 | 104 | \draw[draw=gray!100, opacity=0.5] (yc3.north west) -- ($(yc3.south west) + (1.5, 0)$); 105 | \draw[draw=gray!100, opacity=0.5] (yc3.south west) -- ($(yc3.north west) + (1.5, 0)$); 106 | \draw[draw=gray!100, opacity=0.5] ($(yc3.north west) + (1.5, 0)$) -- ($(yc3.south west) + (1.5, 0)$); 107 | 108 | 109 | % output segments 110 | \node[block, minimum height=1em, minimum width=25mm, anchor=west](y0) at ($(x.west) - (0, 8)$) {$y_0[k]$}; 111 | \node[block, right of=y0, minimum height=1em, minimum width=25mm] (y1){$y_1[k]$}; 112 | \node[block, right of=y1, minimum height=1em, minimum width=25mm] (y2){$y_2[k]$}; 113 | \node[block, right of=y2, minimum height=1em, minimum width=25mm] (y3){$y_3[k]$}; 114 | \node[right of=y3, xshift=-5mm] {$\dots$}; 115 | 116 | % segment borders 117 | \begin{pgfonlayer}{background} 118 | \draw[dashed] (x.south west) -- (y0.north west); 119 | \draw[dashed] (x0.south east) -- (y1.north west); 120 | \draw[dashed] (x1.south east) -- (y2.north west); 121 | \draw[dashed] (x2.south east) -- (y3.north west); 122 | \draw[dashed] (x3.south east) -- (y3.north east); 123 | \end{pgfonlayer} 124 | 125 | % sizes 126 | \draw ($(x0.north west) + (0,.1) $) -- ($(x0.north west) + (0,.4) $); 127 | \draw ($(x0.north east) + (0,.1) $) -- ($(x0.north east) + (0,.4) $); 128 | \draw[<->] ($(x0.north west) + (0,.3) $) -- ($(x0.north east) + (0,.3) $) node[midway]{$P$}; 129 | 130 | \draw ($(yc0.south west) + (0,-.1) $) -- ($(yc0.south west) + (0,-.4) $); 131 | \draw[<->] ($(yc0.south west) + (0,-.3) $) -- ($(yc0.south west) + (1.5,-.3) $) node[midway, below]{$N-1$}; 132 | 133 | 134 | \end{tikzpicture} 135 | 136 | 137 | % model for round-off error 138 | \begin{tikzpicture}[auto, node distance=2cm] 139 | \node [input, name=input] {}; 140 | \node [sum,right of=input, xshift=1cm] (mul){$\times$}; 141 | \node [sum,right of=mul, xshift=1cm] (sum){$+$}; 142 | \node [input, below of=sum,yshift=1cm] (error) {}; 143 | \node [input, above of=mul,yshift=-1cm] (coeff) {}; 144 | \node [output, right of=sum,xshift=0cm] (output) {}; 145 | 146 | \draw [-latex] (input) node[left]{$x_Q[k]$} -- (mul); 147 | \draw [-latex] (mul) -- (sum); 148 | \draw [-latex] (sum) -- (output) node[right]{$y_Q[k]$}; 149 | \draw [-latex] (error) node[below]{$e[k]$} -- (sum); 150 | \draw [-latex] (coeff) node[above]{$a_Q$} -- (mul); 151 | 152 | \draw [dashed] (.5,-1.6) rectangle (5.5,0.7); 153 | 154 | \end{tikzpicture} 155 | 156 | 157 | 158 | \end{document} -------------------------------------------------------------------------------- /images/prefix.tex: -------------------------------------------------------------------------------- 1 | \documentclass[tikz, convert={density=3000, outext=.png}]{standalone} 2 | %\documentclass[convert={density=3000, outext=.png}, multi=true]{standalone} 3 | 4 | % ===== packages ===== 5 | \usepackage{amsmath} 6 | \usepackage{amssymb} 7 | \usepackage{ss2-figures} 8 | 9 | % ===== environment for non-tikz pages ===== 10 | \newenvironment{image}{\ignorespaces}{\unskip} 11 | \standaloneenv{image} -------------------------------------------------------------------------------- /images/quantization.tex: -------------------------------------------------------------------------------- 1 | \input{prefix} 2 | 3 | % ============================================================================= 4 | % ============================================================================= 5 | \begin{document} 6 | 7 | 8 | % ============================================================================= 9 | % model of quantization process 10 | \begin{tikzpicture}[auto, node distance=2cm] 11 | \node [input, name=input] {}; 12 | \node [sum,right of=input, xshift=1cm] (sum){$+$}; 13 | \node [input, below of=sum,yshift=1cm] (error) {}; 14 | \node [output, right of=sum,xshift=0cm] (output) {}; 15 | 16 | \draw [-latex] (input) node[left]{$x[k]$} -- (sum); 17 | \draw [-latex] (sum) -- (output) node[right]{$x_Q[k]$}; 18 | \draw [-latex] (error) node[below]{$e[k]$} -- (sum); 19 | 20 | \draw [dashed] (.5,-1.6) rectangle (3.5,0.5); 21 | 22 | \end{tikzpicture} 23 | 24 | 25 | % ============================================================================= 26 | % linear uniform mid-tread quantizer characteristic 27 | \pgfplotsset{axis style={ 28 | mathaxis, 29 | ytick={1,2,3,4}, 30 | yticklabels={\tiny $Q$}, 31 | xtick={-4,0.5,4}, 32 | xticklabels={\tiny $x_\text{min}$, \tiny $\frac{Q}{2}$,\tiny $x_\text{max}$}, 33 | xlabel=$x$, 34 | }} 35 | 36 | \begin{tikzpicture} 37 | 38 | \begin{axis}[ylabel={$x_Q$}] 39 | \addplot[blue,thick] plot coordinates{(-6,-4) (-3.5,-4) (-3.5,-3) (-2.5,-3) (-2.5,-2) (-1.5,-2) (-1.5,-1) (-.5,-1) (-.5,0) (.5,0) (.5,1) (1.5,1) (1.5,2) (2.5,2) (2.5,3) (3.5,3) (3.5,4) (6,4) }; 40 | \addplot[red,dashed,domain=-5:5,samples=50] { x }; 41 | \end{axis}; 42 | 43 | \end{tikzpicture} 44 | 45 | 46 | % ============================================================================= 47 | % linear uniform mid-rise quantizer characteristic 48 | \pgfplotsset{axis style={ 49 | mathaxis, 50 | ytick={.5,1.5,2.5,3.5}, 51 | yticklabels={\tiny $\frac{Q}{2}$}, 52 | xtick={-4,1,4}, 53 | xticklabels={\tiny $x_\text{min}$, \tiny $Q$,\tiny $x_\text{max}$}, 54 | xlabel=$x$, 55 | }} 56 | 57 | \begin{tikzpicture} 58 | 59 | \begin{axis}[ylabel={$x_Q$}] 60 | \addplot[blue,thick] plot coordinates{(-6,-3.5) (-4,-3.5) (-3,-3.5) (-3,-2.5) (-2,-2.5) (-2,-1.5) (-1,-1.5) (-1,-.5) (0,-0.5) (0,0.5) (1,0.5) (1,1.5) (2,1.5) (2,2.5) (3,2.5) (3,3.5) (4,3.5) (6,3.5) }; 61 | \addplot[red,dashed,domain=-5:5,samples=50] { x }; 62 | \end{axis}; 63 | 64 | \end{tikzpicture} 65 | 66 | 67 | % ============================================================================= 68 | % block diagram of noise-shaping 69 | \begin{tikzpicture}[auto, node distance=2cm] 70 | \node [input, name=input] {}; 71 | \node [sum,right of=input, xshift=0cm] (sum){$+$}; 72 | \node [block, right of=sum, xshift=2cm](quantizer){\Large $\mathcal{Q}$}; 73 | \node [output, right of=quantizer,xshift=1cm] (output) {}; 74 | \node [sum, below of=quantizer,yshift=-.7cm] (sum2) {$+$}; 75 | \coordinate [left=1cm of quantizer] (abzweigL); 76 | \coordinate [right=1cm of quantizer] (abzweigR); 77 | \node [block, below of=sum2, xshift=-2cm, yshift=0cm](filter){\Large $h[k]$}; 78 | 79 | \draw [-latex] (input) node[left]{$x[k]$} -- (sum); 80 | \draw [-latex] (sum) -- (quantizer); 81 | \draw [-latex] (quantizer) -- (output) node[right]{$x_Q[k]$}; 82 | \draw[-latex] (abzweigL) |- (sum2); 83 | \draw[-latex] (abzweigR) |- (sum2); 84 | \draw[-latex] (sum2) |- (filter); 85 | \draw[-latex] (filter.west) -| (sum.south); 86 | \node at ($(sum2.center)+(-.7,.2)$) {$-$}; 87 | \node at ($(sum2.center)+(.3,-.7)$) {$e[k]$}; 88 | \node at ($(sum.center)+(-.2,-.7)$) {$-$}; 89 | 90 | \end{tikzpicture} 91 | 92 | 93 | % ============================================================================= 94 | % block diagram of ideal sampling and quantization w/o anti-aliasing filter 95 | \begin{tikzpicture}[auto, node distance=2cm] 96 | \node [input, name=input] {}; 97 | \node [sum, right of=input, xshift=1cm](sampling){$\times$}; 98 | \node [block, right of=sampling, xshift=1cm](quantizer){\Large $\mathcal{Q}$}; 99 | \node [output, right of=quantizer,xshift=0cm] (output) {}; 100 | \node [input, below of=sampling,yshift=1cm] (dirac) {}; 101 | 102 | \draw [-latex] (input) node[left]{$x(t)$} -- (sampling); 103 | \draw [-latex] (sampling) -- (quantizer); 104 | \draw [-latex] (quantizer) -- (output) node[right]{$x_Q[k]$}; 105 | \draw [-latex] (dirac) node[below]{$\frac{1}{T} \sha\left(\frac{t}{T}\right)$} -- (sampling); 106 | \node at ($(sampling.center)+(.7,.25)$) {$x[k]$}; 107 | 108 | \end{tikzpicture} 109 | 110 | 111 | % ============================================================================= 112 | % block diagram of oversampling w/o anti-aliasing filter 113 | \begin{tikzpicture}[auto, node distance=2cm] 114 | \node [input, name=input] {}; 115 | \node [sum, right of=input, xshift=1cm](sampling){$\times$}; 116 | \node [block, right of=sampling, xshift=1cm](quantizer){\Large $\mathcal{Q}$}; 117 | \node [block, right of=quantizer, xshift=1cm](dlowpass){\Large $H_\text{LP}(e^{j \Omega})$}; 118 | \node [block, right of=dlowpass, xshift=1cm](subsampling){\Large $\downarrow L$}; 119 | 120 | \node [output, right of=subsampling,xshift=0cm] (output) {}; 121 | \node [input, below of=sampling,yshift=1cm] (dirac) {}; 122 | 123 | \draw [-latex] (input) node[left]{$x(t)$} -- (sampling); 124 | \draw [-latex] (sampling) -- (quantizer); 125 | \draw [-latex] (quantizer) -- (dlowpass); 126 | \draw [-latex] (dlowpass) -- (subsampling); 127 | \draw [-latex] (subsampling) -- (output) node[right]{$x_Q[k]$}; 128 | \draw [-latex] (dirac) node[below]{$\frac{1}{T} \sha\left(\frac{t}{T}\right)$} -- (sampling); 129 | \node at ($(sampling.center)+(.7,.25)$) {$x[k]$}; 130 | 131 | \end{tikzpicture} 132 | 133 | 134 | % ============================================================================= 135 | % block diagram of oversampling 136 | \begin{tikzpicture}[auto, node distance=2cm] 137 | \node [input, name=input] {}; 138 | \node [block, right of=input, xshift=0cm](lowpass){\Large $H_\text{LP}(\omega)$}; 139 | \node [sum, right of=lowpass, xshift=2cm](sampling){$\times$}; 140 | \node [block, right of=sampling, xshift=1cm](quantizer){\Large $\mathcal{Q}$}; 141 | \node [block, right of=quantizer, xshift=1cm](dlowpass){\Large $H_\text{LP}(e^{j \Omega})$}; 142 | \node [block, right of=dlowpass, xshift=1cm](subsampling){\Large $\downarrow L$}; 143 | 144 | \node [output, right of=subsampling,xshift=0cm] (output) {}; 145 | \node [input, below of=sampling,yshift=1cm] (dirac) {}; 146 | 147 | \draw [-latex] (input) node[left]{$x(t)$} -- (lowpass); 148 | \draw [-latex] (lowpass) -- (sampling); 149 | \draw [-latex] (sampling) -- (quantizer); 150 | \draw [-latex] (quantizer) -- (dlowpass); 151 | \draw [-latex] (dlowpass) -- (subsampling); 152 | \draw [-latex] (subsampling) -- (output) node[right]{$x_Q[k]$}; 153 | \draw [-latex] (dirac) node[below]{$\frac{1}{T} \sha\left(\frac{t}{T}\right)$} -- (sampling); 154 | \node at ($(sampling.center)+(.7,.25)$) {$x[k]$}; 155 | 156 | \end{tikzpicture} 157 | 158 | 159 | 160 | 161 | 162 | 163 | \end{document} -------------------------------------------------------------------------------- /images/random_signals.tex: -------------------------------------------------------------------------------- 1 | \input{prefix} 2 | 3 | % ============================================================================= 4 | % ============================================================================= 5 | \begin{document} 6 | 7 | % Measurement of physical quantities 8 | \begin{tikzpicture}[auto, node distance=3cm] 9 | \node [input, name=input] {}; 10 | \node [sum,right of=input,xshift=1cm] (sum1){$+$}; 11 | \node [block, right of=sum1,yshift=0cm] (system1){\Large $\mathcal{H}$}; 12 | \node [output, right of=system1,xshift=0cm] (output) {}; 13 | \node [input, below of=sum1,yshift=2cm] (noise) {}; 14 | 15 | \draw [-latex] (input) node[left]{\shortstack{physical \\ quantity}} -- (sum1); 16 | \draw [-latex] (sum1) -- (system1); 17 | \draw [-latex] (system1) -- (output) node[right]{sensor data}; 18 | \draw [-latex] (noise) node[below]{noise} -- (sum1); 19 | \end{tikzpicture} 20 | 21 | % Communication channel 22 | \begin{tikzpicture}[auto, node distance=3cm] 23 | \node [input, name=input] {}; 24 | \node [block, right of=input,yshift=0cm] (system1){\Large $\mathcal{H}$}; 25 | \node [sum,right of=system1,xshift=1cm] (sum1){$+$}; 26 | \node [output, right of=system1,xshift=0cm] (output) {}; 27 | \node [input, below of=sum1,yshift=2cm] (noise) {}; 28 | 29 | \draw [-latex] (input) node[left]{message} -- (system1); 30 | \draw [-latex] (system1) -- (sum1); 31 | \draw [-latex] (sum1) -- (output) node[right]{\shortstack{received\\message}}; 32 | \draw [-latex] (noise) node[below]{noise} -- (sum1); 33 | \end{tikzpicture} 34 | 35 | 36 | \end{document} -------------------------------------------------------------------------------- /images/recursive_filters.tex: -------------------------------------------------------------------------------- 1 | \input{prefix} 2 | 3 | % ============================================================================= 4 | % ============================================================================= 5 | \begin{document} 6 | 7 | 8 | 9 | 10 | % direct form I 11 | \begin{tikzpicture}[auto, node distance=25mm] 12 | % blocks 1st level 13 | \node[input] (in){}; 14 | \node[sum, right of=in, xshift=10mm, label={$b_0$}](b0){$\times$}; 15 | \node[sum, right of=b0, xshift=10mm](s0){$+$}; 16 | \node[sum, right of=s0, xshift=5mm](s0r){$+$}; 17 | \node[output, right of=s0r, xshift=15mm] (out){}; 18 | \node at ($(b0.west)-(1, 0)$) (c0){}; 19 | \node at ($(out)-(.8, 0)$) (c0r){}; 20 | 21 | % blocks 2nd level 22 | \node[block, below of=c0, minimum width=5mm, minimum height=7mm, yshift=15mm](d0){$z^{-1}$}; 23 | \node[sum, below of=b0, yshift=-10mm, label={$b_1$}](b1){$\times$}; 24 | \node[sum, below of=s0, yshift=-10mm](s1){$+$}; 25 | \node[sum, below of=s0r, yshift=-10mm](s1r){$+$}; 26 | \node[sum, right of=s1r, xshift=10mm, label={$- a_1$}](a1){$\times$}; 27 | \node[block, below of=c0r, minimum width=5mm, minimum height=7mm, yshift=15mm](d0r){$z^{-1}$}; 28 | 29 | % blocks M-th level 30 | \node[block, below of=d0, minimum width=5mm, minimum height=7mm, yshift=-5mm](d1){$z^{-1}$}; 31 | \node[sum, below of=b1, yshift=-20mm, label={$b_M$}](b2){$\times$}; 32 | \node[block, below of=d0r, minimum width=5mm, minimum height=7mm, yshift=-5mm](d1r){$z^{-1}$}; 33 | \node[sum, below of=a1, yshift=-20mm, label={$-a_N$}](a2){$\times$}; 34 | 35 | %lines 36 | \draw[->] (in) node[left]{$x[k]$}--(b0); 37 | \draw[->] (b0)--(s0); 38 | \draw[->] (s0)--(s0r); 39 | \draw[->] (s0r)--(out) node[right]{$y[k]$}; 40 | 41 | \draw[->] (c0.center)--(d0); 42 | \draw[->] (d0) |- (b1); 43 | \draw[->] (b1) -- (s1); 44 | \draw[->] (s1) -- (s0); 45 | \draw[->] (c0r.center) -- (d0r); 46 | \draw[->] (d0r) |- (a1); 47 | \draw[->] (a1) -- (s1r); 48 | \draw[->] (s1r) -- (s0r); 49 | 50 | \draw[->, dashed] (d0)--(d1); 51 | \draw[->] (d1) |- (b2); 52 | \draw[->, dashed] (b2) -| (s1); 53 | \draw (b2) -| ($(s1)-(0,1.5)$); 54 | 55 | \draw[->, dashed] (d0r)--(d1r); 56 | \draw[->] (d1r) |- (a2); 57 | \draw[->, dashed] (a2) -| (s1r); 58 | \draw (a2) -| ($(s1r)-(0,1.5)$); 59 | 60 | % delayed signals 61 | \node[below of=in, yshift=5mm, xshift=-2mm] {\tiny $x[k-1]$}; 62 | \node[below of=in, yshift=-25mm, xshift=-1mm] {\tiny $x[k-M]$}; 63 | \node[below of=out, yshift=5mm, xshift=2mm] {\tiny $y[k-1]$}; 64 | \node[below of=out, yshift=-25mm, xshift=1mm] {\tiny $y[k-N]$}; 65 | 66 | \node[right of=s0, yshift=-3mm, xshift=-18mm] {$w[k]$}; 67 | 68 | \node[below of=b1, yshift=15mm]{\large $\vdots$}; 69 | \node[below of=a1, yshift=15mm]{\large $\vdots$}; 70 | 71 | \end{tikzpicture} 72 | 73 | 74 | % direct form II 75 | \begin{tikzpicture}[auto, node distance=25mm] 76 | 77 | % blocks 1st level 78 | \node[input] (in){}; 79 | \node[sum, right of=in, xshift=0mm](s0r){$+$}; 80 | \node[sum, right of=s0r, xshift=50mm, label={$b_0$}](b0){$\times$}; 81 | \node[sum, right of=b0, xshift=5mm](s0){$+$}; 82 | \node[output, right of=s0, xshift=-15mm] (out){}; 83 | \node at ($(s0r.center)+(3.7, 0)$) (c0){}; 84 | \node[above of=c0, yshift=-20mm](w){$w[k]$}; 85 | 86 | % blocks 2nd level 87 | \node[block, below of=c0, minimum width=5mm, minimum height=7mm, yshift=15mm](d0){$z^{-1}$}; 88 | \node[sum, below of=b0, yshift=-10mm, label={$b_1$}](b1){$\times$}; 89 | \node[sum, below of=s0, yshift=-10mm](s1){$+$}; 90 | \node[sum, below of=s0r, yshift=-10mm](s1r){$+$}; 91 | \node[sum, right of=s1r, xshift=5mm, label={$- a_1$}](a1){$\times$}; 92 | 93 | % blocks M-th level 94 | \node[block, below of=d0, minimum width=5mm, minimum height=7mm, yshift=-5mm](d1){$z^{-1}$}; 95 | \node[sum, below of=b1, yshift=-20mm, label={$b_M$}](b2){$\times$}; 96 | \node[sum, below of=a1, yshift=-20mm, label={$-a_N$}](a2){$\times$}; 97 | 98 | 99 | 100 | %lines 101 | \draw[->] (in) node[left]{$x[k]$}--(s0r); 102 | \draw[->] (s0r)--(b0); 103 | \draw[->] (b0)--(s0); 104 | \draw[->] (s0)--(out) node[right]{$y[k]$}; 105 | 106 | \draw[->] (c0.center)--(d0); 107 | \draw[->] (d0) |- (b1); 108 | \draw[->] (b1) -- (s1); 109 | \draw[->] (s1) -- (s0); 110 | \draw[->] (d0) |- (a1); 111 | \draw[->] (a1) -- (s1r); 112 | \draw[->] (s1r) -- (s0r); 113 | 114 | \draw[->, dashed] (d0)--(d1); 115 | \draw[->] (d1) |- (b2); 116 | \draw[->] (d1) |- (a2); 117 | 118 | \draw[->, dashed] (a2) -| (s1r); 119 | \draw[->, dashed] (b2) -| (s1); 120 | \draw (a2) -| ($(s1r)-(0,1.5)$); 121 | \draw (b2) -| ($(s1)-(0,1.5)$); 122 | 123 | \node[below of=b1, yshift=15mm]{\large $\vdots$}; 124 | \node[below of=a1, yshift=15mm]{\large $\vdots$}; 125 | 126 | 127 | \end{tikzpicture} 128 | 129 | 130 | % direct form II transposed 131 | \begin{tikzpicture}[auto, node distance=25mm] 132 | 133 | % blocks 1st level 134 | \node[input] (in){}; 135 | \node[right of=in, xshift=-10mm](c0){}; 136 | \node[sum, right of=c0, xshift=5mm, label={$b_0$}](b0){$\times$}; 137 | \node[sum, right of=b0, xshift=10mm](s0){$+$}; 138 | \node[right of=s0, xshift=10mm](c1){}; 139 | \node[output, right of=c1, xshift=-15mm] (out){}; 140 | 141 | %\node at ($(s0r.center)+(3.7, 0)$) (c0){}; 142 | 143 | % blocks 2nd level 144 | \node[block, below of=s0, minimum width=5mm, minimum height=7mm, yshift=10mm](d0){$z^{-1}$}; 145 | \node[sum, below of=b0, yshift=-20mm, label={$b_1$}](b1){$\times$}; 146 | \node[sum, below of=d0, yshift=-5mm](s1){$+$}; 147 | \node[sum, right of=s1, xshift=10mm, label={$- a_1$}](a1){$\times$}; 148 | 149 | % blocks M-th level 150 | \node[block, below of=d0, minimum width=5mm, minimum height=7mm, yshift=-10mm](d1){$z^{-1}$}; 151 | \node[sum, below of=d1, yshift=-5mm](s2){$+$}; 152 | \node[sum, below of=b1, yshift=-25mm, label={$b_M$}](b2){$\times$}; 153 | \node[sum, below of=a1, yshift=-25mm, label={$-a_N$}](a2){$\times$}; 154 | 155 | 156 | 157 | %lines 158 | \draw[->] (in) node[left]{$x[k]$}--(b0); 159 | \draw[->] (b0)--(s0); 160 | \draw[->] (s0)--(out) node[right]{$y[k]$}; 161 | 162 | \draw[->] (c0.center) |- (b1); 163 | \draw[->] (b1) -- (s1); 164 | \draw[->] (s1) -- (d0) node[midway, right]{$w_1[k]$}; 165 | \draw[->] (d0) -- (s0); 166 | \draw[->] (c1.center) |- (a1); 167 | \draw[->] (a1) -- (s1); 168 | 169 | \draw[->, dashed] (c0)|-(b2); 170 | \draw[->] (b2) -- (s2); 171 | \draw[->] (s2) -- (d1) node[midway, right]{$w_N[k]$}; 172 | \draw[->, dashed] (d1) -- (s1); 173 | 174 | \draw[->, dashed] (c1)|-(a2); 175 | \draw[->] (a2) -- (s2); 176 | 177 | \draw ($(c0)-(0,4.5)$) |- (b2); 178 | \draw (a2) -| ($(c1)-(0,4.5)$); 179 | 180 | \node[below of=b1, yshift=15mm]{\large $\vdots$}; 181 | \node[below of=a1, yshift=15mm]{\large $\vdots$}; 182 | 183 | 184 | \end{tikzpicture} 185 | 186 | 187 | % coupled form 188 | \begin{tikzpicture}[auto, node distance=25mm] 189 | 190 | % blocks 1st level 191 | \node[input] (in){}; 192 | \node[sum, right of=in, xshift=0mm](s0){$+$}; 193 | \node[block, right of=s0, minimum width=5mm, minimum height=7mm, xshift=-5mm](d0){$z^{-1}$}; 194 | \node[right of=d0, xshift=-12mm](c0){}; 195 | \node[sum, right of=c1, xshift=-40mm, label={$\Im\{ z_\infty \}$}](a0){$\times$}; 196 | \node[sum, right of=a0, xshift=5mm](s1){$+$}; 197 | \node[right of=s1, xshift=5mm](c1){}; 198 | \node[output, right of=c1, xshift=-15mm] (out){}; 199 | 200 | % blocks 2nd level 201 | \node[sum, below of=d0, yshift=-10mm, label={$\Re\{ z_\infty \}$}](a1){$\times$}; 202 | \node[sum, below of=s0, yshift=-10mm](s2){$+$}; 203 | \node[block, below of=c1, minimum width=5mm, minimum height=7mm, yshift=15mm](d1){$z^{-1}$}; 204 | \node[sum, left of=d1, yshift=-10mm, xshift=-7mm, label={$\Re\{ z_\infty \}$}](a2){$\times$}; 205 | 206 | % feedback 207 | \node[sum, below of=a0, yshift=-25mm, label={$- \Im\{ z_\infty \}$}](a3){$\times$}; 208 | 209 | % lines 210 | \draw[->] (in) node[left]{$x[k]$}--(s0); 211 | \draw[->] (s0) -- (d0) node[midway, above]{$w[k]$}; 212 | \draw[->] (d0) -- (a0); 213 | \draw[->] (a0) -- (s1); 214 | \draw[->] (s1) --(out) node[right]{$y[k]$}; 215 | 216 | \draw[->] (c0.center) |- (a1); 217 | \draw[->] (a1) -- (s2); 218 | \draw[->] (s2) -- (s0); 219 | \draw[->] (c1.center) -- (d1); 220 | \draw[->] (d1) |- (a2); 221 | \draw[->] (a2) -| (s1); 222 | 223 | \draw[->] (d1) |- (a3); 224 | \draw[->] (a3) -| (s2); 225 | 226 | \end{tikzpicture} 227 | 228 | 229 | 230 | 231 | \end{document} -------------------------------------------------------------------------------- /images/spectral_analysis.tex: -------------------------------------------------------------------------------- 1 | \input{prefix} 2 | 3 | % ============================================================================= 4 | % ============================================================================= 5 | \begin{document} 6 | 7 | 8 | % links between Fourier transforms 9 | \begin{tikzpicture}[auto, node distance=4cm] 10 | \node (cont) {$x(t)$}; 11 | \node [right of=cont] (F) {$X(j \omega)$}; 12 | \draw [o-*] (cont)--(F) node[midway, above]{$\mathcal{F}$}; 13 | 14 | \node [below of=cont, yshift=2.2cm] (samp) {$x[k]$}; 15 | \node [right of=samp] (DTFT) {$X(e^{j \Omega})$}; 16 | \draw [o-*] (samp)--(DTFT) node[midway, above]{$\mathcal{F}_*$}; 17 | \draw [->] (cont)--(samp) node[midway, left]{\shortstack[r]{sampling\\$x[k] = x(k T)$}}; 18 | 19 | \node [below of=samp, yshift=2.2cm] (wind) {$x_N[k]$}; 20 | \node [right of=wind] (DTFTN) {$X_N(e^{j \Omega})$}; 21 | \draw [o-*] (wind)--(DTFTN) node[midway, above]{$\mathcal{F}_*$}; 22 | \draw [->] (samp)--(wind) node[midway, left]{\shortstack[r]{windowing\\$x_N[k] = x[k] \cdot w[k]$}};; 23 | 24 | \node [below of=wind, yshift=2.2cm] (disc) {$x_N[k]$}; 25 | \node [right of=disc] (DFT) {$X_N[\mu]$}; 26 | \draw [o-*] (disc)--(DFT) node[midway, above]{$\text{DFT}_N$}; 27 | \draw [->] (DTFTN)--(DFT) node[midway, right]{\shortstack[l]{sampling\\$X_N[\mu] = X_N(e^{j \frac{2 \pi}{N} \mu})$}}; 28 | 29 | \end{tikzpicture} 30 | 31 | 32 | \end{document} 33 | -------------------------------------------------------------------------------- /images/ss2-figures.sty: -------------------------------------------------------------------------------- 1 | % TikZ-Einstellungen etc. für die Vorlesung Signale und Systeme 2 2 | 3 | \usepackage{tikz} 4 | \usepackage{pgfplots} 5 | \pgfplotsset{compat=newest} 6 | \usepackage{circuitikz} 7 | 8 | \usetikzlibrary{shapes} 9 | \usetikzlibrary{positioning} 10 | %\usetikzlibrary{snakes} 11 | \usetikzlibrary{decorations} 12 | \usetikzlibrary{decorations.pathreplacing} 13 | \usetikzlibrary{arrows} 14 | \usetikzlibrary{patterns} 15 | 16 | % ===== tikzstyles for block diagrams, etc. ===== 17 | \tikzstyle{block} = [draw, fill=gray!20, rectangle, minimum height=3em, minimum width=6em] 18 | \tikzstyle{sum} = [draw, fill=gray!20, circle, node distance=1cm] 19 | \tikzstyle{mul} = [draw, fill=gray!20, circle, node distance=1cm] 20 | \tikzstyle{input} = [coordinate] 21 | \tikzstyle{output} = [coordinate] 22 | \tikzset{>=latex} % arrow heads 23 | %\tikzset{>=stealth} % arrow heads 24 | 25 | \tikzstyle{every node}=[font=\small] 26 | 27 | \pgfkeys{% 28 | /pgfplots/axis style/.code={% 29 | \pgfkeysalso{/pgfplots/every axis/.append style={#1}}}, 30 | } 31 | 32 | \pgfplotsset{ 33 | mathaxis/.style={ 34 | axis lines=center, 35 | xtick=\empty, 36 | ytick=\empty, 37 | xlabel style=below, 38 | ylabel style=left, 39 | % Make sure the origin is shown (http://tex.stackexchange.com/a/91253) 40 | before end axis/.code={ 41 | \addplot [draw=none, forget plot] coordinates {(0,0)}; 42 | }, 43 | anchor=origin, 44 | }, 45 | stemaxis/.style={ 46 | mathaxis, 47 | x=.8em, 48 | y=6ex, 49 | enlarge x limits={abs=1.2em}, 50 | enlarge y limits={abs=1.2em}, 51 | } 52 | } 53 | 54 | % bei den einzelnen Achsen: \begin{axis}[...] 55 | 56 | %scale=.35, 57 | %x post scale=.5, 58 | %y post scale=1.3, 59 | %xlabel style=right, 60 | %xlabel style={xshift=1ex}, 61 | 62 | \tikzstyle{stem}=[ycomb,mark=*,mark size=2\pgflinewidth,color=blue,thick] 63 | 64 | % vim:filetype=tex 65 | 66 | \newcommand{\sha}{\bot \!\! \bot \!\! \bot} -------------------------------------------------------------------------------- /images/systems.tex: -------------------------------------------------------------------------------- 1 | \input{prefix} 2 | 3 | % ============================================================================= 4 | % ============================================================================= 5 | \begin{document} 6 | 7 | % generic system 8 | \begin{tikzpicture}[auto, node distance=3cm] 9 | \node [input, name=input] {}; 10 | \node [block, right of=input,yshift=0cm] (system){\Large $\mathcal{H}$}; 11 | \node [output, right of=system,xshift=0cm] (output) {}; 12 | 13 | \draw [-latex] (input) node[left]{$x[k]$} -- (system); 14 | \draw [-latex] (system) -- (output) node[right]{$y[k]$}; 15 | \end{tikzpicture} 16 | 17 | % LTI with impulse response 18 | \begin{tikzpicture}[auto, node distance=3cm] 19 | \node [input, name=input] {}; 20 | \node [block, right of=input,yshift=0cm] (system){\Large $h[k]$}; 21 | \node [output, right of=system,xshift=0cm] (output) {}; 22 | 23 | \draw [-latex] (input) node[left]{$x[k]$} -- (system); 24 | \draw [-latex] (system) -- (output) node[right]{$y[k]$}; 25 | \end{tikzpicture} 26 | 27 | % system for ARMA models 28 | \begin{tikzpicture}[auto, node distance=3cm] 29 | \node [input, name=input] {}; 30 | \node [block, right of=input,yshift=0cm] (system){\Large $H(e^{j \Omega})$}; 31 | \node [output, right of=system,xshift=0cm] (output) {}; 32 | 33 | \draw [-latex] (input) node[left]{$n[k]$} -- (system); 34 | \draw [-latex] (system) -- (output) node[right]{$x[k]$}; 35 | \end{tikzpicture} 36 | 37 | % inverse system for AR models 38 | \begin{tikzpicture}[auto, node distance=3cm] 39 | \node [input, name=input] {}; 40 | \node [block, right of=input,yshift=0cm] (system){\Large $G(e^{j \Omega})$}; 41 | \node [output, right of=system,xshift=0cm] (output) {}; 42 | 43 | \draw [-latex] (input) node[left]{$x[k]$} -- (system); 44 | \draw [-latex] (system) -- (output) node[right]{$e[k]$}; 45 | \end{tikzpicture} 46 | 47 | \end{document} -------------------------------------------------------------------------------- /images/wiener_filter.tex: -------------------------------------------------------------------------------- 1 | \input{prefix} 2 | 3 | % ============================================================================= 4 | % ============================================================================= 5 | \begin{document} 6 | 7 | % Signal model for Wiener filter 8 | \begin{tikzpicture}[auto, node distance=2cm] 9 | \node [input, name=input] {}; 10 | \node [block, right of=input,yshift=0cm] (system){\Large $G(e^{j \Omega})$}; 11 | \node [sum,right of=system, xshift=1cm] (sum){$+$}; 12 | \node [input, below of=sum,yshift=1cm] (noise) {}; 13 | \node [input, right of=sum, xshift=-1cm] (observation1) {}; 14 | \node [input, right of=observation1, xshift=-1.2cm] (observation) {}; 15 | \node [block, right of=observation,yshift=0cm] (filter){\Large $H(e^{j \Omega})$}; 16 | \node [output, right of=filter,xshift=0cm] (output) {}; 17 | 18 | \draw [-latex] (input) node[left]{$s[k]$} -- (system); 19 | \draw [-latex] (system) -- (sum); 20 | \draw [-latex] (sum) -- (observation1) node[right]{$x[k]$}; 21 | \draw [-latex] (observation) -- (filter); 22 | \draw [-latex] (filter) -- (output) node[right]{$y[k]$}; 23 | \draw [-latex] (noise) node[below]{$n[k]$} -- (sum); 24 | 25 | \draw [draw, dashed] (5.5, -2.0) -- (5.5, -.55); 26 | \node at (2, -1.8) {Distortion}; 27 | \node at (8, -1.8) {Reconstruction}; 28 | 29 | \end{tikzpicture} 30 | 31 | 32 | \end{document} -------------------------------------------------------------------------------- /index.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "nbsphinx": "hidden" 7 | }, 8 | "source": [ 9 | "# Digital Signal Processing\n", 10 | "\n", 11 | "This collection of [jupyter](https://jupyter.org/) notebooks introduces various topics of [Digital Signal Processing](https://en.wikipedia.org/wiki/Digital_signal_processing). The theory is accompanied by computational examples written in [IPython 3](http://ipython.org/). The notebooks constitute the lecture notes to the masters course Digital Signal Processing read by Sascha Spors, Institute of Communications Engineering, Universität Rostock. The sources of the notebooks, as well as installation and usage instructions can be found on [GitHub](https://github.com/spatialaudio/digital-signal-processing-lecture)." 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": { 17 | "nbsphinx-toctree": { 18 | "maxdepth": 3, 19 | "numbered": true 20 | } 21 | }, 22 | "source": [ 23 | "# 1. Introduction" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": { 29 | "nbsphinx-toctree": { 30 | "maxdepth": 3, 31 | "numbered": true 32 | } 33 | }, 34 | "source": [ 35 | "* [Introduction](introduction/introduction.ipynb)" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "metadata": {}, 41 | "source": [ 42 | "# 2. Spectral Analysis of Deterministic Signals" 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": { 48 | "nbsphinx-toctree": { 49 | "maxdepth": 3, 50 | "numbered": true 51 | } 52 | }, 53 | "source": [ 54 | "* [The Leakage-Effect](spectral_analysis_deterministic_signals/leakage_effect.ipynb)\n", 55 | "* [Window Functions](spectral_analysis_deterministic_signals/window_functions.ipynb)\n", 56 | "* [Zero-Padding](spectral_analysis_deterministic_signals/zero_padding.ipynb)\n", 57 | "* [Short-Time Fourier Transform](spectral_analysis_deterministic_signals/stft.ipynb)\n", 58 | "* [Summary](spectral_analysis_deterministic_signals/summary.ipynb)" 59 | ] 60 | }, 61 | { 62 | "cell_type": "markdown", 63 | "metadata": {}, 64 | "source": [ 65 | "# 3. Random Signals" 66 | ] 67 | }, 68 | { 69 | "cell_type": "markdown", 70 | "metadata": { 71 | "nbsphinx-toctree": { 72 | "maxdepth": 3, 73 | "numbered": true 74 | } 75 | }, 76 | "source": [ 77 | "* [Introduction](random_signals/introduction.ipynb)\n", 78 | "* [Amplitude Distributions](random_signals/distributions.ipynb)\n", 79 | "* [Ensemble Averages](random_signals/ensemble_averages.ipynb)\n", 80 | "* [Stationary and Ergodic Processes](random_signals/stationary_ergodic.ipynb)\n", 81 | "* [Correlation Functions](random_signals/correlation_functions.ipynb)\n", 82 | "* [Power Spectral Densities](random_signals/power_spectral_densities.ipynb)\n", 83 | "* [Independent Processes](random_signals/independent.ipynb)\n", 84 | "* [Important Amplitude Distributions](random_signals/important_distributions.ipynb)\n", 85 | "* [White Noise](random_signals/white_noise.ipynb)\n", 86 | "* [Superposition of Random Signals](random_signals/superposition.ipynb)" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "# 4. Random Signals and LTI Systems" 94 | ] 95 | }, 96 | { 97 | "cell_type": "markdown", 98 | "metadata": { 99 | "nbsphinx-toctree": { 100 | "maxdepth": 3, 101 | "numbered": true 102 | } 103 | }, 104 | "source": [ 105 | "* [Introduction](random_signals_LTI_systems/introduction.ipynb)\n", 106 | "* [Linear Mean](random_signals_LTI_systems/linear_mean.ipynb)\n", 107 | "* [Correlation Functions](random_signals_LTI_systems/correlation_functions.ipynb)\n", 108 | "* [Example: Measurement of Acoustic Impulse Responses](random_signals_LTI_systems/acoustic_impulse_response_measurement.ipynb)\n", 109 | "* [Power Spectral Densities](random_signals_LTI_systems/power_spectral_densities.ipynb)\n", 110 | "* [Wiener Filter](random_signals_LTI_systems/wiener_filter.ipynb)\n", 111 | "* [Linear Prediction](random_signals_LTI_systems/linear_prediction.ipynb)" 112 | ] 113 | }, 114 | { 115 | "cell_type": "markdown", 116 | "metadata": {}, 117 | "source": [ 118 | "# 5. Spectral Estimation for Random Signals" 119 | ] 120 | }, 121 | { 122 | "cell_type": "markdown", 123 | "metadata": { 124 | "nbsphinx-toctree": { 125 | "maxdepth": 3, 126 | "numbered": true 127 | } 128 | }, 129 | "source": [ 130 | "* [Introduction](spectral_estimation_random_signals/introduction.ipynb)\n", 131 | "* [Periodogram](spectral_estimation_random_signals/periodogram.ipynb)\n", 132 | "* [Welch-Method](spectral_estimation_random_signals/welch_method.ipynb)\n", 133 | "* [Parametric Methods](spectral_estimation_random_signals/parametric_methods.ipynb)" 134 | ] 135 | }, 136 | { 137 | "cell_type": "markdown", 138 | "metadata": {}, 139 | "source": [ 140 | "# 6. Quantization" 141 | ] 142 | }, 143 | { 144 | "cell_type": "markdown", 145 | "metadata": { 146 | "nbsphinx-toctree": { 147 | "maxdepth": 3, 148 | "numbered": true 149 | } 150 | }, 151 | "source": [ 152 | "* [Introduction](quantization/introduction.ipynb)\n", 153 | "* [Characteristic of Linear Uniform Quantization](quantization/linear_uniform_characteristic.ipynb)\n", 154 | "* [Quantization Error of Linear Uniform Quantization](quantization/linear_uniform_quantization_error.ipynb)\n", 155 | "* [Example: Requantization of a Speech Signal](quantization/requantization_speech_signal.ipynb)\n", 156 | "* [Noise Shaping](quantization/noise_shaping.ipynb)\n", 157 | "* [Oversampling](quantization/oversampling.ipynb)\n", 158 | "* [Example: Non-Linear Quantization of a Speech Signal](quantization/nonlinear_quantization_speech_signal.ipynb)" 159 | ] 160 | }, 161 | { 162 | "cell_type": "markdown", 163 | "metadata": {}, 164 | "source": [ 165 | "# 7. Realization of Non-Recursive Filters" 166 | ] 167 | }, 168 | { 169 | "cell_type": "markdown", 170 | "metadata": { 171 | "nbsphinx-toctree": { 172 | "maxdepth": 3, 173 | "numbered": true 174 | } 175 | }, 176 | "source": [ 177 | "* [Introduction](nonrecursive_filters/introduction.ipynb)\n", 178 | "* [Fast Convolution](nonrecursive_filters/fast_convolution.ipynb)\n", 179 | "* [Segmented Convolution](nonrecursive_filters/segmented_convolution.ipynb)\n", 180 | "* [Quantization Effects](nonrecursive_filters/quantization_effects.ipynb)" 181 | ] 182 | }, 183 | { 184 | "cell_type": "markdown", 185 | "metadata": {}, 186 | "source": [ 187 | "# 8. Realization of Recursive Filters" 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "metadata": { 193 | "nbsphinx-toctree": { 194 | "maxdepth": 3, 195 | "numbered": true 196 | } 197 | }, 198 | "source": [ 199 | "* [Introduction](recursive_filters/introduction.ipynb)\n", 200 | "* [Direct Form Structures](recursive_filters/direct_forms.ipynb)\n", 201 | "* [Cascaded Structures](recursive_filters/cascaded_structures.ipynb)\n", 202 | "* [Quantization of Filter Coefficients](recursive_filters/quantization_of_coefficients.ipynb)\n", 203 | "* [Quantization of Variables and Operations](recursive_filters/quantization_of_variables.ipynb)" 204 | ] 205 | }, 206 | { 207 | "cell_type": "markdown", 208 | "metadata": {}, 209 | "source": [ 210 | "# 9. Design of Digital Filters" 211 | ] 212 | }, 213 | { 214 | "cell_type": "markdown", 215 | "metadata": { 216 | "nbsphinx-toctree": { 217 | "maxdepth": 3, 218 | "numbered": true 219 | } 220 | }, 221 | "source": [ 222 | "* [Design of Non-Recursive Filters by the Window Method](filter_design/window_method.ipynb)\n", 223 | "* [Design of Non-Recursive Filters by the Frequency Sampling Method](filter_design/frequency_sampling_method.ipynb)\n", 224 | "* [Design of Recursive Filters by the Bilinear Transform](filter_design/bilinear_transform.ipynb)\n", 225 | "* [Example: Non-Recursive versus Recursive Filter](filter_design/comparison_non_recursive.ipynb)\n", 226 | "* [Examples: Typical IIR-Filters in Audio](filter_design/audiofilter.ipynb)" 227 | ] 228 | }, 229 | { 230 | "cell_type": "markdown", 231 | "metadata": { 232 | "nbsphinx": "hidden" 233 | }, 234 | "source": [ 235 | "# Reference Cards\n", 236 | "\n", 237 | "* [Reference Card Discrete Signals and Systems](reference_cards/RC_discrete_signals_and_systems.pdf)\n", 238 | "* [Reference Card Random Signals and LTI Systems](reference_cards/RC_random_signals_and_LTI_systems.pdf)" 239 | ] 240 | }, 241 | { 242 | "cell_type": "markdown", 243 | "metadata": {}, 244 | "source": [ 245 | "# Literature\n", 246 | "\n", 247 | "The contents base on the following literature:\n", 248 | "\n", 249 | "* Alan V. Oppenheim and Ronald W. Schafer, *Discrete-Time Signal Processing*, Pearson Prentice Hall, 2010.\n", 250 | "* John G. Proakis and Dimitris K. Manolakis, *Digital Signal Processing*, Pearson, 2006.\n", 251 | "* Athanasios Papoulis and S. Unnikrishna Pillai, *Probability, Random Variables, and Stochastic Processes*, Mcgraw-Hill, 2002.\n", 252 | "* Petre Stoica and Randolph Moses, *Spectral Analysis of Signals*, Prentice Hall, 2005.\n", 253 | "* Udo Zölzer, *Digitale Audiosignalverarbeitung*, Teubner, 2005.\n", 254 | "* Peter Vary, Ulrich Heute and Wolfgang Hess, *Digitale Sprachsignalverarbeitung*, Teubner, 1998.\n", 255 | "* Bernard Widrow and István Kollár, *Quantization Noise - Roundoff Error in Digital Computation, Signal Processing, Control, and Communications*, Cambridge University Press, 2010.\n", 256 | "* Simon Haykin, *Adaptive Filter Theory*, Pearson Education Limited, 2013.\n", 257 | "* Bernd Girod, Rudolf Rabenstein, Alexander Stenger, *Einführung in die Systemtheorie*, B.G. Teubner Verlag, 2007." 258 | ] 259 | }, 260 | { 261 | "cell_type": "markdown", 262 | "metadata": {}, 263 | "source": [ 264 | "# Contributors\n", 265 | "\n", 266 | "* Sascha Spors (author)\n", 267 | "* Frank Schultz (author, proofreading)\n", 268 | "* Vera Erbes (author, proofreading)\n", 269 | "* Matthias Geier (technical advice, code review, nbsphinx)" 270 | ] 271 | }, 272 | { 273 | "cell_type": "markdown", 274 | "metadata": {}, 275 | "source": [ 276 | "**Copyright**\n", 277 | "\n", 278 | "The notebooks are provided as [Open Educational Resources](https://en.wikipedia.org/wiki/Open_educational_resources). Feel free to use the notebooks for your own purposes. The text is licensed under [Creative Commons Attribution 4.0](https://creativecommons.org/licenses/by/4.0/), the code of the IPython examples under the [MIT license](https://opensource.org/licenses/MIT). Please attribute the work as follows: *Sascha Spors, Digital Signal Processing - Lecture notes featuring computational examples*." 279 | ] 280 | } 281 | ], 282 | "metadata": { 283 | "anaconda-cloud": {}, 284 | "kernelspec": { 285 | "display_name": "Python 3 (ipykernel)", 286 | "language": "python", 287 | "name": "python3" 288 | }, 289 | "language_info": { 290 | "codemirror_mode": { 291 | "name": "ipython", 292 | "version": 3 293 | }, 294 | "file_extension": ".py", 295 | "mimetype": "text/x-python", 296 | "name": "python", 297 | "nbconvert_exporter": "python", 298 | "pygments_lexer": "ipython3", 299 | "version": "3.9.13" 300 | } 301 | }, 302 | "nbformat": 4, 303 | "nbformat_minor": 2 304 | } 305 | -------------------------------------------------------------------------------- /index.rst: -------------------------------------------------------------------------------- 1 | Preface 2 | ======= 3 | 4 | 5 | Introduction 6 | ============ 7 | 8 | .. toctree:: 9 | :maxdepth: 3 10 | 11 | introduction/introduction 12 | 13 | 14 | Spectral Analysis of Deterministic Signals 15 | ========================================== 16 | 17 | .. toctree:: 18 | :maxdepth: 3 19 | 20 | spectral_analysis_deterministic_signals/leakage_effect 21 | spectral_analysis_deterministic_signals/window_functions 22 | spectral_analysis_deterministic_signals/zero_padding 23 | spectral_analysis_deterministic_signals/stft 24 | spectral_analysis_deterministic_signals/summary 25 | 26 | 27 | Random Signals 28 | ============== 29 | 30 | .. toctree:: 31 | :maxdepth: 3 32 | 33 | random_signals/introduction 34 | random_signals/distributions 35 | random_signals/ensemble_averages 36 | random_signals/stationary_ergodic 37 | random_signals/correlation_functions 38 | random_signals/power_spectral_densities 39 | random_signals/independent 40 | random_signals/important_distributions 41 | random_signals/white_noise 42 | random_signals/superposition 43 | 44 | 45 | Random Signals and LTI Systems 46 | ============================== 47 | 48 | .. toctree:: 49 | :maxdepth: 3 50 | 51 | random_signals_LTI_systems/introduction 52 | random_signals_LTI_systems/linear_mean 53 | random_signals_LTI_systems/correlation_functions 54 | random_signals_LTI_systems/acoustic_impulse_response_measurement 55 | random_signals_LTI_systems/power_spectral_densities 56 | random_signals_LTI_systems/wiener_filter 57 | random_signals_LTI_systems/linear_prediction 58 | 59 | 60 | Spectral Estimation for Random Signals 61 | ====================================== 62 | 63 | .. toctree:: 64 | :maxdepth: 3 65 | 66 | spectral_estimation_random_signals/introduction 67 | spectral_estimation_random_signals/periodogram 68 | spectral_estimation_random_signals/welch_method 69 | spectral_estimation_random_signals/parametric_methods 70 | 71 | 72 | Quantization 73 | ============ 74 | 75 | .. toctree:: 76 | :maxdepth: 3 77 | 78 | quantization/introduction.ipynb 79 | quantization/linear_uniform_characteristic 80 | quantization/linear_uniform_quantization_error 81 | quantization/requantization_speech_signal 82 | quantization/noise_shaping 83 | quantization/oversampling 84 | quantization/nonlinear_quantization_speech_signal 85 | 86 | 87 | Realization of Non-Recursive Filters 88 | ==================================== 89 | 90 | .. toctree:: 91 | :maxdepth: 3 92 | 93 | nonrecursive_filters/introduction 94 | nonrecursive_filters/fast_convolution 95 | nonrecursive_filters/segmented_convolution 96 | nonrecursive_filters/quantization_effects 97 | 98 | 99 | Realization of Recursive Filters 100 | ================================ 101 | 102 | .. toctree:: 103 | :maxdepth: 3 104 | 105 | recursive_filters/introduction 106 | recursive_filters/direct_forms 107 | recursive_filters/cascaded_structures 108 | recursive_filters/quantization_of_coefficients 109 | recursive_filters/quantization_of_variables 110 | 111 | 112 | Design of Digital Filters 113 | ========================= 114 | 115 | .. toctree:: 116 | :maxdepth: 3 117 | 118 | filter_design/window_method 119 | filter_design/frequency_sampling_method 120 | filter_design/bilinear_transform 121 | filter_design/comparison_non_recursive 122 | filter_design/audiofilter 123 | -------------------------------------------------------------------------------- /introduction/DSP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/introduction/DSP.png -------------------------------------------------------------------------------- /introduction/analog_discrete_digital.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/introduction/analog_discrete_digital.png -------------------------------------------------------------------------------- /introduction/introduction.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "nbsphinx": "hidden" 7 | }, 8 | "source": [ 9 | "# Introduction\n", 10 | "\n", 11 | "*This jupyter notebook is part of a [collection of notebooks](../index.ipynb) on various topics of Digital Signal Processing. Please direct questions and suggestions to [Sascha.Spors@uni-rostock.de](mailto:Sascha.Spors@uni-rostock.de).*" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "## Digital Signal Processing\n", 19 | "\n", 20 | "A digital signal is a discrete representation of the information conveyed by the signal. The information itself may be discrete by nature, as numbers or letters, or it may be be continuous as most physical quantities. In many cases a digital signal has been derived by [sampling](https://en.wikipedia.org/wiki/Sampling_(signal_processing%29) and [quantization](https://en.wikipedia.org/wiki/Quantization_(signal_processing%29) of an analog signal captured by a sensor from the real world.\n", 21 | "\n", 22 | "![Analog, discrete and digital signal](analog_discrete_digital.png)\n", 23 | "\n", 24 | "The process of sampling and quantization is technically realized by an [analog-to-digital converter](https://en.wikipedia.org/wiki/Analog-to-digital_converter) (ADC). An example for a digital signal is the sound pressure produced by a human speaker picked up by a microphone whose electrical signal is fed into an ADC after amplification.\n", 25 | "\n", 26 | "[Digital Signal Processing](https://en.wikipedia.org/wiki/Digital_signal_processing) (DSP) refers to the digital processing of signals. The field covers the mathematics, algorithms, techniques and hardware to analyze, manipulate and generate digital signals. This may involve linear as well as nonlinear processing which is performed on the signals itself or their representations in other domains. For instance processing in the frequency or spectral domain. The processing is realized either directly in hardware or more common these days by software on general purpose or specialized ([Digital Signal Processor](https://en.wikipedia.org/wiki/Digital_signal_processor)) microprocessors. By use of a [digital-to-analog converter](https://en.wikipedia.org/wiki/Digital-to-analog_converter) (DAC) digital signals may be converted back into the analog domain. For instance to feed a loudspeaker or control a display. A typical signal processing chain is depicted below.\n", 27 | "\n", 28 | "![Digital signal processing chain](DSP.png)\n", 29 | "\n", 30 | "The history of DSP is directly coupled to the spread of microprocessors and computers. While many foundations may be found in the field of numerical mathematics before, specialized theory for the processing of digital signals has emerged in the 1950s. In its early stage, DSP was only applied to a few critical applications due to limited availability and high cost of microprocessors. However, with widespread availability of highly integrated circuits at reasonable prices the usage of DSP techniques has exploded since the 1980s. Nowadays, they can be found in almost any non-commercial and commercial device. Application areas include but are not limited to the processing of audio/image/video signals, communications engineering, radar/sonar/seismics, instrumentation, control systems, simulations and medicine. \n", 31 | "\n", 32 | "A number of benefits make the usage of digital in contrast to analog signal processing very attractive:\n", 33 | "\n", 34 | "* **robustness against external influences**: Analog systems show typically some gradual dependency on environmental conditions. For instance the analog elements of a circuit change their values when the ambient temperature changes. Digital systems generate the same results as long as the logic circuits/microprocessors are used within their technical specifications.\n", 35 | "* **long-term stability**: The elements of analog systems change their values gradually when aging. Digital systems do not show gradual changes until they malfunction. \n", 36 | "* **flexibility of implementations**: DSP implemented by means of software offers a high degree of flexibility which is hard to realize by analog circuits. For instance branching and looping.\n", 37 | "* **extended possibilities**: Besides traditional signal processing techniques (e.g. filtering) the digital processing of signals may involve algorithms from numerical mathematics or machine learning, just to name a few.\n", 38 | "\n", 39 | "In summary, at less technical effort the reproducibility of DSP is higher compared to analog signal processing. DSP system are typically cheaper compared to their analog counterparts. This is due to the tremendous efforts that have been spend in the last decades in the development and production of digital circuits." 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": {}, 45 | "source": [ 46 | "## Exercises and Computational Examples \n", 47 | "\n", 48 | "The theory discussed in this course is accompanied by computational examples and exercises. They aim at improving the understanding and show typical applications. Most of the basis DSP techniques can be implemented quite straightforward in software. Various programming languages and software environments are used for this purpose. Quite common is the use of MATLAB® and Simulink® from [MathWorks®](https://www.mathworks.com), [GNU Octave](https://www.gnu.org/software/octave) and [Python](https://www.python.org/).\n", 49 | "\n", 50 | "Here interactive Python ([IPython](https://ipython.org/)) scripts are used which are directly embedded in [Jupyter](http://jupyter.org/) notebooks. The scripts and their results can be viewed straightforward as static snapshots. However, interactive use is highly recommended. For instance by rerunning the examples after a change of parameters. The exercises point to cases of interest and include also sample solutions. Feel motivated to extend the examples and write your own algorithms. If you are not familiar with IPython and Jupyter please take a look at the various tutorials available, for instance this [video](https://www.youtube.com/watch?v=HW29067qVWk). The examples base on various Python toolboxes/modules for convenience and performance. The basic functionality for most signal processing applications is provided by [`numpy`](http://www.numpy.org/) and [`scipy.signal`](https://docs.scipy.org/doc/scipy/reference/signal.html). For visualization purposes [`matplotlib`](https://matplotlib.org/) is used." 51 | ] 52 | }, 53 | { 54 | "cell_type": "markdown", 55 | "metadata": {}, 56 | "source": [ 57 | "## Contents\n", 58 | "\n", 59 | "An understanding of the underlying mechanisms and the limitations of basic DSP techniques is essential for the design of more complex algorithms. This course covers the fundamentals of DSP. A focus is laid on the discussion of generic building blocks in contrast to more specific complex algorithms. These blocks are addressed by a detailed mathematical treatise as well as practical examples and exercises. The discussion of the mathematical background is important to understand the principles of operation and derive properties in a more general manner. An outlook to practical applications is given whenever possible.\n", 60 | "\n", 61 | "The materials start off with a discussion of the limitations of **spectral analysis of deterministic signals**. These are essentially the limitations of the discrete Fourier transform and play therefore a prominent role in many fields of DSP. Practical signals are often of stochastic nature. The foundations of **random signals and their processing by linear time-invariant systems** is the next topic. It is not sensible to describe random signals by their amplitude values, instead statistical measures are introduced which characterize average properties. The **quantization** of sampled signals is required to derive a digital signal suitable for DSP. In general, quantization is a non-linear process from which the amplitude continuous signal cannot be recovered exactly. In order to quantify the resulting deviations, a statistical analysis of the quantization error is presented for various signal classes. The filtering of signals is a basic task in DSP. The **realization of non-recursive and recursive filters** is therefore discussed in detail. Amongst others this covers practically relevant aspects like computationally efficient algorithms and the effects of quantization. For the **design of digital filters** various techniques are introduced in the last section." 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "metadata": {}, 67 | "source": [ 68 | "## Prerequisites\n", 69 | "\n", 70 | "The materials assume that the reader is already well familiarized with the theory of signals and linear time-invariant systems. In particular\n", 71 | "\n", 72 | "* continuous signals and systems,\n", 73 | "* Fourier and Laplace transform,\n", 74 | "* sampling of signals,\n", 75 | "* discrete signals and systems,\n", 76 | "* discrete-time Fourier transform (DTFT), discrete Fourier transform (DFT) and $z$-transform.\n", 77 | "\n", 78 | "These topics are covered by various textbooks." 79 | ] 80 | }, 81 | { 82 | "cell_type": "markdown", 83 | "metadata": { 84 | "nbsphinx": "hidden" 85 | }, 86 | "source": [ 87 | "**Copyright**\n", 88 | "\n", 89 | "This notebook is provided as [Open Educational Resource](https://en.wikipedia.org/wiki/Open_educational_resources). Feel free to use the notebook for your own purposes. The text is licensed under [Creative Commons Attribution 4.0](https://creativecommons.org/licenses/by/4.0/), the code of the IPython examples under the [MIT license](https://opensource.org/licenses/MIT). Please attribute the work as follows: *Sascha Spors, Digital Signal Processing - Lecture notes featuring computational examples, 2016-2018*." 90 | ] 91 | } 92 | ], 93 | "metadata": { 94 | "kernelspec": { 95 | "display_name": "Python 3 (ipykernel)", 96 | "language": "python", 97 | "name": "python3" 98 | }, 99 | "language_info": { 100 | "codemirror_mode": { 101 | "name": "ipython", 102 | "version": 3 103 | }, 104 | "file_extension": ".py", 105 | "mimetype": "text/x-python", 106 | "name": "python", 107 | "nbconvert_exporter": "python", 108 | "pygments_lexer": "ipython3", 109 | "version": "3.9.13" 110 | } 111 | }, 112 | "nbformat": 4, 113 | "nbformat_minor": 1 114 | } 115 | -------------------------------------------------------------------------------- /ipython_kernel_config.py: -------------------------------------------------------------------------------- 1 | c.InlineBackend.figure_formats = {"svg", "pdf"} 2 | c.InlineBackend.rc = {"figure.dpi": 96} 3 | -------------------------------------------------------------------------------- /nonrecursive_filters/LTI_system_td.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/nonrecursive_filters/LTI_system_td.png -------------------------------------------------------------------------------- /nonrecursive_filters/introduction.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "nbsphinx": "hidden" 7 | }, 8 | "source": [ 9 | "# Realization of Non-Recursive Filters\n", 10 | "\n", 11 | "*This jupyter notebook is part of a [collection of notebooks](../index.ipynb) on various topics of Digital Signal Processing. Please direct questions and suggestions to [Sascha.Spors@uni-rostock.de](mailto:Sascha.Spors@uni-rostock.de).*" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "## Introduction\n", 19 | "\n", 20 | "Computing the output $y[k] = \\mathcal{H} \\{ x[k] \\}$ of a [linear time-invariant](https://en.wikipedia.org/wiki/LTI_system_theory) (LTI) system is of central importance in digital signal processing. This is often referred to as [*filtering*](https://en.wikipedia.org/wiki/Digital_filter) of the input signal $x[k]$. The methods for this purpose are typically classified into\n", 21 | "\n", 22 | "* non-recursive and\n", 23 | "* recursive\n", 24 | "\n", 25 | "techniques. This section focuses on the realization of non-recursive filters." 26 | ] 27 | }, 28 | { 29 | "cell_type": "markdown", 30 | "metadata": {}, 31 | "source": [ 32 | "### Non-Recursive Filters\n", 33 | "\n", 34 | "An LTI system can be characterized completely by its impulse response $h[k]$ \n", 35 | "\n", 36 | "![Linear time-invariant system](LTI_system_td.png)\n", 37 | "\n", 38 | "The output signal $y[k]$ is given by (linear) convolution of the input signal $x[k]$ with the impulse response $h[k]$\n", 39 | "\n", 40 | "\\begin{equation}\n", 41 | "y[k] = x[k] * h[k] = \\sum_{\\kappa = -\\infty}^{\\infty} x[\\kappa] \\; h[k-\\kappa]\n", 42 | "\\end{equation}\n", 43 | "\n", 44 | "Two aspects of this representation become evident when inspecting above equation:\n", 45 | "\n", 46 | "1. The output signal $y[k]$ is a linear combination of the input signal $x[k]$. There is no feedback of the output signal of past time-instants. Therefore, such filters are termed as *non-recursive* filters.\n", 47 | "\n", 48 | "2. In order to compute the output signal at one particular time-instant $k$, the input signal needs to be known for all past and future time-instants.\n", 49 | "\n", 50 | "The second aspect prohibits a practical realization. In order to be able to realize a non-recursive filter by convolution, the output at time-instant $k$ should only depend on the input signal $x[k]$ up to time-index $k$\n", 51 | "\n", 52 | "\\begin{equation}\n", 53 | "y[k] = \\sum_{\\kappa = -\\infty}^{k} x[\\kappa] \\; h[k-\\kappa]\n", 54 | "\\end{equation}\n", 55 | "\n", 56 | "This is the case when the impulse response is causal, hence when $h[k] = 0$ for $k<0$. However, this still requires knowledge of the input signal for all past time-instants. If we further assume that the input signal is causal, $x[k] = 0$ for $k<0$, we get\n", 57 | "\n", 58 | "\\begin{equation}\n", 59 | "y[k] = \\sum_{\\kappa = 0}^{k} x[\\kappa] \\; h[k-\\kappa]\n", 60 | "\\end{equation}" 61 | ] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": {}, 66 | "source": [ 67 | "### Finite Impulse Response\n", 68 | "\n", 69 | "Many practical systems have an impulse response of finite length $N$ or can be approximated by an impulse response of finite length\n", 70 | "\n", 71 | "\\begin{equation}\n", 72 | "h_N[k] = \\begin{cases} h[k] & \\text{ for } 0 \\leq k < N \\\\ 0 & \\text{ otherwise} \\end{cases}\n", 73 | "\\end{equation}\n", 74 | "\n", 75 | "Such an impulse response is denoted as [*finite impulse response*](https://en.wikipedia.org/wiki/Finite_impulse_response) (FIR). Introducing $h_N[k]$ into above sum and rearranging terms yields\n", 76 | "\n", 77 | "\\begin{equation}\n", 78 | "y[k] = \\sum_{\\kappa = 0}^{k} x[\\kappa] \\; h_N[k-\\kappa] = \\sum_{\\kappa = 0}^{N-1} h_N[\\kappa] \\; x[k-\\kappa]\n", 79 | "\\end{equation}\n", 80 | "\n", 81 | "Hence for a causal input signal $x[k]$ and a FIR the output of the system can be computed by a finite number of operations. \n", 82 | "\n", 83 | "The evaluation of the convolution for a FIR of length $N$ requires $N$ multiplications and $N-1$ additions per time index $k$. For the real-time convolution of an audio signal with a sampling rate of $f_\\text{S} = 48$ kHz with a FIR of length $N = 48000$ we have to compute around $2 \\times 2.3 \\cdot 10^9$ numerical operations per second. This is a considerable numerical complexity, especially on embedded or mobile platforms. Therefore, various techniques have been developed to lower the computational complexity." 84 | ] 85 | }, 86 | { 87 | "cell_type": "markdown", 88 | "metadata": { 89 | "nbsphinx": "hidden" 90 | }, 91 | "source": [ 92 | "**Copyright**\n", 93 | "\n", 94 | "This notebook is provided as [Open Educational Resource](https://en.wikipedia.org/wiki/Open_educational_resources). Feel free to use the notebook for your own purposes. The text is licensed under [Creative Commons Attribution 4.0](https://creativecommons.org/licenses/by/4.0/), the code of the IPython examples under the [MIT license](https://opensource.org/licenses/MIT). Please attribute the work as follows: *Sascha Spors, Digital Signal Processing - Lecture notes featuring computational examples*." 95 | ] 96 | } 97 | ], 98 | "metadata": { 99 | "kernelspec": { 100 | "display_name": "Python 3", 101 | "language": "python", 102 | "name": "python3" 103 | }, 104 | "language_info": { 105 | "codemirror_mode": { 106 | "name": "ipython", 107 | "version": 3 108 | }, 109 | "file_extension": ".py", 110 | "mimetype": "text/x-python", 111 | "name": "python", 112 | "nbconvert_exporter": "python", 113 | "pygments_lexer": "ipython3", 114 | "version": "3.7.9" 115 | } 116 | }, 117 | "nbformat": 4, 118 | "nbformat_minor": 1 119 | } 120 | -------------------------------------------------------------------------------- /nonrecursive_filters/overlap_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/nonrecursive_filters/overlap_add.png -------------------------------------------------------------------------------- /nonrecursive_filters/overlap_save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/nonrecursive_filters/overlap_save.png -------------------------------------------------------------------------------- /nonrecursive_filters/roundoff_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/nonrecursive_filters/roundoff_model.png -------------------------------------------------------------------------------- /quantization/analog_discrete_digital.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/analog_discrete_digital.png -------------------------------------------------------------------------------- /quantization/ideal_ADC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/ideal_ADC.png -------------------------------------------------------------------------------- /quantization/ipython_kernel_config.py: -------------------------------------------------------------------------------- 1 | ../ipython_kernel_config.py -------------------------------------------------------------------------------- /quantization/mid_rise_characteristic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/mid_rise_characteristic.png -------------------------------------------------------------------------------- /quantization/mid_tread_characteristic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/mid_tread_characteristic.png -------------------------------------------------------------------------------- /quantization/model_quantization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/model_quantization.png -------------------------------------------------------------------------------- /quantization/noise_shaping.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/noise_shaping.png -------------------------------------------------------------------------------- /quantization/oversampling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/oversampling.png -------------------------------------------------------------------------------- /quantization/oversampling_anti_aliasing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/oversampling_anti_aliasing.png -------------------------------------------------------------------------------- /quantization/speech_2bit.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/speech_2bit.wav -------------------------------------------------------------------------------- /quantization/speech_2bit_error.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/speech_2bit_error.wav -------------------------------------------------------------------------------- /quantization/speech_4bit.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/speech_4bit.wav -------------------------------------------------------------------------------- /quantization/speech_4bit_error.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/speech_4bit_error.wav -------------------------------------------------------------------------------- /quantization/speech_6bit.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/speech_6bit.wav -------------------------------------------------------------------------------- /quantization/speech_6bit_error.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/speech_6bit_error.wav -------------------------------------------------------------------------------- /quantization/speech_8bit.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/speech_8bit.wav -------------------------------------------------------------------------------- /quantization/speech_8bit_error.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/speech_8bit_error.wav -------------------------------------------------------------------------------- /quantization/speech_8k_8bit.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/speech_8k_8bit.wav -------------------------------------------------------------------------------- /quantization/speech_8k_8bit_error.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/speech_8k_8bit_error.wav -------------------------------------------------------------------------------- /quantization/speech_Alaw_8k_8bit.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/speech_Alaw_8k_8bit.wav -------------------------------------------------------------------------------- /quantization/speech_Alaw_8k_8bit_error.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/quantization/speech_Alaw_8k_8bit_error.wav -------------------------------------------------------------------------------- /random_signals/communication_channel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/random_signals/communication_channel.png -------------------------------------------------------------------------------- /random_signals/cosine.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/random_signals/cosine.wav -------------------------------------------------------------------------------- /random_signals/cosine_noise.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/random_signals/cosine_noise.wav -------------------------------------------------------------------------------- /random_signals/ipython_kernel_config.py: -------------------------------------------------------------------------------- 1 | ../ipython_kernel_config.py -------------------------------------------------------------------------------- /random_signals/measurement_channel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/random_signals/measurement_channel.png -------------------------------------------------------------------------------- /random_signals/noise.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/random_signals/noise.wav -------------------------------------------------------------------------------- /random_signals/speech_noise.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/random_signals/speech_noise.wav -------------------------------------------------------------------------------- /random_signals/uniform_white_noise.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/random_signals/uniform_white_noise.wav -------------------------------------------------------------------------------- /random_signals_LTI_systems/LTI_system_td.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/random_signals_LTI_systems/LTI_system_td.png -------------------------------------------------------------------------------- /random_signals_LTI_systems/Wiener_observed_signal.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/random_signals_LTI_systems/Wiener_observed_signal.wav -------------------------------------------------------------------------------- /random_signals_LTI_systems/Wiener_output.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/random_signals_LTI_systems/Wiener_output.wav -------------------------------------------------------------------------------- /random_signals_LTI_systems/acoustic_impulse_response_measurement.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "nbsphinx": "hidden" 7 | }, 8 | "source": [ 9 | "# Random Signals and LTI-Systems\n", 10 | "\n", 11 | "*This jupyter notebook is part of a [collection of notebooks](../index.ipynb) on various topics of Digital Signal Processing. Please direct questions and suggestions to [Sascha.Spors@uni-rostock.de](mailto:Sascha.Spors@uni-rostock.de).*" 12 | ] 13 | }, 14 | { 15 | "cell_type": "markdown", 16 | "metadata": {}, 17 | "source": [ 18 | "## Measurement of Acoustic Impulse Responses\n", 19 | "\n", 20 | "The propagation of sound from one position (e.g. transmitter) to another (e.g. receiver) conforms reasonable well to the properties of a linear time-invariant (LTI) system. Consequently, the impulse response $h[k]$ characterizes the propagation of sound between theses two positions. Impulse responses have various applications in acoustics. For instance as [head-related impulse responses](https://en.wikipedia.org/wiki/Head-related_transfer_function) (HRIRs) or room impulse responses (RIRs) for the characterization of room acoustics. \n", 21 | "\n", 22 | "The following example demonstrates how an acoustic impulse response can be estimated with [correlation-based system identification techniques](correlation_functions.ipynb#System-Identification) using the soundcard of a computer. The module [`sounddevice`](http://python-sounddevice.readthedocs.org/) provides access to the soundcard via [`portaudio`](http://www.portaudio.com/)." 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 1, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "import numpy as np\n", 32 | "import matplotlib.pyplot as plt\n", 33 | "import scipy.signal as sig\n", 34 | "import sounddevice as sd" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "### Generation of the Measurement Signal\n", 42 | "\n", 43 | "We generate white noise with a uniform distribution between $\\pm 0.5$ as the excitation signal $x[k]$" 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": 2, 49 | "metadata": {}, 50 | "outputs": [], 51 | "source": [ 52 | "fs = 44100 # sampling rate\n", 53 | "T = 5 # length of the measurement signal in sec\n", 54 | "Tr = 2 # length of the expected system response in sec\n", 55 | "\n", 56 | "x = np.random.uniform(-0.5, 0.5, size=T * fs)" 57 | ] 58 | }, 59 | { 60 | "cell_type": "markdown", 61 | "metadata": {}, 62 | "source": [ 63 | "### Playback of Measurement Signal and Recording of Room Response\n", 64 | "\n", 65 | "The measurement signal $x[k]$ is played through the output of the soundcard and the response $y[k]$ is captured synchronously by the input of the soundcard. The length of the played/captured signal has to be of equal length when using the soundcard. The measurement signal $x[k]$ is zero-padded so that the captured signal $y[k]$ includes the complete system response.\n", 66 | "\n", 67 | "Be sure not to overdrive the speaker and the microphone by keeping the input level well below 0 dB." 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": 3, 73 | "metadata": {}, 74 | "outputs": [ 75 | { 76 | "name": "stdout", 77 | "output_type": "stream", 78 | "text": [ 79 | "Playback level: -6.02060087394 dB\n", 80 | "Input level: -2.23183822753 dB\n" 81 | ] 82 | } 83 | ], 84 | "source": [ 85 | "x = np.concatenate((x, np.zeros(Tr * fs)))\n", 86 | "y = sd.playrec(x, fs, channels=1)\n", 87 | "sd.wait()\n", 88 | "y = np.squeeze(y)\n", 89 | "\n", 90 | "print(\"Playback level: \", 20 * np.log10(max(x)), \" dB\")\n", 91 | "print(\"Input level: \", 20 * np.log10(max(y)), \" dB\")" 92 | ] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "metadata": {}, 97 | "source": [ 98 | "### Estimation of the Acoustic Impulse Response\n", 99 | "\n", 100 | "The acoustic impulse response is estimated by cross-correlation $\\varphi_{yx}[\\kappa]$ of the output with the input signal. Since the cross-correlation function (CCF) for finite-length signals is given as $\\varphi_{yx}[\\kappa] = \\frac{1}{K} \\cdot y[\\kappa] * x[-\\kappa]$, the computation of the CCF can be speeded up with the fast convolution method." 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": 4, 106 | "metadata": {}, 107 | "outputs": [], 108 | "source": [ 109 | "h = 1 / len(y) * sig.fftconvolve(y, x[::-1], mode=\"full\")\n", 110 | "h = h[fs * (T + Tr) : fs * (T + 2 * Tr)]" 111 | ] 112 | }, 113 | { 114 | "cell_type": "code", 115 | "execution_count": 5, 116 | "metadata": {}, 117 | "outputs": [ 118 | { 119 | "data": { 120 | "image/png": "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\npOz445MAKIXBM7E770wC47hxyS+gSOFaiJL0hz+EAChJ/x19Kv7iF9JHPypdf33u9uvrc0czr10b\n5otdUuf735fWrSv5cDul2D5/7z1phx2S+ebm4vUmT5YWLWp7/QsXSkuXdq2NaNuUKX3nvfv66z3/\neomvSFCr4isldCt379RN0lclmaTTJP1O0q87u642ttFP0jxJu0vqL+lFSXvn1Tlb0vXR9MmS7o6m\n94nq94+Wnxe1t911Rst7rLU1+btxoxc1fXpSr6nJ/cADk/saG91bWtwXLy6+bOyRR9zvvTdMv/CC\n+7XXuq9Ykdzf0uL+3nttr6Ncra3uS5cmbY5t2FBYtn5957YxcmQ4mbZgQW75woXuP/hB0oaVK92b\nm8N9gweH+9N+9Sv3a64J02vWuL/8cnJfc3PYxjPPJGVr15bXvi9/OazrxRfDOuLHOW2a+1tvhW25\nh3bGz3t8gjBNcv/kJ8P0e++FZWPx/mttTZ6HDRsK1xH7wAfcH3ssTC9Z4v6nP4Xnp6UllL35ZnmP\nrVzr17u/9lpo29NPJ4/vkkuSaW7Jba+9wt/3388t33vv3Pn5891/+9vC5d1z5xctcv/HP8J+iMsa\nG90PPjiZ/8Y3kv3v7n7CCaF8333dv/td91/8Iswfemjuvm1tDe+l+fPD/K67ut96a5iePdv9lVeS\nup/7XFjH6tVh/qKLwuv/e98L5a2tyWMePz53O2vX5j6+1tZkPn4P5T9u97CtGTPC6y/2+uvugwaF\nOvFnwiuvhPfCNtvkbnfVqtz5998Pz01XtLS4z5sXHsPKle7r1oXy//gP9wkTcutu2BD+Pv108XWt\nXx/2bTELFrjPmROmzzrL/cILc+9fvNj94x93v/zyMP/226E96e+fGTMKv48k91Gjim+ztdV96FD3\n5cuT59Y9fF499VQy/8Yb7nPnhs+uhQvDduPHW+pzy939Jz9J2vPuu7n3nXFG28vGz8Xy5e6HHx4+\nm4t91i5cmKx79eqwv/K/rzZuDK+j++8v3M64ce5PPBGmP/IR90MOSfaje9jeSy/lLjNxovvo0cn8\nO+8kn4/pz3r38J09a1bY/po14fst3t6MGcVfnxs2uC9bVli+enVu25YsCducPTspW7nS/aqr0u2X\nu3cwZ3WosvSspBuj4Le3pP8j6WJJH5a0VUc3Xsb2PiVpcmp+rKSxeXUmSzokmq6T9E40fYmki/Pq\nHVrOOqPynA+tG290/9KXCj/Uf/7z3Plf/artL5H99gt/GxrC3wEDwt9rr03qXH557jI//an77rsX\nrmv77ZPpj37U/fTTk/nVq91/9KPCZRYtSoKT5P6tb4W/O+3k/qlPJeV//7v7Djsk8/GLd8GC3PUt\nXuy+3Xa5Zffe6z5pUjJ/7LHhgyX+oorLzz47d7mTTkqmX3st/P3xj5OybbfNrf/b34YPz3j+ttvc\n77gjt87ZZ7v/8peFz8NNNxWW/fjH7gcckFt23XXuX/lKYd0RI9xvuMH9iCOK7+c//jGZfvzxZHrm\nzNx9/Y1vhA/4L3wheU2Uul1xRe78Ndck0/ffn7uvxoxx79ev9LoeeqjtbV18cdv3Z/32b/+WO5//\n2ix1i98Hlbql31/l3HbaKXyppstWrAh/hwxJyhobc+s8+aT7s8+G6fQX9llnuV92WW7dm28O4TNd\n9o9/FLblnXcKy15/vXC76X9W0p8zxfbR+PG5ZZtvngTs738/KR850n3YsGT+rruS6QceSKbvv9/9\n299O5j/xifC3f//wGR2/5+6+O3e7P/hB+PvLX4YwXqy9f/pTCEPpEC25n3xy2/tw4MCkHfFtypRk\n+je/CZ9h+a/RPfYo3NbMmcW3sXx58o/OTjuF/flf/1VYL/25Uewz9uabw+M58cTyX6O//rX7Bz9Y\n+vGlX3vDh+eWbdzofsopYTr9unzhhcLHt2xZ+22ZMcN9662T+Z/9rLzHkP58njw5ec/tuWduvfif\nsfjxfehD7v/5n+E7YvTopF5LS+E2wj9j6nAI7NB1As1spKQXJB0WBar9Ja2X9Jykv7r7X8peWXnb\n+5qko9399Gj+mwqB79xUnRlRnSXR/DxJh0hqkDTF3f8Yld8s6ZFosZFtrTMqd5U9DgboWy66SLr6\n6mq3AgBQvsoODJG7T44m749uMrM6SfspnH7tblVOYQ2p6froBvR9HfjfEABQFU3RrfPKHhhiZgcV\nK3f3Fnd/zt0ntFe3ExZLGpaaHyYpv/vxYkm7RtutkzTQ3ZcVWXZotGw564w0pG71HWr4Kad0qDpq\n3HXXdW35zXrZZdnjELj99tVtR1916aXVbkGhyy9vv84jj7RfJ/a5z3W+LUBf8KEPde/6Cq9AUK/c\nnNIJHeifd5mk0WXeLuumPoF1kl5TGMSxuUoPDLkhmh6lwoEhmyv0WXxNYWBIu+tM9wmcPTv0kZkw\n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\n", 121 | "text/plain": [ 122 | "" 123 | ] 124 | }, 125 | "metadata": {}, 126 | "output_type": "display_data" 127 | } 128 | ], 129 | "source": [ 130 | "plt.figure(figsize=(10, 5))\n", 131 | "t = 1 / fs * np.arange(len(h))\n", 132 | "plt.plot(t, h)\n", 133 | "plt.axis([0.0, 1.0, -1.1 * np.max(np.abs(h)), 1.1 * np.max(np.abs(h))])\n", 134 | "plt.xlabel(r\"$t$ in s\")\n", 135 | "plt.ylabel(r\"$\\hat{h}[k]$\")" 136 | ] 137 | }, 138 | { 139 | "cell_type": "markdown", 140 | "metadata": { 141 | "nbsphinx": "hidden" 142 | }, 143 | "source": [ 144 | "**Copyright**\n", 145 | "\n", 146 | "This notebook is provided as [Open Educational Resource](https://en.wikipedia.org/wiki/Open_educational_resources). Feel free to use the notebook for your own purposes. The text is licensed under [Creative Commons Attribution 4.0](https://creativecommons.org/licenses/by/4.0/), the code of the IPython examples under the [MIT license](https://opensource.org/licenses/MIT). Please attribute the work as follows: *Sascha Spors, Digital Signal Processing - Lecture notes featuring computational examples*." 147 | ] 148 | } 149 | ], 150 | "metadata": { 151 | "anaconda-cloud": {}, 152 | "kernelspec": { 153 | "display_name": "Python 3", 154 | "language": "python", 155 | "name": "python3" 156 | }, 157 | "language_info": { 158 | "codemirror_mode": { 159 | "name": "ipython", 160 | "version": 3 161 | }, 162 | "file_extension": ".py", 163 | "mimetype": "text/x-python", 164 | "name": "python", 165 | "nbconvert_exporter": "python", 166 | "pygments_lexer": "ipython3", 167 | "version": "3.7.9" 168 | }, 169 | "nbsphinx": { 170 | "execute": "never" 171 | } 172 | }, 173 | "nbformat": 4, 174 | "nbformat_minor": 1 175 | } 176 | -------------------------------------------------------------------------------- /random_signals_LTI_systems/artificial_vocal.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/random_signals_LTI_systems/artificial_vocal.wav -------------------------------------------------------------------------------- /random_signals_LTI_systems/ipython_kernel_config.py: -------------------------------------------------------------------------------- 1 | ../ipython_kernel_config.py -------------------------------------------------------------------------------- /random_signals_LTI_systems/model_wiener_filter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/random_signals_LTI_systems/model_wiener_filter.png -------------------------------------------------------------------------------- /random_signals_LTI_systems/uniform_pink_noise.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/random_signals_LTI_systems/uniform_pink_noise.wav -------------------------------------------------------------------------------- /random_signals_LTI_systems/uniform_white_noise.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/random_signals_LTI_systems/uniform_white_noise.wav -------------------------------------------------------------------------------- /recursive_filters/coupled_form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/recursive_filters/coupled_form.png -------------------------------------------------------------------------------- /recursive_filters/direct_form_i.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/recursive_filters/direct_form_i.png -------------------------------------------------------------------------------- /recursive_filters/direct_form_ii.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/recursive_filters/direct_form_ii.png -------------------------------------------------------------------------------- /recursive_filters/direct_form_ii_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/recursive_filters/direct_form_ii_t.png -------------------------------------------------------------------------------- /recursive_filters/ipython_kernel_config.py: -------------------------------------------------------------------------------- 1 | ../ipython_kernel_config.py -------------------------------------------------------------------------------- /reference_cards/RC_discrete_signals_and_systems.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/reference_cards/RC_discrete_signals_and_systems.pdf -------------------------------------------------------------------------------- /reference_cards/RC_random_signals_and_LTI_systems.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/reference_cards/RC_random_signals_and_LTI_systems.pdf -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | matplotlib 2 | numpy 3 | scipy 4 | soundfile 5 | sympy 6 | statsmodels 7 | sounddevice 8 | -------------------------------------------------------------------------------- /spectral_analysis_deterministic_signals/Fourier_transforms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/spectral_analysis_deterministic_signals/Fourier_transforms.png -------------------------------------------------------------------------------- /spectral_analysis_deterministic_signals/ipython_kernel_config.py: -------------------------------------------------------------------------------- 1 | ../ipython_kernel_config.py -------------------------------------------------------------------------------- /spectral_estimation_random_signals/analysis_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/spectral_estimation_random_signals/analysis_model.png -------------------------------------------------------------------------------- /spectral_estimation_random_signals/ipython_kernel_config.py: -------------------------------------------------------------------------------- 1 | ../ipython_kernel_config.py -------------------------------------------------------------------------------- /spectral_estimation_random_signals/synthesis_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spatialaudio/digital-signal-processing-lecture/a45a0f45540990df494d7abef733d364d7c2fad9/spectral_estimation_random_signals/synthesis_model.png --------------------------------------------------------------------------------