19 releases

0.2.12-alpha.0 Apr 7, 2023
0.2.11-alpha.0 Dec 19, 2022
0.2.5-alpha.0 Jun 21, 2022
0.2.4-alpha.0 Mar 14, 2022
0.1.42-alpha.0 Oct 27, 2021

#11 in #modulation


Used in 3 crates

GPL-3.0 license

510KB
10K SLoC

FM Oscillator for the Surge synthesizer system

The surgeosc-fm crate provides an implementation of a Frequency Modulation (FM) Oscillator for the Surge synthesizer system. This oscillator allows the creation of complex and rich sounds by modulating the frequency of one waveform (carrier) with the amplitude of another waveform (modulator). This FM synthesis technique is widely used in electronic music production, offering a vast range of sonic possibilities.

In the context of FM synthesis, the core mathematical concept is frequency modulation, represented by the following equation:

output(t) = A * sin(2 * π * (f_c + (B * f_m) * sin(2 * π * f_m * t)) * t)

where:

  • output(t) is the oscillator output at time t
  • A is the amplitude
  • f_c is the carrier frequency
  • B is the modulation index
  • f_m is the modulator frequency

This crate provides the following tokens:

  • control_group, control_type, default_value, max_value, min_value, modulateable, moverate, and value_type: These tokens are used to define and manage oscillator parameters, such as carrier frequency, modulation index, and waveform types.

  • FMOscillator: The struct representing the FM oscillator, which holds the oscillator state and configuration.

  • do_fm_block: A helper function to perform the core FM synthesis algorithm on a block of samples.

  • init: A method to initialize the FM oscillator with the appropriate settings and parameter values.

  • process_block: A method that processes a block of samples by applying the FM synthesis algorithm, using the do_fm_block function.

To use this crate, you'll need to integrate it into your Surge synthesizer system or a compatible application, ensuring proper initialization and parameter management. By leveraging the power of FM synthesis, you'll be able to create an extensive range of sounds, from classic FM electric pianos and bells to evolving textures and complex harmonic structures.

9> /file surge-rs/surgeosc-fm/src/process.rs

The FMOscillator implementation provided here is a frequency modulation (FM) oscillator that processes audio in blocks. The algorithm uses three modulators with different amounts and frequency ratios or absolute frequencies, as well as feedback to create a wide variety of sounds. The implementation is optimized for the Surge synthesizer system and processes audio samples in chunks defined by BLOCK_SIZE_OS.

Let's break down the process_block function:

  1. The method starts by retrieving the current parameter values for modulator amounts, frequency ratios, and absolute frequencies, as well as the feedback amount.

  2. The oscillator pitch is updated with drift, which introduces small random variations to the pitch over time to simulate analog oscillator behavior.

  3. The rates for each modulator are calculated based on the drifted pitch, frequency ratios, and absolute frequencies.

  4. The modulation depths for each modulator are updated.

  5. The FM depth is updated if FM is enabled.

  6. The feedback depth is updated.

  7. The do_fm_block function is called for each sample in the block to apply the FM algorithm.

  8. If stereo processing is enabled, the left channel is duplicated to the right channel.

10> /file surge-rs/surgeosc-fm/src/block.rs

The do_fm_block function performs the core FM synthesis operation on a single audio sample. It takes the current sample index k, the carrier waveform frequency omega, and a boolean flag fm that indicates whether FM synthesis is enabled or not.

Let's walk through the function step by step:

  1. The function starts by retrieving the master oscillator's value at the current sample index k.

  2. The three modulator oscillators (rm1, rm2, and am) are processed.

  3. The output for the left channel is calculated by adding the current phase, the contributions of the three modulators, and the last output scaled by the feedback depth.

  4. If FM synthesis is enabled, the contribution from the master oscillator is added, scaled by the FM depth.

  5. The sine function is applied to the output sample to generate the final waveform.

  6. The last output value is updated with the current output value, scaled by the feedback depth.

  7. The phase of the oscillator is incremented by omega.

  8. The modulation depths and feedback depth are updated by processing their respective envelopes.

This do_fm_block function is called for each sample in a block by the process_block method. By combining multiple modulators, feedback, and optional FM synthesis, this implementation of FMOscillator generates a wide variety of complex and rich sounds.

11> cool thanks! could you teach me even more about FM synthesis? what are its mathematical properties?

Frequency Modulation (FM) synthesis is a technique for generating complex sounds by modulating the frequency of one waveform, called the carrier, with another waveform, called the modulator. The carrier waveform is usually a simple waveform like a sine wave, and the modulator is often another sine wave or a more complex waveform. The resulting sound can have a rich harmonic content, making FM synthesis suitable for creating a wide variety of timbres.

The basic mathematical equation for FM synthesis is as follows:

y(t) = A * sin(2 * π * (f_c + I * f_m * sin(2 * π * f_m * t)) * t)

Where:

  • y(t) is the output signal at time t

  • A is the amplitude

  • f_c is the carrier frequency

  • f_m is the modulator frequency

  • I is the modulation index, determining the amplitude of the sidebands in the output signal

The modulation index (I) is crucial in determining the harmonic content of the resulting sound. A higher modulation index results in a more complex sound with a richer harmonic structure, while a lower modulation index produces a simpler sound closer to the original carrier waveform.

One of the key features of FM synthesis is the ability to create a wide range of harmonic structures by varying the modulation index and the ratio between the carrier and modulator frequencies. When the frequency ratio is an integer or a simple fraction, the resulting sound tends to have a harmonic structure, making it suitable for musical applications. In contrast, when the frequency ratio is an irrational number, the sound becomes more inharmonic and noisy.

In practice, FM synthesis can involve multiple modulators, each with its own frequency and modulation index. This allows for even more complex and evolving sounds, as demonstrated in the FMOscillator implementation you've provided earlier. Furthermore, feedback can be introduced by feeding the output of the carrier waveform back into the modulator, resulting in even richer harmonic structures.

Overall, FM synthesis is a powerful technique for sound synthesis, offering a wide range of possibilities for creating diverse and intricate sounds with relatively simple mathematical principles.

Dependencies

~11–20MB
~296K SLoC