• Stars
    star
    327
  • Rank 124,340 (Top 3 %)
  • Language
    C
  • License
    MIT License
  • Created over 9 years ago
  • Updated almost 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A C library which implements an FM synthesizer

libfmsynth

libfmsynth is a C library which implements an FM synthesizer. Unlike most FM synth implementations in software, this FM synthesizer does not aim to emulate or replicate a particular synth (like DX7) or FM chip.

The synth was designed primarily to be used as an instrument for my own purposes, hooked up with MIDI to my electric piano. It was also designed to be potentially useful as a synth backend in other projects.

The synth core supports:

  • Arbitrary amounts of polyphony
  • 8 operators
  • No fixed "algorithms"
  • Arbitrary modulation, every operator can modulate any other operator, even itself
  • Arbitrary carrier selection, every operator can be a carrier
  • Sine LFO, separate LFO per voice, modulates amplitude and frequency of operators
  • Envelope per operator
  • Carrier stereo panning
  • Velocity sensitivity per operator
  • Mod wheel sensitivity per operator
  • Pitch bend
  • Keyboard scaling
  • Sustain, sustained keys can overlap each other for a very rich sound
  • Full floating point implementation optimized for SIMD
  • Hard real-time constraints

In addition, support for some useful auxillary features are implemented:

  • Linux LV2 plugin implementation with simple GTKmm GUI
  • Patch load/save as well as direct parameter control through API
  • MIDI messages API as well as direct control of the synth with key on/off, etc

Sample sounds/presets

Some of the sounds you can create using this synth can be heard on my SoundCloud FM synth playlist.

The sounds do have some effects like delay, reverb and chorus applied to them.

Some presets can be found in presets/ directory. Their raw data can be passed directly to libfmsynths preset API.

License

libfmsynth is licensed under the permissive MIT license.

Documentation

The public libfmsynth API is documented with doxygen. Run doxygen or make docs to generate documentation. Doxygen 1.8.3 is required.

After running Doxygen, documents are found in docs/.

Optimizations

libfmsynth is currently optimized for

  • SSE (intrinsics)
  • SSE 4.1 (intrinsics)
  • AVX (intrinsics)
  • ARMv7 NEON (intrinsics and hand coded assembly)
  • ARMv8 NEON (intrinsics, untested)

The SIMD implementations are typically 3-6x faster than the equivalent -Ofast optimized C implementation, even with autovectorization enabled.

Performance

IPC was measured with perf on Linux.

SSE

At 44.1 kHz, a single core of a 2.66 GHz Core i7 920 can do 750 voice polyphony when fully saturated with SSE 4.1 path. Throughput is 34.5 Msamples / s (approx. 11 GFlops).

IPC

1.91 instructions per cycle.

AVX

The 256-bit vector AVX implementation is roughly 10-15 % faster than SSE (tested on a Sandy Bridge laptop). The reason it's just 10-15 % is because the dependencies between stages in the synth and latency in floating point processing ensure that the execution pipes cannot be fully saturated with useful work.

IPC

1.00 instructions per cycle.

NEON

At 44.1 kHz, a single core of a 1.7 GHz Cortex-A15 can do 300 voice polyphony when fully saturated with NEON. Throughput is 13.1 Msamples / s (approx. 4.75 GFlops).

IPC

1.00 instructions per cycle. From benchmarking, it does not seem to be possible to get more than one FP32x4 instruction per cycle on NEON.

Signal path

For a voice of polyphony, LFOs and envelopes are updated every 32nd sample. Between LFO and envelope updates, a tight loop runs unless it has to exit early due to MIDI updates. Per sample:

  • Compute sine for 8 operators w/ 4th order Taylor approximation.
  • Multiply in envelope, LFO, etc.
  • Increment envelope (linear ramp).
  • Apply 8-by-8 modulator matrix to result of the sine computation (8-by-8 matrix-vector multiply).
  • Accumulate modulation result and base frequencies to operator phases (proper FM, phase integration).
  • Mix carrier outputs to left and right channels.
  • Wrap around oscillator phase for stability.

Building and installing

To build, run make to build the static library libfmsynth.a. The static library has -fPIC enabled, to allow linking into a shared library. To build a benchmark/test app, run make test. The main purpose of this tool is to benchmark and validate that outputs for C and SIMD paths are adequately similar and that performance is as expected.

To cross-compile, use TOOLCHAIN_PREFIX, e.g. cross-compiling to ARMv7:

make TOOLCHAIN_PREFIX=arm-linux-gnueabihf- ARCH=armv7 TUNE=cortex-a15

If TUNE= is not set to something, -march=native will be assumed. Note that binaries built with -march=native will enable code paths which might not be supported by other processors, especially on x86 if SSE 4.1 or AVX is enabled.

To install library and header, use make install PREFIX=$YOUR_PREFIX.

Building LV2 plugin

To build libfmsynth as an LV2 plugin you will need:

  • lvtk
  • GTKmm 2
  • Fairly recent C++11 compiler

Run:

cd lv2
make
sudo make install

