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

PitchShiftExample

this uses the mouse to control granular playback of the buffer left and right moves around in the buffer. up and down controls rate of triggers.

Python Code

from mmm_src.MMMAudio import MMMAudio

mmm_audio = MMMAudio(128, num_input_channels = 12, graph_name="PitchShiftExample", package_name="examples")

mmm_audio.start_audio() # start the audio thread - or restart it where it left off

mmm_audio.send_float("which_input", 0)
mmm_audio.send_float("pitch_shift", 1.25)
mmm_audio.send_float("grain_size", 0.4)
mmm_audio.send_float("pitch_dispersion", 0.4)
mmm_audio.send_float("time_dispersion", 0.5)

mmm_audio.stop_audio()  # stop the audio thread

Mojo Code

from mmm_src.MMMWorld import MMMWorld
from mmm_utils.functions import *

from mmm_dsp.PlayBuf import *
from mmm_dsp.Filters import VAMoogLadder
from mmm_utils.functions import linexp
from random import random_float64
from mmm_utils.Messenger import Messenger

# THE SYNTH

struct PitchShiftExample(Representable, Movable, Copyable):
    var world: UnsafePointer[MMMWorld]

    var pitch_shift: PitchShift[num_chans=2]
    var messenger: Messenger
    var shift: Float64
    var grain_size: Float64
    var pitch_dispersion: Float64
    var time_dispersion: Float64
    var which_input: Float64

    fn __init__(out self, world: UnsafePointer[MMMWorld]):
        self.world = world
        self.pitch_shift = PitchShift[num_chans=2](world, 1.0) # the duration of the buffer needs to == grain size*(max_pitch_shift-1).
        self.messenger = Messenger(world)
        self.shift = 1.0
        self.grain_size = 0.2
        self.pitch_dispersion = 0.0
        self.time_dispersion = 0.0
        self.which_input = 0.0

    @always_inline
    fn next(mut self) -> SIMD[DType.float64, 2]:
        self.messenger.update(self.which_input, "which_input")
        temp = self.world[].sound_in[0]
        input_sig = select(self.which_input, [SIMD[DType.float64, 2](temp, temp), SIMD[DType.float64, 2](temp, 0.0), SIMD[DType.float64, 2](0.0, temp)])

        self.messenger.update(self.shift,"pitch_shift")
        self.messenger.update(self.grain_size,"grain_size")
        self.messenger.update(self.pitch_dispersion,"pitch_dispersion")
        self.messenger.update(self.time_dispersion,"time_dispersion")

        # shift = linexp(self.world[].mouse_y, 0.0, 1.0, 0.25, 4.0)
        # grain_size = linexp(self.world[].mouse_x, 0.0, 1.0, 0.05, 0.3)
        out = self.pitch_shift.next(input_sig, self.grain_size, self.shift, self.pitch_dispersion, self.time_dispersion)

        return out

    fn __repr__(self) -> String:
        return String("PitchShift")