Skip to content

For more information about the examples, such as how the Python and Mojo files interact with each other, see the Examples Overview

FFTScramble

Python Code

from mmm_python import *

mmm_audio = MMMAudio(
    in_device=None,
    out_device='default',
    blocksize=128, 
    graph_name="FFTScramble", 
    package_name="examples"
    )

mmm_audio.start_audio()

mmm_audio.send_int("n_scrambles",80)
mmm_audio.send_int("scramble_range",20)

mmm_audio.send_trig("scramble")

mmm_audio.stop_audio()

Mojo Code

from mmm_audio import *

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

struct FFTScrambleWindow(FFTProcessable):
    var world: World
    var swaps: List[Tuple[Int,Int]]
    var nbins: Int
    var nscrambles: Int
    var scramble_range: Int
    var m: Messenger

    def next_frame(mut self, mut magnitudes: List[Float64], mut phases: List[Float64]) -> None:
        for (i,j) in self.swaps:
            temp_mag = magnitudes[i]
            magnitudes[i] = magnitudes[j]
            magnitudes[j] = temp_mag
            temp_phase = phases[i]
            phases[i] = phases[j]
            phases[j] = temp_phase

    def __init__(out self, world: World, nbins: Int):
        self.world = world
        self.nbins = nbins
        self.nscrambles = 30
        self.swaps = List[Tuple[Int,Int]]()
        self.scramble_range = 10
        self.m = Messenger(self.world)
        self.scramble()

    def scramble(mut self) -> None:
        self.swaps.clear()
        for _ in range(self.nscrambles):
            i_f = linlin(random_float64() ** 3, 0.0, 1.0, 0.0, Float64(self.nbins - 1))
            i = Int(i_f)
            minj = max(i - self.scramble_range,0)
            maxj = min(i + self.scramble_range, self.nbins - 1)
            j_f = rrand(minj, maxj)
            j = Int(j_f)
            self.swaps.append((i,j))

    def get_messages(mut self) -> None:
        self.m.update("n_scrambles", self.nscrambles)
        self.m.update("scramble_range", self.scramble_range)
        if self.m.notify_trig("scramble"):
            self.scramble()

struct FFTScramble(Movable, Copyable):
    var world: World
    var buffer: Buffer
    var playBuf: Play
    var fft_scramble: FFTProcess[FFTScrambleWindow]

    def __init__(out self, world: World):
        self.world = world
        self.buffer = Buffer.load("resources/Shiverer.wav")
        self.playBuf = Play(self.world) 
        self.fft_scramble = FFTProcess[FFTScrambleWindow](self.world,process=FFTScrambleWindow(self.world,(windowsize//2)+1),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_scramble.next(input)
        return SIMD[DType.float64,2](out,out)