bool PlayerWillMixSample(IGATBufferedSample sample, int length, float[] audioBuffer)
{
int indexInProcessingBuffer = 0;
int appliedLength;
int lengthToMix = length;
float fromGain, toGain;
switch (_currentState)
{
case State.Attack:
if (_nextIndex >= _decayStartIndex) //handle attack = 0;
{
_currentState = State.Decay;
goto case State.Decay;
}
else
{
if (sample.IsFirstChunk && length > _attackLength)
{
appliedLength = _attackLength;
}
else
{
appliedLength = length;
}
//Interpolate gain
fromGain = (( float )(_nextIndex - _attackStartIndex)) / (_attackLength);
if (_nextIndex + appliedLength >= _decayStartIndex) //attack slope will finish before the end of the buffer
{
appliedLength = _decayStartIndex - _nextIndex;
toGain = 1f;
_data.CopySmoothedGainTo(_nextIndex, sample.ProcessingBuffer, 0, appliedLength, fromGain, toGain);
_nextIndex = _decayStartIndex;
indexInProcessingBuffer = appliedLength;
_currentState = State.Decay;
goto case State.Decay;
}
else
{
toGain = (( float )(_nextIndex + appliedLength - _attackStartIndex)) / (_attackLength);
_data.CopySmoothedGainTo(_nextIndex, sample.ProcessingBuffer, 0, appliedLength, fromGain, toGain);
_nextIndex += appliedLength;
}
}
break;
case State.Decay:
appliedLength = GATInfo.AudioBufferSizePerChannel - indexInProcessingBuffer;
if (_nextIndex + appliedLength >= _loopStartIndex) // decay will end this buffer
{
appliedLength = _loopStartIndex - _nextIndex;
_data.CopyTo(sample.ProcessingBuffer, indexInProcessingBuffer, _nextIndex, appliedLength);
_nextIndex = _loopStartIndex;
indexInProcessingBuffer += appliedLength;
if (_noLoop)
{
_currentState = State.Release;
goto case State.Release;
}
else if (_loopCrossfadeLength == _loopLength)
{
_currentState = State.SustainCrossfade;
goto case State.SustainCrossfade;
}
else
{
_currentState = State.Sustain;
goto case State.Sustain;
}
}
else
{
_data.CopyTo(sample.ProcessingBuffer, indexInProcessingBuffer, _nextIndex, appliedLength);
_nextIndex += appliedLength;
}
break;
case State.Sustain:
appliedLength = GATInfo.AudioBufferSizePerChannel - indexInProcessingBuffer;
if (_nextIndex + appliedLength >= _loopCrossfadeIndex) // will start crossfading in this buffer
{
appliedLength = _loopCrossfadeIndex - _nextIndex;
_data.CopyTo(sample.ProcessingBuffer, indexInProcessingBuffer, _nextIndex, appliedLength);
indexInProcessingBuffer += appliedLength;
_nextIndex += appliedLength;
if (_keepLooping)
{
_currentState = State.SustainCrossfade;
goto case State.SustainCrossfade;
}
else
{
_releaseIndex = _nextIndex;
_endIndex = _nextIndex + _releaseLength;
_currentState = State.Release;
goto case State.Release;
}
}
else
{
_data.CopyTo(sample.ProcessingBuffer, indexInProcessingBuffer, _nextIndex, appliedLength);
_nextIndex += appliedLength;
}
break;
case State.SustainCrossfade:
appliedLength = GATInfo.AudioBufferSizePerChannel - indexInProcessingBuffer;
int crossfadeOffset = _nextIndex - _loopCrossfadeIndex;
//Crossfade gains
fromGain = 1f - ( float )(crossfadeOffset) / _loopCrossfadeLength;
if (_nextIndex + appliedLength > _loopEndIndex) //will finish loop in current buffer
{
appliedLength = _loopEndIndex - _nextIndex;
_data.CopySmoothedGainTo(_nextIndex, sample.ProcessingBuffer, indexInProcessingBuffer, appliedLength, fromGain, 0f);
_data.MixSmoothedGainTo(_loopStartIndex - (_loopCrossfadeLength - crossfadeOffset), sample.ProcessingBuffer, indexInProcessingBuffer, appliedLength, 1f - fromGain, 1f);
indexInProcessingBuffer += appliedLength;
_nextIndex = _loopStartIndex; //need to loop even if release, as xfade has already started
if (_keepLooping)
{
_currentState = State.Sustain;
goto case State.Sustain;
}
else
{
_releaseIndex = _loopStartIndex;
_endIndex = _loopStartIndex + _releaseLength;
_currentState = State.Release;
goto case State.Release;
}
}
else
{
//crossfade gain
toGain = 1f - ( float )(crossfadeOffset + appliedLength) / _loopCrossfadeLength;
_data.CopySmoothedGainTo(_nextIndex, sample.ProcessingBuffer, indexInProcessingBuffer, appliedLength, fromGain, toGain);
_data.MixSmoothedGainTo(_loopStartIndex - (_loopCrossfadeLength - crossfadeOffset), sample.ProcessingBuffer, indexInProcessingBuffer, appliedLength, 1f - fromGain, 1f - toGain);
_nextIndex += appliedLength;
}
break;
case State.Release:
appliedLength = GATInfo.AudioBufferSizePerChannel - indexInProcessingBuffer;
fromGain = 1f - (( float )(_nextIndex - _releaseIndex)) / (_releaseLength);
if (_nextIndex + appliedLength >= _endIndex) //release slope will finish before the end of the buffer
{
toGain = 0f;
sample.IsLastChunk = true;
IsPlaying = false;
appliedLength = _endIndex - _nextIndex;
lengthToMix = appliedLength + indexInProcessingBuffer;
_data.CopySmoothedGainTo(_nextIndex, sample.ProcessingBuffer, indexInProcessingBuffer, appliedLength, fromGain, toGain);
}
else
{
toGain = 1f - (( float )(_nextIndex + appliedLength - _releaseIndex)) / (_releaseLength);
_data.CopySmoothedGainTo(_nextIndex, sample.ProcessingBuffer, indexInProcessingBuffer, appliedLength, fromGain, toGain);
_nextIndex += appliedLength;
}
break;
}
sample.NextIndex = _nextIndex;
sample.Track.MixFrom(sample.ProcessingBuffer, 0, sample.OffsetInBuffer, lengthToMix);
return(false);
}