pyFDN 0.2.0__tar.gz → 0.4.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.
Files changed (272) hide show
  1. pyfdn-0.4.0/AUTHORS.rst +17 -0
  2. {pyfdn-0.2.0 → pyfdn-0.4.0}/CONTRIBUTING.rst +29 -2
  3. pyfdn-0.4.0/HISTORY.rst +91 -0
  4. {pyfdn-0.2.0 → pyfdn-0.4.0}/PKG-INFO +20 -2
  5. {pyfdn-0.2.0 → pyfdn-0.4.0}/README.rst +12 -0
  6. pyfdn-0.4.0/docs/Makefile +39 -0
  7. {pyfdn-0.2.0 → pyfdn-0.4.0}/docs/api_reference.rst +96 -14
  8. {pyfdn-0.2.0 → pyfdn-0.4.0}/docs/audio_gallery.py +2 -2
  9. {pyfdn-0.2.0 → pyfdn-0.4.0}/docs/conf.py +50 -4
  10. {pyfdn-0.2.0 → pyfdn-0.4.0}/docs/example_gallery.py +14 -23
  11. {pyfdn-0.2.0 → pyfdn-0.4.0}/docs/index.rst +1 -0
  12. pyfdn-0.4.0/docs/patch_rst.py +35 -0
  13. pyfdn-0.4.0/docs/training_losses.rst +99 -0
  14. {pyfdn-0.2.0 → pyfdn-0.4.0}/docs/usage.rst +5 -0
  15. {pyfdn-0.2.0 → pyfdn-0.4.0}/pyproject.toml +10 -4
  16. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/__init__.py +114 -27
  17. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/auxiliary/__init__.py +2 -2
  18. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/auxiliary/acoustics.py +8 -209
  19. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/auxiliary/coupled_rooms.py +5 -5
  20. pyfdn-0.4.0/src/pyFDN/auxiliary/flamo.py +1103 -0
  21. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/auxiliary/flamo_graph.py +59 -24
  22. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/auxiliary/marimo_utils.py +25 -2
  23. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/auxiliary/plot.py +47 -34
  24. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/auxiliary/utils.py +1 -1
  25. pyfdn-0.4.0/src/pyFDN/build_io.py +176 -0
  26. pyfdn-0.4.0/src/pyFDN/eq/__init__.py +45 -0
  27. pyfdn-0.4.0/src/pyFDN/eq/_backend.py +34 -0
  28. {pyfdn-0.2.0/src/pyFDN/graphicEQ → pyfdn-0.4.0/src/pyFDN/eq}/absorption_geq.py +13 -15
  29. pyfdn-0.4.0/src/pyFDN/eq/bandpass_filter.py +42 -0
  30. pyfdn-0.4.0/src/pyFDN/eq/design_geq.py +175 -0
  31. pyfdn-0.4.0/src/pyFDN/eq/designs.py +177 -0
  32. pyfdn-0.4.0/src/pyFDN/eq/first_order.py +168 -0
  33. {pyfdn-0.2.0/src/pyFDN/graphicEQ → pyfdn-0.4.0/src/pyFDN/eq}/graphic_eq.py +26 -17
  34. pyfdn-0.4.0/src/pyFDN/eq/one_pole.py +76 -0
  35. pyfdn-0.4.0/src/pyFDN/eq/shelving_filter.py +64 -0
  36. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/allpass_FDN/allpass_completion.py +3 -1
  37. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/allpass_FDN/homogeneous_allpass_fdn.py +9 -10
  38. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/fdn_matrix_gallery.py +66 -27
  39. pyfdn-0.4.0/src/pyFDN/presets.py +50 -0
  40. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/process.py +7 -6
  41. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/resources/ATTRIBUTION.md +2 -1
  42. pyfdn-0.4.0/src/pyFDN/resources/presets/colorless_FDN/colorless_N16_d1.json +396 -0
  43. pyfdn-0.4.0/src/pyFDN/resources/presets/colorless_FDN/colorless_N16_d2.json +396 -0
  44. pyfdn-0.4.0/src/pyFDN/resources/presets/colorless_FDN/colorless_N4_d1.json +72 -0
  45. pyfdn-0.4.0/src/pyFDN/resources/presets/colorless_FDN/colorless_N4_d2.json +72 -0
  46. pyfdn-0.4.0/src/pyFDN/resources/presets/colorless_FDN/colorless_N6_d1.json +106 -0
  47. pyfdn-0.4.0/src/pyFDN/resources/presets/colorless_FDN/colorless_N6_d2.json +106 -0
  48. pyfdn-0.4.0/src/pyFDN/resources/presets/colorless_FDN/colorless_N8_d1.json +148 -0
  49. pyfdn-0.4.0/src/pyFDN/resources/presets/colorless_FDN/colorless_N8_d2.json +148 -0
  50. pyfdn-0.4.0/src/pyFDN/resources/presets/colorless_FDN/colorless_init_N16_d1.json +396 -0
  51. pyfdn-0.4.0/src/pyFDN/resources/presets/colorless_FDN/colorless_init_N16_d2.json +396 -0
  52. pyfdn-0.4.0/src/pyFDN/resources/presets/colorless_FDN/colorless_init_N4_d1.json +72 -0
  53. pyfdn-0.4.0/src/pyFDN/resources/presets/colorless_FDN/colorless_init_N4_d2.json +72 -0
  54. pyfdn-0.4.0/src/pyFDN/resources/presets/colorless_FDN/colorless_init_N6_d1.json +106 -0
  55. pyfdn-0.4.0/src/pyFDN/resources/presets/colorless_FDN/colorless_init_N6_d2.json +106 -0
  56. pyfdn-0.4.0/src/pyFDN/resources/presets/colorless_FDN/colorless_init_N8_d1.json +148 -0
  57. pyfdn-0.4.0/src/pyFDN/resources/presets/colorless_FDN/colorless_init_N8_d2.json +148 -0
  58. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/resources/references.bib +9 -0
  59. pyfdn-0.4.0/src/pyFDN/td/__init__.py +58 -0
  60. pyfdn-0.4.0/src/pyFDN/td/connectors.py +300 -0
  61. pyfdn-0.4.0/src/pyFDN/td/operators.py +508 -0
  62. pyfdn-0.4.0/src/pyFDN/train/__init__.py +84 -0
  63. pyfdn-0.4.0/src/pyFDN/train/build.py +456 -0
  64. pyfdn-0.4.0/src/pyFDN/train/engine.py +207 -0
  65. pyfdn-0.4.0/src/pyFDN/train/losses/__init__.py +46 -0
  66. pyfdn-0.4.0/src/pyFDN/train/losses/_targets.py +63 -0
  67. pyfdn-0.4.0/src/pyFDN/train/losses/base.py +151 -0
  68. pyfdn-0.4.0/src/pyFDN/train/losses/parameter.py +66 -0
  69. pyfdn-0.4.0/src/pyFDN/train/losses/spectral.py +356 -0
  70. pyfdn-0.4.0/src/pyFDN/train/losses/temporal.py +347 -0
  71. pyfdn-0.4.0/src/pyFDN/train/params.py +152 -0
  72. pyfdn-0.4.0/src/pyFDN/train/response.py +148 -0
  73. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/translate/dss_to_flamo.py +55 -41
  74. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/translate/dss_to_impz.py +19 -28
  75. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/translate/impz_to_res.py +1 -1
  76. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN.egg-info/PKG-INFO +20 -2
  77. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN.egg-info/SOURCES.txt +45 -89
  78. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN.egg-info/requires.txt +6 -0
  79. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_api_reference.py +6 -0
  80. pyfdn-0.4.0/tests/test_audio_gallery.py +24 -0
  81. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_auxiliary_acoustics.py +0 -61
  82. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_auxiliary_flamo.py +3 -10
  83. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_auxiliary_plot.py +35 -14
  84. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_auxiliary_utils.py +39 -1
  85. pyfdn-0.4.0/tests/test_build_io.py +60 -0
  86. pyfdn-0.4.0/tests/test_eq_designs.py +289 -0
  87. pyfdn-0.4.0/tests/test_example_gallery.py +37 -0
  88. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_flamo_graph.py +4 -4
  89. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_flamo_to_pr.py +1 -1
  90. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_generate.py +36 -21
  91. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_packaged_resources.py +4 -0
  92. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_process_extensions.py +58 -16
  93. pyfdn-0.4.0/tests/test_td_connectors.py +288 -0
  94. pyfdn-0.4.0/tests/test_td_graph_processing.py +674 -0
  95. pyfdn-0.4.0/tests/test_td_operators.py +418 -0
  96. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_time_varying_matrix.py +7 -3
  97. pyfdn-0.4.0/tests/test_train.py +1408 -0
  98. pyfdn-0.2.0/AUTHORS.rst +0 -11
  99. pyfdn-0.2.0/HISTORY.rst +0 -17
  100. pyfdn-0.2.0/docs/Makefile +0 -20
  101. pyfdn-0.2.0/docs/audio_gallery.rst +0 -99
  102. pyfdn-0.2.0/docs/examples_gallery.rst +0 -133
  103. pyfdn-0.2.0/docs/generated/pyFDN.DFiltMatrix.rst +0 -23
  104. pyfdn-0.2.0/docs/generated/pyFDN.FeedbackDelay.rst +0 -25
  105. pyfdn-0.2.0/docs/generated/pyFDN.FilterMatrix.rst +0 -36
  106. pyfdn-0.2.0/docs/generated/pyFDN.TFMatrix.rst +0 -25
  107. pyfdn-0.2.0/docs/generated/pyFDN.ZFIR.rst +0 -32
  108. pyfdn-0.2.0/docs/generated/pyFDN.ZSOS.rst +0 -32
  109. pyfdn-0.2.0/docs/generated/pyFDN.ZScalar.rst +0 -32
  110. pyfdn-0.2.0/docs/generated/pyFDN.ZTF.rst +0 -38
  111. pyfdn-0.2.0/docs/generated/pyFDN.absorption_filters.rst +0 -6
  112. pyfdn-0.2.0/docs/generated/pyFDN.absorption_to_rt.rst +0 -6
  113. pyfdn-0.2.0/docs/generated/pyFDN.construct_cascaded_paraunitary_matrix.rst +0 -6
  114. pyfdn-0.2.0/docs/generated/pyFDN.construct_velvet_feedback_matrix.rst +0 -6
  115. pyfdn-0.2.0/docs/generated/pyFDN.db_to_lin.rst +0 -6
  116. pyfdn-0.2.0/docs/generated/pyFDN.db_to_sq.rst +0 -6
  117. pyfdn-0.2.0/docs/generated/pyFDN.det_polynomial.rst +0 -6
  118. pyfdn-0.2.0/docs/generated/pyFDN.dss_to_impz.rst +0 -6
  119. pyfdn-0.2.0/docs/generated/pyFDN.dss_to_ss.rst +0 -6
  120. pyfdn-0.2.0/docs/generated/pyFDN.echo_density.rst +0 -6
  121. pyfdn-0.2.0/docs/generated/pyFDN.edc.rst +0 -6
  122. pyfdn-0.2.0/docs/generated/pyFDN.ensure_3d.rst +0 -6
  123. pyfdn-0.2.0/docs/generated/pyFDN.hertz_to_unit.rst +0 -6
  124. pyfdn-0.2.0/docs/generated/pyFDN.interpolate_orthogonal.rst +0 -6
  125. pyfdn-0.2.0/docs/generated/pyFDN.is_almost_zero.rst +0 -6
  126. pyfdn-0.2.0/docs/generated/pyFDN.is_bounding_curve.rst +0 -6
  127. pyfdn-0.2.0/docs/generated/pyFDN.is_orthogonal.rst +0 -6
  128. pyfdn-0.2.0/docs/generated/pyFDN.last_nonzero_indices.rst +0 -6
  129. pyfdn-0.2.0/docs/generated/pyFDN.lin_to_db.rst +0 -6
  130. pyfdn-0.2.0/docs/generated/pyFDN.matrix_convolution.rst +0 -6
  131. pyfdn-0.2.0/docs/generated/pyFDN.matrix_delay_approximation.rst +0 -6
  132. pyfdn-0.2.0/docs/generated/pyFDN.matrix_polyder.rst +0 -6
  133. pyfdn-0.2.0/docs/generated/pyFDN.matrix_polyval.rst +0 -6
  134. pyfdn-0.2.0/docs/generated/pyFDN.matrix_sqrt.rst +0 -6
  135. pyfdn-0.2.0/docs/generated/pyFDN.mgrpdelay.rst +0 -6
  136. pyfdn-0.2.0/docs/generated/pyFDN.ms_to_smp.rst +0 -6
  137. pyfdn-0.2.0/docs/generated/pyFDN.mulaw_decode.rst +0 -6
  138. pyfdn-0.2.0/docs/generated/pyFDN.mulaw_encode.rst +0 -6
  139. pyfdn-0.2.0/docs/generated/pyFDN.negpolyder.rst +0 -6
  140. pyfdn-0.2.0/docs/generated/pyFDN.one_pole_absorption.rst +0 -6
  141. pyfdn-0.2.0/docs/generated/pyFDN.outer_sum_approximation.rst +0 -6
  142. pyfdn-0.2.0/docs/generated/pyFDN.peak_normalize.rst +0 -6
  143. pyfdn-0.2.0/docs/generated/pyFDN.plot_impulse_response_matrix.rst +0 -6
  144. pyfdn-0.2.0/docs/generated/pyFDN.plot_system_matrix.rst +0 -6
  145. pyfdn-0.2.0/docs/generated/pyFDN.pole_boundaries.rst +0 -6
  146. pyfdn-0.2.0/docs/generated/pyFDN.poly_degree.rst +0 -6
  147. pyfdn-0.2.0/docs/generated/pyFDN.polyder_rational.rst +0 -6
  148. pyfdn-0.2.0/docs/generated/pyFDN.polydiag.rst +0 -6
  149. pyfdn-0.2.0/docs/generated/pyFDN.process_fdn.rst +0 -6
  150. pyfdn-0.2.0/docs/generated/pyFDN.random_matrix_shift.rst +0 -6
  151. pyfdn-0.2.0/docs/generated/pyFDN.random_orthogonal.rst +0 -6
  152. pyfdn-0.2.0/docs/generated/pyFDN.rt_to_gain_per_sample.rst +0 -6
  153. pyfdn-0.2.0/docs/generated/pyFDN.rt_to_slope.rst +0 -6
  154. pyfdn-0.2.0/docs/generated/pyFDN.shift_matrix.rst +0 -6
  155. pyfdn-0.2.0/docs/generated/pyFDN.shift_matrix_distribute.rst +0 -6
  156. pyfdn-0.2.0/docs/generated/pyFDN.skew.rst +0 -6
  157. pyfdn-0.2.0/docs/generated/pyFDN.slope_to_rt.rst +0 -6
  158. pyfdn-0.2.0/docs/generated/pyFDN.sq_to_db.rst +0 -6
  159. pyfdn-0.2.0/docs/generated/pyFDN.tiny_rotation_matrix.rst +0 -6
  160. pyfdn-0.2.0/docs/patch_rst.py +0 -41
  161. pyfdn-0.2.0/src/pyFDN/auxiliary/flamo.py +0 -648
  162. pyfdn-0.2.0/src/pyFDN/dsp/__init__.py +0 -3
  163. pyfdn-0.2.0/src/pyFDN/dsp/dfilt_matrix.py +0 -53
  164. pyfdn-0.2.0/src/pyFDN/dsp/feedback_delay.py +0 -47
  165. pyfdn-0.2.0/src/pyFDN/dsp/sos_filter_bank.py +0 -57
  166. pyfdn-0.2.0/src/pyFDN/dsp/time_varying_matrix.py +0 -144
  167. pyfdn-0.2.0/src/pyFDN/graphicEQ/__init__.py +0 -17
  168. pyfdn-0.2.0/src/pyFDN/graphicEQ/bandpass_filter.py +0 -34
  169. pyfdn-0.2.0/src/pyFDN/graphicEQ/design_geq.py +0 -73
  170. pyfdn-0.2.0/src/pyFDN/graphicEQ/shelving_filter.py +0 -55
  171. pyfdn-0.2.0/src/pyFDN/presets.py +0 -60
  172. pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_N16_d1.mat +0 -0
  173. pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_N16_d2.mat +0 -0
  174. pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_N4_d1.mat +0 -0
  175. pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_N4_d2.mat +0 -0
  176. pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_N6_d1.mat +0 -0
  177. pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_N6_d2.mat +0 -0
  178. pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_N8_d1.mat +0 -0
  179. pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_N8_d2.mat +0 -0
  180. pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_init_N16_d1.mat +0 -0
  181. pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_init_N16_d2.mat +0 -0
  182. pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_init_N4_d1.mat +0 -0
  183. pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_init_N4_d2.mat +0 -0
  184. pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_init_N6_d1.mat +0 -0
  185. pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_init_N6_d2.mat +0 -0
  186. pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_init_N8_d1.mat +0 -0
  187. pyfdn-0.2.0/src/pyFDN/resources/presets/colorless_FDN/param_init_N8_d2.mat +0 -0
  188. pyfdn-0.2.0/src/pyFDN/train/__init__.py +0 -35
  189. pyfdn-0.2.0/src/pyFDN/train/build.py +0 -321
  190. pyfdn-0.2.0/src/pyFDN/train/engine.py +0 -182
  191. pyfdn-0.2.0/src/pyFDN/train/objectives.py +0 -207
  192. pyfdn-0.2.0/tests/test_audio_gallery.py +0 -17
  193. pyfdn-0.2.0/tests/test_example_gallery.py +0 -29
  194. pyfdn-0.2.0/tests/test_graphic_eq.py +0 -129
  195. pyfdn-0.2.0/tests/test_train.py +0 -269
  196. {pyfdn-0.2.0 → pyfdn-0.4.0}/LICENSE +0 -0
  197. {pyfdn-0.2.0 → pyfdn-0.4.0}/MANIFEST.in +0 -0
  198. {pyfdn-0.2.0 → pyfdn-0.4.0}/docs/__init__.py +0 -0
  199. {pyfdn-0.2.0 → pyfdn-0.4.0}/docs/authors.rst +0 -0
  200. {pyfdn-0.2.0 → pyfdn-0.4.0}/docs/contributing.rst +0 -0
  201. {pyfdn-0.2.0 → pyfdn-0.4.0}/docs/history.rst +0 -0
  202. {pyfdn-0.2.0 → pyfdn-0.4.0}/docs/installation.rst +0 -0
  203. {pyfdn-0.2.0 → pyfdn-0.4.0}/docs/logo/logo_pyFDN_3.png +0 -0
  204. {pyfdn-0.2.0 → pyfdn-0.4.0}/docs/logo/logo_pyFDN_4.png +0 -0
  205. {pyfdn-0.2.0 → pyfdn-0.4.0}/docs/logo/pyfdn_logo_basic.png +0 -0
  206. {pyfdn-0.2.0 → pyfdn-0.4.0}/docs/logo/pyfdn_logo_wave.png +0 -0
  207. {pyfdn-0.2.0 → pyfdn-0.4.0}/docs/make.bat +0 -0
  208. {pyfdn-0.2.0 → pyfdn-0.4.0}/docs/readme.rst +0 -0
  209. {pyfdn-0.2.0 → pyfdn-0.4.0}/docs/references.py +0 -0
  210. {pyfdn-0.2.0 → pyfdn-0.4.0}/setup.cfg +0 -0
  211. {pyfdn-0.2.0 → pyfdn-0.4.0}/setup.py +0 -0
  212. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/auxiliary/allpass.py +0 -0
  213. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/auxiliary/audio.py +0 -0
  214. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/auxiliary/delay.py +0 -0
  215. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/auxiliary/math.py +0 -0
  216. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/auxiliary/poles.py +0 -0
  217. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/auxiliary/tiny_rotation_matrix.py +0 -0
  218. {pyfdn-0.2.0/src/pyFDN/graphicEQ → pyfdn-0.4.0/src/pyFDN/eq}/probe_sos.py +0 -0
  219. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/SDN.py +0 -0
  220. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/allpass_FDN/__init__.py +0 -0
  221. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/allpass_FDN/rand_admissible_homogeneous_allpass.py +0 -0
  222. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/allpass_in_fdn.py +0 -0
  223. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/anderson_matrix.py +0 -0
  224. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/complete_orthogonal.py +0 -0
  225. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/construct_cascaded_paraunitary_matrix.py +0 -0
  226. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/construct_paraunitary_from_elementals.py +0 -0
  227. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/construct_velvet_feedback_matrix.py +0 -0
  228. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/degree_one_lossless.py +0 -0
  229. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/householder_matrix.py +0 -0
  230. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/is_almost_zero.py +0 -0
  231. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/nearest_orthogonal.py +0 -0
  232. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/nearest_sign_agnostic_orthogonal.py +0 -0
  233. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/random_matrix_shift.py +0 -0
  234. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/random_orthogonal.py +0 -0
  235. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/sample_delay_lengths.py +0 -0
  236. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/schroeder_reverberator.py +0 -0
  237. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/shift_matrix.py +0 -0
  238. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/generate/shift_matrix_distribute.py +0 -0
  239. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/references.py +0 -0
  240. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/resources/__init__.py +0 -0
  241. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/resources/audio/drums/drums.wav +0 -0
  242. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/resources/audio/general/synth_dry.wav +0 -0
  243. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/resources/audio/metadata.json +0 -0
  244. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/resources/audio/rir/s3_r4_o.wav +0 -0
  245. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/resources/audio/speech/P1_Set1_8.wav +0 -0
  246. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/resources/audio/speech/P20_Set1_8.wav +0 -0
  247. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/resources/audio/strings/Kleiderschrank_Taylor_DI.wav +0 -0
  248. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/resources/audio/strings/Sommerhit2016_Taylor_DI.wav +0 -0
  249. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/resources/licenses/diff-fdn-colorless-MIT.txt +0 -0
  250. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/translate/dss_to_pr.py +0 -0
  251. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/translate/dss_to_ss.py +0 -0
  252. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/translate/dss_to_tf.py +0 -0
  253. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/translate/flamo_to_pr.py +0 -0
  254. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/translate/mtf_to_impz.py +0 -0
  255. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN/translate/pr_to_impz.py +0 -0
  256. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN.egg-info/dependency_links.txt +0 -0
  257. {pyfdn-0.2.0 → pyfdn-0.4.0}/src/pyFDN.egg-info/top_level.txt +0 -0
  258. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/__init__.py +0 -0
  259. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/conftest.py +0 -0
  260. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/matloader.py +0 -0
  261. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/reference/README.md +0 -0
  262. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/reference/example_onePoleAbsorption.mat +0 -0
  263. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/reference/onePoleAbsorption_reference.mat +0 -0
  264. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_auxiliary_delay.py +0 -0
  265. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_auxiliary_math.py +0 -0
  266. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_coupled_rooms.py +0 -0
  267. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_dss_to_pr.py +0 -0
  268. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_flamo_one_pole_absorption.py +0 -0
  269. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_marimo_examples_run.py +0 -0
  270. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_pyFDN.py +0 -0
  271. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_sdn.py +0 -0
  272. {pyfdn-0.2.0 → pyfdn-0.4.0}/tests/test_translate.py +0 -0
