#3882 Mathematica Manipulation of Oscillator Waves

#3882 Mathematica Manipulation of Oscillator Waves

#3882 Describe the various ways Mathematica could be used to shape the oscillator waves for a synth

Mathematica (Wolfram Language) is exceptionally powerful for sound synthesis because it treats audio not just as a "stream of sound," but as computable mathematical functions.1 This allows you to design oscillator shapes with a precision that is difficult to achieve in standard Digital Audio Workstations (DAWs).

Here are the primary ways you can use Mathematica to shape oscillator waves, moving from basic math to complex data export.


1. Additive Synthesis (Harmonic Construction)

The most fundamental way to shape a wave in Mathematica is by summing sine waves. You can visualize and listen to how adding harmonics changes the waveform from a pure tone to a complex shape (like a square or sawtooth approximation).

  • The Math: You sum a fundamental frequency $f$ with integer multiples (harmonics).

  • Wolfram Approach: Use Sum or Table to define the harmonic series.

(* Create a Square Wave approximation using odd harmonics *)
harmonics = 20;
freq = 220; (* Hz *)
wave[t_] := Sum[Sin[2 Pi (2 n - 1) freq t] / (2 n - 1), {n, 1, harmonics}];

(* Visualize it *)
Plot[wave[t], {t, 0, 0.01}]

(* Hear it *)
Play[wave[t], {t, 0, 1}]

2. Non-Linear Waveshaping (Distortion Functions)

This is where Mathematica shines. You can feed a standard wave (like a Sine) into a non-linear transfer function to "bend" the shape. This simulates analog distortion or saturation.

  • Sigmoid/Tanh Shaping: Simulates "tube" saturation or soft clipping.

    f(t) = \tanh(A \cdot \sin(\omega t))
  • Chebyshev Polynomials: Used to manipulate specific harmonics without affecting others.

(* Hard clipping/shaping a sine wave *)
drive = 5;
shapedWave[t_] := Tanh[drive * Sin[2 Pi 220 t]];

Play[shapedWave[t], {t, 0, 1}]

3. Frequency Modulation (FM) & Phase Modulation

You can easily prototype FM synthesis algorithms by nesting functions. Because Mathematica handles symbolic math, you can experiment with complex modulation ratios that would be tedious to dial in on hardware.

  • The Math: The frequency of the carrier wave is modulated by the amplitude of a modulator wave.

    y(t) = A \sin(2\pi f_c t + I \sin(2\pi f_m t))
carrier = 440;
modulator = 110;
index = 5; (* Modulation index *)

fmWave[t_] := Sin[2 Pi carrier t + index * Sin[2 Pi modulator t]];
Play[fmWave[t], {t, 0, 2}]

4. Generating Wavetables for Hardware/Software Synths

If you are building a digital synth or coding a VST, you rarely generate math in real-time; you use a Wavetable. Mathematica allows you to calculate a single cycle of a highly complex wave and export it as a list of values (CSV) or a .wav file to load into synths like Serum, Pigments, or an Arduino/Daisy microcontroller.

  • Process: Generate a list of numerical values for exactly one cycle of the wave, then normalize them between -1.0 and 1.0.

(* Generate one cycle of a complex function *)
sampleRate = 44100;
freq = 44100/2048; (* To fit exactly 2048 samples *)
data = Table[N[Sin[2 Pi freq t] + 0.5*Sin[2 Pi 2 freq t]], {t, 0, 1/freq, 1/sampleRate}];

(* Export to CSV for coding or WAV for samplers *)
Export["wavetable.csv", data]
Export["wavetable.wav", Audio[data, SampleRate -> 44100]]

5. Chaotic and Exotic Functions

You can use Mathematica to generate noise and textures that do not exist in standard oscillators by utilizing chaotic attractors or fractal math.

  • Logistic Map: Can create "noise" that has a pitch.

  • Random Walk / Brownian Noise: Good for control voltages (LFOs).

