On Monday, January 23, 2017 00:32:40 Frank Neumann wrote:
> Just summarizing, for clarity sake: With these 2 changes applied, the issue
> is gone (of course this is not a fix yet):

@Grigor, @Andreas: are you still around on this list? Maybe you can comment as 
well, because I am not very familiar with the SignalUnitRack stuff of the SFZ 
engine.

I had a look at this issue described by Frank. It is a bug in the 
SignalUnitRack handling. In very short, the following would fix the issue 
Frank encountered with his SFZ file:


Index: src/engines/common/SignalUnit.cpp
===================================================================
--- src/engines/common/SignalUnit.cpp   (revision 3099)
+++ src/engines/common/SignalUnit.cpp   (working copy)
@@ -25,6 +25,6 @@
 
 namespace LinuxSampler {
     bool SignalUnit::DelayStage() {
-        return (DelayTrigger() >= pRack->GetCurrentStep());
+        return (DelayTrigger() > pRack->GetCurrentStep());
     }
 } // namespace LinuxSampler


But, and there is a big "but", that short patch would just cure the symptom in 
Frank's particular case, as far as I can see it, the bug would still be 
triggered in other scenarios (more complex SFZ files) though. So here is a 
more detailed description about this issue:

The SFZ engine is calling:

        pSignalUnitRack->GetEndpointUnit()->GetVolume()

inside of method AbstractVoice::Synthesize() to get the current volume factor 
to be applied for the voice in the current audio (sub)fragment. Since Frank's 
sfz file is very simple (no volume modulators), that GetVolume() call would 
always return 1.0f (neutral volume factor), except of one case: at the very 
beginning of the life time of each voice (that is when pVoice->Pos == 0.0) 
that GetVolume() call returns 0.0f instead. And that is wrong.

GetVolume() does return 0.0f at the very beginning of a voice's life time, 
because EndPointUnit::GetVolume() calls
suVolEG.GetLevel() [SfzSignalUnitRack.cpp, line 617], which is implemented 
like this [SfzSignalUnitRack.h, line 165]:

        virtual float GetLevel() { return DelayStage() ? 0 : EG.getLevel(); }

Now in Frank's case, it is simply a bug to assume that it would be in a delay 
stage at the beginning of the voice's life time and the short patch above 
would fix it. But apart from Frank's case, simply returning 0 here looks odd 
to me.

As I said, I am not familiar with the SignalUnitRack code base, but 
intuitively I would rather expect the GetLevel() implementation either

a) to always return EG.getLevel() (even in delay stage) or

b) to return an "identity element" in delay stage instead, which depends on 
whether that result is going to be used in a mathematical add operation (in 
which case the identity element is 0) or rather in a mathematical multiply 
operation (in which case the identity element is 1).

Thoughts? Am I missing something?

CU
Christian

------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
_______________________________________________
Linuxsampler-devel mailing list
Linuxsampler-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxsampler-devel

Reply via email to