|
1 | | -A modular synthesizer application written in C, using SDL2 for graphics and audio, and supporting MIDI input via libremidi. The GUI is resizable and features oscilloscope and spectrum displays, keyboard input, and real-time control of oscillators, effects, mixer, and arpeggiator. |
2 | | - |
3 | | - |
4 | | - |
5 | | - |
6 | | - |
7 | | -[](https://github.com/koppi/sdl2-synth/actions/workflows/os.yml) |
8 | | -[](https://github.com/koppi/sdl2-synth/actions/workflows/web.yml) |
9 | | -[](https://github.com/koppi/sdl2-synth/issues) |
| 1 | +A modular synthesizer application written in C, using SDL2 for graphics and audio, and supporting MIDI input via libremidi. |
10 | 2 |
|
11 | 3 | ## Features |
12 | 4 |
|
13 | | -- **4-oscillator synth**: Each with independent waveform, pitch, detune, gain, phase, pulse width, and unison controls. |
14 | | -- **Comprehensive Parameter Control**: All oscillator parameters accessible via intuitive combo boxes: |
15 | | - - **Waveform Selection**: SINE, SAW, SQUARE, TRI, NOISE |
16 | | - - **Pitch Presets**: Common semitone offsets (-24 to +24) |
17 | | - - **Detune Presets**: Standard cent values (-100¢ to +100¢) |
18 | | - - **Gain Presets**: Common levels (0%, 12%, 25%, 50%, 75%, 87%, 100%) |
19 | | - - **Phase Presets**: Musical phase relationships (0°, 45°, 90°, 135°, 180°, etc.) |
20 | | - - **Pulse Width Presets**: Standard duty cycles (10%, 25%, 50%, 75%, 90%) |
21 | | - - **Unison Voices**: 1 to 8 voice layering |
22 | | - - **Unison Spread**: Preset detuning amounts (Off, Tight, Medium, Wide, Extra Wide) |
23 | | - - **Modern Dear ImGui Interface**: Clean, responsive GUI using the Dear ImGui library- **Mixer**: Control the mix and master volume of each oscillator with bus compression. |
24 | | -- **Mastering**: Professional post-processing with DC filter, soft clipping, auto gain, and level meters. |
25 | | -- **Effects**: Flanger, delay, reverb, and analog filter with real-time controls. |
26 | | - - **Analog Filter**: Professional-grade resonant filter with multiple types and advanced processing. |
27 | | - - **Filter Types**: Low-pass, High-pass, Bandpass, Notch |
28 | | - - **Adjustable Cutoff**: 20Hz - 20kHz with logarithmic control |
29 | | - - **Resonance (Q)**: 0.1 - 10.0 for filter peaking and character |
30 | | - - **Drive Control**: 1.0 - 10.0 with soft saturation for warmth and distortion |
31 | | - - **Oversampling**: 1x, 2x, 4x, 8x for aliasing reduction |
32 | | - - **Inertial Smoothing**: Prevents zipper noise during parameter changes |
33 | | - - **Wet/Dry Mix**: 0% - 100% for parallel processing |
34 | | - - **Arpeggiator**: Multiple modes, adjustable tempo, octave control, and multi-octave chord arpeggiation. |
35 | | - - **Arpeggiator Modes**: UP, DOWN, ORDER, RANDOM |
36 | | - - **Octave Control**: Select base octave (0-4 = octaves 1-5) for all notes |
37 | | - - **Multi-Octave Spread**: Spread chords across 1-6 octaves for rich, layered arpeggios |
38 | | - - **Hold Function**: Sustain arpeggios after key release |
39 | | - - **Polyphonic Mode**: Play all notes simultaneously or cycle through them in order |
40 | | - - **MIDI CC Control**: |
41 | | - - CC #90: Enable/disable arpeggiator |
42 | | - - CC #91: Select arpeggiator mode (UP/DOWN/ORDER/RANDOM) |
43 | | - - CC #92: Hold function on/off |
44 | | - - CC #93: Base octave selection (0-4) |
45 | | - - CC #94: Octaves spread control (1-6) |
46 | | - - **Mastering**: Professional post-processing with visual feedback. |
47 | | - - **DC Filter**: Removes DC offset with adjustable cutoff (1-100Hz) |
48 | | - - **Soft Clipper**: Gentle clipping with threshold and knee controls (-20 to 0dB) |
49 | | - - **Auto Gain**: Automatic gain adjustment to target level (-20 to 0dB) |
50 | | - - **Level Meters**: Real-time peak and RMS level visualization |
51 | | - - **Status Indicators**: Visual feedback for processing state |
52 | | -- **Multi-Octave Arpeggiation**: |
53 | | - - **Rich Chords**: Set octaves=3 with a C major chord |
54 | | - - **Rising Sequences**: Set octaves=2 and use UP mode with moderate tempo |
55 | | - - **Descending Patterns**: Set octaves=4 with DOWN mode for descending bass lines |
56 | | - - **Random Exploration**: Set octaves=6 with RANDOM mode for experimental textures |
57 | | -- **Oscilloscope & Spectrum**: Visualize output waveform and frequency spectrum. |
58 | | -- **MIDI input**: Map MIDI CC to synth parameters for external control. |
59 | | -- **Interactive Keyboard**: On-screen piano keyboard with visual feedback. |
| 5 | +- **4-oscillator synth**: Each with independent waveform, pitch, detune, gain, phase, pulse width, and unison controls |
| 6 | +- **Mixer**: Control the mix and master volume of each oscillator with bus compression |
| 7 | +- **Effects**: Flanger, delay, reverb, and analog filter with real-time controls |
| 8 | +- **Arpeggiator**: Multiple modes, adjustable tempo, octave control, and multi-octave chord arpeggiation |
| 9 | +- **Oscilloscope & Spectrum**: Visualize output waveform and frequency spectrum |
| 10 | +- **MIDI input**: Map MIDI CC to synth parameters for external control |
| 11 | +- **Interactive Keyboard**: On-screen piano keyboard with visual feedback |
60 | 12 |
|
61 | 13 | ## Build Dependencies |
62 | 14 |
|
63 | | -- [SDL2](https://www.libsdl.org/) (graphics, audio, events) |
64 | | -- [SDL2_ttf](https://github.com/libsdl-org/SDL_ttf) (font rendering) |
65 | | -- [Dear ImGui](https://github.com/ocornut/imgui) (GUI library) |
66 | | - - [libremidi](https://github.com/celtera/libremidi) (MIDI input) |
67 | | - - [math.h], [string.h], [stdlib.h], [stdio.h] |
68 | | - |
| 15 | +- SDL2 (graphics, audio, events) |
| 16 | +- SDL2_ttf (font rendering) |
| 17 | +- Dear ImGui (GUI library) |
| 18 | +- libremidi (MIDI input) |
| 19 | + |
69 | 20 | ## Build Instructions |
70 | 21 |
|
71 | 22 | ### Linux |
72 | 23 |
|
73 | | -Install dependencies (example for Debian/Ubuntu): |
74 | | - |
75 | 24 | ```sh |
76 | 25 | sudo apt-get install git cmake ninja libsdl2-dev libsdl2-ttf-dev |
77 | | -``` |
78 | | - |
79 | | -Clone, build and run: |
80 | | - |
81 | | -```sh |
82 | 26 | git clone https://github.com/koppi/sdl2-synth && cd sdl2-synth |
83 | 27 | cmake --preset release |
84 | 28 | cmake --build --preset synth-release && build/release/synth |
85 | 29 | ``` |
86 | 30 |
|
87 | 31 | ### macOS |
88 | 32 |
|
89 | | -Install dependencies (with Homebrew): |
90 | | - |
91 | 33 | ```sh |
92 | 34 | brew install git ninja sdl2 sdl2_ttf |
| 35 | +# Then build as above |
93 | 36 | ``` |
94 | 37 |
|
95 | | -Then build as above. |
96 | | - |
97 | 38 | ### Windows |
98 | 39 |
|
99 | | -- Install SDL2, SDL2_ttf and libremidi development libraries. |
100 | | -- Use MinGW or Visual Studio to build the sources (adjust includes/libs as needed). |
101 | | - |
102 | | -### Web (Emscripten) |
103 | | - |
104 | | -To build the synthesizer as a WebAssembly (WASM) application that runs in the browser: |
105 | | - |
106 | | -#### Setup Emscripten |
107 | | - |
108 | | -First, install the Emscripten SDK: |
109 | | - |
110 | | -```sh |
111 | | -cd /tmp |
112 | | -git clone https://github.com/emscripten-core/emsdk.git |
113 | | -cd emsdk |
114 | | -./emsdk install latest |
115 | | -./emsdk activate latest |
116 | | -source ./emsdk_env.sh |
117 | | -``` |
118 | | - |
119 | | -Add to your shell profile for permanent access: |
120 | | - |
121 | | -```sh |
122 | | -echo 'source "/tmp/emsdk/emsdk_env.sh"' >> $HOME/.bashrc |
123 | | -``` |
124 | | - |
125 | | -#### Build with CMake and Emscripten |
126 | | - |
127 | | -```sh |
128 | | -cd sdl2-synth |
129 | | -cmake --preset emscripten |
130 | | -cmake --build --preset synth-emscripten |
131 | | -``` |
132 | | - |
133 | | -This generates: |
134 | | -- `synth.js` - JavaScript runtime |
135 | | -- `synth.wasm` - WebAssembly binary |
136 | | - |
137 | | -#### Serve the Web Build |
138 | | - |
139 | | -Start a local web server to test: |
140 | | - |
141 | | -```sh |
142 | | -python3 -m http.server 8000 |
143 | | -``` |
144 | | - |
145 | | -Then open `http://localhost:8000` in your browser and navigate to the build output directory. |
| 40 | +Install SDL2, SDL2_ttf and libremidi development libraries, then build with MinGW or Visual Studio. |
146 | 41 |
|
147 | 42 | ## Running |
148 | 43 |
|
149 | 44 | ```sh |
150 | | -gdb build/debug/synth # debug the build |
151 | | -build/release/synth # run the release build |
| 45 | +build/release/synth |
152 | 46 | ``` |
153 | 47 |
|
154 | | -The application will open a window with the synthesizer GUI. |
155 | | - |
156 | | -## MIDI CC Control Mapping |
157 | | - |
158 | | -This synthesizer implements General MIDI CC (Continuous Controller) mapping following standard MIDI specifications for universal compatibility with hardware controllers and DAWs. All MIDI CC messages are automatically scaled from MIDI range (0-127) to the appropriate parameter ranges. |
159 | | - |
160 | | -### Standard MIDI CC Assignments |
161 | | - |
162 | | -#### General MIDI Controllers (CC 1-31) |
163 | | -- **CC 1**: Modulation Wheel → OSC 1 Detune (±1.0 semitones) |
164 | | -- **CC 7**: Volume (Channel Volume) → OSC 1 Gain (0.0-1.0) |
165 | | -- **CC 10**: Pan → OSC 1 Waveform (0=SINE,1=SAW,2=SQUARE,3=TRI,4=NOISE) |
166 | | -- **CC 11**: Expression → OSC 1 Pulse Width (0.0-1.0) |
167 | | - |
168 | | -#### Bank Select Controllers (CC 32-63) |
169 | | -- **CC 33**: LSB Bank Select → OSC 6 Waveform (0=SINE,1=SAW,2=SQUARE,3=TRI,4=NOISE) |
170 | | -- **CC 34**: LSB Bank Select → OSC 5 Waveform (0=SINE,1=SAW,2=SQUARE,3=TRI,4=NOISE) |
171 | | -- **CC 35**: LSB Bank Select → OSC 4 Waveform (0=SINE,1=SAW,2=SQUARE,3=TRI,4=NOISE) |
172 | | -- **CC 36**: LSB Bank Select → OSC 3 Waveform (0=SINE,1=SAW,2=SQUARE,3=TRI,4=NOISE) |
173 | | -- **CC 37**: LSB Bank Select → OSC 2 Waveform (0=SINE,1=SAW,2=SQUARE,3=TRI,4=NOISE) |
174 | | -- **CC 38**: LSB Bank Select → OSC 1 Waveform (0=SINE,1=SAW,2=SQUARE,3=TRI,4=NOISE) |
175 | | - |
176 | | -#### Effect Controllers (CC 64-95) |
177 | | -- **CC 70**: Sound Controller 1 → Delay Time (0.0-1.0s) |
178 | | -- **CC 71**: Sound Controller 2 → Delay Feedback (0.0-1.0) |
179 | | -- **CC 72**: Sound Controller 3 → Delay Mix (0.0-1.0) |
180 | | -- **CC 73**: Sound Controller 4 → Flanger Rate (0.0-5.0 Hz) |
181 | | -- **CC 74**: Sound Controller 5 → Flanger Depth (0.0-1.0) |
182 | | -- **CC 75**: Sound Controller 6 → Reverb Size (0.0-1.0) |
183 | | -- **CC 76**: Sound Controller 7 → Reverb Mix (0.0-1.0) |
184 | | -- **CC 77**: Sound Controller 8 → Filter Cutoff (20.0-20000.0 Hz) |
185 | | -- **CC 78**: Sound Controller 9 → Filter Resonance (0.1-10.0) |
186 | | -- **CC 79**: Sound Controller 10 → Filter Drive (1.0-10.0) |
187 | | -- **CC 80**: Sound Controller 11 → Filter Mix (0.0-1.0) |
188 | | - |
189 | | -#### Channel Pressure & Aftertouch |
190 | | -- **CC 2**: Breath Controller → Alternative OSC 1 Detune (±1.0 semitones) |
191 | | - |
192 | | -#### Footswitches & Pedals (CC 64-127) |
193 | | -- **CC 64**: Damper Pedal (Sustain) → Sustain On/Off |
194 | | -- **CC 65**: Portamento → Portamento On/Off |
195 | | -- **CC 66**: Sostenuto → Sostenuto On/Off |
196 | | -- **CC 67**: Soft Pedal → Soft Pedal On/Off |
197 | | -- **CC 68**: Legato Pedal → Legato On/Off |
198 | | -- **CC 69**: Hold Pedal → Hold On/Off |
199 | | -- **CC 83**: General Purpose Controller 1 → Master Volume (0.0-2.0) |
200 | | -- **CC 84**: General Purpose Controller 2 → Compressor Threshold (-24.0 to 0.0 dB) |
201 | | -- **CC 85**: General Purpose Controller 3 → Compressor Ratio (1.0-10.0:1) |
202 | | -- **CC 86**: General Purpose Controller 4 → Compressor Attack (1.0-100.0 ms) |
203 | | -- **CC 87**: General Purpose Controller 5 → Compressor Release (10.0-1000.0 ms) |
204 | | -- **CC 88**: General Purpose Controller 6 → Compressor Makeup Gain (0.0-12.0 dB) |
205 | | - |
206 | | -#### High Resolution Controllers (CC 102-119) |
207 | | -- **CC 102-120**: Undefined/Custom → Extended Parameter Control |
208 | | -- **CC 121-119**: RPN/NRPN → Extended parameter access |
209 | | - |
210 | | -#### Synthesizer-Specific Mappings (CC 89-95) |
211 | | -- **CC 89**: Sound Controller 1 → Arpeggiator Tempo (60.0-240.0 BPM) |
212 | | -- **CC 90**: Sound Controller 2 → Arpeggiator Enable (0=OFF, 1=ON) |
213 | | -- **CC 91**: Sound Controller 3 → Arpeggiator Mode (0=OFF,1=CHORD,2=UP,3=DOWN,4=UP/DOWN,5=PENDULUM,6=CONVERGE,7=DIVERGE,8=LEAPFROG,9=THUMB-UP,10=THUMB-DOWN,11=PINKY-UP,12=PINKY-DOWN,13=REPEAT,14=RANDOM,15=RANDOM WALK,16=SHUFFLE,17=ORDER) |
214 | | -- **CC 92**: Sound Controller 4 → Arpeggiator Hold (0=OFF, 1=ON) |
215 | | -- **CC 93**: Sound Controller 5 → Arpeggiator Base Octave (0-4 octaves above played note) |
216 | | -- **CC 94**: Sound Controller 6 → Arpeggiator Octave Spread (1-6 octaves of arpeggiated output) |
217 | | - |
218 | | -### Multi-Channel Support |
219 | | - |
220 | | -#### Channel Messages (CC#1-16) |
221 | | -- **Note On**: Universal on all MIDI channels (1-16) |
222 | | -- **Note Off**: Universal on all MIDI channels (1-16) |
223 | | -- **Velocity Sensitivity**: MIDI velocity 0-127 mapped to amplitude (0.0-1.0) |
224 | | -- **Polyphonic Mode**: Support for multiple simultaneous notes |
225 | | -- **Omni Mode**: Receives on all channels simultaneously |
226 | | - |
227 | | -## MIDI Implementation Details |
228 | | - |
229 | | -- **MIDI Channel**: Omnitone reception on all channels (1-16) |
230 | | -- **Velocity Sensitivity**: Note velocity maps to amplitude (0/127 = silent, 127/127 = maximum) |
231 | | -- **CC Resolution**: 7-bit MIDI CC scaled to float parameter ranges |
232 | | -- **Real-time Response**: All parameter changes are applied immediately |
233 | | -- **Preset Compatibility**: All MIDI CC mappings work with saved/loaded presets |
234 | | - |
235 | | -### Live Performance Control |
236 | | -``` |
237 | | -Hands-free control: Assign commonly used parameters to accessible CC numbers |
238 | | -Filter sweeps: Map filter cutoff to CC for real-time sweeps |
239 | | -Dynamic effects: Use CC 69-76 for effect parameter automation |
240 | | -Layer mixing: Use individual OSC gain CCs for live mixing |
241 | | -``` |
242 | | - |
243 | | -This comprehensive MIDI CC implementation provides studio-level control over all synthesizer parameters, enabling both live performance and production automation workflows. |
244 | | - |
245 | | -## Notes |
| 48 | +## MIDI Control |
246 | 49 |
|
247 | | -- MIDI input is mapped to numerous parameters (see `src/midi.c` for mapping). |
248 | | -- All GUI controls respond to mouse drag and mouse wheel. |
249 | | -- The oscilloscope is fed directly from the audio callback thread for real-time visualization |
| 50 | +MIDI input is mapped to numerous parameters (see `src/midi.c` for mapping). All GUI controls respond to mouse drag and mouse wheel. The oscilloscope is fed directly from the audio callback thread for real-time visualization. |
0 commit comments