pyFDN 0.1.0__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyfdn-0.2.0/HISTORY.rst +17 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/MANIFEST.in +1 -1
- {pyfdn-0.1.0 → pyfdn-0.2.0}/PKG-INFO +11 -2
- {pyfdn-0.1.0 → pyfdn-0.2.0}/README.rst +5 -0
- pyfdn-0.2.0/docs/__init__.py +1 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/api_reference.rst +30 -2
- pyfdn-0.2.0/docs/audio_gallery.py +150 -0
- pyfdn-0.2.0/docs/audio_gallery.rst +99 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/conf.py +3 -1
- pyfdn-0.2.0/docs/example_gallery.py +184 -0
- pyfdn-0.2.0/docs/examples_gallery.rst +133 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/index.rst +8 -1
- pyfdn-0.2.0/docs/patch_rst.py +41 -0
- pyfdn-0.2.0/docs/references.py +8 -0
- pyfdn-0.2.0/docs/usage.rst +34 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/pyproject.toml +24 -9
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/__init__.py +26 -5
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/auxiliary/acoustics.py +187 -43
- pyfdn-0.2.0/src/pyFDN/auxiliary/audio.py +83 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/auxiliary/flamo_graph.py +1 -3
- pyfdn-0.2.0/src/pyFDN/auxiliary/marimo_utils.py +48 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/auxiliary/utils.py +23 -0
- pyfdn-0.2.0/src/pyFDN/presets.py +60 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/process.py +24 -16
- pyfdn-0.2.0/src/pyFDN/references.py +105 -0
- pyfdn-0.2.0/src/pyFDN/resources/ATTRIBUTION.md +31 -0
- pyfdn-0.2.0/src/pyFDN/resources/__init__.py +1 -0
- pyfdn-0.2.0/src/pyFDN/resources/audio/drums/drums.wav +0 -0
- {pyfdn-0.1.0/src/pyFDN/audio → pyfdn-0.2.0/src/pyFDN/resources/audio/general}/synth_dry.wav +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/audio/metadata.json +79 -0
- pyfdn-0.2.0/src/pyFDN/resources/audio/rir/s3_r4_o.wav +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/audio/speech/P1_Set1_8.wav +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/audio/speech/P20_Set1_8.wav +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/audio/strings/Kleiderschrank_Taylor_DI.wav +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/audio/strings/Sommerhit2016_Taylor_DI.wav +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/licenses/diff-fdn-colorless-MIT.txt +21 -0
- pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_N16_d1.mat +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_N16_d2.mat +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_N4_d1.mat +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_N4_d2.mat +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_N6_d1.mat +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_N6_d2.mat +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_N8_d1.mat +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_N8_d2.mat +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_init_N16_d1.mat +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_init_N16_d2.mat +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_init_N4_d1.mat +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_init_N4_d2.mat +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_init_N6_d1.mat +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_init_N6_d2.mat +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_init_N8_d1.mat +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_init_N8_d2.mat +0 -0
- pyfdn-0.2.0/src/pyFDN/resources/references.bib +281 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/train/__init__.py +8 -2
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/train/build.py +2 -2
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/train/engine.py +2 -6
- pyfdn-0.2.0/src/pyFDN/translate/dss_to_impz.py +128 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN.egg-info/PKG-INFO +11 -2
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN.egg-info/SOURCES.txt +39 -4
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN.egg-info/requires.txt +3 -1
- pyfdn-0.2.0/tests/test_audio_gallery.py +17 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_auxiliary_acoustics.py +71 -5
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_auxiliary_utils.py +33 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_example_gallery.py +2 -8
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_marimo_examples_run.py +15 -0
- pyfdn-0.2.0/tests/test_packaged_resources.py +94 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_process_extensions.py +56 -1
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_train.py +28 -15
- pyfdn-0.1.0/HISTORY.rst +0 -8
- pyfdn-0.1.0/docs/examples_gallery.rst +0 -131
- pyfdn-0.1.0/docs/usage.rst +0 -17
- pyfdn-0.1.0/src/pyFDN/audio/example_process_fdn_output.wav +0 -0
- pyfdn-0.1.0/src/pyFDN/audio/s3_r4_o.wav +0 -0
- pyfdn-0.1.0/src/pyFDN/auxiliary/audio.py +0 -54
- pyfdn-0.1.0/src/pyFDN/pyFDN.py +0 -1
- pyfdn-0.1.0/src/pyFDN/translate/dss_to_impz.py +0 -48
- {pyfdn-0.1.0 → pyfdn-0.2.0}/AUTHORS.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/CONTRIBUTING.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/LICENSE +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/Makefile +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/authors.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/contributing.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.DFiltMatrix.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.FeedbackDelay.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.FilterMatrix.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.TFMatrix.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.ZFIR.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.ZSOS.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.ZScalar.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.ZTF.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.absorption_filters.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.absorption_to_rt.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.construct_cascaded_paraunitary_matrix.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.construct_velvet_feedback_matrix.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.db_to_lin.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.db_to_sq.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.det_polynomial.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.dss_to_impz.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.dss_to_ss.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.echo_density.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.edc.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.ensure_3d.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.hertz_to_unit.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.interpolate_orthogonal.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.is_almost_zero.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.is_bounding_curve.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.is_orthogonal.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.last_nonzero_indices.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.lin_to_db.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.matrix_convolution.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.matrix_delay_approximation.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.matrix_polyder.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.matrix_polyval.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.matrix_sqrt.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.mgrpdelay.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.ms_to_smp.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.mulaw_decode.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.mulaw_encode.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.negpolyder.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.one_pole_absorption.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.outer_sum_approximation.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.peak_normalize.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.plot_impulse_response_matrix.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.plot_system_matrix.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.pole_boundaries.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.poly_degree.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.polyder_rational.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.polydiag.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.process_fdn.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.random_matrix_shift.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.random_orthogonal.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.rt_to_gain_per_sample.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.rt_to_slope.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.shift_matrix.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.shift_matrix_distribute.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.skew.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.slope_to_rt.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.sq_to_db.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/generated/pyFDN.tiny_rotation_matrix.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/history.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/installation.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/logo/logo_pyFDN_3.png +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/logo/logo_pyFDN_4.png +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/logo/pyfdn_logo_basic.png +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/logo/pyfdn_logo_wave.png +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/make.bat +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/docs/readme.rst +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/setup.cfg +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/setup.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/auxiliary/__init__.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/auxiliary/allpass.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/auxiliary/coupled_rooms.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/auxiliary/delay.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/auxiliary/flamo.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/auxiliary/math.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/auxiliary/plot.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/auxiliary/poles.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/auxiliary/tiny_rotation_matrix.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/dsp/__init__.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/dsp/dfilt_matrix.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/dsp/feedback_delay.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/dsp/sos_filter_bank.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/dsp/time_varying_matrix.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/SDN.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/allpass_FDN/__init__.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/allpass_FDN/allpass_completion.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/allpass_FDN/homogeneous_allpass_fdn.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/allpass_FDN/rand_admissible_homogeneous_allpass.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/allpass_in_fdn.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/anderson_matrix.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/complete_orthogonal.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/construct_cascaded_paraunitary_matrix.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/construct_paraunitary_from_elementals.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/construct_velvet_feedback_matrix.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/degree_one_lossless.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/fdn_matrix_gallery.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/householder_matrix.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/is_almost_zero.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/nearest_orthogonal.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/nearest_sign_agnostic_orthogonal.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/random_matrix_shift.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/random_orthogonal.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/sample_delay_lengths.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/schroeder_reverberator.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/shift_matrix.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/generate/shift_matrix_distribute.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/graphicEQ/__init__.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/graphicEQ/absorption_geq.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/graphicEQ/bandpass_filter.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/graphicEQ/design_geq.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/graphicEQ/graphic_eq.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/graphicEQ/probe_sos.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/graphicEQ/shelving_filter.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/train/objectives.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/translate/dss_to_flamo.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/translate/dss_to_pr.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/translate/dss_to_ss.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/translate/dss_to_tf.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/translate/flamo_to_pr.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/translate/impz_to_res.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/translate/mtf_to_impz.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN/translate/pr_to_impz.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN.egg-info/dependency_links.txt +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/src/pyFDN.egg-info/top_level.txt +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/__init__.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/conftest.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/matloader.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/reference/README.md +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/reference/example_onePoleAbsorption.mat +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/reference/onePoleAbsorption_reference.mat +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_api_reference.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_auxiliary_delay.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_auxiliary_flamo.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_auxiliary_math.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_auxiliary_plot.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_coupled_rooms.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_dss_to_pr.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_flamo_graph.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_flamo_one_pole_absorption.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_flamo_to_pr.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_generate.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_graphic_eq.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_pyFDN.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_sdn.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_time_varying_matrix.py +0 -0
- {pyfdn-0.1.0 → pyfdn-0.2.0}/tests/test_translate.py +0 -0
pyfdn-0.2.0/HISTORY.rst
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
=======
|
|
2
|
+
History
|
|
3
|
+
=======
|
|
4
|
+
|
|
5
|
+
0.2.0 (2026-08-10)
|
|
6
|
+
------------------
|
|
7
|
+
|
|
8
|
+
* Package compact audio examples and predefined colorless-FDN coefficients so
|
|
9
|
+
browser-hosted tutorials work without repository-relative files.
|
|
10
|
+
* Add public APIs for packaged audio, FDN presets, and paper references.
|
|
11
|
+
* Add generated documentation galleries and wheel-content checks.
|
|
12
|
+
* Keep decay-estimation dependencies optional for a smaller core installation.
|
|
13
|
+
|
|
14
|
+
0.1.0 (2025-07-02)
|
|
15
|
+
------------------
|
|
16
|
+
|
|
17
|
+
* First release on PyPI.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyFDN
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Python library for Feedback Delay Networks
|
|
5
5
|
Author: Sebastian J. Schlecht, Facundo Franchino, Jeremy Bai
|
|
6
6
|
Maintainer: Facundo Franchino, Sebastian J. Schlecht
|
|
@@ -16,20 +16,23 @@ Classifier: Programming Language :: Python :: 3.11
|
|
|
16
16
|
Requires-Python: >=3.10
|
|
17
17
|
Description-Content-Type: text/x-rst
|
|
18
18
|
License-File: LICENSE
|
|
19
|
+
License-File: src/pyFDN/resources/ATTRIBUTION.md
|
|
20
|
+
License-File: src/pyFDN/resources/licenses/diff-fdn-colorless-MIT.txt
|
|
19
21
|
Requires-Dist: numpy
|
|
20
22
|
Requires-Dist: soundfile
|
|
21
23
|
Requires-Dist: scipy
|
|
22
24
|
Requires-Dist: flamo>=0.2.14
|
|
23
25
|
Requires-Dist: flareverb
|
|
24
|
-
Requires-Dist: pyroomacoustics
|
|
25
26
|
Provides-Extra: examples
|
|
26
27
|
Requires-Dist: marimo; extra == "examples"
|
|
27
28
|
Requires-Dist: matplotlib>=3.5.0; extra == "examples"
|
|
28
29
|
Requires-Dist: plotly>=5.0.0; extra == "examples"
|
|
30
|
+
Requires-Dist: multislope>=0.1.1; extra == "examples"
|
|
29
31
|
Provides-Extra: test
|
|
30
32
|
Requires-Dist: marimo; extra == "test"
|
|
31
33
|
Requires-Dist: matplotlib>=3.5.0; extra == "test"
|
|
32
34
|
Requires-Dist: plotly>=5.0.0; extra == "test"
|
|
35
|
+
Requires-Dist: multislope>=0.1.1; extra == "test"
|
|
33
36
|
Requires-Dist: pytest>=7.0.0; extra == "test"
|
|
34
37
|
Requires-Dist: pytest-cov>=4.0.0; extra == "test"
|
|
35
38
|
Requires-Dist: coverage>=7.0.0; extra == "test"
|
|
@@ -56,6 +59,7 @@ Requires-Dist: ipykernel>=6.0.0; extra == "docs"
|
|
|
56
59
|
Requires-Dist: pandoc>=2.0; extra == "docs"
|
|
57
60
|
Requires-Dist: plotly>=5.0.0; extra == "docs"
|
|
58
61
|
Requires-Dist: matplotlib>=3.5.0; extra == "docs"
|
|
62
|
+
Requires-Dist: multislope>=0.1.1; extra == "docs"
|
|
59
63
|
Dynamic: license-file
|
|
60
64
|
|
|
61
65
|
=====
|
|
@@ -89,6 +93,11 @@ Overview
|
|
|
89
93
|
|
|
90
94
|
``pyFDN`` provides building blocks for designing, simulating, and analysing Feedback Delay Networks (FDNs). The package focuses on reusable, tested helper functions that simplify typical FDN workflows such as creating orthogonal feedback matrices, designing loop filters, and inspecting pole locations. Using ``flamo`` as a dependency, ``pyFDN`` allows modular design of advanced FDN structure with DSP operations in time and frequency domain.
|
|
91
95
|
|
|
96
|
+
The source code is MIT-licensed. Small packaged tutorial resources retain the
|
|
97
|
+
separate terms recorded in ``src/pyFDN/resources/ATTRIBUTION.md``; in
|
|
98
|
+
particular, the Pori concert-hall impulse response is limited to
|
|
99
|
+
noncommercial use.
|
|
100
|
+
|
|
92
101
|
|
|
93
102
|
Highlights
|
|
94
103
|
----------
|
|
@@ -29,6 +29,11 @@ Overview
|
|
|
29
29
|
|
|
30
30
|
``pyFDN`` provides building blocks for designing, simulating, and analysing Feedback Delay Networks (FDNs). The package focuses on reusable, tested helper functions that simplify typical FDN workflows such as creating orthogonal feedback matrices, designing loop filters, and inspecting pole locations. Using ``flamo`` as a dependency, ``pyFDN`` allows modular design of advanced FDN structure with DSP operations in time and frequency domain.
|
|
31
31
|
|
|
32
|
+
The source code is MIT-licensed. Small packaged tutorial resources retain the
|
|
33
|
+
separate terms recorded in ``src/pyFDN/resources/ATTRIBUTION.md``; in
|
|
34
|
+
particular, the Pori concert-hall impulse response is limited to
|
|
35
|
+
noncommercial use.
|
|
36
|
+
|
|
32
37
|
|
|
33
38
|
Highlights
|
|
34
39
|
----------
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Documentation build helpers; this package is not distributed in the wheel."""
|
|
@@ -93,8 +93,11 @@ Acoustics & Absorption
|
|
|
93
93
|
pyFDN.absorption_to_rt
|
|
94
94
|
pyFDN.estimate_initial_level_bands
|
|
95
95
|
pyFDN.estimate_rt_bands
|
|
96
|
+
pyFDN.octave_bands
|
|
97
|
+
pyFDN.octave_band_filterbank
|
|
96
98
|
pyFDN.rt_to_gain_per_sample
|
|
97
99
|
pyFDN.rt_to_slope
|
|
100
|
+
pyFDN.slope_amplitude_to_level
|
|
98
101
|
pyFDN.slope_to_rt
|
|
99
102
|
|
|
100
103
|
Graphic EQ
|
|
@@ -172,6 +175,7 @@ General Utilities
|
|
|
172
175
|
pyFDN.lin_to_db
|
|
173
176
|
pyFDN.sq_to_db
|
|
174
177
|
pyFDN.ensure_3d
|
|
178
|
+
pyFDN.fade_out
|
|
175
179
|
pyFDN.hertz_to_unit
|
|
176
180
|
pyFDN.hertz_to_rad
|
|
177
181
|
pyFDN.rad_to_hertz
|
|
@@ -181,10 +185,24 @@ General Utilities
|
|
|
181
185
|
pyFDN.mulaw_decode
|
|
182
186
|
pyFDN.mulaw_encode
|
|
183
187
|
pyFDN.peak_normalize
|
|
184
|
-
pyFDN.load_audio
|
|
185
188
|
pyFDN.pole_boundaries
|
|
186
189
|
pyFDN.skew
|
|
187
190
|
|
|
191
|
+
Packaged Examples & References
|
|
192
|
+
------------------------------
|
|
193
|
+
|
|
194
|
+
.. autosummary::
|
|
195
|
+
:toctree: generated/
|
|
196
|
+
:nosignatures:
|
|
197
|
+
|
|
198
|
+
pyFDN.available_audio
|
|
199
|
+
pyFDN.audio_metadata
|
|
200
|
+
pyFDN.load_audio
|
|
201
|
+
pyFDN.available_fdn_presets
|
|
202
|
+
pyFDN.load_fdn_preset
|
|
203
|
+
pyFDN.paper_reference
|
|
204
|
+
pyFDN.paper_link
|
|
205
|
+
|
|
188
206
|
State-Space Translators
|
|
189
207
|
-----------------------
|
|
190
208
|
|
|
@@ -194,6 +212,7 @@ State-Space Translators
|
|
|
194
212
|
|
|
195
213
|
pyFDN.dss_to_ss
|
|
196
214
|
pyFDN.dss_to_impz
|
|
215
|
+
pyFDN.build_to_impz
|
|
197
216
|
pyFDN.dss_to_tf
|
|
198
217
|
pyFDN.dss_to_pr
|
|
199
218
|
pyFDN.dss_to_flamo
|
|
@@ -225,7 +244,7 @@ Training
|
|
|
225
244
|
|
|
226
245
|
pyFDN.build_fdn
|
|
227
246
|
pyFDN.trainable_from_build
|
|
228
|
-
pyFDN.
|
|
247
|
+
pyFDN.build_set_decay
|
|
229
248
|
pyFDN.Trainable
|
|
230
249
|
pyFDN.train_fdn
|
|
231
250
|
pyFDN.TrainLog
|
|
@@ -252,6 +271,15 @@ Plotting
|
|
|
252
271
|
pyFDN.downsample_minmax
|
|
253
272
|
pyFDN.downsample_plotly_trace
|
|
254
273
|
|
|
274
|
+
Notebook Display
|
|
275
|
+
----------------
|
|
276
|
+
|
|
277
|
+
.. autosummary::
|
|
278
|
+
:toctree: generated/
|
|
279
|
+
:nosignatures:
|
|
280
|
+
|
|
281
|
+
pyFDN.labeled_audio
|
|
282
|
+
|
|
255
283
|
FLAMO Graph
|
|
256
284
|
-----------
|
|
257
285
|
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""Generate the audio gallery from the audio files packaged with pyFDN."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import html
|
|
6
|
+
import json
|
|
7
|
+
from collections import defaultdict
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from urllib.parse import quote
|
|
11
|
+
|
|
12
|
+
DOCS_DIR = Path(__file__).resolve().parent
|
|
13
|
+
PROJECT_ROOT = DOCS_DIR.parent
|
|
14
|
+
AUDIO_SOURCE_DIR = PROJECT_ROOT / "src" / "pyFDN" / "resources" / "audio"
|
|
15
|
+
AUDIO_REFERENCES_FILE = AUDIO_SOURCE_DIR / "metadata.json"
|
|
16
|
+
OUTPUT_FILE = DOCS_DIR / "audio_gallery.rst"
|
|
17
|
+
GITHUB_AUDIO_ROOT = (
|
|
18
|
+
"https://raw.githubusercontent.com/artificial-audio/pyFDN/"
|
|
19
|
+
"main/src/pyFDN/resources/audio/"
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
UNCATEGORIZED = "uncategorized"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(frozen=True)
|
|
26
|
+
class AudioExample:
|
|
27
|
+
path: Path
|
|
28
|
+
category: str
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def filename(self) -> str:
|
|
32
|
+
return self.path.name
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def display_label(self) -> str:
|
|
36
|
+
return f"{self.filename}"
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def audio_url(self) -> str:
|
|
40
|
+
relative = self.path.relative_to(AUDIO_SOURCE_DIR)
|
|
41
|
+
return GITHUB_AUDIO_ROOT + quote(relative.as_posix())
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def discover_audio_files() -> list[AudioExample]:
|
|
45
|
+
examples = []
|
|
46
|
+
for path in sorted(AUDIO_SOURCE_DIR.rglob("*.wav")):
|
|
47
|
+
relative = path.relative_to(AUDIO_SOURCE_DIR)
|
|
48
|
+
category = relative.parts[0] if len(relative.parts) > 1 else UNCATEGORIZED
|
|
49
|
+
examples.append(AudioExample(path, category))
|
|
50
|
+
return examples
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def render_gallery(examples: list[AudioExample]) -> str:
|
|
54
|
+
# Load audio metadata
|
|
55
|
+
with open(AUDIO_REFERENCES_FILE, encoding="utf-8") as f:
|
|
56
|
+
audio_references = {item["filename"]: item for item in json.load(f)}
|
|
57
|
+
|
|
58
|
+
grouped: dict[str, list[AudioExample]] = defaultdict(list)
|
|
59
|
+
for example in examples:
|
|
60
|
+
grouped[example.category].append(example)
|
|
61
|
+
|
|
62
|
+
categories = sorted(
|
|
63
|
+
grouped, key=lambda name: (name == UNCATEGORIZED, name.casefold())
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
lines = [
|
|
67
|
+
".. This file is generated by docs/audio_gallery.py. Do not edit it manually.",
|
|
68
|
+
"",
|
|
69
|
+
"============",
|
|
70
|
+
"Audio Gallery",
|
|
71
|
+
"============",
|
|
72
|
+
"",
|
|
73
|
+
"Audio examples demonstrating ``pyFDN``. The gallery is generated",
|
|
74
|
+
"automatically from every packaged ``.wav`` file, grouped by resource category.",
|
|
75
|
+
"",
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
for category in categories:
|
|
79
|
+
entries = sorted(grouped[category], key=lambda item: item.filename.casefold())
|
|
80
|
+
|
|
81
|
+
lines.extend(
|
|
82
|
+
[
|
|
83
|
+
category,
|
|
84
|
+
"-" * len(category),
|
|
85
|
+
"",
|
|
86
|
+
".. raw:: html",
|
|
87
|
+
"",
|
|
88
|
+
]
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
for example in entries:
|
|
92
|
+
label_html = html.escape(example.display_label)
|
|
93
|
+
src = example.audio_url
|
|
94
|
+
|
|
95
|
+
if example.filename in audio_references:
|
|
96
|
+
audio_ref = audio_references[example.filename]
|
|
97
|
+
|
|
98
|
+
title = html.escape(audio_ref["source"])
|
|
99
|
+
url = html.escape(audio_ref["source_url"])
|
|
100
|
+
creator = html.escape(audio_ref["creator"])
|
|
101
|
+
license_name = html.escape(audio_ref["license"])
|
|
102
|
+
license_url = html.escape(audio_ref["license_url"])
|
|
103
|
+
|
|
104
|
+
lines.extend(
|
|
105
|
+
[
|
|
106
|
+
f" <p>{label_html}<br>",
|
|
107
|
+
f' Source: <a href="{url}">{title}</a> — {creator}<br>',
|
|
108
|
+
f' Terms: <a href="{license_url}">{license_name}</a><br>',
|
|
109
|
+
" <audio controls>",
|
|
110
|
+
f' <source src="{src}" type="audio/wav">',
|
|
111
|
+
" Your browser does not support the audio element.",
|
|
112
|
+
" </audio>",
|
|
113
|
+
" </p>",
|
|
114
|
+
]
|
|
115
|
+
)
|
|
116
|
+
else:
|
|
117
|
+
lines.extend(
|
|
118
|
+
[
|
|
119
|
+
f" <p>{label_html}<br>",
|
|
120
|
+
" <audio controls>",
|
|
121
|
+
f' <source src="{src}" type="audio/wav">',
|
|
122
|
+
" Your browser does not support the audio element.",
|
|
123
|
+
" </audio>",
|
|
124
|
+
" </p>",
|
|
125
|
+
]
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
lines.append("")
|
|
129
|
+
|
|
130
|
+
lines.extend(
|
|
131
|
+
[
|
|
132
|
+
"----",
|
|
133
|
+
"",
|
|
134
|
+
"All audio files can also be browsed in the repository's",
|
|
135
|
+
"`packaged audio directory <https://github.com/artificial-audio/pyFDN/tree/main/src/pyFDN/resources/audio>`_.",
|
|
136
|
+
"",
|
|
137
|
+
]
|
|
138
|
+
)
|
|
139
|
+
return "\n".join(lines)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def generate_audio_gallery(output_file: Path = OUTPUT_FILE) -> str:
|
|
143
|
+
examples = discover_audio_files()
|
|
144
|
+
rendered = render_gallery(examples)
|
|
145
|
+
output_file.write_text(rendered, encoding="utf-8")
|
|
146
|
+
return rendered
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
if __name__ == "__main__":
|
|
150
|
+
generate_audio_gallery()
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
.. This file is generated by docs/audio_gallery.py. Do not edit it manually.
|
|
2
|
+
|
|
3
|
+
============
|
|
4
|
+
Audio Gallery
|
|
5
|
+
============
|
|
6
|
+
|
|
7
|
+
Audio examples demonstrating ``pyFDN``. The gallery is generated
|
|
8
|
+
automatically from every packaged ``.wav`` file, grouped by resource category.
|
|
9
|
+
|
|
10
|
+
drums
|
|
11
|
+
-----
|
|
12
|
+
|
|
13
|
+
.. raw:: html
|
|
14
|
+
|
|
15
|
+
<p>drums.wav<br>
|
|
16
|
+
Source: <a href="https://github.com/artificial-audio/pyFDN">Original pyFDN drum example</a> — Sebastian J. Schlecht<br>
|
|
17
|
+
Terms: <a href="https://creativecommons.org/publicdomain/zero/1.0/">CC0-1.0</a><br>
|
|
18
|
+
<audio controls>
|
|
19
|
+
<source src="https://raw.githubusercontent.com/artificial-audio/pyFDN/main/src/pyFDN/resources/audio/drums/drums.wav" type="audio/wav">
|
|
20
|
+
Your browser does not support the audio element.
|
|
21
|
+
</audio>
|
|
22
|
+
</p>
|
|
23
|
+
|
|
24
|
+
general
|
|
25
|
+
-------
|
|
26
|
+
|
|
27
|
+
.. raw:: html
|
|
28
|
+
|
|
29
|
+
<p>synth_dry.wav<br>
|
|
30
|
+
Source: <a href="https://github.com/artificial-audio/pyFDN">Original pyFDN synthesizer example</a> — Sebastian J. Schlecht<br>
|
|
31
|
+
Terms: <a href="https://creativecommons.org/publicdomain/zero/1.0/">CC0-1.0</a><br>
|
|
32
|
+
<audio controls>
|
|
33
|
+
<source src="https://raw.githubusercontent.com/artificial-audio/pyFDN/main/src/pyFDN/resources/audio/general/synth_dry.wav" type="audio/wav">
|
|
34
|
+
Your browser does not support the audio element.
|
|
35
|
+
</audio>
|
|
36
|
+
</p>
|
|
37
|
+
|
|
38
|
+
rir
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
.. raw:: html
|
|
42
|
+
|
|
43
|
+
<p>s3_r4_o.wav<br>
|
|
44
|
+
Source: <a href="http://legacy.spa.aalto.fi/projects/poririrs/">Concert Hall Impulse Responses — Pori, Finland</a> — Juha Merimaa, Timo Peltonen, Tapio Lokki, Helsinki University of Technology, and Akukon Oy<br>
|
|
45
|
+
Terms: <a href="http://legacy.spa.aalto.fi/projects/poririrs/">PORIRIR noncommercial terms</a><br>
|
|
46
|
+
<audio controls>
|
|
47
|
+
<source src="https://raw.githubusercontent.com/artificial-audio/pyFDN/main/src/pyFDN/resources/audio/rir/s3_r4_o.wav" type="audio/wav">
|
|
48
|
+
Your browser does not support the audio element.
|
|
49
|
+
</audio>
|
|
50
|
+
</p>
|
|
51
|
+
|
|
52
|
+
speech
|
|
53
|
+
------
|
|
54
|
+
|
|
55
|
+
.. raw:: html
|
|
56
|
+
|
|
57
|
+
<p>P1_Set1_8.wav<br>
|
|
58
|
+
Source: <a href="https://zenodo.org/records/15034732">Dataset of Audiovisual Speech for AR Telepresence Studies</a> — Nils Meyer-Kahlen, Anja Hofmann, Sebastian J. Schlecht, and Tapio Lokki<br>
|
|
59
|
+
Terms: <a href="https://zenodo.org/records/15034732">Included with creator permission</a><br>
|
|
60
|
+
<audio controls>
|
|
61
|
+
<source src="https://raw.githubusercontent.com/artificial-audio/pyFDN/main/src/pyFDN/resources/audio/speech/P1_Set1_8.wav" type="audio/wav">
|
|
62
|
+
Your browser does not support the audio element.
|
|
63
|
+
</audio>
|
|
64
|
+
</p>
|
|
65
|
+
<p>P20_Set1_8.wav<br>
|
|
66
|
+
Source: <a href="https://zenodo.org/records/15034732">Dataset of Audiovisual Speech for AR Telepresence Studies</a> — Nils Meyer-Kahlen, Anja Hofmann, Sebastian J. Schlecht, and Tapio Lokki<br>
|
|
67
|
+
Terms: <a href="https://zenodo.org/records/15034732">Included with creator permission</a><br>
|
|
68
|
+
<audio controls>
|
|
69
|
+
<source src="https://raw.githubusercontent.com/artificial-audio/pyFDN/main/src/pyFDN/resources/audio/speech/P20_Set1_8.wav" type="audio/wav">
|
|
70
|
+
Your browser does not support the audio element.
|
|
71
|
+
</audio>
|
|
72
|
+
</p>
|
|
73
|
+
|
|
74
|
+
strings
|
|
75
|
+
-------
|
|
76
|
+
|
|
77
|
+
.. raw:: html
|
|
78
|
+
|
|
79
|
+
<p>Kleiderschrank_Taylor_DI.wav<br>
|
|
80
|
+
Source: <a href="https://phaidra.kug.ac.at/detail/o:68022">Gemeinfreie Gitarrenaufnahmen 1</a> — Franz Zotter and Daniel Rudrich<br>
|
|
81
|
+
Terms: <a href="https://creativecommons.org/publicdomain/mark/1.0/">PDM-1.0</a><br>
|
|
82
|
+
<audio controls>
|
|
83
|
+
<source src="https://raw.githubusercontent.com/artificial-audio/pyFDN/main/src/pyFDN/resources/audio/strings/Kleiderschrank_Taylor_DI.wav" type="audio/wav">
|
|
84
|
+
Your browser does not support the audio element.
|
|
85
|
+
</audio>
|
|
86
|
+
</p>
|
|
87
|
+
<p>Sommerhit2016_Taylor_DI.wav<br>
|
|
88
|
+
Source: <a href="https://phaidra.kug.ac.at/detail/o:68022">Gemeinfreie Gitarrenaufnahmen 1</a> — Franz Zotter and Daniel Rudrich<br>
|
|
89
|
+
Terms: <a href="https://creativecommons.org/publicdomain/mark/1.0/">PDM-1.0</a><br>
|
|
90
|
+
<audio controls>
|
|
91
|
+
<source src="https://raw.githubusercontent.com/artificial-audio/pyFDN/main/src/pyFDN/resources/audio/strings/Sommerhit2016_Taylor_DI.wav" type="audio/wav">
|
|
92
|
+
Your browser does not support the audio element.
|
|
93
|
+
</audio>
|
|
94
|
+
</p>
|
|
95
|
+
|
|
96
|
+
----
|
|
97
|
+
|
|
98
|
+
All audio files can also be browsed in the repository's
|
|
99
|
+
`packaged audio directory <https://github.com/artificial-audio/pyFDN/tree/main/src/pyFDN/resources/audio>`_.
|
|
@@ -9,12 +9,14 @@ sys.path.insert(
|
|
|
9
9
|
0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "src"))
|
|
10
10
|
)
|
|
11
11
|
|
|
12
|
+
from audio_gallery import generate_audio_gallery
|
|
12
13
|
from example_gallery import generate_gallery # noqa: E402
|
|
13
14
|
|
|
14
15
|
import pyFDN # noqa: E402
|
|
15
16
|
|
|
16
|
-
# Keep the gallery in sync with every marimo notebook before Sphinx reads it.
|
|
17
|
+
# Keep the gallery in sync with every marimo notebook and audio file before Sphinx reads it.
|
|
17
18
|
generate_gallery()
|
|
19
|
+
generate_audio_gallery()
|
|
18
20
|
|
|
19
21
|
# -- Project information ------------------------------------------------------
|
|
20
22
|
project = "pyFDN"
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"""Generate the examples gallery from the marimo notebooks."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import ast
|
|
6
|
+
import re
|
|
7
|
+
from collections import defaultdict
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
DOCS_DIR = Path(__file__).resolve().parent
|
|
12
|
+
PROJECT_ROOT = DOCS_DIR.parent
|
|
13
|
+
EXAMPLES_DIR = PROJECT_ROOT / "examples"
|
|
14
|
+
OUTPUT_FILE = DOCS_DIR / "examples_gallery.rst"
|
|
15
|
+
|
|
16
|
+
CATEGORY_ORDER = (
|
|
17
|
+
"Getting Started",
|
|
18
|
+
"Absorption & Filters",
|
|
19
|
+
"Translation Examples",
|
|
20
|
+
"Allpass FDN Examples",
|
|
21
|
+
"Special FDNs",
|
|
22
|
+
"FDN Design & Analysis",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass(frozen=True)
|
|
27
|
+
class Example:
|
|
28
|
+
path: Path
|
|
29
|
+
title: str
|
|
30
|
+
description: str
|
|
31
|
+
category: str
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def output_name(self) -> str:
|
|
35
|
+
relative = self.path.relative_to(EXAMPLES_DIR).with_suffix("")
|
|
36
|
+
return "_".join(relative.parts)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _markdown_blocks(path: Path) -> list[str]:
|
|
40
|
+
"""Return literal Markdown strings passed to ``mo.md`` calls."""
|
|
41
|
+
tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path))
|
|
42
|
+
blocks: list[str] = []
|
|
43
|
+
for node in ast.walk(tree):
|
|
44
|
+
if not isinstance(node, ast.Call) or not node.args:
|
|
45
|
+
continue
|
|
46
|
+
if not isinstance(node.func, ast.Attribute) or node.func.attr != "md":
|
|
47
|
+
continue
|
|
48
|
+
value = node.args[0]
|
|
49
|
+
if isinstance(value, ast.Constant) and isinstance(value.value, str):
|
|
50
|
+
blocks.append(value.value.strip())
|
|
51
|
+
return blocks
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _plain_text(markdown: str) -> str:
|
|
55
|
+
text = re.sub(r"\[([^]]+)]\([^)]+\)", r"\1", markdown)
|
|
56
|
+
text = re.sub(r"`+([^`]+?)`+", r"``\1``", text)
|
|
57
|
+
text = re.sub(r"\*\*([^*]+)\*\*", r"\1", text)
|
|
58
|
+
text = re.sub(r"(?<!\*)\*([^*]+)\*(?!\*)", r"\1", text)
|
|
59
|
+
text = re.sub(r"\s+", " ", text)
|
|
60
|
+
return text.strip()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _title_and_description(path: Path) -> tuple[str, str]:
|
|
64
|
+
blocks = _markdown_blocks(path)
|
|
65
|
+
for block in blocks:
|
|
66
|
+
lines = block.splitlines()
|
|
67
|
+
for index, line in enumerate(lines):
|
|
68
|
+
if not line.startswith("# "):
|
|
69
|
+
continue
|
|
70
|
+
title = _plain_text(line[2:])
|
|
71
|
+
paragraphs = "\n".join(lines[index + 1 :]).strip().split("\n\n")
|
|
72
|
+
description = next(
|
|
73
|
+
(
|
|
74
|
+
_plain_text(paragraph)
|
|
75
|
+
for paragraph in paragraphs
|
|
76
|
+
if paragraph.strip() and not paragraph.lstrip().startswith("#")
|
|
77
|
+
),
|
|
78
|
+
"Open the rendered marimo notebook.",
|
|
79
|
+
)
|
|
80
|
+
return title, description
|
|
81
|
+
|
|
82
|
+
fallback = path.stem.removeprefix("example_").replace("_", " ").title()
|
|
83
|
+
return fallback, "Open the rendered marimo notebook."
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _metadata(path: Path) -> dict[str, str]:
|
|
87
|
+
"""Read ``# gallery_<key>: <value>`` comments."""
|
|
88
|
+
metadata: dict[str, str] = {}
|
|
89
|
+
for line in path.read_text(encoding="utf-8").splitlines()[:20]:
|
|
90
|
+
match = re.match(r"# gallery_(\w+):\s*(.+)", line)
|
|
91
|
+
if match:
|
|
92
|
+
metadata[match.group(1)] = match.group(2).strip()
|
|
93
|
+
return metadata
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _required_category(path: Path) -> str:
|
|
97
|
+
metadata = _metadata(path)
|
|
98
|
+
category = metadata.get("category")
|
|
99
|
+
if category:
|
|
100
|
+
return category
|
|
101
|
+
relative = path.relative_to(PROJECT_ROOT)
|
|
102
|
+
raise ValueError(f"{relative} is missing a required '# gallery_category: ...' tag")
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def discover_examples() -> list[Example]:
|
|
106
|
+
examples = []
|
|
107
|
+
for path in sorted(EXAMPLES_DIR.rglob("example_*.py")):
|
|
108
|
+
title, description = _title_and_description(path)
|
|
109
|
+
examples.append(
|
|
110
|
+
Example(
|
|
111
|
+
path,
|
|
112
|
+
title,
|
|
113
|
+
description,
|
|
114
|
+
_required_category(path),
|
|
115
|
+
)
|
|
116
|
+
)
|
|
117
|
+
return examples
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def render_gallery(examples: list[Example]) -> str:
|
|
121
|
+
grouped: dict[str, list[Example]] = defaultdict(list)
|
|
122
|
+
for example in examples:
|
|
123
|
+
grouped[example.category].append(example)
|
|
124
|
+
|
|
125
|
+
categories = list(CATEGORY_ORDER)
|
|
126
|
+
categories.extend(sorted(set(grouped) - set(categories)))
|
|
127
|
+
|
|
128
|
+
lines = [
|
|
129
|
+
".. This file is generated by docs/example_gallery.py. Do not edit it manually.",
|
|
130
|
+
"",
|
|
131
|
+
"================",
|
|
132
|
+
"Examples Gallery",
|
|
133
|
+
"================",
|
|
134
|
+
"",
|
|
135
|
+
"Rendered Marimo notebooks demonstrating ``pyFDN``. The gallery is generated",
|
|
136
|
+
"automatically from every ``example_*.py`` file under ``examples/``.",
|
|
137
|
+
"",
|
|
138
|
+
]
|
|
139
|
+
|
|
140
|
+
for category in categories:
|
|
141
|
+
entries = grouped.get(category, [])
|
|
142
|
+
if not entries:
|
|
143
|
+
continue
|
|
144
|
+
lines.extend(
|
|
145
|
+
[
|
|
146
|
+
category,
|
|
147
|
+
"-" * len(category),
|
|
148
|
+
"",
|
|
149
|
+
".. list-table::",
|
|
150
|
+
" :widths: 35 65",
|
|
151
|
+
" :header-rows: 0",
|
|
152
|
+
"",
|
|
153
|
+
]
|
|
154
|
+
)
|
|
155
|
+
for example in sorted(entries, key=lambda item: item.title.casefold()):
|
|
156
|
+
url = f"_static/marimo/notebooks/{example.output_name}.html"
|
|
157
|
+
lines.extend(
|
|
158
|
+
[
|
|
159
|
+
f" * - `{example.title} <{url}>`_",
|
|
160
|
+
f" - {example.description}",
|
|
161
|
+
]
|
|
162
|
+
)
|
|
163
|
+
lines.append("")
|
|
164
|
+
|
|
165
|
+
lines.extend(
|
|
166
|
+
[
|
|
167
|
+
"----",
|
|
168
|
+
"",
|
|
169
|
+
"All notebooks can also be browsed in the repository's",
|
|
170
|
+
"`examples directory <https://github.com/artificial-audio/pyFDN/tree/main/examples>`_.",
|
|
171
|
+
"",
|
|
172
|
+
]
|
|
173
|
+
)
|
|
174
|
+
return "\n".join(lines)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def generate_gallery(output_file: Path = OUTPUT_FILE) -> str:
|
|
178
|
+
rendered = render_gallery(discover_examples())
|
|
179
|
+
output_file.write_text(rendered, encoding="utf-8")
|
|
180
|
+
return rendered
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
if __name__ == "__main__":
|
|
184
|
+
generate_gallery()
|