For more information about the examples, such as how the Python and Mojo files interact with each other, see the Examples Overview
DattorroReverbExample¶
This example demonstrates the Dattorro Reverb graph, which is a reverb algorithm created by Jon Dattorro in his paper "Effect Design Part 1: Reverberator and Other Filters".
Python Code¶
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent))
from mmm_python.GUI import Handle, ControlSpec
from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout, QCheckBox
from mmm_python import *
def add_handle(layout, mmm_audio, name: str, min: float, max: float, exp: float, default: float, resolution: float, display_resolution: int):
"""Create a slider and connect it to the audio graph."""
slider = Handle(name, ControlSpec(min, max, exp), default, callback=lambda v: mmm_audio.send_float(name, v), resolution = resolution, display_resolution = display_resolution)
layout.addWidget(slider)
mmm_audio.send_float(name, default)
def main():
# instantiate and load the graph
m_a = MMMAudio(128, 18, graph_name="DattorroReverbExample", package_name="examples")
m_a.send_int("in_chan", 0)
m_a.start_audio()
app = QApplication([])
# Create the main window
window = QWidget()
window.setWindowTitle("Dattorro Reverb")
window.resize(300, 100)
# stop audio when window is closed
window.closeEvent = lambda event: (m_a.exit_all(), event.accept())
# Create layout
layout = QVBoxLayout()
# Add all the controls
add_handle(layout, m_a, "pre_delay_time", 0.0, 0.5, 1.0, 0.00, 10000, 6)
add_handle(layout, m_a, "decay", 0.001, 1.0, 1.0, 0.83, 10000, 6)
add_handle(layout, m_a, "input_diffusion1", 0.0, 1.0, 1.0, 0.81, 10000, 6)
add_handle(layout, m_a, "input_diffusion2", 0.0, 1.0, 1.0, 0.66, 10000, 6)
add_handle(layout, m_a, "decay_diffusion1", 0.0, 1.0, 1.0, 0.43, 10000, 6)
add_handle(layout, m_a, "decay_diffusion2", 0.0, 1.0, 1.0, 0.81, 10000, 6)
add_handle(layout, m_a, "bandwidth", 0.0, 1.0, 1.0, 0.3, 10000, 6)
add_handle(layout, m_a, "damping", 0.0, 1.0, 1.0, 0.004, 10000, 6)
# Set the layout for the main window
window.setLayout(layout)
# Show the window
window.show()
# Start the application's event loop
sys.exit(app.exec())
if __name__ == "__main__":
main()
Mojo Code¶
from mmm_audio import *
struct DattorroReverbExample(Movable, Copyable):
var world: World
var m: Messenger
var reverb: DattorroReverb[Interp.none] #the original uses Interp.none on the non-modulated delay lines
var in_chan: Int
fn __init__(out self, world: World):
self.world = world
self.m = Messenger(world)
self.reverb = DattorroReverb[Interp.none](world)
self.in_chan = 0
fn next(mut self) -> MFloat[2]:
self.m.update(self.in_chan, "in_chan")
input = MFloat[2](self.world[].sound_in[self.in_chan])
self.m.update(self.reverb.pre_delay_time, "pre_delay_time")
self.m.update(self.reverb.decay, "decay")
self.m.update(self.reverb.bandwidth, "bandwidth")
self.m.update(self.reverb.damping, "damping")
self.m.update(self.reverb.decay_diffusion1, "decay_diffusion1")
self.m.update(self.reverb.decay_diffusion2, "decay_diffusion2")
self.m.update(self.reverb.input_diffusion1, "input_diffusion1")
self.m.update(self.reverb.input_diffusion2, "input_diffusion2")
return self.reverb.next(input)