@@ -0,0 +1,17 @@
1
+ =======
2
+ Credits
3
+ =======
4
+
5
+
6
+ Core Contributors
7
+ -----------------
8
+
9
+ * Sebastian J. Schlecht
10
+ * Facundo Franchino
11
+ * Jeremy Bai
12
+ * Alma Hova
13
+ * Cristóbal Andrade
14
+ * Gloria Dal Santo
15
+ * Bharadwaj Lakuduva Suresh Babu
16
+ * Gian Marco De Bortoli
17
+ * Kalyan Pandey
@@ -137,8 +137,35 @@ Building the Documentation
137
137
  Repository Index
138
138
  ----------------
139
139
 
140
- .. note::
141
- This section will be filled out later with the goal structure of the repository.
140
+ The repository separates the installable package, executable examples,
141
+ documentation sources, and tests:
142
+
143
+ * ``src/pyFDN/`` contains the library. The top-level ``__init__.py`` defines
144
+ the public API, while ``process.py``, ``build_io.py``, and ``presets.py``
145
+ provide the main processing and persistence entry points.
146
+ * ``src/pyFDN/generate/`` contains feedback-matrix and FDN construction
147
+ algorithms, including the allpass and scattering-delay-network builders.
148
+ * ``src/pyFDN/td/`` contains stateful block-processing operators and the
149
+ connectors (``Series``, ``Parallel``, ``Recursion``) that wire them into a
150
+ time-domain graph. ``process_fdn`` uses ``MatrixFIR`` for polynomial feedback
151
+ matrices; ``SOSBank`` implements per-delay-line filter cascades used for
152
+ frequency-dependent absorption.
153
+ * ``src/pyFDN/eq/`` contains every EQ and absorption-filter design, while
154
+ ``src/pyFDN/translate/`` converts between delay state-space, transfer
155
+ function, pole-residue, impulse-response, and FLAMO representations.
156
+ * ``src/pyFDN/train/`` contains the trainable FDN construction, the composable
157
+ losses in ``train/losses/``, and the optimization loop. ``src/pyFDN/auxiliary/`` holds shared analysis,
158
+ plotting, audio, delay, and numerical helpers.
159
+ * ``examples/`` contains executable Marimo notebooks. Metadata at the top of
160
+ each ``example_*.py`` file drives the generated documentation gallery.
161
+ * ``tests/`` mirrors the public feature areas with unit, regression, and
162
+ integration coverage; ``tests/reference/`` stores reference data and its
163
+ provenance notes.
164
+ * ``docs/`` contains authored Sphinx pages and the scripts that generate API
165
+ stubs and galleries. Generated pages and HTML output are intentionally not
166
+ committed.
167
+ * ``.github/`` contains the continuous-integration, packaging, and GitHub
168
+ Pages workflows.
142
169
 
