---
title: Synths
layout: ../../layouts/MainLayout.astro
---

import { MiniRepl } from '../../docs/MiniRepl';
import { JsDoc } from '../../docs/JsDoc';

# Synths

In addition to the sampling engine, strudel comes with a synthesizer to create sounds on the fly.

## Basic Waveforms

The basic waveforms are `sine`, `sawtooth`, `square` and `triangle`, which can be selected via `sound` (or `s`):

<MiniRepl
  client:idle
  tune={`note("c2 <eb2 <g2 g1>>")
.sound("<sawtooth square triangle sine>")
.scope()`}
/>

If you don't set a `sound` but a `note` the default value for `sound` is `triangle`!

### Additive Synthesis

To tame the harsh sound of the basic waveforms, we can set the `n` control to limit the overtones of the waveform:

<MiniRepl
  client:idle
  tune={`note("c2 <eb2 <g2 g1>>")
.sound("sawtooth")
.n("<32 16 8 4>")
.scope()`}
/>

When the `n` control is used on a basic waveform, it defines the number of harmonic partials the sound is getting.
You can also set `n` directly in mini notation with `sound`:

<MiniRepl
  client:idle
  tune={`note("c2 <eb2 <g2 g1>>")
.sound("sawtooth:<32 16 8 4>")
.scope()`}
/>

Note for tidal users: `n` in tidal is synonymous to `note` for synths only.
In strudel, this is not the case, where `n` will always change timbre, be it though different samples or different waveforms.

## Vibrato

### vib

<JsDoc client:idle name="vib" h={0} />

### vibmod

<JsDoc client:idle name="vibmod" h={0} />

## FM Synthesis

FM Synthesis is a technique that changes the frequency of a basic waveform rapidly to alter the timbre.

You can use fm with any of the above waveforms, although the below examples all use the default triangle wave.

### fm

<JsDoc client:idle name="fm" h={0} />

### fmh

<JsDoc client:idle name="fmh" h={0} />

### fmattack

<JsDoc client:idle name="fmattack" h={0} />

### fmdecay

<JsDoc client:idle name="fmdecay" h={0} />

### fmsustain

<JsDoc client:idle name="fmsustain" h={0} />

### fmenv

<JsDoc client:idle name="fmenv" h={0} />

## Wavetable Synthesis

Strudel can also use the sampler to load custom waveforms as a replacement of the default waveforms used by WebAudio for the base synth. A default set of more than 1000 wavetables is accessible by default (coming from the [AKWF](https://www.adventurekid.se/akrt/waveforms/adventure-kid-waveforms/) set). You can also import/use your own. A wavetable is a one-cycle waveform, which is then repeated to create a sound at the desired frequency. It is a classic but very effective synthesis technique.

Any sample preceded by the `wt_` prefix will be loaded as a wavetable. This means that the `loop` argument will be set to `1` by defalt. You can scan over the wavetable by using `loopBegin` and `loopEnd` as well.

<MiniRepl
  client:idle
  tune={`samples('github:Bubobubobubobubo/Dough-Waveforms/main/');

note("<[g3,b3,e4]!2 [a3,c3,e4] [b3,d3,f#4]>")
.n("<1 2 3 4 5 6 7 8 9 10>/2").room(0.5).size(0.9)
.s('wt_flute').velocity(0.25).often(n => n.ply(2))
.release(0.125).decay("<0.1 0.25 0.3 0.4>").sustain(0)
.cutoff(2000).scope({}).cutoff("<1000 2000 4000>").fast(2)`}
/>

## ZZFX

The "Zuper Zmall Zound Zynth" [ZZFX](https://github.com/KilledByAPixel/ZzFX) is also integrated in strudel.
Developed by [Frank Force](https://frankforce.com/), it is a synth and FX engine originally intended to be used for size coding games.

It has 20 parameters in total, here is a snippet that uses all:

<MiniRepl
  client:idle
  tune={`note("<c2 eb2 f2 g2>") // also supports freq
  .s("<z_sawtooth z_tan z_noise z_sine z_square>")
  .zrand(0) // randomization
  // zzfx envelope
  .attack(0.001)
  .decay(0.1)
  .sustain(.8)
  .release(.1)
  // special zzfx params
  .curve(1) // waveshape 1-3
  .slide(0) // +/- pitch slide
  .deltaSlide(0) // +/- pitch slide (?)
  .noise(0) // make it dirty
  .zmod(0) // fm speed
  .zcrush(0) // bit crush 0 - 1
  .zdelay(0) // simple delay
  .pitchJump(0) // +/- pitch change after pitchJumpTime
  .pitchJumpTime(0) // >0 time after pitchJump is applied
  .lfo(0) // >0 resets slide + pitchJump + sets tremolo speed
  .tremolo(0) // 0-1 lfo volume modulation amount
  //.duration(.2) // overwrite strudel event duration
  //.gain(1) // change volume
  .scope() // vizualise waveform (not zzfx related)
`}
/>

Note that you can also combine zzfx with all the other audio fx (next chapter).

Next up: [Audio Effects](/learn/effects)...
