Skip to content

rpvelloso/fluidsynth

master
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code
This branch is 19 commits ahead, 1195 commits behind FluidSynth:master.

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
src
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Single Header Stripped off version of FluidSynth

Only synth and sound font functionality were kept.

What was removed:

  • networking;
  • audio drivers;
  • bindings;
  • command line program;
  • tests;
  • documentation;
  • Glib dependency (header fluid_glib_remover.h).

What was kept:

  • synth;
  • player;
  • SF loader.

The single header library:

Usage:

  • Compile the source C file fs.c (e.g., gcc -c fs.c -o fs.o) and;
  • Include the header fs.h in your code;
  • Link your software with fs.o.

Example (converts MIDI to 16 bit stereo PCM):

/* 
compile with: 
	gcc -c fs.c -o fs.o 
	gcc -c test.c -o test.o 
	gcc fs.o test.o -o test 

run:
	./test
	
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "fs.h"

#define SAMPLE_RATE 44100
#define CHANNELS 2
#define BITS_PER_SAMPLE 16
#define BYTES_PER_SAMPLE (BITS_PER_SAMPLE>>3)
#define FRAME_SIZE (BYTES_PER_SAMPLE*CHANNELS)

#define SF_FILE "mysoundfont.sf2"
#define BUF_LEN (FRAME_SIZE * 4 * 1024) // 4k frames
#define FILENAME "mymidifile.mid"
#define OUTFILE "output.wav"

void loadMidiFile(const char *filename, void **buf, size_t *len) {
	FILE *midiFile = fopen(filename, "rb");
	
	if (midiFile != NULL) {
		fseek(midiFile, 0, SEEK_END);
		*len = ftell(midiFile);
		*buf = malloc(*len);
		if (*buf != NULL) {
			rewind(midiFile);
			fread(*buf, *len, 1, midiFile);
		}
		fclose(midiFile);
	}
}

typedef struct WaveHeader {
	char RIFF[4];
	uint32_t chunkSize;
	char WAVE[4];
	char fmt[4];
	uint32_t subChunkSize;

	uint16_t audioFormat;
	uint16_t numChannels;
	uint32_t sampleRate;
	uint32_t byteRate;
	uint16_t blockAlign;
	uint16_t bitsPerSample;

	char data[4];
	uint32_t dataSize;
} WaveHeader;

int main() {
	void *inputBuffer; // midi file loaded in memory
	size_t inputBufferSize;

	loadMidiFile(FILENAME, &inputBuffer, &inputBufferSize);

	if (inputBuffer != NULL && fluid_is_soundfont(SF_FILE)) {
		fluid_settings_t *settings = new_fluid_settings();
		fluid_synth_t *synth = new_fluid_synth(settings);
		fluid_player_t *player = new_fluid_player(synth);
		fluid_synth_sfload(synth, SF_FILE, 1);
		fluid_player_add_mem(player, inputBuffer, inputBufferSize);
		fluid_player_play(player);

		WaveHeader waveHeader = {
			{'R','I','F', 'F'}, 
			0, 
			{'W', 'A', 'V', 'E'}, 
			{'f', 'm', 't', ' '}, 
			0x10, 1, 
			CHANNELS, 
			SAMPLE_RATE, 
			FRAME_SIZE*SAMPLE_RATE, 
			FRAME_SIZE, 
			BITS_PER_SAMPLE, 
			{'d', 'a', 't', 'a'}, 0};

		FILE *out = fopen(OUTFILE, "wb");
		fwrite(&waveHeader, sizeof(waveHeader), 1, out);
		
		void *buf = malloc(BUF_LEN);
		
		while (fluid_player_get_status(player) != FLUID_PLAYER_DONE) {
			fluid_synth_write_s16(
				synth,
				BUF_LEN / FRAME_SIZE,
				buf, 0, BYTES_PER_SAMPLE,
				buf, 1, BYTES_PER_SAMPLE);
			fwrite(buf, BUF_LEN, 1, out);
			waveHeader.dataSize += BUF_LEN;
		}
		
		free(buf);
		
		delete_fluid_player(player);
		delete_fluid_synth(synth);
		delete_fluid_settings(settings);
		
		free(inputBuffer);
		
		rewind(out);
		waveHeader.chunkSize = waveHeader.dataSize + 36;
		fwrite(&waveHeader, sizeof(waveHeader), 1, out);
		fclose(out);
	}
}

About

Software synthesizer based on the SoundFont 2 specifications

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C 96.9%
  • CMake 2.3%
  • Other 0.8%