SF2cute is a C++ library for writing SoundFont 2.
First of all, install the following prerequisite softwares.
The following command will generate a Makefile for your system. You can use cmake-gui if you want to use a GUI and configure the options.
Then compile the library using the generated project file.
Here is an example of SoundFont file writing.
   10 using namespace sf2cute;
    12 /// Makes a pulse wave of n/8 duty cycle.
    13 /// @param n the duty cycle n/8.
    14 /// @return the pulse wave sample datapoints.
    15 std::vector<int16_t> MakePulseVector(int n) {
    16   std::vector<int16_t> data(200);
    17   size_t width = data.size() * n / 8;
    18   std::fill(data.begin(), std::next(data.begin(), width), 0x4000);
    19   std::fill(std::next(data.begin(), width), data.end(), 0);
    23 /// Writes SoundFont 2 file using SF2cute.
    24 /// @param argc Number of arguments. Not used.
    25 /// @param argv Argument vector. Not used.
    26 /// @return 0 if the SoundFont file is successfully written.
    27 int main(int argc, char * argv[]) {
    31   sf2.set_sound_engine("EMU8000");
    32   sf2.set_bank_name("Chipsound");
    33   sf2.set_rom_name("ROM");
    35   // Construct sample datapoints.
    36   std::vector<int16_t> data_50 = MakePulseVector(4);
    39   std::shared_ptr<SFSample> sample_50 = sf2.NewSample(
    41     data_50,                  // sample data
    43     uint32_t(data_50.size()), // end loop
    48   // Make an instrument zone.
    49   SFInstrumentZone instrument_zone(sample_50,
    50     std::vector<SFGeneratorItem>{
    51       //SFGeneratorItem(SFGenerator::kKeyRange, RangesType(0, 127)),
    52       //SFGeneratorItem(SFGenerator::kVelRange, RangesType(0, 127)),
    53       SFGeneratorItem(SFGenerator::kSampleModes, uint16_t(SampleMode::kLoopContinuously)),
    55     std::vector<SFModulatorItem>{});
    56   // Add more generators (or modulators) if necessary.
    57   instrument_zone.SetGenerator(SFGeneratorItem(SFGenerator::kReverbEffectsSend, 618));
    60   std::shared_ptr<SFInstrument> instrument_50 = sf2.NewInstrument(
    62     std::vector<SFInstrumentZone>{
    63       std::move(instrument_zone)
    67   std::shared_ptr<SFPreset> preset_50 = sf2.NewPreset(
    68     instrument_50->name(), 0, 0,
    69     std::vector<SFPresetZone>{
    70       SFPresetZone(instrument_50)
    73   // Write SoundFont file.
    75     std::ofstream ofs("output.sf2", std::ios::binary);
    79   catch (const std::fstream::failure & e) {
    81     std::cerr << e.what() << std::endl;
    84   catch (const std::exception & e) {
    86     // For example: Too many samples.
    87     std::cerr << e.what() << std::endl;