143
170
 
144
171
  Testing Pipeline
@@ -0,0 +1,91 @@
1
+ =======
2
+ History
3
+ =======
4
+
5
+ 0.4.0 (2026-08-23)
6
+ ------------------
7
+
8
+ * **Breaking:** replace ``train_fdn``'s ``mode`` string, and the ``target``,
9
+ ``criteria``, ``sparsity_alpha`` and ``mss_nfft`` arguments that went with
10
+ it, with a composed loss object. An objective is now written out --
11
+ ``FlatMagnitude() + 0.2 * Sparsity(param(model, "feedback"))`` -- and every
12
+ loss is a function of the impulse response, carried as a ``Response``, so
13
+ losses own their reference data and one objective can fit two different
14
+ references. ``pyFDN.train.objectives`` and ``build_objective`` are gone.
15
+ * **Breaking:** collect every EQ design in ``pyFDN.eq`` (formerly
16
+ ``pyFDN.graphicEQ``) behind one ``EQDesign`` interface, with ``GraphicEQ``,
17
+ ``FirstOrderShelf`` and ``OnePole`` sharing a single implementation across
18
+ the numpy and torch backends.
19
+ * **Breaking:** remove ``absorption_filters`` and ``absorption_to_rt``; the FIR
20
+ absorption path they served has no callers left.
21
+ * **Breaking:** name the three filter hooks ``post_delay``, ``post_matrix`` and
22
+ ``post_output`` everywhere -- on ``FDNBuild``, in the FLAMO graph, in the
23
+ plots and in the JSON schema -- and add the slot for the third. The build
24
+ schema is version 2; version 1 files no longer load.
25
+ * Fix colorless training on a lossless FDN, whose poles sit on the unit circle
26
+ and leave ``|H|`` unbounded. ``build_fdn`` now defaults ``alias_decay_db``
27
+ from ``rt`` (``LOSSLESS_ALIAS_DECAY_DB`` when ``rt`` is None) and
28
+ ``trainable_from_build`` threads it into every module, so a magnitude
29
+ objective sees a bounded response.
30
+ * Train the decay: ``DecayFilter`` parametrizes the in-loop absorption filter
31
+ by reverberation time per band, so the loop stays contractive for every value
32
+ the parameter can take, and takes either one RT curve for the network or one
33
+ per delay line. ``OutputEQ`` trains the output filter outside the recursion,
34
+ the only part of an FDN that shapes the spectral envelope without touching
35
+ the decay. Both are passed as the ``post_delay`` and ``post_output`` hooks of
36
+ ``trainable_from_build``.
37
+ * Add the losses that go with it: ``AsymmetricFlatMagnitude``,
38
+ ``FlatSpectrogram``, ``MatchEnergyDecay``, ``MatchCumulativeEnergy``,
39
+ ``MatchMagnitude``, ``MatchSpectrogram``, ``MatchMelSpectrogram``,
40
+ ``MatchImpulseResponse``, ``Energy``, ``Sparsity``, ``L1`` and ``L2``.
41
+ * Resolve trainable parameters by name: ``param(model, "feedback")`` fails
42
+ where you write it with the list of available names, and ``params(model)``
43
+ enumerates them.
44
+ * Export the FLAMO graph builders (``assemble_fdn_core``, ``wrap_fdn_shell``,
45
+ ``gain_module``, ``delay_module``, ``matrix_module``, ``fir_matrix_module``,
46
+ ``sos_filter_module``, ``hook_module``, ``DecayFilter``, ``OutputEQ``) from
47
+ the top-level namespace.
48
+ * Make ``build_to_impz`` apply all three hooks, so it no longer rejects builds
49
+ that carry an output EQ, and make ``extract_build`` refuse a hook it cannot
50
+ bake rather than silently dropping it.
51
+ * Add an example notebook that fits every parameter of an FDN, decay included,
52
+ to a measured concert-hall RIR, and document the loss rationale and
53
+ measurements in ``docs/training_losses.rst``.
54
+ * Fix stereo orientation in ``labeled_audio``, which decoded a stereo render as
55
+ thousands of channels.
56
+ * Check packaging metadata in CI and fail the documentation build on notebook
57
+ cell errors.
58
+
59
+ 0.3.0 (2026-08-17)
60
+ ------------------
61
+
62
+ * **Breaking:** replace the ``pyFDN.dsp`` subpackage with ``pyFDN.td``. The
63
+ top-level ``FeedbackDelay``, ``FIRMatrixFilter`` and ``SOSFilterBank``
64
+ exports are gone; use ``pyFDN.td`` operators instead.
65
+ * **Breaking:** ship the packaged colorless-FDN presets as JSON rather than
66
+ MATLAB ``.mat`` files.
67
+ * Add ``pyFDN.td``, a time-domain block-based processing graph built on NumPy
68
+ alone (no torch, no FFT), with the ``Series``, ``Parallel`` and
69
+ ``Recursion`` connectors and stateful ``Gain``, ``Delay``, ``SOSBank``,
70
+ ``MatrixFIR``, ``MatrixConvolver`` and ``TimeVaryingMatrix`` operators.
71
+ * Add ``load_fdn_build``, ``save_fdn_build``, ``fdn_build_from_dict`` and
72
+ ``fdn_build_to_dict`` for reading and writing FDN builds as JSON.
73
+ * Add an FDN-to-FAUST example that compiles a pyFDN design with adac, and a
74
+ reverberation-enhancement example.
75
+ * Improve the example gallery and stop tracking generated documentation in the
76
+ repository.
77
+ * Test on Python 3.14 in CI and the documentation build.
78
+
79
+ 0.2.0 (2026-08-10)
80
+ ------------------
81
+
82
+ * Package compact audio examples and predefined colorless-FDN coefficients so
83
+ browser-hosted tutorials work without repository-relative files.
84
+ * Add public APIs for packaged audio, FDN presets, and paper references.
85
+ * Add generated documentation galleries and wheel-content checks.
86
+ * Keep decay-estimation dependencies optional for a smaller core installation.
87
+
88
+ 0.1.0 (2025-07-02)
89
+ ------------------
90
+
91
+ * First release on PyPI.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyFDN
3
- Version: 0.2.0
3
+ Version: 0.4.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
@@ -12,7 +12,7 @@ Classifier: Development Status :: 3 - Alpha
12
12
  Classifier: Intended Audience :: Science/Research
