diff --git a/Audio/Chain/DSP/DSPHRTFNode.m b/Audio/Chain/DSP/DSPHRTFNode.m index 5f6cc8d0c..44abd6ca8 100644 --- a/Audio/Chain/DSP/DSPHRTFNode.m +++ b/Audio/Chain/DSP/DSPHRTFNode.m @@ -13,6 +13,8 @@ #import "DSPHRTFNode.h" +#import "lpc.h" + #import "HeadphoneFilter.h" static void * kDSPHRTFNodeContext = &kDSPHRTFNodeContext; @@ -75,6 +77,8 @@ static void unregisterMotionListener(void) { BOOL processEntered; BOOL resetFilter; + size_t needPrefill; + BOOL observersapplied; AudioStreamBasicDescription lastInputFormat; @@ -89,7 +93,11 @@ static void unregisterMotionListener(void) { simd_float4x4 rotationMatrix; simd_float4x4 referenceMatrix; + float prefillBuffer[4096 * 32]; float outBuffer[4096 * 2]; + + void *extrapolate_buffer; + size_t extrapolate_buffer_size; } + (void)initialize { @@ -131,6 +139,11 @@ static void unregisterMotionListener(void) { [self cleanUp]; [self removeObservers]; [super cleanUp]; + if(extrapolate_buffer) { + free(extrapolate_buffer); + extrapolate_buffer = NULL; + extrapolate_buffer_size = 0; + } } - (void)addObservers { @@ -210,6 +223,8 @@ static void unregisterMotionListener(void) { outputChannelConfig = AudioChannelSideLeft | AudioChannelSideRight; resetFilter = NO; + + needPrefill = [hrtf needPrefill]; } else { if(lastEnableHeadTracking) { lastEnableHeadTracking = NO; @@ -359,6 +374,18 @@ static void unregisterMotionListener(void) { size_t frameCount = [chunk frameCount]; NSData *sampleData = [chunk removeSamples:frameCount]; + if(needPrefill) { + size_t maxToUse = 4096 - needPrefill; + if(maxToUse > frameCount) { + maxToUse = frameCount; + } + size_t channels = inputFormat.mChannelsPerFrame; + memcpy(&prefillBuffer[needPrefill * channels], [sampleData bytes], maxToUse * sizeof(float) * channels); + lpc_extrapolate_bkwd(&prefillBuffer[needPrefill * channels], maxToUse, maxToUse, (int)channels, LPC_ORDER, needPrefill, &extrapolate_buffer, &extrapolate_buffer_size); + [hrtf process:&prefillBuffer[0] sampleCount:(int)needPrefill toBuffer:&outBuffer[0]]; + needPrefill = 0; + } + [hrtf process:(const float *)[sampleData bytes] sampleCount:(int)frameCount toBuffer:&outBuffer[0]]; AudioChunk *outputChunk = [[AudioChunk alloc] init]; diff --git a/Audio/Chain/DSP/HeadphoneFilter.h b/Audio/Chain/DSP/HeadphoneFilter.h index 3a0fc44e7..68e5d173b 100644 --- a/Audio/Chain/DSP/HeadphoneFilter.h +++ b/Audio/Chain/DSP/HeadphoneFilter.h @@ -39,6 +39,8 @@ - (void)reset; +- (size_t)needPrefill; + @end #endif /* HeadphoneFilter_h */ diff --git a/Audio/Chain/DSP/HeadphoneFilter.mm b/Audio/Chain/DSP/HeadphoneFilter.mm index 31a37c1df..cdf926b30 100644 --- a/Audio/Chain/DSP/HeadphoneFilter.mm +++ b/Audio/Chain/DSP/HeadphoneFilter.mm @@ -379,4 +379,8 @@ static impulseSetCache *_sharedController = nil; } } +- (size_t)needPrefill { + return paddedBufferSize; +} + @end