I'm testing with the AweROMGM and 8MBGMSFX Soundfonts. But some instruments(like harps and string instruments), for some reason, have very loud volume(despite being soft foreground notes). They completely overwhelm most of the background instruments, making them unable to be heared. Can anyone see what's going wrong? Attenuation causes? I've based it completely on the Soundfont 2.04 specification.
But, the tones are still off for some songs? Anyone can see what's going wrong? (Look at rootMIDItone variable handling for exact handling of it, and related processing of playback samplerate factor)
This is what I'm currently using to determine the factor(linear factor) to apply to the samplerate(thus playing the samples at that factor's speed to obtain the effective tone without pitch bend. Pitch bends are calculated the same way and multiplied with this factor to obtain the final factor to use as the playback speed):
1 //Now, calculate the speedup according to the note applied! 2 cents = 0; //Default: none! 3 4 //Calculate MIDI difference in notes! 5 if (lookupSFInstrumentGenGlobal(soundfont, LE16(instrumentptr.genAmount.wAmount), ibag, overridingRootKey, &applyigen)) 6 { 7 rootMIDITone = LE16(applyigen.genAmount.wAmount); //The MIDI tone to apply is different! 8 if ((rootMIDITone<0) || (rootMIDITone>127)) //Invalid? 9 { 10 rootMIDITone = voice->sample.byOriginalPitch; //Original MIDI tone! 11 } 12 } 13 else 14 { 15 rootMIDITone = voice->sample.byOriginalPitch; //Original MIDI tone! 16 } 17 18 rootMIDITone -= (sword)note->note; //>=positive difference, <=negative difference. 19 //Ammount of MIDI notes too high is in rootMIDITone. 20 21 //Coarse tune... 22 if (lookupSFInstrumentGenGlobal(soundfont, LE16(instrumentptr.genAmount.wAmount), ibag, coarseTune, &applyigen)) 23 { 24 cents = LE16(applyigen.genAmount.shAmount); //How many semitones! 25 cents *= 100; //Apply to the cents: 1 semitone = 100 cents! 26 } 27 28 //Fine tune... 29 if (lookupSFInstrumentGenGlobal(soundfont, LE16(instrumentptr.genAmount.wAmount), ibag, fineTune, &applyigen)) 30 { 31 cents += LE16(applyigen.genAmount.shAmount); //Add the ammount of cents! 32 } 33 34 //Scale tuning: how the MIDI number affects semitone (percentage of semitones) 35 tonecents = 100; //Default: 100 cents(%) scale tuning! 36 if (lookupSFPresetGenGlobal(soundfont, preset, pbag, scaleTuning, &applygen)) 37 { 38 tonecents = LE16(applygen.genAmount.shAmount); //Apply semitone factor in percent for each tone! 39 } 40 else if (lookupSFInstrumentGenGlobal(soundfont, LE16(instrumentptr.genAmount.wAmount), ibag, scaleTuning, &applyigen)) 41 { 42 tonecents = LE16(applyigen.genAmount.shAmount); //Apply semitone factor in percent for each tone! 43 } 44 45 tonecents *= -rootMIDITone; //Difference in tones we use is applied to the ammount of cents! 46 47 cents += tonecents; //Apply the MIDI tone cents for the MIDI tone! 48 49 //Now the cents variable contains the diviation in cents. 50 voice->initsamplespeedup = cents; //Load the default speedup we need for our tone!
The initsamplespeedup is multiplied with cents2samplesfactorf(pitchcents) to apply pitch bends, which is finally multiplied with the current sample(at the base rate determined by the sample that's playing). That should result in a proper playback of samples? What's going wrong with this? Some instruments somehow end up with wrong pitches?
**************
This is the way attenuation is calculated, with it being applied to the resulting samples by simple multiplication:
1 attenuation = 0.0f; //Init to default value! 2 if (lookupSFInstrumentGenGlobal(soundfont, LE16(instrumentptr.genAmount.wAmount), ibag, initialAttenuation, &applyigen)) 3 { 4 attenuation = (float)LE16(applyigen.genAmount.shAmount); //Apply semitone factor in percent for each tone! 5 if (attenuation>1440.0f) attenuation = 1440.0f; //Limit to max! 6 if (attenuation<0.0f) attenuation = 0.0f; //Limit to min! 7 } 8 9 //Apply volume modulation! 10 if (lookupSFPresetModGlobal(soundfont, preset,pbag,0x0502,&applymod)) //Gotten Note On velocity to Initial Attenuation? 11 { 12 applymod.modAmount = LE16(applymod.modAmount); //Patch! 13 if (applymod.modAmount>960) applymod.modAmount = 960; //Limit to max value if needed! 14 else if (applymod.modAmount<0) applymod.modAmount = 0; //Limit to min value if needed! 15 attenuation += MIDIconcave((float)applymod.modAmount,960.0f); //Range is 960cB, so convert and apply(add to the initial attenuation generator)! 16 } 17 else if (lookupSFInstrumentModGlobal(soundfont, LE16(instrumentptr.genAmount.wAmount),ibag,0x0502,&applymod)) //Gotten Note On velocity to Initial Attenuation? 18 { 19 applymod.modAmount = LE16(applymod.modAmount); //Patch! 20 if (applymod.modAmount>960) applymod.modAmount = 960; //Limit to max value if needed! 21 else if (applymod.modAmount<0) applymod.modAmount = 0; //Limit to min value if needed! 22 attenuation += MIDIconcave((float)applymod.modAmount*((((float)((sword)note->noteon_velocity-0x40)))/64.0f),960.0f); //Range is 960cB, so convert and apply(add to the initial attenuation generator)! 23 } 24 else //Default? 25 { 26 attenuation += MIDIconcave((float)960.0f*((((float)((sword)note->noteon_velocity-0x40)))/64.0f),960.0f); 27 } 28 29 if (lookupSFPresetModGlobal(soundfont, preset,pbag,0x0582,&applymod)) //Gotten MIDI Continuous Controller 7 to Initial Attenuation? 30 { 31 applymod.modAmount = LE16(applymod.modAmount); //Patch! 32 if (applymod.modAmount>960) applymod.modAmount = 960; //Limit to max value if needed! 33 else if (applymod.modAmount<0) applymod.modAmount = 0; //Limit to min value if needed! 34 attenuation += MIDIconcave((float)applymod.modAmount,960.0f); //Range is 960cB, so convert and apply(add to the initial attenuation generator)! 35 } 36 else if (lookupSFInstrumentModGlobal(soundfont, LE16(instrumentptr.genAmount.wAmount),ibag,0x0582,&applymod)) //Gotten MIDI Continuous Controller 7 to Initial Attenuation? 37 { 38 applymod.modAmount = LE16(applymod.modAmount); //Patch! 39 if (applymod.modAmount>960) applymod.modAmount = 960; //Limit to max value if needed! 40 else if (applymod.modAmount<0) applymod.modAmount = 0; //Limit to min value if needed! 41 attenuation += MIDIconcave((float)applymod.modAmount*((((float)(((sword)((channel->volume>>7)&0x7F)-0x40))))/64.0f),960.0f); //Range is 960cB, so convert and apply(add to the initial attenuation generator)! 42 } 43 else //Default? 44 { 45 attenuation += MIDIconcave((float)960.0f*((((float)((sword)(((channel->volume>>7)&0x7F)-0x40))))/64.0f),960.0f); 46 } 47 48 if (lookupSFPresetModGlobal(soundfont, preset,pbag,0x058B,&applymod)) //Gotten MIDI Continuous Controller 11 to Initial Attenuation? 49 { 50 applymod.modAmount = LE16(applymod.modAmount); //Patch! 51 if (applymod.modAmount>960) applymod.modAmount = 960; //Limit to max value if needed! 52 else if (applymod.modAmount<0) applymod.modAmount = 0; //Limit to min value if needed! 53 attenuation += MIDIconcave((float)applymod.modAmount,960.0f); //Range is 960cB, so convert and apply(add to the initial attenuation generator)! 54 } 55 else if (lookupSFInstrumentModGlobal(soundfont, LE16(instrumentptr.genAmount.wAmount),ibag,0x058B,&applymod)) //Gotten MIDI Continuous Controller 11 to Initial Attenuation? 56 { 57 applymod.modAmount = LE16(applymod.modAmount); //Patch! 58 if (applymod.modAmount>960) applymod.modAmount = 960; //Limit to max value if needed! 59 else if (applymod.modAmount<0) applymod.modAmount = 0; //Limit to min value if needed! 60 attenuation += MIDIconcave((float)applymod.modAmount*((((float)((sword)(((channel->volume>>14)&0x7F)-0x40))))/64.0f),960.0f); //Range is 960cB, so convert and apply(add to the initial attenuation generator)!
…Show last 10 lines
61 } 62 else //Default? 63 { 64 attenuation += MIDIconcave((float)960.0f*((((float)((sword)(((channel->volume>>14)&0x7F)-0x40))))/64.0f),960.0f); 65 } 66 67 if (attenuation>4320.0f) attenuation = 4320.0f; //Limit to max! 68 if (attenuation<0.0f) attenuation = 0.0f; //Limit to min! 69 70 voice->initialAttenuation = (float)dB2factor((((4320.0-(double)attenuation)*(96.0f/432.0f))/10.0),96.0); //We're converted to a rate of 960 cb!
Anyone knows if this is correct? Why are some tones in various songs(like harp and other echoey instruments) pretty much saturating their outputs, which causes clipping on the channels themselves? This happens to e.g. instrument 000:046 Harp of the soundfont.
Looking at the decay of the harp, I notice it's generating 367990 samples of decay of instrument Troubharp E2(44.1kHz samplerate) and 113985 samples of release. It's supposed to be 0.00s decay, 0.01s release. So UniPCemu somehow calculates around 8.3s decay and 2.5s release? That cannot be right, according to the Viena Soundfont editor?
Edit: This seems to be in the instrument level, I was looking at the preset level. There, Viena Sound Editor does show the 8.3s decay and 2.5s release. So the values calculated by UniPCemu are correct. Then, why do the various channels keep running so long?
I've improved the lookups for generators and modulators to take the endOper and NULL modulators into account. But for some reason, some instruments still disappear after playing them, as well as loudness problems?
Looking at the renderer again, it seems the MIDI pitch bend messages were being substracted to become signed(by 8192, which is no pitch bend) twice. Thus causing any pitch bend to be doubled instead of applied as supposed to.