13
13
  Classifier: Programming Language :: Python :: 3
14
14
  Classifier: Programming Language :: Python :: 3.10
15
- Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.14
16
16
  Requires-Python: >=3.10
17
17
  Description-Content-Type: text/x-rst
18
18
  License-File: LICENSE
@@ -25,14 +25,18 @@ Requires-Dist: flamo>=0.2.14
25
25
  Requires-Dist: flareverb
26
26
  Provides-Extra: examples
27
27
  Requires-Dist: marimo; extra == "examples"
28
+ Requires-Dist: adac; extra == "examples"
28
29
  Requires-Dist: matplotlib>=3.5.0; extra == "examples"
29
30
  Requires-Dist: plotly>=5.0.0; extra == "examples"
30
31
  Requires-Dist: multislope>=0.1.1; extra == "examples"
32
+ Requires-Dist: pyroomacoustics; extra == "examples"
31
33
  Provides-Extra: test
32
34
  Requires-Dist: marimo; extra == "test"
35
+ Requires-Dist: adac; extra == "test"
33
36
  Requires-Dist: matplotlib>=3.5.0; extra == "test"
34
37
  Requires-Dist: plotly>=5.0.0; extra == "test"
35
38
  Requires-Dist: multislope>=0.1.1; extra == "test"
39
+ Requires-Dist: pyroomacoustics; extra == "test"
36
40
  Requires-Dist: pytest>=7.0.0; extra == "test"
