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

SpectralFluxOnsetExample

This example demonstrates using SpectralFluxOnsets to detect onsets in an audio file. The audio plays in the left channel and onset impulses are heard in the right channel.

Python Code

from mmm_python import *
ma = MMMAudio(128, graph_name="SpectralFluxOnsetExample", package_name="examples")
ma.start_audio()

# Adjust threshold for onset sensitivity (lower = more sensitive)
ma.send_float("thresh", 67)
# Adjust minimum slice length between onsets (higher = less sensitive)
ma.send_float("minSliceLength", 0.3)  

# Adjust impulse volume
ma.send_float("impulse_vol", 0.5)

ma.stop_audio()

Mojo Code

from mmm_audio import *

comptime fft_size: Int = 1024

struct SpectralFluxOnsetExample(Movable, Copyable):
    var world: World
    var buffer: Buffer
    var playBuf: Play
    var onsets: SpectralFluxOnsets
    var m: Messenger
    var impulse_vol: Float64
    var onsetcounter: Int64

    fn __init__(out self, world: World):
        self.world = world
        self.buffer = Buffer.load("resources/Shiverer.wav")
        self.playBuf = Play(self.world)
        self.onsets = SpectralFluxOnsets(self.world,(fft_size//2) + 1)
        self.onsets.thresh = 67.0
        self.onsets.min_slice_len = 0.3
        self.m = Messenger(self.world)
        self.impulse_vol = 0.5
        self.onsetcounter = 0

    fn next(mut self) -> MFloat[2]:

        self.m.update(self.onsets.thresh,"thresh")
        self.m.update(self.impulse_vol,"impulse_vol")
        self.m.update(self.onsets.min_slice_len,"minSliceLength")

        # play the audio file
        audio = self.playBuf.next(self.buffer)

        # analyze for onsets
        _ = self.onsets.next(audio)

        # update threshold

        if self.onsets.state:
            print("onset",self.onsetcounter)
            self.onsetcounter += 1

        # generate impulse when onset detected
        impulse = self.impulse_vol if self.onsets.state else 0.0

        # left channel: audio, right channel: impulses
        return MFloat[2](audio, impulse)