# Gjalla

[![Build](https://github.com/andreademurtas/gjalla/actions/workflows/build.yml/badge.svg)](https://github.com/andreademurtas/gjalla/actions/workflows/build.yml)

*Gjalla* (Old Norse for "to shriek, to resound") is a free and open-source black
metal guitar amp simulator plugin (VST3, CLAP, AU + standalone). Solid state,
no tubes, no sag: a cheap transistor head, a distortion pedal in front of it and
a cabinet that stops dead above 5 kHz. Built with [JUCE](https://juce.com);
sibling of [Galdr](https://github.com/andreademurtas/galdr) and
[Gala](https://github.com/andreademurtas/gala).

![Gjalla GUI](docs/screenshot.png)

## Features

- One chain from dry guitar to finished tone, in signal order: input trim,
  noise gate, pedal, preamp, tone stack, power section, presence, cabinet,
  frost, output trim
- Noise gate on the clean signal ahead of every gain stage, with fixed 0.5 ms
  attack, 80 ms release and 4 dB of hysteresis, and no added latency
- Three pedal voicings sharing one set of knobs: see the table below
- Solid-state preamp: two cascaded gain-plus-waveshaper stages up to +36 dB,
  a sweepable 20-300 Hz tight filter ahead of the clipping, and a deliberate
  asymmetry that puts even harmonics in without leaving DC behind
- Three-band tone stack plus a presence control after the power section
- Three analytic cabinet voicings (4x12, practice combo, boombox) with every
  coefficient in one table in `src/Cabinet.h`, or load your own WAV/AIFF
  impulse response up to 2 seconds, or switch the cabinet off entirely for an
  external IR loader
- Frost: a tilt filter at 1 kHz that takes the amp from dark to thin
- 2x or 4x oversampling around the whole nonlinear path, polyphase IIR
  halfbands, 6 samples of latency (0.13 ms at 48 kHz) reported to the host and
  identical at both quality settings
- Level compensation on the pedal and the preamp, so drive and gain buy
  distortion rather than volume and Master stays the volume control
- Six factory presets, in/out level meters, right-click any knob to reset it or
  type a value, undo/redo with Ctrl+Z / Ctrl+Shift+Z
- Dark GUI shared with Galdr and Gala, resizable 0.75x to 2x, tooltips on
  every control
- Versioned session state: settings saved today keep loading in future versions
- Headless DSP test suite and CI validation with pluginval at strictness 10
  plus clap-validator on every platform
- No telemetry, no network access, no update checks, no accounts. `JUCE_USE_CURL`
  and `JUCE_WEB_BROWSER` are compiled out
- VST3, CLAP, AU (macOS) and standalone builds for Windows, macOS and Linux

## The pedal knobs

The pedal has three knobs and three voicings, and each knob means something
different per voicing:

| | Dist | Chainsaw | Fuzz |
|---|---|---|---|
| Reference | cheap 90s distortion box | HM-2 style | starved transistor fuzz |
| **Drive** | 0 to +40 dB into an asymmetric diode clipper | clip amount, 0 to +36 dB into a hard clipper | 0 to +50 dB into a lopsided hard clipper |
| **Tone** | tilt around 800 Hz, dark to thin | sweeps the upper of the two pre-clip peaks, 700 Hz to 1.5 kHz | post low-pass, 1 to 8 kHz |
| **Level** | output trim, -12 to +12 dB | output trim | output trim |

Dist high-passes at 60 Hz before clipping. Chainsaw pushes two fixed +9 dB
peaks (250 Hz and the swept one) into the clipper and low-passes at 6 kHz
afterwards, which is where the buzzsaw comes from. Fuzz clips harder on the
positive rail than the negative one.

## Building

Requirements: git, CMake ≥ 3.22 and a C++20 compiler (Visual Studio 2022 on Windows,
Xcode on macOS, GCC or Clang on Linux).

```sh
git clone --recurse-submodules https://github.com/andreademurtas/gjalla
cd gjalla
cmake -B build
cmake --build build --config Release
```

On Linux, install the JUCE build dependencies first (see the package list in
`.github/workflows/build.yml`).

Artifacts are written to `build/Gjalla_artefacts/Release/`:

| Artifact | Install location |
|---|---|
| `VST3/Gjalla.vst3` | Windows: `C:\Program Files\Common Files\VST3` · macOS: `~/Library/Audio/Plug-Ins/VST3` · Linux: `~/.vst3` |
| `CLAP/Gjalla.clap` | Windows: `C:\Program Files\Common Files\CLAP` · macOS: `~/Library/Audio/Plug-Ins/CLAP` · Linux: `~/.clap` |
| `AU/Gjalla.component` | macOS only: `~/Library/Audio/Plug-Ins/Components` |
| `Standalone/` | Run directly, no installation needed |

### Tests

```sh
cmake --build build --config Release --target GjallaTests
ctest --test-dir build -C Release --output-on-failure
```

The suite covers numerical safety at 44.1/48/96 kHz across block sizes 1 to
4096 and parameter extremes, silence in giving silence out, the gate's
click-free gain, exact state round-trips, the latency contract, every cabinet
and pedal mode, and a warn-only aliasing measurement. `ctest` and running the
binary directly do the same thing; the binary gives more readable output when a
DSP measurement is what failed.

## Notes for the curious

- **Where the oversampling starts and stops.** The pedal, preamp, tone stack
  and power section all run inside one oversampling block. The tone stack is a
  linear filter and would normally sit at the base rate, but it lives between
  two nonlinear stages, so pulling it out would mean a second up/downsample
  pair, which is more CPU and more phase smear than running three biquads at 4x.
  Presence, cabinet, frost and the output trim run at the base rate.
- **Why the biquads are hand-rolled.** `juce::dsp::IIR::Coefficients` allocates
  on every coefficient update, and Gjalla recomputes coefficients once per block
  on the audio thread.
- **No shared LookAndFeel module.** `src/BlackMetalLookAndFeel.h` is the third
  copy of the same file across Galdr, Gala and Gjalla. The provenance comment at
  the top of the file records where it came from. Factoring the three copies
  into a shared module is worth doing and has not been done.

## License

This project is licensed under the **GNU General Public License v3.0 or later**
(see [LICENSE](LICENSE)).

It uses the [JUCE framework](https://github.com/juce-framework/JUCE), licensed under
the AGPLv3, the VST3 SDK interfaces distributed with JUCE under the MIT license, and
[clap-juce-extensions](https://github.com/free-audio/clap-juce-extensions) (MIT) for
the CLAP export. Binary releases ship the relevant license texts in a `licenses/`
folder plus a `NOTICE.txt` with full attributions.

The GUI embeds the fonts [UnifrakturMaguntia](https://fonts.google.com/specimen/UnifrakturMaguntia)
and [IM Fell English](https://fonts.google.com/specimen/IM+Fell+English), both licensed under the
[SIL Open Font License](assets/fonts/OFL-UnifrakturMaguntia.txt).

*VST is a registered trademark of Steinberg Media Technologies GmbH.*