37
41
  Requires-Dist: pytest-cov>=4.0.0; extra == "test"
38
42
  Requires-Dist: coverage>=7.0.0; extra == "test"
@@ -60,6 +64,8 @@ Requires-Dist: pandoc>=2.0; extra == "docs"
60
64
  Requires-Dist: plotly>=5.0.0; extra == "docs"
61
65
  Requires-Dist: matplotlib>=3.5.0; extra == "docs"
62
66
  Requires-Dist: multislope>=0.1.1; extra == "docs"
67
+ Requires-Dist: pyroomacoustics; extra == "docs"
68
+ Requires-Dist: adac; extra == "docs"
63
69
  Dynamic: license-file
64
70
 
65
71
  =====
@@ -93,6 +99,9 @@ Overview
93
99
 
94
100
  ``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.
95
101
 
102
+ The `pyFDN tutorial
103
+ <https://artificial-audio.github.io/pyfdn-tutorial-2026/>`_ provides an introduction to the package.
104
+
96
105
  The source code is MIT-licensed. Small packaged tutorial resources retain the
97
106
  separate terms recorded in ``src/pyFDN/resources/ATTRIBUTION.md``; in
98
107
  particular, the Pori concert-hall impulse response is limited to
@@ -165,3 +174,12 @@ Or, inside an activated virtual environment::
165
174
 