(* Using a chaotic function for noise generation *)
data = NestList[4 # (1 - #) &, 0.1, 44100]; (* Logistic Map *)
Audio[data, SampleRate -> 44100]

Summary Table of Mathematica Audio Functions

FunctionPurposeApplication
Play[f[t], {t, 0, d}]Quick audio previewTesting math concepts audibly.
AudioGenerator[type]Built-in primitivesGenerating standard Sine, Square, Noise.
Audio[data]Convert list to soundCreating wavetables from raw data arrays.
Export["file.wav", obj]Save fileMoving your wave to a DAW or hardware sampler.

Next Step

Would you like me to write a script that generates a Wavetable bank (a series of evolving waves) based on a specific formula, which you could then export as a .wav file?


Yes

Here is a Mathematica script designed to create a Wavetable Bank suitable for modern synthesizers like Serum, Vital, or Pigments.

This script generates a sequence of 64 frames (individual single-cycle waves). As the bank progresses, the waveform morphs from a pure Sine wave into a complex, rich FM-style wave.

The Script: Morphing Phase Distortion

We will use Phase Modulation for this example. We start with a Sine wave and progressively add a second Sine wave inside the phase of the first. This mimics the "FM Amount" knob turning up on a synth.

Copy and paste this into a Mathematica notebook:

(* 1. CONFIGURATION *)
sampleRate = 44100;
frameSize = 2048;      (* Standard frame size for Serum/Vital *)
numFrames = 64;        (* Number of slots in the wavetable *)

(* 2. THE MORPH FORMULA *)
(* t is time (0 to 1), m is the morph amount (0 to 1) *)
(* As m increases, the wave gets more "gnarly" *)
waveFunction[t_, m_] := Sin[2 Pi t + (m * 3.0) * Sin[2 Pi t]];

(* 3. GENERATE THE DATA *)
(* We create a list of lists, then flatten it into one long audio stream *)
wavetableData = Table[
   (* Calculate the 'morph' amount for this specific frame *)
   morphAmount = frameIndex / (numFrames - 1.0);
   
   (* Generate one single cycle (one frame) *)
   Table[
    waveFunction[i/frameSize, morphAmount],
    {i, 0, frameSize - 1}
    ],
   {frameIndex, 0, numFrames - 1}
   ];

(* Flatten the table into a single stream of samples *)
audioStream = Flatten[wavetableData];

(* 4. NORMALIZE *)
(* Ensure the audio peaks at -0.1 dB so it doesn't clip *)
maxVal = Max[Abs[audioStream]];
normalizedStream = audioStream / maxVal * 0.99;

(* 5. EXPORT *)
(* Create the audio object *)
audioObj = Audio[normalizedStream, SampleRate -> sampleRate];

(* Export to .wav file in your Documents folder (or change path) *)
exportPath = FileNameJoin[{$UserDocumentsDirectory, "MorphingFM_Wavetable.wav"}];
Export[exportPath, audioObj]

(* 6. VISUALIZE (Optional) *)
(* Show the first, middle, and last frame to verify the morph *)
ListLinePlot[{
  wavetableData[[1]], 
  wavetableData[[32]], 
  wavetableData[[64]]
  }, PlotLabel -> "First, Middle, and Last Frames"]

How to use this file

  1. Run the code: It will save MorphingFM_Wavetable.wav to your Documents folder.

  2. Importing to Serum/Vital:

    • Open the Wavetable Editor in your synth.

    • Drag and drop this .wav file onto the editor.

    • Select "Import: 2048 samples (samples)" or "Import as Wavetable" if prompted.

  3. The Result: You will see a 3D terrain of waves. As you turn the "Wavetable Position" (WT Pos) knob, the sound will smoothly sweep from a dull hum to a bright, metallic buzz.

Why 2048 Samples?

Most modern wavetable synths (Serum, Vital, Ableton Wavetable) prefer a frame size of 2048 samples. If the math calculates exactly 2048 points for one cycle, the synth knows exactly where to "slice" the file to create the separate frames without you having to manually edit loop points.

Next Step

Would you like me to modify this script to use Additive Synthesis instead (specifically controlling the volume of odd vs. even harmonics) to create a "Vintage Organ to Square Wave" morph?


From <https://gemini.google.com/app/>  Google Gemini 3.0 Pro (Thinking)

Comments

Popular posts from this blog

#2892 Example of ChatGPT o1 Prompt

#3105 Federal and State Spending Idiocy