shithub: sf2mid

Download patch

ref: 1bfb3616300b913f931d510fc9d7d33b850c9ce3
parent: 8d5e0448baaa1cb6de7fc45d2d74289f207b8db4
author: Bernhard Schelling <schellingb@gmail.com>
date: Sat Mar 24 15:31:05 EDT 2018

- Handle preset global zone
- Correctly combine preset and instrument volume (attenuation) generators

--- a/tsf.h
+++ b/tsf.h
@@ -515,7 +515,7 @@
 		case KeyRange:                   region->lokey = amount->range.lo; region->hikey = amount->range.hi; break;
 		case VelRange:                   region->lovel = amount->range.lo; region->hivel = amount->range.hi; break;
 		case StartloopAddrsCoarseOffset: region->loop_start += amount->shortAmount * 32768; break;
-		case InitialAttenuation:         region->volume += -amount->shortAmount / 100.0f; break;
+		case InitialAttenuation:         region->volume += amount->shortAmount / 100.0f; break;
 		case EndloopAddrsCoarseOffset:   region->loop_end += amount->shortAmount * 32768; break;
 		case CoarseTune:                 region->transpose += amount->shortAmount; break;
 		case FineTune:                   region->tune += amount->shortAmount; break;
@@ -558,6 +558,7 @@
 		struct tsf_hydra_phdr *otherphdr;
 		struct tsf_preset* preset;
 		struct tsf_hydra_pbag *ppbag, *ppbagEnd;
+		struct tsf_region globalRegion;
 		for (otherphdr = hydra->phdrs; otherphdr != pphdrMax; otherphdr++)
 		{
 			if (otherphdr == pphdr || otherphdr->bank > pphdr->bank) continue;
@@ -600,14 +601,14 @@
 		}
 
 		preset->regions = (struct tsf_region*)TSF_MALLOC(preset->regionNum * sizeof(struct tsf_region));
+		tsf_region_clear(&globalRegion, TSF_TRUE);
 
 		// Zones.
-		//*** TODO: Handle global zone (modulators only).
 		for (ppbag = hydra->pbags + pphdr->presetBagNdx, ppbagEnd = hydra->pbags + pphdr[1].presetBagNdx; ppbag != ppbagEnd; ppbag++)
 		{
 			struct tsf_hydra_pgen *ppgen, *ppgenEnd; struct tsf_hydra_inst *pinst; struct tsf_hydra_ibag *pibag, *pibagEnd; struct tsf_hydra_igen *pigen, *pigenEnd;
-			struct tsf_region presetRegion;
-			tsf_region_clear(&presetRegion, TSF_TRUE);
+			struct tsf_region presetRegion = globalRegion;
+			int hadGenInstrument = 0;
 
 			// Generators.
 			for (ppgen = hydra->pgens + ppbag->genNdx, ppgenEnd = hydra->pgens + ppbag[1].genNdx; ppgen != ppgenEnd; ppgen++)
@@ -700,13 +701,6 @@
 								if (zoneRegion.end && zoneRegion.end < fontSampleCount) zoneRegion.end++;
 								else zoneRegion.end = fontSampleCount;
 
-								// Pin initialAttenuation to max +6dB.
-								if (zoneRegion.volume > 6.0f)
-								{
-									zoneRegion.volume = 6.0f;
-									//addUnsupportedOpcode("extreme gain in initialAttenuation");
-								}
-
 								preset->regions[region_index] = zoneRegion;
 								region_index++;
 								hadSampleID = 1;
@@ -721,6 +715,7 @@
 						// Modulators (TODO)
 						//if (ibag->instModNdx < ibag[1].instModNdx) addUnsupportedOpcode("any modulator");
 					}
+					hadGenInstrument = 1;
 				}
 				else tsf_region_operator(&presetRegion, ppgen->genOper, &ppgen->genAmount);
 			}
@@ -727,6 +722,10 @@
 
 			// Modulators (TODO)
 			//if (pbag->modNdx < pbag[1].modNdx) addUnsupportedOpcode("any modulator");
+
+			// Handle preset's global zone.
+			if (ppbag == hydra->pbags + pphdr->presetBagNdx && !hadGenInstrument)
+				globalRegion = presetRegion;
 		}
 	}
 }
@@ -750,7 +749,7 @@
 	}
 }
 
-static void tsf_voice_envelope_nextsegment(struct tsf_voice_envelope* e, int active_segment, float outSampleRate)
+static void tsf_voice_envelope_nextsegment(struct tsf_voice_envelope* e, short active_segment, float outSampleRate)
 {
 	switch (active_segment)
 	{
@@ -1257,7 +1256,7 @@
 		voice->playingPreset = preset_index;
 		voice->playingKey = key;
 		voice->playIndex = voicePlayIndex;
-		voice->noteGainDB = f->globalGainDB + region->volume - tsf_gainToDecibels(1.0f / vel);
+		voice->noteGainDB = f->globalGainDB - region->volume - tsf_gainToDecibels(1.0f / vel);
 
 		if (f->channels)
 		{