166
175
  For linting and packaging helpers see ``Makefile`` (``make lint``/``make docs``)
167
176
  and ``tox.ini`` for multi-environment testing.
177
+
178
+
179
+ Helpful links
180
+ -------------
181
+
182
+ * `List of papers on Feedback Delay Networks <https://github.com/gdalsanto/delay-network-reverbs>`_ .
183
+ * `Multislope Estimation library <https://github.com/artificial-audio/multislope>`_ .
184
+ * `FLAMO (An Open-Source Library for Frequency-Domain Differentiable Audio Processing) <https://github.com/gdalsanto/flamo>`_ .
185
+ * `ADAC (Automatic Differentiable Audio Compilation) library <https://github.com/cucuwritescode/adac>`_ .
@@ -29,6 +29,9 @@ 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 `pyFDN tutorial
33
+ <https://artificial-audio.github.io/pyfdn-tutorial-2026/>`_ provides an introduction to the package.
34
+
32
35
  The source code is MIT-licensed. Small packaged tutorial resources retain the
33
36
  separate terms recorded in ``src/pyFDN/resources/ATTRIBUTION.md``; in
34
37
  particular, the Pori concert-hall impulse response is limited to
@@ -101,3 +104,12 @@ Or, inside an activated virtual environment::
101
104
 
102
105
  For linting and packaging helpers see ``Makefile`` (``make lint``/``make docs``)
103
106
  and ``tox.ini`` for multi-environment testing.
107
+
108
+
109
+ Helpful links
110
+ -------------
111
+
112
+ * `List of papers on Feedback Delay Networks <https://github.com/gdalsanto/delay-network-reverbs>`_ .
113
+ * `Multislope Estimation library <https://github.com/artificial-audio/multislope>`_ .
114
+ * `FLAMO (An Open-Source Library for Frequency-Domain Differentiable Audio Processing) <https://github.com/gdalsanto/flamo>`_ .
115
+ * `ADAC (Automatic Differentiable Audio Compilation) library <https://github.com/cucuwritescode/adac>`_ .
@@ -0,0 +1,39 @@
1
+ # Minimal makefile for Sphinx documentation
2
+ #
3
+
4
+ # You can set these variables from the command line.
5
+ PYTHON ?= python
6
+ SPHINXOPTS =
7
+ SPHINXBUILD ?= $(PYTHON) -msphinx
8
+ SPHINXPROJ = pyFDN
9
+ SOURCEDIR = .
10
+ BUILDDIR = _build
11
+ SPHINXAPIDOC ?= $(PYTHON) -msphinx.ext.apidoc
12
+
13
+ # Put it first so that "make" without argument is like "make help".
14
+ help:
15
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
16
+
17
+ .PHONY: help Makefile clean clean-generated generate-rst html
18
+
19
+ # API stubs and autosummary pages are reproducible build inputs. Remove them
20
+ # before every build so deleted or renamed public objects cannot leave stale
21
+ # documentation behind.
22
+ clean-generated:
23
+ $(RM) modules.rst pyFDN.rst pyFDN.*.rst
24
+ $(RM) -r generated
25
+
26
+ generate-rst: clean-generated
27
+ $(SPHINXAPIDOC) -f -o "$(SOURCEDIR)" ../src/pyFDN
28
+ $(PYTHON) patch_rst.py
29
+
30
+ clean: clean-generated
31
+ @$(SPHINXBUILD) -M clean "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
32
+
33
+ html: generate-rst
34
+ @$(SPHINXBUILD) -M html "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
35
+
36
+ # Catch-all target: route all unknown targets to Sphinx using the new
37
+ # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
38
+ %: Makefile
39
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
@@ -83,14 +83,9 @@ Acoustics & Absorption
83
83
  :toctree: generated/
84
84
  :nosignatures:
85
85
 
86
- pyFDN.absorption_filters
87
- pyFDN.first_order_absorption
88
- pyFDN.first_order_shelving_eq
89
- pyFDN.one_pole_absorption
90
86
  pyFDN.sos_gain_per_sample_curves
91
87
  pyFDN.echo_density
92
88
  pyFDN.edc
93
- pyFDN.absorption_to_rt
94
89
  pyFDN.estimate_initial_level_bands
95
90
  pyFDN.estimate_rt_bands
96
91
  pyFDN.octave_bands
@@ -100,30 +95,58 @@ Acoustics & Absorption
100
95
  pyFDN.slope_amplitude_to_level
101
96
  pyFDN.slope_to_rt
102
97
 
103
- Graphic EQ
104
- ----------
98
+ EQ & Absorption Design (``pyFDN.eq``)
99
+ --------------------------------------
100
+
101
+ Three designs of the same two filters -- an FDN's in-loop absorption and its
102
+ output EQ -- behind one interface. A design carries its own target and maps it
103
+ to biquad sections in numpy or in torch from a single implementation, which is
104
+ what a trainable :class:`pyFDN.DecayFilter` or :class:`pyFDN.OutputEQ` runs
105
+ inside a training loop.
105
106
 
106
107
  .. autosummary::
107
108
  :toctree: generated/
108
109
  :nosignatures:
109
110
 
111
+ pyFDN.EQDesign
112
+ pyFDN.GraphicEQ
113
+ pyFDN.FirstOrderShelf
114
+ pyFDN.OnePole
110
115
  pyFDN.design_geq
116
+ pyFDN.geq_sos
117
+ pyFDN.geq_design_matrix
111
118
  pyFDN.graphic_eq
112
119
  pyFDN.absorption_geq
120
+ pyFDN.first_order_absorption
121
+ pyFDN.first_order_shelving_eq
122
+ pyFDN.one_pole_absorption
113
123
  pyFDN.probe_sos
114
124
  pyFDN.shelving_filter
115
125
  pyFDN.bandpass_filter
116
126
 
117
- DSP Components
118
- --------------
127
+ Time-Domain Graph (``pyFDN.td``)
128
+ --------------------------------
129
+
130
+ Stateful block-processing operators, wired into a graph by the connectors and
131
+ rendered with ``.process(signal)``. See :mod:`pyFDN.td`.
119
132
 
120
133
  .. autosummary::
121
134
  :toctree: generated/
122
135
  :nosignatures:
123
136
 
