shithub: sf2mid

Download patch

ref: d21c521c2f7fc85b9d490a5852fa05f2994171eb
parent: 2e4021b25f023a79c9b53811289c3e975f903533
author: Bernhard Schelling <schellingb@gmail.com>
date: Wed Feb 14 21:51:25 EST 2018

Correctly filter zone regions by key/velocity ranges of parent preset region

--- a/tsf.h
+++ b/tsf.h
@@ -495,7 +495,7 @@
 
 static void tsf_load_presets(tsf* res, struct tsf_hydra *hydra)
 {
-	enum { GenInstrument = 41, GenSampleID = 53 };
+	enum { GenInstrument = 41, GenKeyRange = 43, GenVelRange = 44, GenSampleID = 53 };
 	// Read each preset.
 	struct tsf_hydra_phdr *pphdr, *pphdrMax;
 	for (pphdr = hydra->phdrs, pphdrMax = pphdr + hydra->phdrNum - 1; pphdr != pphdrMax; pphdr++)
@@ -523,16 +523,25 @@
 		//count regions covered by this preset
 		for (ppbag = hydra->pbags + pphdr->presetBagNdx, ppbagEnd = hydra->pbags + pphdr[1].presetBagNdx; ppbag != ppbagEnd; ppbag++)
 		{
+			unsigned char plokey = 0, phikey = 127, plovel = 0, phivel = 127;
 			struct tsf_hydra_pgen *ppgen, *ppgenEnd; struct tsf_hydra_inst *pinst; struct tsf_hydra_ibag *pibag, *pibagEnd; struct tsf_hydra_igen *pigen, *pigenEnd;
 			for (ppgen = hydra->pgens + ppbag->genNdx, ppgenEnd = hydra->pgens + ppbag[1].genNdx; ppgen != ppgenEnd; ppgen++)
 			{
+				if (ppgen->genOper == GenKeyRange) { plokey = ppgen->genAmount.range.lo; phikey = ppgen->genAmount.range.hi; continue; }
+				if (ppgen->genOper == GenVelRange) { plovel = ppgen->genAmount.range.lo; phivel = ppgen->genAmount.range.hi; continue; }
 				if (ppgen->genOper != GenInstrument) continue;
 				if (ppgen->genAmount.wordAmount >= hydra->instNum) continue;
 				pinst = hydra->insts + ppgen->genAmount.wordAmount;
 				for (pibag = hydra->ibags + pinst->instBagNdx, pibagEnd = hydra->ibags + pinst[1].instBagNdx; pibag != pibagEnd; pibag++)
+				{
+					unsigned char ilokey = 0, ihikey = 127, ilovel = 0, ihivel = 127;
 					for (pigen = hydra->igens + pibag->instGenNdx, pigenEnd = hydra->igens + pibag[1].instGenNdx; pigen != pigenEnd; pigen++)
-						if (pigen->genOper == GenSampleID)
-							preset->regionNum++;
+					{
+						if (pigen->genOper == GenKeyRange) { ilokey = pigen->genAmount.range.lo; ihikey = pigen->genAmount.range.hi; continue; }
+						if (pigen->genOper == GenVelRange) { ilovel = pigen->genAmount.range.lo; ihivel = pigen->genAmount.range.hi; continue; }
+						if (pigen->genOper == GenSampleID && ihikey >= plokey && ilokey <= phikey && ihivel >= plovel && ilovel <= phivel) preset->regionNum++;
+					}
+				}
 			}
 		}
 
@@ -557,15 +566,6 @@
 					if (whichInst >= hydra->instNum) continue;
 
 					tsf_region_clear(&instRegion, TSF_FALSE);
-					// Preset generators are supposed to be "relative" modifications of
-					// the instrument settings, but that makes no sense for ranges.
-					// For those, we'll have the instrument's generator take
-					// precedence, though that may not be correct.
-					instRegion.lokey = presetRegion.lokey;
-					instRegion.hikey = presetRegion.hikey;
-					instRegion.lovel = presetRegion.lovel;
-					instRegion.hivel = presetRegion.hivel;
-
 					pinst = &hydra->insts[whichInst];
 					for (pibag = hydra->ibags + pinst->instBagNdx, pibagEnd = hydra->ibags + pinst[1].instBagNdx; pibag != pibagEnd; pibag++)
 					{
@@ -576,8 +576,16 @@
 						{
 							if (pigen->genOper == GenSampleID)
 							{
-								struct tsf_hydra_shdr* pshdr = &hydra->shdrs[pigen->genAmount.wordAmount];
+								struct tsf_hydra_shdr* pshdr;
 
+								//preset region key and vel ranges are a filter for the zone regions
+								if (zoneRegion.hikey < presetRegion.lokey || zoneRegion.lokey > presetRegion.hikey) continue;
+								if (zoneRegion.hivel < presetRegion.lovel || zoneRegion.lovel > presetRegion.hivel) continue;
+								if (presetRegion.lokey > zoneRegion.lokey) zoneRegion.lokey = presetRegion.lokey;
+								if (presetRegion.hikey < zoneRegion.hikey) zoneRegion.hikey = presetRegion.hikey;
+								if (presetRegion.lovel > zoneRegion.lovel) zoneRegion.lovel = presetRegion.lovel;
+								if (presetRegion.hivel < zoneRegion.hivel) zoneRegion.hivel = presetRegion.hivel;
+
 								//sum regions
 								zoneRegion.offset += presetRegion.offset;
 								zoneRegion.end += presetRegion.end;
@@ -626,6 +634,7 @@
 								else if (zoneRegion.pan > 100.0f) zoneRegion.pan = 100.0f;
 								if (zoneRegion.initialFilterQ < 1500 || zoneRegion.initialFilterQ > 13500) zoneRegion.initialFilterQ = 0;
 
+								pshdr = &hydra->shdrs[pigen->genAmount.wordAmount];
 								zoneRegion.offset += pshdr->start;
 								zoneRegion.end += pshdr->end;
 								zoneRegion.loop_start += pshdr->startLoop;