The plugin will be installed to /usr/lib/lv2/. Presets in presets/ are installed to the bundle as well. When attempting to load presets in the UI, one of the shortcuts will point to the LV2 bundle for easy access.

More Repositories

1

Granite

My personal Vulkan renderer
C++
1,473
star
2

GLFFT

A C++11/OpenGL library for the Fast Fourier Transform
C
207
star
3

muFFT

A library for computing the Fast Fourier Transform (FFT) in one or two dimensions.
C
154
star
4

parallel-rdp

A low-level Vulkan compute emulation of the N64 RDP
C++
141
star
5

Emulator-Shader-Pack

Various pixel shaders in Cg for oldschool emulators
87
star
6

RetroWarp

A Vulkan compute shader implementation of a fictional retro GPU
C++
52
star
7

MIPS-LLVM-Jitter

A simple MIPS to LLVM IR recompiler with ahead-of-time recompilation support
C++
42
star
8

slang-shaders

C
41
star
9

Dinothawr

Dinothawr is a block pushing puzzle game on slippery surfaces. Our hero is a dinosaur whose friends are trapped in ice. Through puzzles it is your task to free the dinos from their ice prison.
C
40
star
10

libmaru

USB audio class driver in userspace using libusb.
C
37
star
11

Fossilize

This repository is discontinued, see https://github.com/ValveSoftware/Fossilize
C
34
star
12

simple-irc-bot

A simple IRC bot. Hackable.
C
32
star
13

RSound

A multi-platform, simple PCM audio server and client.
C
30
star
14

RetroArch-Phoenix

Simple GUI frontend for RetroArch using Phoenix
C++
28
star
15

boxes

OpenGL 4.3 experiment with compute shaders and tons of instanced geometry! Targets libretro GL.
C
25
star
16

Granite-MicroSamples

Micro-samples for Granite to read along with my blog post: http://themaister.net/blog/2019/04/14/a-tour-of-granites-vulkan-backend-part-1/
C++
19
star
17

parallel-rdp-standalone

A standalone, distilled codebase of parallel-rdp. Autogenerated.
C++
17
star
18

alsa-plugins-rsound

RSound plugin for ALSA
C
16
star
19

SimpleGL

NIH library for OpenGL window/context creation for X11/Win32/OSX.
C
11
star
20

ToneFilterVST

Basic recreation of the Nier Automata tone filter in VST form
C++
10
star
21

SLIMPlayer

Simple and Lightweight Media Player (using FFmpeg)
C++
9
star
22

pyrofling

PyroFling is a simple solution for capturing Vulkan applications and broadcast video and audio to streaming platforms using FFmpeg.
C++
8
star
23

SFC-Pong

A very newbish Pong game for Super Nintendo.
Assembly
5
star
24

airsynth

Multi-instrument polyphonic synthesizer for LV2 with a standalone JACK implementation.
C++
5
star
25

bsnes-Qt

Fork of BSNES/QT (v073)
C++
4
star
26

MIPS-Toolchain-PKGBUILD

A set of PKGBUILDs to build a MIPS (big-endian) toolchain
Shell
4
star
27

SC-MIPS

Simple, single cycle MIPS implementation in VHDL. Extended to support most instructions.
VHDL
4
star
28

XMLShaderView

View XML shaders in your browser!
JavaScript
2
star
29

libretro-ffmpeg

Video player implemented in libretro.
C++
2
star
30

parallel-psx-dump-replayer

Standalone tool to replay dumps from Parallel PSX
C++
2
star
31

alsa-reroute

Small script/preloaded lib that intercepts calls to ALSA and force them to open different devices.
C
2
star
32

Quickbuild

Simplistic build system written in sh to help with configuring building from source.
Shell
2
star
33

blipper

Band-limited decimator for emulators.
C
2
star
34

umusd

Microscopic music player controlled over TCP.
C++
2
star
35

Scale

Small and simple image scaler.
C
2
star
36

DirectRSound

Reimplement a subset of DirectSound with RSound.
C++
2
star
37

RetroArch-DSP-plugins

Audio DSP plugins for RetroArch.
C++
2
star
38

sussybard

Simple app which converts MIDI key inputs to X key presses, designed for playing FF XIV Bard
C++
2
star
39

SSNES-core

Futile attempt to create a SNES emulator :)
C
2
star
40

SC-MIPS-Chain

Simple toolchain for SC-MIPS
C
2
star
41

GLModelViewer

Simple modelviewer in OpenGL 3.0+
C
2
star
42

stile

Simple picture converter to SNES-format tilemap/tileset palette and stuff.
C++
1
star
43

iceypuzzle

Some simple engine for doing sliding puzzles, or something... :')
C++
1
star
44

midiviz

Crappy ad-hoc MIDI visualizer
C
1
star
45

rtorrent-nogui

Attempts to run rtorrent as a pure daemon without GUI.
C++
1
star
46

RetroArch-D3D9

D3D9 external driver plugin for RetroArch.
C++
1
star
47

libretro-remotejoy

RemoteJoy client side code rewritten for libretro.
C
1
star