ZiggySynth is a SoundFont MIDI synthesizer written in pure Zig, ported from MeltySynth for C#.
- Suitable for both real-time and offline synthesis.
 - Support for standard MIDI files.
 - No dependencies other than the standard library.
 - All the functionality is in a single file.
 
- Zig v0.15.x is required.
 - Copy ziggysynth.zig to your project.
 
Video:
https://www.youtube.com/watch?v=E8E17ejfRuc
Code:
https://github.com/sinshu/ziggysynth-test
Video:
https://www.youtube.com/watch?v=eUKQ9T5Pjbg
Code:
https://github.com/sinshu/ziggysynth-test/tree/piano
Some useful aliases:
const ziggysynth = @import("ziggysynth.zig");
const SoundFont = ziggysynth.SoundFont;
const Synthesizer = ziggysynth.Synthesizer;
const SynthesizerSettings = ziggysynth.SynthesizerSettings;
const MidiFile = ziggysynth.MidiFile;
const MidiFileSequencer = ziggysynth.MidiFileSequencer;An example code to synthesize a simple chord:
// Load the SoundFont.
var sf2 = try fs.cwd().openFile("TimGM6mb.sf2", .{});
defer sf2.close();
var sf2_buffer: [1024]u8 = undefined;
var sf2_reader = sf2.reader(&sf2_buffer);
var sound_font = try SoundFont.init(allocator, &sf2_reader.interface);
defer sound_font.deinit();
// Create the synthesizer.
var settings = SynthesizerSettings.init(44100);
var synthesizer = try Synthesizer.init(allocator, &sound_font, &settings);
defer synthesizer.deinit();
// Play some notes (middle C, E, G).
synthesizer.noteOn(0, 60, 100);
synthesizer.noteOn(0, 64, 100);
synthesizer.noteOn(0, 67, 100);
// The output buffer (3 seconds).
const sample_count: usize = @intCast(3 * settings.sample_rate);
const left: []f32 = try allocator.alloc(f32, sample_count);
defer allocator.free(left);
const right: []f32 = try allocator.alloc(f32, sample_count);
defer allocator.free(right);
// Render the waveform.
synthesizer.render(left, right);Another example code to synthesize a MIDI file:
// Load the SoundFont.
var sf2 = try fs.cwd().openFile("TimGM6mb.sf2", .{});
defer sf2.close();
var sf2_buffer: [1024]u8 = undefined;
var sf2_reader = sf2.reader(&sf2_buffer);
var sound_font = try SoundFont.init(allocator, &sf2_reader.interface);
defer sound_font.deinit();
// Create the synthesizer.
var settings = SynthesizerSettings.init(44100);
var synthesizer = try Synthesizer.init(allocator, &sound_font, &settings);
defer synthesizer.deinit();
// Load the MIDI file.
var mid = try fs.cwd().openFile("flourish.mid", .{});
defer mid.close();
var mid_buffer: [1024]u8 = undefined;
var mid_reader = mid.reader(&mid_buffer);
var midi_file = try MidiFile.init(allocator, &mid_reader.interface);
defer midi_file.deinit();
// Create the sequencer.
var sequencer = MidiFileSequencer.init(&synthesizer);
// Play the MIDI file.
sequencer.play(&midi_file, false);
// The output buffer.
const sample_count = @as(f64, @floatFromInt(settings.sample_rate)) * midi_file.getLength();
const left: []f32 = try allocator.alloc(f32, @intFromFloat(sample_count));
defer allocator.free(left);
const right: []f32 = try allocator.alloc(f32, @intFromFloat(sample_count));
defer allocator.free(right);
// Render the waveform.
sequencer.render(left, right);- Wave synthesis
- SoundFont reader
 - Waveform generator
 - Envelope generator
 - Low-pass filter
 - Vibrato LFO
 - Modulation LFO
 
 - MIDI message processing
- Note on/off
 - Bank selection
 - Modulation
 - Volume control
 - Pan
 - Expression
 - Hold pedal
 - Program change
 - Pitch bend
 - Tuning
 
 - Effects
- Reverb
 - Chorus
 
 - Other things
- Standard MIDI file support
 - Performace optimization
 
 
ZiggySynth is available under the MIT license.

