session-ios/Signal/src/audio/incall_audio/processing/StretchFactorController.m

80 lines
3.3 KiB
Objective-C

#import "Constraints.h"
#import "StretchFactorController.h"
#define STRETCH_MODE_EXPAND 0
#define STRETCH_MODE_NORMAL 1
#define STRETCH_MODE_SHRINK 2
#define STRETCH_MODE_SUPER_SHRINK 3
static double STRETCH_MODE_FACTORS[] = {1 / 0.95, 1, 1 / 1.05, 0.5};
#define SUPER_SHRINK_THRESHOLD 10
#define SHRINK_THRESHOLD 3.0
#define EXPAND_THRESHOLD -2.0
#define BUFFER_DEPTH_DECAYING_FACTOR 0.05
@implementation StretchFactorController
+ (StretchFactorController *)stretchFactorControllerForJitterQueue:(JitterQueue *)jitterQueue {
ows_require(jitterQueue != nil);
DesiredBufferDepthController *desiredBufferDepthController =
[DesiredBufferDepthController desiredBufferDepthControllerForJitterQueue:jitterQueue];
StretchFactorController *p = [StretchFactorController new];
p->desiredBufferDepthController = desiredBufferDepthController;
p->currentStretchMode = STRETCH_MODE_NORMAL;
p->bufferDepthMeasure = jitterQueue;
p->decayingBufferDepthMeasure =
[DecayingSampleEstimator decayingSampleEstimatorWithInitialEstimate:0
andDecayPerUnitSample:BUFFER_DEPTH_DECAYING_FACTOR];
p->stretchModeChangeLogger = [Environment.logging getValueLoggerForValue:@"stretch factor" from:self];
return p;
}
- (int)reconsiderStretchMode {
int16_t currentBufferDepth = bufferDepthMeasure.currentBufferDepth;
[decayingBufferDepthMeasure updateWithNextSample:currentBufferDepth];
double desiredBufferDepth = desiredBufferDepthController.getAndUpdateDesiredBufferDepth;
double currentBufferDepthDelta = currentBufferDepth - desiredBufferDepth;
double decayingBufferDepthDelta = decayingBufferDepthMeasure.currentEstimate - desiredBufferDepth;
bool shouldStartSuperShrink = currentBufferDepthDelta > SUPER_SHRINK_THRESHOLD;
bool shouldMaintainSuperShrink = currentBufferDepthDelta > 0 && currentStretchMode == STRETCH_MODE_SUPER_SHRINK;
bool shouldEndSuperShrinkAndResetEstimate =
!shouldMaintainSuperShrink && currentStretchMode == STRETCH_MODE_SUPER_SHRINK;
bool shouldStartShrink = decayingBufferDepthDelta > SHRINK_THRESHOLD;
bool shouldMaintainShrink = decayingBufferDepthDelta > 0 && currentStretchMode == STRETCH_MODE_SHRINK;
bool shouldStartExpand = decayingBufferDepthDelta < EXPAND_THRESHOLD;
bool shouldMaintainExpand = decayingBufferDepthDelta < 0 && currentStretchMode == STRETCH_MODE_EXPAND;
if (shouldEndSuperShrinkAndResetEstimate) {
[decayingBufferDepthMeasure forceEstimateTo:desiredBufferDepth];
return STRETCH_MODE_NORMAL;
}
if (shouldStartSuperShrink)
return STRETCH_MODE_SUPER_SHRINK;
if (shouldStartShrink)
return STRETCH_MODE_SHRINK;
if (shouldStartExpand)
return STRETCH_MODE_EXPAND;
if (shouldMaintainShrink || shouldMaintainExpand || shouldMaintainSuperShrink)
return currentStretchMode;
return STRETCH_MODE_NORMAL;
}
- (double)getAndUpdateDesiredStretchFactor {
int prevMode = currentStretchMode;
currentStretchMode = [self reconsiderStretchMode];
double factor = STRETCH_MODE_FACTORS[currentStretchMode];
if (prevMode != currentStretchMode) {
[stretchModeChangeLogger logValue:factor];
}
return factor;
}
@end