124
- pyFDN.FeedbackDelay
125
- pyFDN.FIRMatrixFilter
126
- pyFDN.SOSFilterBank
137
+ pyFDN.td.TimeOperator
138
+ pyFDN.td.Identity
139
+ pyFDN.td.Gain
140
+ pyFDN.td.Delay
141
+ pyFDN.td.AbsoluteValue
142
+ pyFDN.td.SOSBank
143
+ pyFDN.td.MatrixFIR
144
+ pyFDN.td.MatrixConvolver
145
+ pyFDN.td.TimeVaryingMatrix
146
+ pyFDN.td.RecursionState
147
+ pyFDN.td.Series
148
+ pyFDN.td.Parallel
149
+ pyFDN.td.Recursion
127
150
 
128
151
  Delay Utilities
129
152
  ---------------
@@ -138,6 +161,29 @@ Delay Utilities
138
161
  pyFDN.flamo_time_response
139
162
  pyFDN.flamo_freq_response
140
163
 
164
+ Building a FLAMO Graph
165
+ ----------------------
166
+
167
+ An FDN as FLAMO modules, assembled from numpy values. The three filter hooks --
168
+ ``post_delay`` inside the loop, ``post_matrix`` on the feedback path,
169
+ ``post_output`` on the wet signal -- are the same three
170
+ :func:`pyFDN.process_fdn` takes, in the same positions and under the same names.
171
+
172
+ .. autosummary::
173
+ :toctree: generated/
174
+ :nosignatures:
175
+
176
+ pyFDN.assemble_fdn_core
177
+ pyFDN.wrap_fdn_shell
178
+ pyFDN.gain_module
179
+ pyFDN.delay_module
180
+ pyFDN.matrix_module
181
+ pyFDN.fir_matrix_module
182
+ pyFDN.sos_filter_module
183
+ pyFDN.hook_module
184
+ pyFDN.DecayFilter
185
+ pyFDN.OutputEQ
186
+
141
187
  Polynomial & Matrix Maths
142
188
  --------------------------
143
189
 
@@ -188,8 +234,8 @@ General Utilities
188
234
  pyFDN.pole_boundaries
189
235
  pyFDN.skew
190
236
 
191
- Packaged Examples & References
192
- ------------------------------
237
+ Build Files, Packaged Examples & References
238
+ --------------------------------------------
193
239
 
194
240
  .. autosummary::
195
241
  :toctree: generated/
@@ -200,6 +246,10 @@ Packaged Examples & References
200
246
  pyFDN.load_audio
201
247
  pyFDN.available_fdn_presets
202
248
  pyFDN.load_fdn_preset
249
+ pyFDN.fdn_build_to_dict
250
+ pyFDN.fdn_build_from_dict
251
+ pyFDN.save_fdn_build
252
+ pyFDN.load_fdn_build
203
253
  pyFDN.paper_reference
204
254
  pyFDN.paper_link
205
255
 
@@ -248,6 +298,38 @@ Training
248
298
  pyFDN.Trainable
249
299
  pyFDN.train_fdn
250
300
  pyFDN.TrainLog
301
+ pyFDN.LOSSLESS_ALIAS_DECAY_DB
302
+
303
+ Training Objectives
304
+ -------------------
305
+
306
+ An objective is a weighted sum of losses, composed with ``+`` and ``*``. Losses
307
+ on the impulse response read a :class:`pyFDN.Response`; losses on a model
308
+ parameter take a :class:`pyFDN.ParamRef` from :func:`pyFDN.param`.
309
+
310
+ .. autosummary::
311
+ :toctree: generated/
312
+ :nosignatures:
313
+
314
+ pyFDN.Response
315
+ pyFDN.model_response
316
+ pyFDN.param
317
+ pyFDN.params
318
+ pyFDN.ParamRef
319
+ pyFDN.Loss
320
+ pyFDN.FlatMagnitude
321
+ pyFDN.AsymmetricFlatMagnitude
322
+ pyFDN.FlatSpectrogram
323
+ pyFDN.MatchMagnitude
324
+ pyFDN.MatchSpectrogram
325
+ pyFDN.MatchMelSpectrogram
326
+ pyFDN.MatchImpulseResponse
327
+ pyFDN.MatchEnergyDecay
328
+ pyFDN.MatchCumulativeEnergy
329
+ pyFDN.Energy
330
+ pyFDN.Sparsity
331
+ pyFDN.L1
332
+ pyFDN.L2
251
333
 
252
334
  Plotting
253
335
  --------
