%23%20gallery_category%3A%20FDN%20Design%20%26%20Analysis%0A%0Aimport%20marimo%0A%0A__generated_with%20%3D%20%220.23.13%22%0Aapp%20%3D%20marimo.App()%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20Denser%20Reverberation%20with%20Delay%20Feedback%20Matrix%0A%0A%20%20%20%20This%20example%20compares%20three%20FDN%20topologies%20and%20their%20**echo%20density**%20(Abel%20%26%20Huang%202006)%3A%0A%0A%20%20%20%201.%20**Vanilla%20FDN**%20%E2%80%94%20Build%20a%20complete%20FDN%20with%20%60pyFDN.fdn_build_gallery%60%2C%20bake%20in%20broadband%20decay%2C%20and%20render%20it%20with%20%60pyFDN.dss_to_flamo%60.%0A%20%20%20%202.%20**Delay%2Bmatrix%2Bdelay%20in%20feedback**%20%E2%80%94%20Copy%20the%20model%20and%20replace%20the%20feedback%20path%20with%20**delay_in%20%E2%86%92%20matrix%20%E2%86%92%20delay_out**%20to%20increase%20echo%20density.%0A%20%20%20%203.%20**Swapped%20feedforward%2Ffeedback**%20%E2%80%94%20Copy%20again%20and%20swap%20the%20base-delay%20and%20delay-matrix%20paths.%0A%0A%20%20%20%20Reference%3A%20*Schlecht%2C%20S.%2C%20Habets%2C%20E.%20(2019).%20Dense%20Reverberation%20with%20Delay%20Feedback%20Matrices.*%20Proc.%20IEEE%20Workshop%20Applicat.%20Signal%20Process.%20Audio%20Acoust.%20(WASPAA).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20plotly.graph_objects%20as%20go%0A%20%20%20%20import%20plotly.io%20as%20pio%0A%0A%20%20%20%20pio.renderers.default%20%3D%20%22sphinx_gallery%22%20%20%23%20interactive%20in%20Jupyter%20%2B%20docs%20HTML%0A%0A%20%20%20%20import%20pyFDN%0A%0A%20%20%20%20return%20go%2C%20np%2C%20pyFDN%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Parameters%0A%0A%20%20%20%20Set%20RNG%20seed%2C%20sampling%20rate%2C%20number%20of%20delay%20lines%20**N**%2C%20broadband%20RT%2C%0A%20%20%20%20and%20base%20delays%20plus%20extra%20**delays_in**%20%2F%20**delays_out**%20for%20the%0A%20%20%20%20delay%2Bmatrix%2Bdelay%20chain.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20pyFDN)%3A%0A%20%20%20%20rng%20%3D%20np.random.default_rng(7)%0A%0A%20%20%20%20fs%20%3D%2048000%0A%20%20%20%20nfft%20%3D%202**18%0A%20%20%20%20N%20%3D%208%0A%20%20%20%20rt%20%3D%203.0%0A%20%20%20%20gain_per_sample%20%3D%20pyFDN.rt_to_gain_per_sample(rt%2C%20fs)%0A%20%20%20%20delays%20%3D%20rng.integers(1000%2C%205000%2C%20size%3DN).astype(np.int64)%0A%20%20%20%20delays_in%20%3D%20rng.integers(0%2C%20200%2C%20size%3DN).astype(np.int64)%0A%20%20%20%20delays_out%20%3D%20rng.integers(0%2C%20200%2C%20size%3DN).astype(np.int64)%0A%20%20%20%20total_delay%20%3D%20delays%20%2B%20delays_in%20%2B%20delays_out%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20delays%2C%0A%20%20%20%20%20%20%20%20delays_in%2C%0A%20%20%20%20%20%20%20%20delays_out%2C%0A%20%20%20%20%20%20%20%20fs%2C%0A%20%20%20%20%20%20%20%20gain_per_sample%2C%0A%20%20%20%20%20%20%20%20nfft%2C%0A%20%20%20%20%20%20%20%20total_delay%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Build%20vanilla%20FDN%0A%0A%20%20%20%20Create%20the%20complete%20broadband%20FDN%20with%20%60pyFDN.fdn_build_gallery%60%2C%20then%0A%20%20%20%20render%20it%20with%20%60pyFDN.dss_to_flamo%60.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(fs%2C%20gain_per_sample%2C%20nfft%2C%20np%2C%20pyFDN%2C%20total_delay)%3A%0A%20%20%20%20build%20%3D%20pyFDN.fdn_build_gallery(%0A%20%20%20%20%20%20%20%20fs%3Dfs%2C%0A%20%20%20%20%20%20%20%20delays%3Dtotal_delay%2C%0A%20%20%20%20%20%20%20%20io_type%3D%22ones%22%2C%0A%20%20%20%20%20%20%20%20direct_gain%3D1.0%2C%0A%20%20%20%20%20%20%20%20rt%3DNone%2C%0A%20%20%20%20%20%20%20%20rng%3D42%2C%0A%20%20%20%20)%0A%20%20%20%20%23%20Bake%20delay-proportional%20broadband%20decay%20into%20the%20lossless%20feedback%20matrix.%0A%20%20%20%20A%20%3D%20np.diag(gain_per_sample**build.delays)%20%40%20build.A%0A%20%20%20%20model%20%3D%20pyFDN.dss_to_flamo(%0A%20%20%20%20%20%20%20%20A%2C%0A%20%20%20%20%20%20%20%20build.B%2C%0A%20%20%20%20%20%20%20%20build.C%2C%0A%20%20%20%20%20%20%20%20build.D%2C%0A%20%20%20%20%20%20%20%20build.delays%2C%0A%20%20%20%20%20%20%20%20build.fs%2C%0A%20%20%20%20%20%20%20%20nfft%3Dnfft%2C%0A%20%20%20%20%20%20%20%20sos_filter%3Dbuild.filters%2C%0A%20%20%20%20%20%20%20%20output_filter%3Dbuild.post_eq%2C%0A%20%20%20%20)%0A%20%20%20%20ir_vanilla%20%3D%20pyFDN.flamo_time_response(model).flatten()%0A%20%20%20%20pyFDN.plot_flamo_graph(model)%0A%20%20%20%20return%20ir_vanilla%2C%20model%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Copy%20model%20and%20insert%20delay%2Bmatrix%2Bdelay%20in%20feedback%0A%0A%20%20%20%20Deep-copy%20the%20vanilla%20model%2C%20split%20its%20total%20delays%20into%20a%20base%20delay%20and%0A%20%20%20%20**delay_in%20%E2%86%92%20matrix%20%E2%86%92%20delay_out**%2C%20then%20move%20the%20latter%20path%20into%20the%0A%20%20%20%20feedback%20branch.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(delays%2C%20delays_in%2C%20delays_out%2C%20model%2C%20pyFDN)%3A%0A%20%20%20%20model_delay_matrix%20%3D%20pyFDN.flamo_delay_feedback_matrix(%0A%20%20%20%20%20%20%20%20model%2C%0A%20%20%20%20%20%20%20%20delays%2C%0A%20%20%20%20%20%20%20%20delays_in%2C%0A%20%20%20%20%20%20%20%20delays_out%2C%0A%20%20%20%20)%0A%0A%20%20%20%20ir_delay_matrix%20%3D%20pyFDN.flamo_time_response(model_delay_matrix).flatten()%0A%0A%20%20%20%20pyFDN.plot_flamo_graph(model_delay_matrix)%0A%20%20%20%20return%20ir_delay_matrix%2C%20model_delay_matrix%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Copy%20model%20and%20swap%20feedforward%20and%20feedback%0A%0A%20%20%20%20Make%20another%20copy%20of%20the%20delay-matrix%20model%20and%20**swap**%20its%20two%20recursion%0A%20%20%20%20paths%20without%20changing%20any%20modules%20or%20parameter%20values.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(model_delay_matrix%2C%20pyFDN)%3A%0A%20%20%20%20model_swapped%20%3D%20pyFDN.swap_flamo_recursion_paths(model_delay_matrix)%0A%0A%20%20%20%20ir_swapped%20%3D%20pyFDN.flamo_time_response(model_swapped).flatten()%0A%0A%20%20%20%20pyFDN.plot_flamo_graph(model_swapped)%0A%20%20%20%20return%20(ir_swapped%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Plot%20and%20listen%0A%0A%20%20%20%20Impulse%20responses%20(%CE%BC-law)%20and%20**echo%20density**%20(Abel%20%26%20Huang%202006)%20for%20the%20three%20topologies.%20Echo%20density%20is%20computed%20with%20%60pyFDN.echo_density%60%3B%20the%20horizontal%20dashed%20line%20marks%20the%20mixing-time%20threshold%20(1.0).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(fs%2C%20go%2C%20ir_delay_matrix%2C%20ir_swapped%2C%20ir_vanilla%2C%20mo%2C%20np%2C%20pyFDN)%3A%0A%20%20%20%20t%20%3D%20np.arange(len(ir_vanilla))%20%2F%20fs%0A%0A%20%20%20%20_%2C%20echo_vanilla%20%3D%20pyFDN.echo_density(ir_vanilla%2C%20n%3D1024%2C%20fs%3Dfs)%0A%20%20%20%20_%2C%20echo_delay_matrix%20%3D%20pyFDN.echo_density(ir_delay_matrix%2C%20n%3D1024%2C%20fs%3Dfs)%0A%20%20%20%20_%2C%20echo_swapped%20%3D%20pyFDN.echo_density(ir_swapped%2C%20n%3D1024%2C%20fs%3Dfs)%0A%0A%20%20%20%20fig%20%3D%20pyFDN.plot_impulse_response(%0A%20%20%20%20%20%20%20%20ir_vanilla%2C%0A%20%20%20%20%20%20%20%20ir_delay_matrix%2C%0A%20%20%20%20%20%20%20%20ir_swapped%2C%0A%20%20%20%20%20%20%20%20fs%3Dfs%2C%0A%20%20%20%20%20%20%20%20labels%3D%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Vanilla%20FDN%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Delay%2Bmatrix%2Bdelay%20in%20feedback%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Swapped%20feedforward%2Ffeedback%22%2C%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20title%3D%22Delay%20feedback%20matrix%20density%22%2C%0A%20%20%20%20)%0A%0A%20%20%20%20fig2%20%3D%20go.Figure()%0A%20%20%20%20fig2.add_trace(%0A%20%20%20%20%20%20%20%20pyFDN.downsampled_scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dt%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Decho_vanilla%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lines%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Vanilla%20FDN%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3D%7B%22width%22%3A%200.8%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20opacity%3D0.8%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20fig2.add_trace(%0A%20%20%20%20%20%20%20%20pyFDN.downsampled_scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dt%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Decho_delay_matrix%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lines%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Delay%2Bmatrix%2Bdelay%20in%20feedback%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3D%7B%22width%22%3A%200.8%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20opacity%3D0.8%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20fig2.add_trace(%0A%20%20%20%20%20%20%20%20pyFDN.downsampled_scatter(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3Dt%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3Decho_swapped%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mode%3D%22lines%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22Swapped%20feedforward%2Ffeedback%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3D%7B%22width%22%3A%200.8%7D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20opacity%3D0.8%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20fig2.add_hline(%0A%20%20%20%20%20%20%20%20y%3D1.0%2C%20line_dash%3D%22dash%22%2C%20line_color%3D%22gray%22%2C%20annotation_text%3D%22mixing%20thresh%22%0A%20%20%20%20)%0A%20%20%20%20fig2.update_layout(%0A%20%20%20%20%20%20%20%20title%3D%22Echo%20density%20(Abel%20%26%20Huang%202006)%22%2C%0A%20%20%20%20%20%20%20%20xaxis_title%3D%22Time%20%5Bs%5D%22%2C%0A%20%20%20%20%20%20%20%20yaxis_title%3D%22Echo%20density%22%2C%0A%20%20%20%20%20%20%20%20xaxis%3D%7B%22range%22%3A%20%5B0%2C%200.8%5D%2C%20%22showgrid%22%3A%20True%2C%20%22gridwidth%22%3A%201%2C%20%22griddash%22%3A%20%22dot%22%7D%2C%0A%20%20%20%20%20%20%20%20yaxis%3D%7B%22showgrid%22%3A%20True%2C%20%22gridwidth%22%3A%201%2C%20%22griddash%22%3A%20%22dot%22%7D%2C%0A%20%20%20%20%20%20%20%20legend%3D%7B%22yanchor%22%3A%20%22bottom%22%2C%20%22y%22%3A%200.99%2C%20%22xanchor%22%3A%20%22right%22%2C%20%22x%22%3A%200.99%7D%2C%0A%20%20%20%20%20%20%20%20height%3D350%2C%0A%20%20%20%20%20%20%20%20margin%3D%7B%22l%22%3A%2060%2C%20%22r%22%3A%2040%2C%20%22t%22%3A%2050%2C%20%22b%22%3A%2050%7D%2C%0A%20%20%20%20)%0A%0A%20%20%20%20plots%20%3D%20mo.vstack(%5Bfig%2C%20fig2%5D)%0A%0A%20%20%20%20audio_blocks%20%3D%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22Vanilla%3A%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.audio(ir_vanilla%2C%20rate%3Dfs)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22Delay%20matrix%3A%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.audio(ir_delay_matrix%2C%20rate%3Dfs)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(%22Swapped%3A%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.audio(ir_swapped%2C%20rate%3Dfs)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%0A%20%20%20%20mo.vstack(%5Bplots%2C%20audio_blocks%5D)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
5b7a42e0be03feb69ac89115960ba05a