Currently my soundfont-based renderer uses the following formula to calculate any factor (Hz, speed multipliers for specified frequencies etc.) in Soundfont rendering:
2^(cents/1200)
Is that correct for both absolute and relative cents, as the 2.o specification calls it?
What is even the difference between absolute and relative cents? Aren't they all applied to the same result in the same way (relative simply adding cents to a static value that's absolute cents? So 500 absolute + 200 relative = 700 absolute cents? Or does it change absolute by means of cent-based multiplication of te absolute cents results? So absolute speed * relative speed?
The modulators are always simply added to generators, aren't they?
What about linked modulators? How do they work?
I'm just wondering. Are the instrument layer (containing the ibag range for said layer)'s splits capable of rendering multiple at the same time for the same note?
Say:
IBag 1 filters the requested note
IBag 2 also filters the requested note
Both belonging to the same Instrument, PBag and Preset.
Does the synth simply play both notes on two channels?
Is that correct use for a normal floating point sample MIDI soundfont-based synthesizer I'm emulating?
The concave/convex etc. is implemented as follows:
Main call using the concave/convex/linear etc. algorithms:
1 //Now, apply type, polarity and direction! 2 type = ((oper >> 10) & 0x3F); //Type! 3 polarity = ((oper >> 9) & 1); //Polarity! 4 direction = ((oper >> 8) & 1); //Direction! 5 6 if (direction) //Direction is reversed? 7 { 8 i = 1.0f - i; //Reverse the direction! 9 } 10 11 switch (type) 12 { 13 default: //Not supported? 14 case 0: //Linear? 15 if (polarity) //Bipolar? 16 { 17 i = (i * 2.0) - 1.0f; //Convert to a range of -1 to 1 for the proper input value! 18 } 19 //Unipolar is left alone(already done)! 20 break; 21 case 1: //Concave? 22 if (polarity) //Bipolar? 23 { 24 if (i>=0.5f) //Past half? Positive half! 25 { 26 i = MIDIconcave((i-0.5)*2.0f); //Positive half! 27 } 28 else //First half? Negative half? 29 { 30 i = -MIDIconcave((0.5-i)*2.0f); //Negative half! 31 } 32 } 33 else //Unipolar? 34 { 35 i = MIDIconcave(i); //Concave normally! 36 } 37 break; 38 case 2: //Convex? 39 if (polarity) //Bipolar? 40 { 41 if (i>=0.5f) //Past half? Positive half! 42 { 43 i = MIDIconvex((i-0.5)*2.0f); //Positive half! 44 } 45 else //First half? Negative half? 46 { 47 i = -MIDIconvex((0.5-i)*2.0f); //Negative half! 48 } 49 } 50 else //Unipolar? 51 { 52 i = MIDIconvex(i); //Concave normally! 53 } 54 break; 55 case 3: //Switch? 56 if (i >= 0.5f) //Past half? 57 { 58 i = 1.0f; //Full! 59 } 60 else //Less than half?
…Show last 12 lines
61 { 62 i = 0.0f; //Empty! 63 } 64 if (polarity) //Bipolar? 65 { 66 i = (i * 2.0) - 1.0f; //Convert to a range of -1 to 1 for the proper input value! 67 } 68 //Unipolar is left alone(already done)! 69 break; 70 } 71 return i; //Give the result! 72}
Concave/convex support:
1//val needs to be a normalized input! Performs a concave from 1 to 0! 2float MIDIconcave(float val) 3{ 4 float result; 5 if (val <= 0.0f) //Invalid? 6 { 7 return 0.0f; //Nothing! 8 } 9 if (val >= 1.0f) //Invalid? 10 { 11 return 1.0f; //Full! 12 } 13 result = 1.0f-val; //Linear! 14 result = (result * result); //Squared! 15 result = (-20.0f / 96.0f) * log10f(result); //Convert to the 0.0-0.9 range! 16 return result; //Give the result! 17} 18 19//val needs to be a normalized input! Performs a convex from 0 to 1! 20float MIDIconvex(float val) 21{ 22 return 1.0f - (MIDIconcave(1.0f - val)); //Convex is concave mirrored horizontally on the input, while also mirrored on the output! 23}
Is that correct? The input I is normalized 0.0-1.0 inputs from the source that's being converted.
What modulator is used for the ADSR in performing attack scale by keynum, like with keynumToVolEnvDecay/Hold and keynumToModEnvDecay/Hold? The DLS document mentions it, but which destination modulator does it use?
OK. After some testing with Viena to modify the soundfont to use specific values to check if my app calcualtes and uses them correctly, I now can at least say that the attack is indeed correct behaviour (even though it sounds delayed for some odd reason). Don't know if the curve is correct though. It's using a convex curve (the same curve generated for modulators actually, same function call, but different locations being called from).
Now, looking further, it looks like somehow the volume controls are off? Maybe the formula is incorrect somehow, or the attenuation is calculated incorrectly?
After fixing volume vs modulation envelope scaling (one uses 100% (0.1 steps) and the other 1440cB scaling (was set to 960cB) it seems to be better wrt volume.
Though I seem to hear (reverb?) echoes on the opposite side of the source of the audio it sounds like? Or does the original music have some weird echo? That happens to both left and right panned audio it looks like?
Anyone knows how the volume envelope works exactly, in the context of 1440cB range, DAHDSR conversions and sustain level? How is the sustain attenuation (in cB) calculated using the other parts (AHD-R top/bottom) and sustain level(supplied in dB of attenuation (Soundfont documentation) or inverted (according to Viena)?
Hmmm... After fixing modulator recursiveness and modifying preset/instrument generator and modulators to become properly additive instead of last-only (except when matching to first found modulator/generator), while giving priority to global over local split generators/modulators (instead of local over global) and adding support for multiple modulator outputs affecting the same split simultaneously (for example LFO to volume + velocity to volume now added together instead of being replaced), I notice something weird. Somehow, playing some instruments seem to get reversed note tones. That would mean their modulators/generators to pitch is reaching negative values somehow? Thus reaching "key*-x cents" instead of proper "key*x cents"? So the summed modulators become so low it reaches too negative cents?
How do global and local splits interact with default modulators?
Right now, they're basically added together, with global splits overruling local splits.
Edit: Fixing it to handle like documented somewhat seems to fix some volume issues.
Some sounds still don't play somehow? Or are muted somehow?