shithub: sf2mid

Download patch

ref: e86d986ed6ccb93b4ee41d2de656c49c721b18db
parent: 77dde8fdc4e1fc618105c7acede22dacbf51fda0
author: Bernhard Schelling <14200249+schellingb@users.noreply.github.com>
date: Thu Nov 18 21:12:43 EST 2021

C89 compatibility and style fixes
Also add missing cleanup in tsf_load_presets if it fails midway through (#67)

--- a/tsf.h
+++ b/tsf.h
@@ -261,6 +261,14 @@
 #define TSF_RENDER_EFFECTSAMPLEBLOCK 64
 #endif
 
+// When using tsf_render_short, to do the conversion a buffer of a fixed size is
+// allocated on the stack. On low memory platforms this could be made smaller.
+// Increasing this above 512 should not have a significant impact on performance.
+// The value should be a multiple of TSF_RENDER_EFFECTSAMPLEBLOCK.
+#ifndef TSF_RENDER_SHORTBUFFERBLOCK
+#define TSF_RENDER_SHORTBUFFERBLOCK 512
+#endif
+
 // Grace release time for quick voice off (avoid clicking noise)
 #define TSF_FASTRELEASETIME 0.01f
 
@@ -700,6 +708,10 @@
 	enum { GenInstrument = 41, GenKeyRange = 43, GenVelRange = 44, GenSampleID = 53 };
 	// Read each preset.
 	struct tsf_hydra_phdr *pphdr, *pphdrMax;
+	res->presetNum = hydra->phdrNum - 1;
+	res->presets = (struct tsf_preset*)TSF_MALLOC(res->presetNum * sizeof(struct tsf_preset));
+	if (!res->presets) return 0;
+	else { int i; for (i = 0; i != res->presetNum; i++) res->presets[i].regions = TSF_NULL; }
 	for (pphdr = hydra->phdrs, pphdrMax = pphdr + hydra->phdrNum - 1; pphdr != pphdrMax; pphdr++)
 	{
 		int sortedIndex = 0, region_index = 0;
@@ -751,7 +763,8 @@
 		preset->regions = (struct tsf_region*)TSF_MALLOC(preset->regionNum * sizeof(struct tsf_region));
 		if (!preset->regions)
 		{
-			preset->regionNum = 0;
+			int i; for (i = 0; i != res->presetNum; i++) TSF_FREE(res->presets[i].regions);
+			TSF_FREE(res->presets);
 			return 0;
 		}
 		tsf_region_clear(&globalRegion, TSF_TRUE);
@@ -854,10 +867,7 @@
 	float* out; unsigned int samplesLeft, samplesToRead, samplesToConvert;
 	samplesLeft = *fontSampleCount = chunkSmpl->size / sizeof(short);
 	out = *fontSamples = (float*)TSF_MALLOC(samplesLeft * sizeof(float));
-	if (!fontSamples) {
-		*fontSamples = 0;
-		return 0;
-	}
+	if (!out) return 0;
 	for (; samplesLeft; samplesLeft -= samplesToRead)
 	{
 		short sampleBuffer[1024], *in = sampleBuffer;;
@@ -1239,8 +1249,6 @@
 	}
 
 	// Read hydra and locate sample data.
-	int hydra_alloc_failed = 0;
-	int samples_alloc_failed = 0;
 	TSF_MEMSET(&hydra, 0, sizeof(hydra));
 	while (tsf_riffchunk_read(&chunkHead, &chunkList, stream))
 	{
@@ -1247,7 +1255,7 @@
 		struct tsf_riffchunk chunk;
 		if (TSF_FourCCEquals(chunkList.id, "pdta"))
 		{
-			while (tsf_riffchunk_read(&chunkList, &chunk, stream) && !hydra_alloc_failed)
+			while (tsf_riffchunk_read(&chunkList, &chunk, stream))
 			{
 				#define HandleChunk(chunkName) (TSF_FourCCEquals(chunk.id, #chunkName) && !(chunk.size % chunkName##SizeInFile)) \
 					{ \
@@ -1254,11 +1262,7 @@
 						int num = chunk.size / chunkName##SizeInFile, i; \
 						hydra.chunkName##Num = num; \
 						hydra.chunkName##s = (struct tsf_hydra_##chunkName*)TSF_MALLOC(num * sizeof(struct tsf_hydra_##chunkName)); \
-						if (!hydra.chunkName##s) \
-						{ \
-							hydra_alloc_failed = 1; \
-							break; \
-						} \
+						if (!hydra.chunkName##s) goto out_of_memory; \
 						for (i = 0; i < num; ++i) tsf_hydra_read_##chunkName(&hydra.chunkName##s[i], stream); \
 					}
 				enum
@@ -1280,63 +1284,42 @@
 			{
 				if (TSF_FourCCEquals(chunk.id, "smpl") && !fontSamples && chunk.size >= sizeof(short))
 				{
-					if (!tsf_load_samples(&fontSamples, &fontSampleCount, &chunk, stream))
-                    {
-                        samples_alloc_failed = 1;
-                    }
+					if (!tsf_load_samples(&fontSamples, &fontSampleCount, &chunk, stream)) goto out_of_memory;
 				}
 				else stream->skip(stream->data, chunk.size);
 			}
 		}
 		else stream->skip(stream->data, chunkList.size);
-		if (hydra_alloc_failed || samples_alloc_failed)
-			break;
 	}
-	if ((!hydra.phdrs || !hydra.pbags || !hydra.pmods || !hydra.pgens || !hydra.insts || !hydra.ibags || !hydra.imods || !hydra.igens || !hydra.shdrs) && !hydra_alloc_failed)
+	if (!hydra.phdrs || !hydra.pbags || !hydra.pmods || !hydra.pgens || !hydra.insts || !hydra.ibags || !hydra.imods || !hydra.igens || !hydra.shdrs)
 	{
 		//if (e) *e = TSF_INVALID_INCOMPLETE;
 	}
-	else if (fontSamples == TSF_NULL && !samples_alloc_failed)
+	else if (fontSamples == TSF_NULL)
 	{
 		//if (e) *e = TSF_INVALID_NOSAMPLEDATA;
 	}
-	else if (!hydra_alloc_failed && !samples_alloc_failed)
+	else
 	{
 		res = (tsf*)TSF_MALLOC(sizeof(tsf));
-		if (res)
-		{
-			TSF_MEMSET(res, 0, sizeof(tsf));
-			res->presetNum = hydra.phdrNum - 1;
-			res->presets = (struct tsf_preset*)TSF_MALLOC(res->presetNum * sizeof(struct tsf_preset));
-			if (!res->presets)
-			{
-				res->presetNum = 0;
-				TSF_FREE(res);
-				res = TSF_NULL;
-				goto skipfontinit;
-			}
-			res->fontSamples = fontSamples;
-			fontSamples = TSF_NULL; //don't free below
-			res->outSampleRate = 44100.0f;
-			
-			if (!tsf_load_presets(res, &hydra, fontSampleCount))
-			{
-				TSF_FREE(res);
-				res = TSF_NULL;
-			}
-			skipfontinit:
-		}
+		if (!res) goto out_of_memory;
+		TSF_MEMSET(res, 0, sizeof(tsf));
+		if (!tsf_load_presets(res, &hydra, fontSampleCount)) goto out_of_memory;
+		res->fontSamples = fontSamples;
+		fontSamples = TSF_NULL; //don't free below
+		res->outSampleRate = 44100.0f;
 	}
+	if (0)
+	{
+		out_of_memory:
+		TSF_FREE(res);
+		res = TSF_NULL;
+		//if (e) *e = TSF_OUT_OF_MEMORY;
+	}
 	TSF_FREE(hydra.phdrs); TSF_FREE(hydra.pbags); TSF_FREE(hydra.pmods);
 	TSF_FREE(hydra.pgens); TSF_FREE(hydra.insts); TSF_FREE(hydra.ibags);
 	TSF_FREE(hydra.imods); TSF_FREE(hydra.igens); TSF_FREE(hydra.shdrs);
 	TSF_FREE(fontSamples);
-	if (!res || hydra_alloc_failed || samples_alloc_failed)
-	{
-		//if (e) *e = TSF_INVALID_ALLOCFAIL;
-		if (res) tsf_close(res);
-		return TSF_NULL;
-	}
 	return res;
 }
 
@@ -1344,10 +1327,10 @@
 {
 	tsf* res;
 	if (!f) return TSF_NULL;
-	if (!f->refCount) {
+	if (!f->refCount)
+	{
 		f->refCount = (int*)TSF_MALLOC(sizeof(int));
-		if (!f->refCount)
-			return TSF_NULL;
+		if (!f->refCount) return TSF_NULL;
 		*f->refCount = 1;
 	}
 	res = (tsf*)TSF_MALLOC(sizeof(tsf));
@@ -1356,19 +1339,17 @@
 	res->voices = TSF_NULL;
 	res->voiceNum = 0;
 	res->channels = TSF_NULL;
-
-	++(*res->refCount);
+	(*res->refCount)++;
 	return res;
 }
 
 TSFDEF void tsf_close(tsf* f)
 {
-	struct tsf_preset *preset, *presetEnd;
 	if (!f) return;
 	if (!f->refCount || !--(*f->refCount))
 	{
-		for (preset = f->presets, presetEnd = preset + f->presetNum; preset != presetEnd; preset++)
-			TSF_FREE(preset->regions);
+		struct tsf_preset *preset = f->presets, *presetEnd = preset + f->presetNum;
+		for (; preset != presetEnd; preset++) TSF_FREE(preset->regions);
 		TSF_FREE(f->presets);
 		TSF_FREE(f->fontSamples);
 		TSF_FREE(f->refCount);
@@ -1429,8 +1410,7 @@
 	int i = f->voiceNum;
 	int newVoiceNum = (f->voiceNum > max_voices ? f->voiceNum : max_voices);
 	struct tsf_voice *newVoices = (struct tsf_voice*)TSF_REALLOC(f->voices, newVoiceNum * sizeof(struct tsf_voice));
-	if (!newVoices)
-		return 0;
+	if (!newVoices) return 0;
 	f->voices = newVoices;
 	f->voiceNum = f->maxVoiceNum = newVoiceNum;
 	for (; i < max_voices; i++)
@@ -1465,6 +1445,7 @@
 
 		if (!voice)
 		{
+			struct tsf_voice* newVoices;
 			if (f->maxVoiceNum)
 			{
 				// voices have been pre-allocated and limited to a maximum, unable to start playing this voice
@@ -1471,11 +1452,8 @@
 				continue;
 			}
 			f->voiceNum += 4;
-			struct tsf_voice* newVoices = (struct tsf_voice*)TSF_REALLOC(f->voices, f->voiceNum * sizeof(struct tsf_voice));
-			if (!newVoices)
-			{
-				return 0;
-			}
+			newVoices = (struct tsf_voice*)TSF_REALLOC(f->voices, f->voiceNum * sizeof(struct tsf_voice));
+			if (!newVoices) return 0;
 			f->voices = newVoices;
 			voice = &f->voices[f->voiceNum - 4];
 			voice[1].playingPreset = voice[2].playingPreset = voice[3].playingPreset = -1;
@@ -1578,17 +1556,13 @@
 
 TSFDEF void tsf_render_short(tsf* f, short* buffer, int samples, int flag_mixing)
 {
-	float *floatSamples;
-	float outputSamples[512];
-
-	while (samples > 0) {
-		const int maxChannelSamples = (sizeof(outputSamples) / sizeof(float)) / (f->outputmode == TSF_MONO ? 1 : 2);
-		int channelSamples = samples;
-		if (channelSamples > maxChannelSamples)
-			channelSamples = maxChannelSamples;
-		short* bufferEnd = buffer + channelSamples * (f->outputmode == TSF_MONO ? 1 : 2);
-
-		floatSamples = outputSamples;
+	float outputSamples[TSF_RENDER_SHORTBUFFERBLOCK];
+	int channels = (f->outputmode == TSF_MONO ? 1 : 2), maxChannelSamples = TSF_RENDER_SHORTBUFFERBLOCK / channels;
+	while (samples > 0)
+	{
+		int channelSamples = (samples > maxChannelSamples ? maxChannelSamples : samples);
+		short* bufferEnd = buffer + channelSamples * channels;
+		float *floatSamples = outputSamples;
 		tsf_render_float(f, floatSamples, channelSamples, TSF_FALSE);
 		samples -= channelSamples;
 
@@ -1636,8 +1610,7 @@
 	if (!f->channels)
 	{
 		f->channels = (struct tsf_channels*)TSF_MALLOC(sizeof(struct tsf_channels) + sizeof(struct tsf_channel) * channel);
-		if (!f->channels)
-			return NULL;
+		if (!f->channels) return NULL;
 		f->channels->setupVoice = &tsf_channel_setup_voice;
 		f->channels->channelNum = 0;
 		f->channels->activeChannel = 0;
@@ -1645,8 +1618,7 @@
 	else
 	{
 		struct tsf_channels *newChannels = (struct tsf_channels*)TSF_REALLOC(f->channels, sizeof(struct tsf_channels) + sizeof(struct tsf_channel) * channel);
-		if (!newChannels)
-			return NULL;
+		if (!newChannels) return NULL;
 		f->channels = newChannels;
 	}
 	i = f->channels->channelNum;
@@ -1679,8 +1651,7 @@
 TSFDEF int tsf_channel_set_presetindex(tsf* f, int channel, int preset_index)
 {
 	struct tsf_channel *c = tsf_channel_init(f, channel);
-	if (!c)
-		return 0;
+	if (!c) return 0;
 	c->presetIndex = (unsigned short)preset_index;
 	return 1;
 }
@@ -1687,10 +1658,9 @@
 
 TSFDEF int tsf_channel_set_presetnumber(tsf* f, int channel, int preset_number, int flag_mididrums)
 {
-	struct tsf_channel *c = tsf_channel_init(f, channel);
-	if (!c)
-		return 0;
 	int preset_index;
+	struct tsf_channel *c = tsf_channel_init(f, channel);
+	if (!c) return 0;
 	if (flag_mididrums)
 	{
 		preset_index = tsf_get_presetindex(f, 128 | (c->bank & 0x7FFF), preset_number);
@@ -1711,8 +1681,7 @@
 TSFDEF int tsf_channel_set_bank(tsf* f, int channel, int bank)
 {
 	struct tsf_channel *c = tsf_channel_init(f, channel);
-	if (!c)
-		return 0;
+	if (!c) return 0;
 	c->bank = (unsigned short)bank;
 	return 1;
 }
@@ -1719,10 +1688,10 @@
 
 TSFDEF int tsf_channel_set_bank_preset(tsf* f, int channel, int bank, int preset_number)
 {
+	int preset_index;
 	struct tsf_channel *c = tsf_channel_init(f, channel);
-	if (!c)
-		return 0;
-	int preset_index = tsf_get_presetindex(f, bank, preset_number);
+	if (!c) return 0;
+	preset_index = tsf_get_presetindex(f, bank, preset_number);
 	if (preset_index == -1) return 0;
 	c->presetIndex = (unsigned short)preset_index;
 	c->bank = (unsigned short)bank;
@@ -1732,6 +1701,8 @@
 TSFDEF int tsf_channel_set_pan(tsf* f, int channel, float pan)
 {
 	struct tsf_voice *v, *vEnd;
+	struct tsf_channel *c = tsf_channel_init(f, channel);
+	if (!c) return 0;
 	for (v = f->voices, vEnd = v + f->voiceNum; v != vEnd; v++)
 		if (v->playingChannel == channel && v->playingPreset != -1)
 		{
@@ -1740,9 +1711,6 @@
 			else if (newpan >=  0.5f) { v->panFactorLeft = 0.0f; v->panFactorRight = 1.0f; }
 			else { v->panFactorLeft = TSF_SQRTF(0.5f - newpan); v->panFactorRight = TSF_SQRTF(0.5f + newpan); }
 		}
-	struct tsf_channel *c = tsf_channel_init(f, channel);
-	if (!c)
-		return 0;
 	c->panOffset = pan - 0.5f;
 	return 1;
 }
@@ -1749,13 +1717,12 @@
 
 TSFDEF int tsf_channel_set_volume(tsf* f, int channel, float volume)
 {
-	struct tsf_channel *c = tsf_channel_init(f, channel);
-	if (!c)
-		return 0;
-	float gainDB = tsf_gainToDecibels(volume), gainDBChange = gainDB - c->gainDB;
+	float gainDB = tsf_gainToDecibels(volume), gainDBChange;
 	struct tsf_voice *v, *vEnd;
-	if (gainDBChange == 0) return 1;
-	for (v = f->voices, vEnd = v + f->voiceNum; v != vEnd; v++)
+	struct tsf_channel *c = tsf_channel_init(f, channel);
+	if (!c) return 0;
+	if (gainDB == c->gainDB) return 1;
+	for (v = f->voices, vEnd = v + f->voiceNum, gainDBChange = gainDB - c->gainDB; v != vEnd; v++)
 		if (v->playingChannel == channel && v->playingPreset != -1)
 			v->noteGainDB += gainDBChange;
 	c->gainDB = gainDB;
@@ -1765,8 +1732,7 @@
 TSFDEF int tsf_channel_set_pitchwheel(tsf* f, int channel, int pitch_wheel)
 {
 	struct tsf_channel *c = tsf_channel_init(f, channel);
-	if (!c)
-		return 0;
+	if (!c) return 0;
 	if (c->pitchWheel == pitch_wheel) return 1;
 	c->pitchWheel = (unsigned short)pitch_wheel;
 	tsf_channel_applypitch(f, channel, c);
@@ -1776,8 +1742,7 @@
 TSFDEF int tsf_channel_set_pitchrange(tsf* f, int channel, float pitch_range)
 {
 	struct tsf_channel *c = tsf_channel_init(f, channel);
-	if (!c)
-		return 0;
+	if (!c) return 0;
 	if (c->pitchRange == pitch_range) return 1;
 	c->pitchRange = pitch_range;
 	if (c->pitchWheel != 8192) tsf_channel_applypitch(f, channel, c);
@@ -1787,8 +1752,7 @@
 TSFDEF int tsf_channel_set_tuning(tsf* f, int channel, float tuning)
 {
 	struct tsf_channel *c = tsf_channel_init(f, channel);
-	if (!c)
-		return 0;
+	if (!c) return 0;
 	if (c->tuning == tuning) return 1;
 	c->tuning = tuning;
 	tsf_channel_applypitch(f, channel, c);
@@ -1841,8 +1805,7 @@
 TSFDEF int tsf_channel_midi_control(tsf* f, int channel, int controller, int control_value)
 {
 	struct tsf_channel* c = tsf_channel_init(f, channel);
-	if (!c)
-		return 0;
+	if (!c) return 0;
 	switch (controller)
 	{
 		case   7 /*VOLUME_MSB*/      : c->midiVolume     = (unsigned short)((c->midiVolume     & 0x7F  ) | (control_value << 7)); goto TCMC_SET_VOLUME;