Skip to content
Traits

trait FFTProcessable

Implement this trait in a custom struct to pass to FFTProcess as a Parameter.

See TestFFTProcess.mojo for an example on how to create a spectral process using a struct that implements FFTProcessable.

This trait requires that two functions be implemented (see below for more details).

  • fn next_frame(): This function gets passed a list of magnitudes and a list of phases that are the result of an FFT. The user should manipulate these values in place so that once this function is done the values in those lists are what the user wants to be used for the IFFT conversion back into amplitude samples. Because the FFT only happens every hop_size samples (and uses the most recent window_size samples), this function only gets called every hop_size samples. hop_size is set as a parameter in the FFTProcessor struct that the user's struct is passed to.
  • fn get_messages(): Because .next_frame() only runs every hop_size samples and a Messenger can only check for new messages from Python at the top of every audio block, it's not guaranteed that these will line up, so this struct could very well miss incoming messages! To remedy this, put all your message getting code in this get_messages() function. It will get called by FFTProcessor (whose .next() function does get called every sample) to make sure that any messages intended for this struct get updated.

Outline of Spectral Processing:

  1. The user creates a custom struct that implements the FFTProcessable trait. The required functions for that are .next_frame() and .get_messages(). .next_frame() is passed a List[Float64] of magnitudes and a List[Float64] of phases. The user can manipulate this data however they want and then needs to replace the values in those lists with what they want to be used for the IFFT.
  2. The user passes their struct (in 1) as a Parameter to the FFTProcess struct. You can see where the parameters such as window_size, hop_size, and window types are expressed.
  3. In the user synth's .next() function (running one sample at a time) they pass in every sample to the FFTProcess's .next() function which:
    • has a BufferedProcess to store samples and pass them on to FFTProcessor when appropriate
    • when FFTProcessor receives a window of amplitude samples, it performs an FFT getting the mags and phases which are then passed on to the user's struct that implements FFTProcessable. The mags and phases are modified in place and then this whole pipeline basically hands the data all the way back out to the user's synth struct where FFTProcess's .next() function returns the next appropriate sample (after buffering -> FFT -> processing -> IFFT -> output buffering) to get out to the speakers (or whatever).

FFTProcessable Required Methods

trait FFTProcessable . fn next_frame

Signature

next_frame(mut self: _Self, mut magnitudes: List[Float64], mut phases: List[Float64])

Arguments

  • magnitudes: List- phases: List

Default Implementation

This method has a default implementation.


trait FFTProcessable . fn next_stereo_frame

Signature

next_stereo_frame(mut self: _Self, mut magnitudes: List[SIMD[DType.float64, 2]], mut phases: List[SIMD[DType.float64, 2]])

Arguments

  • magnitudes: List- phases: List

Default Implementation

This method has a default implementation.


trait FFTProcessable . fn get_messages

Signature

get_messages(mut self: _Self)

Default Implementation

This method has a default implementation.


Structs

struct FFTProcess

Create an FFTProcess for audio manipulation in the frequency domain.

FFTProcess is similar to BufferedProcess, but instead of passing time domain samples to the user defined struct, it passes frequency domain magnitudes and phases (obtained from an FFT). The user defined struct must implement the FFTProcessable trait, which requires the implementation of the .next_frame() function. This function receives two Lists: one for magnitudes and one for phases. The user can do whatever they want with the values in these Lists, and then must replace the values in the Lists with the values they want to be used for the IFFT to convert the information back to amplitude samples.

Traits: AnyType, Copyable, Movable, UnknownDestructibility

FFTProcess Parameters

Name Type Description
T FFTProcessable A user defined struct that implements the FFTProcessable trait.
window_size Int The size of the FFT window. The default is 1024 samples.
hop_size Int The number of samples between each processed spectral frame. The default is 512.
input_window_shape Optional An Optional[Int] specifying what window shape to use to modify the amplitude of the input samples before the FFT. See mmm_utils.Windows -> WindowTypes for the options.
output_window_shape Optional An Optional[Int] specifying what window shape to use to modify the amplitude of the output samples after the IFFT. See mmm_utils.Windows -> WindowTypes for the options.

FFTProcess Functions

struct FFTProcess . fn init

Initializes a FFTProcess struct.

fn init Signature

__init__(out self, world: UnsafePointer[MMMWorld], var process: T)

fn init Arguments

Name Type Default Description
world UnsafePointer A pointer to the MMMWorld.
process T A user defined struct that implements the FFTProcessable trait.

fn init Returns : Self An initialized FFTProcess struct.

Static Method

This is a static method.

struct FFTProcess . fn next

Processes the next input sample and returns the next output sample.

fn next Signature

next(mut self, input: Float64) -> Float64

fn next Arguments

Name Type Default Description
input Float64 The next input sample to process.

fn next Returns : Float64 The next output sample.

struct FFTProcess . fn next_stereo

Processes the next stereo input sample and returns the next output sample.

fn next_stereo Signature

next_stereo(mut self, input: SIMD[DType.float64, 2]) -> SIMD[DType.float64, 2]

fn next_stereo Arguments

Name Type Default Description
input SIMD The next input sample to process.

fn next_stereo Returns : SIMD The next output sample.

struct FFTProcess . fn next_from_buffer

Returns the next output sample from the internal buffered process. The buffered process reads a block of samples from the provided buffer at the given phase and channel on each hop.

fn next_from_buffer Signature

next_from_buffer(mut self, ref buffer: Buffer, phase: Float64, start_chan: Int = 0) -> Float64

fn next_from_buffer Arguments

Name Type Default Description
buffer Buffer The input buffer to read samples from.
phase Float64 The current phase to read from the buffer.
start_chan Int 0 The firstchannel to read from the buffer.

fn next_from_buffer Returns : Float64 The next output sample from the internal buffer.

struct FFTProcess . fn next_from_stereo_buffer

Returns the next stereo output sample from the internal buffered process. The buffered process reads a block of samples from the provided buffer at the given phase and channel on each hop.

fn next_from_stereo_buffer Signature

next_from_stereo_buffer(mut self, ref buffer: Buffer, phase: Float64, start_chan: Int = 0) -> SIMD[DType.float64, 2]

fn next_from_stereo_buffer Arguments

Name Type Default Description
buffer Buffer The input buffer to read samples from.
phase Float64 The current phase to read from the buffer.
start_chan Int 0 The firstchannel to read from the buffer.

fn next_from_stereo_buffer Returns : SIMD The next stereo output sample from the internal buffer.


Documentation generated with mojo doc from Mojo version 0.25.6.1