@@ -66,9 +66,9 @@ def render_gallery(examples: list[AudioExample]) -> str:
66
66
  lines = [
67
67
  ".. This file is generated by docs/audio_gallery.py. Do not edit it manually.",
68
68
  "",
69
- "============",
69
+ "=============",
70
70
  "Audio Gallery",
71
- "============",
71
+ "=============",
72
72
  "",
73
73
  "Audio examples demonstrating ``pyFDN``. The gallery is generated",
74
74
  "automatically from every packaged ``.wav`` file, grouped by resource category.",
@@ -47,6 +47,11 @@ autosummary_imported_members = True
47
47
  # Napoleon settings (Google / NumPy docstrings)
48
48
  napoleon_google_docstring = True
49
49
  napoleon_numpy_docstring = True
50
+ # Render "Attributes" sections as :ivar: fields instead of standalone
51
+ # ``.. attribute::`` directives. Without this, every documented attribute is
52
+ # registered twice (once by napoleon, once by autodoc's member scan) and Sphinx
53
+ # warns about duplicate object descriptions.
54
+ napoleon_use_ivar = True
50
55
 
51
56
 
52
57
  # Intersphinx mapping
@@ -114,7 +119,9 @@ latex_documents = [
114
119
  marimo_notebook_dir = "../examples"
115
120
  marimo_default_height = "800px"
116
121
  marimo_default_width = "100%"
117
- marimo_click_to_load = "overlay" # Use overlay mode for better performance
122
+ # ``True`` is rendered as the extension's overlay mode. Keep this a boolean;
123
+ # sphinx-marimo declares the setting as such and Sphinx warns on string values.
124
+ marimo_click_to_load = True
118
125
  marimo_load_button_text = "Load Interactive Notebook"
119
126
 
120
127
  # Build notebooks serially in-process. The export-mode override below patches the
@@ -141,6 +148,17 @@ marimo_cache_notebooks = False
141
148
  #
142
149
  # This patch lives in conf.py (our repo), so the installed sphinx-marimo package
143
150
  # stays pristine and deployment (RTD / GitHub Actions) needs no vendored changes.
151
+ #
152
+ # Cell errors are build failures: a notebook that raises still produces HTML,
153
+ # with the traceback baked in where the output should be, so a broken example
154
+ # reaches the published site looking like a rendered page. We record every
155
+ # notebook whose export exited non-zero and fail the build at the end (see
156
+ # ``setup`` below) instead of aborting on the first one, so a single run reports
157
+ # all of them. Set ``PYFDN_DOCS_ALLOW_NOTEBOOK_ERRORS=1`` to downgrade this back
158
+ # to a warning when you need a build out of a knowingly broken notebook.
159
+ _marimo_export_failures: "list[tuple[str, str]]" = []
160
+
161
+
144
162
  def _patch_marimo_static_export():
145
163
  import subprocess
146
164
 
@@ -166,8 +184,8 @@ def _patch_marimo_static_export():
166
184
  # `html` (not `html-wasm`) executes the notebook server-side with the real
167
185
  # venv and embeds the outputs. marimo returns a non-zero exit code when any
168
186
  # cell raises during execution, but it still writes the HTML (with the error
169
- # baked in), so we log a warning and keep going rather than aborting the
170
- # whole docs build on one bad notebook.
187
+ # baked in), so we record the failure and keep going; the build-finished
188
+ # handler turns the collected failures into a build error.
171
189
  proc = subprocess.run(
172
190
  [
173
191
  "marimo",
@@ -183,9 +201,10 @@ def _patch_marimo_static_export():
183
201
  )
184
202
  if proc.returncode != 0:
185
203
  print(
186
- f"[conf.py] WARNING: '{relative_path}' had cell errors during static "
204
+ f"[conf.py] ERROR: '{relative_path}' had cell errors during static "
187
205
  f"export (output still written):\n{proc.stderr.strip()}"
188
206
  )
207
+ _marimo_export_failures.append((str(relative_path), proc.stderr.strip()))
189
208
 
190
209
  return {
191
210
  "name": output_name,
@@ -198,3 +217,30 @@ def _patch_marimo_static_export():
198
217
 
199
218
 
200
219
  _patch_marimo_static_export()
220
+
221
+
222
+ def _fail_on_marimo_export_errors(app, exception):
223
+ """Fail the build if any notebook raised while being exported."""
224
+ # The build already failed for another reason; don't mask it.
225
+ if exception is not None or not _marimo_export_failures:
226
+ return
227
+
228
+ report = "\n\n".join(
229
+ f"{path}:\n{stderr}" for path, stderr in _marimo_export_failures
230
+ )
231
+ if os.environ.get("PYFDN_DOCS_ALLOW_NOTEBOOK_ERRORS") == "1":
232
+ print(
233
+ f"[conf.py] WARNING: {len(_marimo_export_failures)} notebook(s) had cell "
234
+ f"errors; failing is disabled via PYFDN_DOCS_ALLOW_NOTEBOOK_ERRORS:\n{report}"
235
+ )
236
+ return
237
+
238
+ raise RuntimeError(
239
+ f"{len(_marimo_export_failures)} example notebook(s) raised during static "
240
+ f"export. The generated HTML contains the traceback instead of the intended "
241
+ f"output, so this must not be published:\n\n{report}"
242
+ )
243
+
244
+
245
+ def setup(app):
246
+ app.connect("build-finished", _fail_on_marimo_export_errors)
@@ -60,27 +60,18 @@ def _plain_text(markdown: str) -> str:
60
60
  return text.strip()
61
61
 
62
62
 
63
- def _title_and_description(path: Path) -> tuple[str, str]:
63
+ def _inferred_title(path: Path) -> str:
64
64
  blocks = _markdown_blocks(path)
65
65
  for block in blocks:
66
66
  lines = block.splitlines()
67
- for index, line in enumerate(lines):
67
+ for line in lines:
68
68
  if not line.startswith("# "):
69
69
  continue
70
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
71
+ return title
81
72
 
82
73
  fallback = path.stem.removeprefix("example_").replace("_", " ").title()
83
- return fallback, "Open the rendered marimo notebook."
74
+ return fallback
84
75
 
85
76
 
86
77
  def _metadata(path: Path) -> dict[str, str]:
@@ -93,25 +84,25 @@ def _metadata(path: Path) -> dict[str, str]:
93
84
  return metadata
94
85
 
95
86
 
96
- def _required_category(path: Path) -> str:
97
- metadata = _metadata(path)
98
- category = metadata.get("category")
99
- if category:
100
- return category
87
+ def _required_metadata(path: Path, metadata: dict[str, str], key: str) -> str:
88
+ value = metadata.get(key)
89
+ if value:
90
+ return value
101
91
  relative = path.relative_to(PROJECT_ROOT)
102
- raise ValueError(f"{relative} is missing a required '# gallery_category: ...' tag")
92
+ raise ValueError(f"{relative} is missing a required '# gallery_{key}: ...' tag")
103
93
 
104
94
 
105
95
  def discover_examples() -> list[Example]:
106
96
  examples = []
107
97
  for path in sorted(EXAMPLES_DIR.rglob("example_*.py")):
108
- title, description = _title_and_description(path)
98
+ metadata = _metadata(path)
99
+ inferred_title = _inferred_title(path)
109
100
  examples.append(
110
101
  Example(
111
102
  path,
112
- title,
113
- description,
114
- _required_category(path),
103
+ metadata.get("title", inferred_title),
104
+ _required_metadata(path, metadata, "description"),
105
+ _required_metadata(path, metadata, "category"),
115
106
  )
116
107
  )
117
108
  return examples
@@ -58,6 +58,7 @@ feedback matrices, designing loop filters, and inspecting pole locations.
58
58
  usage
59
59
  examples_gallery
60
60
  api_reference
61
+ training_losses
61
62
  modules
62
63
  contributing
63
64
  authors
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env python3
2
+ """Patch generated RST files to avoid duplicate object descriptions with api_reference."""
3
+
4
+ import re
5
+ from pathlib import Path
6
+
7
+ DOCS = Path(__file__).parent
8
+
9
+ # Replace pyFDN Module contents automodule with a link (avoids duplicates with api_reference)
10
+ pyfdn_rst = DOCS / "pyFDN.rst"
11
+ if pyfdn_rst.exists():
12
+ text = pyfdn_rst.read_text()
13
+ new = """Module contents
14
+ ---------------
15
+
16
+ See :doc:`API Reference <api_reference>` for full documentation of all functions and classes."""
17
+ text = re.sub(
18
+ r"Module contents\n-+\n\n\.\. automodule:: pyFDN\n( :[^\n]+\n)+",
19
+ new + "\n",
20
+ text,
21
+ )
22
+ pyfdn_rst.write_text(text)
23
+
24
+ # Sub-package "Module contents" sections otherwise re-document every member
25
+ # their __init__ re-exports. Keep the package docstring, but omit those members;
26
+ # api_reference and the submodule sections remain the canonical targets.
27
+ for package_rst in sorted(DOCS.glob("pyFDN.*.rst")):
28
+ package = package_rst.stem # e.g. "pyFDN.graphicEQ"
29
+ text = package_rst.read_text()
30
+ pattern = rf"(\.\. automodule:: {re.escape(package)}\n( :[^\n]+\n)+)"
31
+ match = re.search(pattern, text)
32
+ if match:
33
+ block = f".. automodule:: {package}\n :no-index:\n :no-members:\n"
34
+ text = text[: match.start()] + block + text[match.end() :]
35
+ package_rst.write_text(text)