Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
!doc_generation/**
!examples/
!examples/**
!workshop_templates/
!workshop_templates/**

!mmm_audio/
!mmm_audio/**
Expand Down
44 changes: 44 additions & 0 deletions workshop_templates/FFTTemplate.mojo
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from mmm_audio import *

comptime windowsize: Int = 1024
comptime hopsize: Int = windowsize // 4

struct WorkshopFFTWindow(FFTProcessable):
var world: World
var m: Messenger

def next_frame(mut self, mut magnitudes: List[Float64], mut phases: List[Float64]) -> None:
# do something to the magnitudes and phases here (remove "pass")
pass

def __init__(out self, world: World):
self.world = world
self.m = Messenger(self.world)

def get_messages(mut self) -> None:
# get messages from Python here. For example:
# self.m.update(self.my_parameter, "my_parameter")
# (remove "pass")
pass

struct FFTTemplate(Movable, Copyable):
var world: World
var buffer: Buffer
var playBuf: Play
var fft_process: FFTProcess[WorkshopFFTWindow]

def __init__(out self, world: World):
self.world = world
self.buffer = Buffer.load("resources/Shiverer.wav")
self.playBuf = Play(self.world)
self.fft_process = FFTProcess[WorkshopFFTWindow](
world=self.world,
process=WorkshopFFTWindow(self.world),
window_size=windowsize,
hop_size=hopsize
)

def next(mut self) -> SIMD[DType.float64,2]:
input = self.playBuf.next(self.buffer) # Read samples from the buffer
out = self.fft_process.next(input)
return out
16 changes: 16 additions & 0 deletions workshop_templates/FFTTemplate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from mmm_python import *

mmm_audio = MMMAudio(
in_device='default',
out_device='default',
blocksize=128,
graph_name="FFTTemplate",
package_name="workshop_templates"
)

mmm_audio.start_audio()

# send some parameters to Python here. For example:
# mmm_audio.send_float("my_parameter", 0.5)

mmm_audio.stop_audio()
78 changes: 78 additions & 0 deletions workshop_templates/SubtractiveTemplate.mojo
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"""Subtractive Synthesis Workshop Template.

This is a template for a subtractive synthesis graph. It includes a saw oscillator,
a Moog ladder filter, and an LFO to modulate the filter cutoff.

If you want to just start hacking, go for it. If you want a bit of structure, below are some steps you might follow.

In either case, you'll want to use the documentation!: [https://spluta.github.io/MMMAudio/](https://spluta.github.io/MMMAudio/)

1. Start by running this graph from Python using the SubtractiveTemplate.py file. In that
file, adjust some parameters and hear the result.
2. Change the scaling of the LFO so that it sounds different (note that the "exp" range values of linexp must be
greater than zero).
3. Remove the comment "#" signs that are preventing the wavefolder from being used. In Python, adjust the amount and
listen to the result.
4. Change the oscillator type to something other than a saw by changing the `osc_type` parameter in the `next` method.
5. Add a second LFO to modulate another parameter such as the wavefolder amount or the oscillator frequency.

"""

from mmm_audio import *

comptime num_chans: Int = 2
comptime oversample_index: Int = 1

struct SubtractiveTemplate(Movable, Copyable):
var world: World
var m: Messenger

# Oscillator stuff
var saw: Osc[num_chans=num_chans,interp=Interp.quad,os_index=oversample_index]
var freq: MFloat[1]

# Filter stuff
var lpf: VAMoogLadder[num_chans=num_chans,os_index=oversample_index]
var ffreq: MFloat[1]
var res: MFloat[1]

# LFO stuff
var lfo: Osc[]
var lfo_freq: MFloat[1]

# Wavefolder
# var wavefolder: BuchlaWavefolder[num_chans=num_chans,os_index=oversample_index]
# var fold_amt: MFloat[1]

def __init__(out self, world: World):
self.world = world
self.m = Messenger(self.world)

self.saw = Osc[num_chans=num_chans,interp=Interp.quad,os_index=oversample_index](self.world)
self.freq = MFloat[1](440.0)

# self.wavefolder = BuchlaWavefolder[num_chans=num_chans,os_index=oversample_index](self.world)
# self.fold_amt = MFloat[1](0.5)

self.lfo = Osc[](self.world)
self.lfo_freq = MFloat[1](3)

self.lpf = VAMoogLadder[num_chans=num_chans,os_index=oversample_index](self.world)
self.ffreq = MFloat[1](1000.0)
self.res = MFloat[1](0.5)

def next(mut self) -> MFloat[2]:
self.m.update(self.freq, "freq")
self.m.update(self.ffreq, "ffreq")
self.m.update(self.res, "res")
self.m.update(self.lfo_freq, "lfo_freq")
# self.m.update(self.fold_amt, "fold_amt")

sig = self.saw.next(self.freq,osc_type=OscType.saw)
# sig = self.wavefolder.next(sig, self.fold_amt)

lfo = self.lfo.next(self.lfo_freq)
lfo = linexp(lfo, -1.0, 1.0, 0.1, 10000.0)
ffreq = clip(self.ffreq + lfo, 20.0, 20000.0)
sig = self.lpf.next(sig, ffreq, clip(self.res, 0.0, 1.0))
return sig * dbamp(-10.0)
20 changes: 20 additions & 0 deletions workshop_templates/SubtractiveTemplate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from mmm_python import *

mmm_audio = MMMAudio(
in_device='default',
out_device='default',
blocksize=128,
graph_name="SubtractiveTemplate",
package_name="workshop_templates"
)

mmm_audio.start_audio()

mmm_audio.send_float("freq", 80)
mmm_audio.send_float("ffreq", 1500)
mmm_audio.send_float("res", 0.99)
mmm_audio.send_float("lfo_freq", 2)

mmm_audio.send_float("fold_amt", 0.3)

mmm_audio.stop_audio()
Empty file.
Empty file added workshop_templates/__init__.py
Empty file.
Loading