shithub: sf2mid

Download patch

ref: f1d9f73efeabbe6629d0d0e0eebdf19a0ec90b86
parent: bf574519e601202c3a9d27a74f345921277eed39
parent: 05d006c48418aadfb684394dd93588ae062396e5
author: Bernhard Schelling <14200249+schellingb@users.noreply.github.com>
date: Sun Nov 14 20:36:50 EST 2021

Merge pull request #65 from ell1e/tsf-copy-new

Add "tsf_copy" function for linked copies (rebased from #1)

--- a/tsf.h
+++ b/tsf.h
@@ -89,6 +89,12 @@
 // Generic SoundFont loading method using the stream structure above
 TSFDEF tsf* tsf_load(struct tsf_stream* stream);
 
+// Copy a tsf instance from an existing one, use tsf_close to close it as well.
+// All copied tsf instances and their original instance are linked, and share the underlying soundfont.
+// This allows loading a soundfont only once, but using it for multiple independent playbacks.
+// (This function isn't thread-safe without locking.)
+TSFDEF tsf* tsf_copy(tsf* f);
+
 // Free the memory related to this tsf instance
 TSFDEF void tsf_close(tsf* f);
 
@@ -313,6 +319,7 @@
 	enum TSFOutputMode outputmode;
 	float outSampleRate;
 	float globalGainDB;
+	int* refCount;
 };
 
 #ifndef TSF_NO_STDIO
@@ -1265,6 +1272,9 @@
 		res->presets = (struct tsf_preset*)TSF_MALLOC(res->presetNum * sizeof(struct tsf_preset));
 		res->fontSamples = fontSamples;
 		res->outSampleRate = 44100.0f;
+		res->outputSampleSize = 0;
+		res->refCount = (int*)TSF_MALLOC(sizeof(int));
+		*res->refCount = 1;
 		fontSamples = TSF_NULL; //don't free below
 		tsf_load_presets(res, &hydra, fontSampleCount);
 	}
@@ -1275,17 +1285,40 @@
 	return res;
 }
 
+TSFDEF tsf* tsf_copy(tsf* f)
+{
+	if (!f)
+		return TSF_NULL;
+
+	tsf* res = TSF_NULL;
+
+	res = (tsf*)TSF_MALLOC(sizeof(tsf));
+	memcpy(res, f, sizeof(tsf));
+	res->voices = TSF_NULL;
+	res->voiceNum = 0;
+	res->channels = TSF_NULL;
+	res->outputSamples = TSF_NULL;
+	res->outputSampleSize = 0;
+	++(*res->refCount);
+
+	return res;
+}
+
 TSFDEF void tsf_close(tsf* f)
 {
 	struct tsf_preset *preset, *presetEnd;
 	if (!f) return;
-	for (preset = f->presets, presetEnd = preset + f->presetNum; preset != presetEnd; preset++)
-		TSF_FREE(preset->regions);
-	TSF_FREE(f->presets);
-	TSF_FREE(f->fontSamples);
+	if (--(*f->refCount) == 0)
+	{
+		for (preset = f->presets, presetEnd = preset + f->presetNum; preset != presetEnd; preset++)
+			TSF_FREE(preset->regions);
+		TSF_FREE(f->presets);
+		TSF_FREE(f->fontSamples);
+		TSF_FREE(f->refCount);
+	}
+	TSF_FREE(f->outputSamples);
 	TSF_FREE(f->voices);
 	if (f->channels) { TSF_FREE(f->channels->channels); TSF_FREE(f->channels); }
-	TSF_FREE(f->outputSamples);
 	TSF_FREE(f);
 }