For more information about the examples, such as how the Python and Mojo files interact with each other, see the Examples Overview
PanAzExample¶
Python Code¶
from mmm_src.MMMAudio import MMMAudio
# instantiate and load the graph
# PanAz is not quite right as of yet
mmm_audio = MMMAudio(128, graph_name="PanAzExample", package_name="examples", num_output_channels=8)
mmm_audio.start_audio()
mmm_audio.send_int("num_speakers", 2 ) # set the number of speakers to between 2 and 8
mmm_audio.send_int("num_speakers", 8 ) # set the number of speakers to between 2 and 8
mmm_audio.send_float("width", 1.0 ) # set the width to 1.0 (one speaker at a time)
mmm_audio.send_float("width", 3.0 ) # set the width to 3.0 (extra wide stereo width)
from random import random
mmm_audio.send_float("freq", random() * 500 + 100 ) # set the frequency to a random value
Mojo Code¶
from mmm_src.MMMWorld import MMMWorld
from mmm_utils.Messenger import Messenger
from mmm_utils.functions import *
from mmm_src.MMMTraits import *
from mmm_dsp.Osc import Phasor, Osc
from mmm_dsp.Pan import pan_az
struct PanAz_Synth(Representable, Movable, Copyable):
var world: UnsafePointer[MMMWorld]
var osc: Osc
var freq: Float64
var pan_osc: Phasor
var num_speakers: Int64
var width: Float64
var messenger: Messenger
fn __init__(out self, world: UnsafePointer[MMMWorld]):
self.world = world
self.osc = Osc(self.world)
self.freq = 440.0
self.pan_osc = Phasor(self.world)
self.num_speakers = 7 # default to 7 speakers
self.width = 2.0
self.messenger = Messenger(self.world)
fn __repr__(self) -> String:
return String("Default")
fn next(mut self) -> SIMD[DType.float64, 8]:
self.messenger.update(self.freq, "freq")
self.messenger.update(self.num_speakers, "num_speakers")
self.messenger.update(self.width, "width")
# PanAz needs to be given a SIMD size that is a power of 2, in this case [8], but the speaker size can be anything smaller than that
panned = pan_az[8](self.osc.next(self.freq, osc_type=2), self.pan_osc.next(0.1), self.num_speakers, self.width) * 0.1
if self.num_speakers == 2:
return SIMD[DType.float64, 8](panned[0], panned[1], 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)
else:
return SIMD[DType.float64, 8](panned[0], panned[2], panned[1], 0.0, panned[6], panned[3], panned[5], panned[4])
# there can only be one graph in an MMMAudio instance
# a graph can have as many synths as you want
struct PanAzExample(Representable, Movable, Copyable):
var world: UnsafePointer[MMMWorld]
var synth: PanAz_Synth
fn __init__(out self, world: UnsafePointer[MMMWorld]):
self.world = world
self.synth = PanAz_Synth(self.world)
fn __repr__(self) -> String:
return String("PanAzExample")
fn next(mut self) -> SIMD[DType.float64, 8]:
sample = self.synth.next() # Get the next sample from the synth
# the output will pan to the number of channels available
# if there are fewer than 5 channels, only those channels will be output
return sample # Return the combined output samples